ref: 90204e60f5b1e8fb734f99898e7128052b47d869
dir: /dither.c/
#include <u.h> #include <libc.h> #include <draw.h> #include <memdraw.h> int clamp(int n) { if(n < 0) n = 0; else if(n > 255) n = 255; return n; } uchar* dither(uchar *data, int w, int h, int depth) { #define P(X,Y,C) out[((X) + w*(Y))*depth + C] #define SETP(X,Y,C,E) out[((X) + w*(Y))*depth + C] = clamp(out[((X) + w*(Y))*depth + C] + E) uchar *out; int x, y, c, o, n, q; out = malloc(depth*w*h*sizeof(uchar)); if(out == nil) return nil; for(y = 0; y < depth*w*h; y++) out[y] = data[y]; for(y = 0; y < h; y++){ for(x = 0; x < w; x++){ for(c = 0; c < 3; c++){ /* B G R */ o = P(x, y, c); n = 255*floor(o/255.0 + 0.5); q = o - n; P(x, y, c) = n; if(x + 1 < w) SETP(x + 1, y , c, q * 7.0/16.0); if(x - 1 >= 0 && y + 1 < h) SETP(x - 1, y + 1, c, q * 3.0/16.0); if(y + 1 < h) SETP(x , y + 1, c, q * 5.0/16.0); if(x + 1 < w && y + 1 < h) SETP(x + 1, y + 1, c, q * 1.0/16.0); } } } return out; #undef SETP #undef P } void usage(void) { fprint(2, "usage: %s\n", argv0); exits("usage"); } void main(int argc, char *argv[]) { Memimage *o, *i; int w, h, n; uchar *buf, *out; ARGBEGIN{ default: usage(); break; }ARGEND; if(memimageinit()<0) sysfatal("memimageinit: %r"); o = readmemimage(0); if(o==nil) sysfatal("readmemimage: %r"); i = allocmemimage(rectsubpt(o->r, o->r.min), XRGB32); memimagedraw(i, i->r, o, o->r.min, nil, ZP, S); freememimage(o); w = Dx(i->r); h = Dy(i->r); 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"); freememimage(i); out = dither(buf, w, h, 4); if(out == nil) sysfatal("dither failed: %r"); print(" x8r8g8b8 %11d %11d %11d %11d ", 0, 0, w, h); write(1, out, n); exits(nil); }