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);