ref: a105ad42e036c4b88fe1f728ff9c60cfd7fcd6ca
dir: /ifilter.c/
#include <u.h> #include <libc.h> #include <draw.h> #include <memdraw.h> #define MIN(x,y) ((x)<(y)?(x):(y)) typedef struct Filter Filter; struct Filter { const char *name; void (*filter)(int *r, int *g, int *b, float); }; void grayscale(int *r, int *g, int *b, float) { uchar v = 0.2126*(*r) + 0.7152*(*g) + 0.0722*(*b); *r = *g = *b = v; } void sepia(int *r, int *g, int *b, float) { float fr, fg, fb; 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(int *r, int *g, int *b, float) { *b = 255 - *b; *g = 255 - *g; *r = 255 - *r; } void shade(int *r, int *g, int *b, float factor) { *b = *b * (1 - factor); *g = *g * (1 - factor); *r = *r * (1 - factor); } void tint(int *r, int *g, int *b, float factor) { *b = *b + (255.0 - *b) * factor; *g = *g + (255.0 - *g) * factor; *r = *r + (255.0 - *r) * factor; } void usage(void) { fprint(2, "usage: %s [-f factor] [grayscale|sepia|invert|shade|tint]\n", argv0); exits("usage"); } static Filter filters[] = { { "grayscale", grayscale }, { "sepia", sepia }, { "invert", invert }, { "shade", shade }, { "tint", tint }, }; 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; uchar *buf; Filter *f; float factor; f = nil; factor = 0.0; ARGBEGIN{ case 'f': factor = (float)atof(EARGF(usage())); break; default: usage(); break; }ARGEND; if(argc!=1) usage(); for(n=0; n<nelem(filters); n++){ if(strcmp(*argv, filters[n].name)==0){ f = filters+n; break; } } if(f==nil) usage(); if(factor<0.0 || factor>1.0){ fprint(2, "factor should be between 0.0 and 1.0\n"); exits("invalid factor"); } if(memimageinit()<0) sysfatal("memimageinit: %r"); i = readmemimage(0); if(i==nil) sysfatal("readmemimage: %r"); s = i->depth/8; w = Dx(i->r); h = Dy(i->r); 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+=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); freememimage(i); exits(nil); }