shithub: ifilter

Download patch

ref: a105ad42e036c4b88fe1f728ff9c60cfd7fcd6ca
parent: 56fcd319c56268612ac2406f74d16207935ab730
author: phil9 <[email protected]>
date: Tue Nov 23 02:33:44 EST 2021

handle image with CMAP8 chan properly

	we were making the assumption that all images had a 32bit depth
	with an x8r8g8b8 chan which would obviously not work with CMAP8
	chan format.

--- a/ifilter.c
+++ b/ifilter.c
@@ -10,51 +10,51 @@
 struct Filter
 {
 	const char *name;
-	void (*filter)(uchar[3], float);
+	void (*filter)(int *r, int *g, int *b, float);
 };
 
 void
-grayscale(uchar p[3], float)
+grayscale(int *r, int *g, int *b, float)
 {
-	uchar v = 0.2126*p[2] + 0.7152*p[1] + 0.0722*p[0];
-	p[0] = p[1] = p[2] = v;
+	uchar v = 0.2126*(*r) + 0.7152*(*g) + 0.0722*(*b);
+	*r = *g = *b = v;
 }
 
 void
-sepia(uchar p[3], float)
+sepia(int *r, int *g, int *b, float)
 {
-	float r, g, b;
+	float fr, fg, fb;
 
-	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);
+	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);
 }
 
 void
-invert(uchar p[3], float)
+invert(int *r, int *g, int *b, float)
 {
-	p[0] = 255 - p[0];
-	p[1] = 255 - p[1];
-	p[2] = 255 - p[2];
+	*b = 255 - *b;
+	*g = 255 - *g;
+	*r = 255 - *r;
 }
 
 void
-shade(uchar p[3], float factor)
+shade(int *r, int *g, int *b, float factor)
 {
-	p[0] = p[0] * (1 - factor);
-	p[1] = p[1] * (1 - factor);
-	p[2] = p[2] * (1 - factor);
+	*b = *b * (1 - factor);
+	*g = *g * (1 - factor);
+	*r = *r * (1 - factor);
 }
 
 void
-tint(uchar p[3], float factor)
+tint(int *r, int *g, int *b, float 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;
+	*b = *b + (255.0 - *b) * factor;
+	*g = *g + (255.0 - *g) * factor;
+	*r = *r + (255.0 - *r) * factor;
 }
 
 void
@@ -73,10 +73,47 @@
 };
 
 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;
+	int w, h, p, n, s, r, g, b;
 	uchar *buf;
 	Filter *f;
 	float factor;
@@ -110,16 +147,20 @@
 	i = readmemimage(0);
 	if(i==nil)
 		sysfatal("readmemimage: %r");
+	s = i->depth/8;
 	w = Dx(i->r);
 	h = Dy(i->r);
-	n = 4*w*h*sizeof(uchar);
+	n = s*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+=4)
-		f->filter(buf+p, factor);
+	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);
+	}
 	if(loadmemimage(i, i->r, buf, n)<0)
 		sysfatal("unloadmemimage: %r");
 	writememimage(1, i);