void setup() { PImage img = loadImage("lenna.jpg"); size(img.width, img.height); RenderImageUsingErrorDiffusion(img); save("result.png"); }
void RenderImageUsingErrorDiffusion(PImage img) { float[] error = new float[img.width * img.height * 3]; for (int y = 0; y < img.height; ++y) { for (int x = 0; x < img.width; ++x) { color cc = DiffuseError(x, y, img.pixels[y * img.width + x], img.width, img.height, error); set(x, y, cc); } } }
color DiffuseError(int x, int y, color c, int w, int h, float[] error) { float r = max(0, min(1, gamma(red(c) / 255) + error[(y * w + x) * 3 + 0])); float g = max(0, min(1, gamma(green(c) / 255) + error[(y * w + x) * 3 + 1])); float b = max(0, min(1, gamma(blue(c) / 255) + error[(y * w + x) * 3 + 2])); int rr = 0, gg = 0, bb = 0; if (r >= 0.5) { rr = 255; r -= 1.0; } if (g >= 0.5) { gg = 255; g -= 1.0; } if (b >= 0.5) { bb = 255; b -= 1.0; } Propagate(x + 1, y, r, g, b, 7.0 / 16, w, h, error); Propagate(x - 1, y + 1, r, g, b, 3.0 / 16, w, h, error); Propagate(x, y + 1, r, g, b, 5.0 / 16, w, h, error); Propagate(x + 1, y + 1, r, g, b, 1.0 / 16, w, h, error); return color(rr, gg, bb); }
void Propagate(int x, int y, float r, float g, float b, float ratio, int w, int h, float[] error) { if (0 <= x && x < w && 0 <= y && y < h) { error[(y * w + x) * 3 + 0] += r * ratio; error[(y * w + x) * 3 + 1] += g * ratio; error[(y * w + x) * 3 + 2] += b * ratio; } }
float gamma(float x) { return pow(x, 2.2); }
|