shithub: ifilter

Download patch

ref: 2b8de34339eaee77261ac891ce3e701b2e66a84f
parent: a105ad42e036c4b88fe1f728ff9c60cfd7fcd6ca
author: phil9 <telephil9@gmail.com>
date: Wed Nov 24 00:57:03 EST 2021

use a single image format

	instead of adding more and more code to handle each and every possible
	image formats we now use an image with the required format and draw the
	input on this image before applying the filter.
	This greatly simplifies the code and removes the risk for unhandled cases.

	A big thank you to qwx for suggesting this!

--- a/ifilter.c
+++ b/ifilter.c
@@ -10,51 +10,51 @@
 struct Filter
 {
 	const char *name;
-	void (*filter)(int *r, int *g, int *b, float);
+	void (*filter)(uchar[3], float);
 };
 
 void
-grayscale(int *r, int *g, int *b, float)
+grayscale(uchar p[3], float)
 {
-	uchar v = 0.2126*(*r) + 0.7152*(*g) + 0.0722*(*b);
-	*r = *g = *b = v;
+	uchar v = 0.2126*p[2] + 0.7152*p[1] + 0.0722*p[0];
+	p[0] = p[1] = p[2] = v;
 }
 
 void
-sepia(int *r, int *g, int *b, float)
+sepia(uchar p[3], float)
 {
-	float fr, fg, fb;
+	float r, g, b;
 
-	fr = 0.393*(*r) + 0.769*(*g) + 0.189*(*b);
-	fg = 0.349*(*r) + 0.686*(*g) + 0.168*(*b);
-	fb = 0.272*(*r) + 0.534*(*g) + 0.131*(*b);
-	*r = MIN(fr, 255);
-	*g = MIN(fg, 255);
-	*b = MIN(fb, 255);
+	r = 0.393*p[2] + 0.769*p[1] + 0.189*p[0];
+	g = 0.349*p[2] + 0.686*p[1] + 0.168*p[0];
+	b = 0.272*p[2] + 0.534*p[1] + 0.131*p[0];
+	p[2] = MIN(r, 255);
+	p[1] = MIN(g, 255);
+	p[0] = MIN(b, 255);
 }
 
 void
-invert(int *r, int *g, int *b, float)
+invert(uchar p[3], float)
 {
-	*b = 255 - *b;
-	*g = 255 - *g;
-	*r = 255 - *r;
+	p[0] = 255 - p[0];
+	p[1] = 255 - p[1];
+	p[2] = 255 - p[2];
 }
 
 void
-shade(int *r, int *g, int *b, float factor)
+shade(uchar p[3], float factor)
 {
-	*b = *b * (1 - factor);
-	*g = *g * (1 - factor);
-	*r = *r * (1 - factor);
+	p[0] = p[0] * (1 - factor);
+	p[1] = p[1] * (1 - factor);
+	p[2] = p[2] * (1 - factor);
 }
 
 void
-tint(int *r, int *g, int *b, float factor)
+tint(uchar p[3], float factor)
 {
-	*b = *b + (255.0 - *b) * factor;
-	*g = *g + (255.0 - *g) * factor;
-	*r = *r + (255.0 - *r) * factor;
+	p[0] = p[0] + (255.0 - p[0]) * factor;
+	p[1] = p[1] + (255.0 - p[1]) * factor;
+	p[2] = p[2] + (255.0 - p[2]) * factor;
 }
 
 void
@@ -73,47 +73,10 @@
 };
 
 void
-getcolor(int depth, uchar *buf, int *r, int *g, int *b)
-{
-	int c;
-
-	switch(depth){
-	case 8:
-		c = cmap2rgb(*buf);
-		*r = (c >> 8 * 2) & 0xFF;
-		*g = (c >> 8 * 1) & 0xFF;
-		*b = (c >> 8 * 0) & 0xFF;
-		break;
-	case 24:
-	case 32:
-		*r = buf[2];
-		*g = buf[1];
-		*b = buf[0];
-		break;
-	}
-}
-
-void
-setcolor(int depth, uchar *buf, int r, int g, int b)
-{
-	switch(depth){
-	case 8:
-		*buf = rgb2cmap(r, g, b);
-		break;
-	case 32:
-		buf[2] = r;
-		buf[1] = g;
-		buf[0] = b;
-		break;
-	}
-
-}
-
-void
 main(int argc, char *argv[])
 {
-	Memimage *i;
-	int w, h, p, n, s, r, g, b;
+	Memimage *o, *i;
+	int w, h, p, n;
 	uchar *buf;
 	Filter *f;
 	float factor;
@@ -144,23 +107,22 @@
 	}
 	if(memimageinit()<0)
 		sysfatal("memimageinit: %r");
-	i = readmemimage(0);
-	if(i==nil)
+	o = readmemimage(0);
+	if(o==nil)
 		sysfatal("readmemimage: %r");
-	s = i->depth/8;
+	i = allocmemimage(o->r, XRGB32);
+	memimagedraw(i, i->r, o, o->r.min, nil, ZP, S);
+	freememimage(o);
 	w = Dx(i->r);
 	h = Dy(i->r);
-	n = s*w*h*sizeof(uchar);
+	n = 4*w*h*sizeof(uchar);
 	buf = malloc(n);
 	if(buf==nil)
 		sysfatal("malloc: %r");
 	if(unloadmemimage(i, i->r, buf, n)<0)
 		sysfatal("unloadmemimage: %r");
-	for(p = 0; p < n; p+=s){
-		getcolor(i->depth, buf+p, &r, &g, &b);
-		f->filter(&r, &g, &b, factor);
-		setcolor(i->depth, buf+p, r, g, b);
-	}
+	for(p = 0; p < n; p+=4)
+		f->filter(buf+p, factor);
 	if(loadmemimage(i, i->r, buf, n)<0)
 		sysfatal("unloadmemimage: %r");
 	writememimage(1, i);