We closed this forum 18 June 2010. It has served us well since 2005 as the ALPHA forum did before it from 2002 to 2005. New discussions are ongoing at the new URL http://forum.processing.org. You'll need to sign up and get a new user account. We're sorry about that inconvenience, but we think it's better in the long run. The content on this forum will remain online.
IndexProgramming Questions & HelpSyntax Questions › Floyd–Steinberg dithering implementation
Page Index Toggle Pages: 1
Floyd–Steinberg dithering implementation (Read 1374 times)
Floyd–Steinberg dithering implementation
Jan 20th, 2010, 9:19am
 
I'm trying to implement Floyd-Steinberg dithering (the wikipedia article has some pseudo-code), but it doesn't seem to be working right.

I ported a working Flash AS3 version, but for me, everything past the initial posterization doesn't seem to affect the image. I've been fiddling with it for a good 3 hours so far, but no luck. Anyone have any ideas?

Code:
PImage b;
PImage source;
int levels = 1;

void setup() {
 size(200, 200, P2D);
 colorMode(RGB, 255);
 b = loadImage("jelly.jpg");
 noLoop();
}

void draw () {
 source = createImage(200, 200, RGB);
 source = b;
 
 float lNorm = 255/levels;
 
 // FS Kernal
 float d1 = 7 / 16;
 float d2 = 3 / 16;
 float d3 = 5 / 16;
 float d4 = 1 / 16;
 
 int c, nc, lc, rc;
 float r, g, b;
 float nr, ng, nb;
 float er, eg, eb;
 float lr, lg, lb;
 int x = 0, y = 0;
 
 // Ordered Dithering Implementation
 for (y = 0; y < 200; y++) {
   for (x = 0; x <= 200; x++) {
     // Retrieve current RGB value
     c = source.get(x, y);
     r = (c >> 16) & 0xFF;
     g = (c >> 8) & 0xFF;
     b = c & 0xFF;
     
     // Normalize and scale to number of levels
     // basically a cheap but crappy form of color quantization
     nr = round((r/255) * levels) * lNorm;
     ng = round((g/255) * levels) * lNorm;
     nb = round((b/255) * levels) * lNorm;
     
     // Set the current pixel
     nc = color(nr, ng, nb);
     source.set(x, y, nc);
     
     // Quantization Error
     er = r-nr;
     eg = g-ng;
     eb = b-nb;
     
     // EVERYTHING AFTER THIS POINT DOESN'T SEEM TO AFFECT THE IMAGE
///////////////////////////////////////////////////////////////////
     
     // Apply the kernel
     // +1, 0
     lc = source.get(x + 1, y);
     lr = (lc >> 16 & 0xFF) + d1 * er;
     lg = (lc >> 8 & 0xFF) + d1 * eg;
     lb = (lc & 0xFF) + d1 * eb;
     source.set(x + 1, y, color(lr, lg, lb));

     // -1, +1
     lc = source.get(x - 1, y + 1);
     lr = (lc >> 16 & 0xFF) + (d2*er);
     lg = (lc >> 8 & 0xFF) + (d2*eg);
     lb = (lc & 0xFF) + (d2*eb);
     source.set(x - 1, y + 1, color(lr, lg, lb));
     
     // 0, +1
     lc = source.get(x, y + 1);
     lr = (lc >> 16 & 0xFF) + (d3*er);
     lg = (lc >> 8 & 0xFF) + (d3*eg);
     lb = (lc & 0xFF) + (d3*eb);
     source.set(x, y + 1, color(lr, lg, lb));
     
     // +1, +1
     lc = source.get(x+1, y+1);
     lr = (lc >> 16 & 0xFF) + (d4*er);
     lg = (lc >> 8 & 0xFF) + (d4*eg);
     lb = (lc & 0xFF) + (d4*eb);
     source.set(x+1, y+1, color(lr, lg, lb));
   }
 }
 println("done");
 image(source, 0, 0);
}
Re: Floyd–Steinberg dithering implementation
Reply #1 - Jan 20th, 2010, 9:53am
 
Run this code and you'll see why:
Code:

void setup()
{
 
 float d1 = 7 / 16;
 float d2 = 3 / 16;
 float d3 = 5 / 16;
 float d4 = 1 / 16;
 
 println(d1 + ", " + d2 + ", " + d3 + ", " + d4);
}
Re: Floyd–Steinberg dithering implementation
Reply #2 - Jan 20th, 2010, 9:59am
 
wellll... that's just weird! Guess I'll just divide them out manually and use those numbers instead, and see where that gets me. Thanks!
Re: Floyd–Steinberg dithering implementation
Reply #3 - Jan 20th, 2010, 10:02am
 
yep, that seemed to do it, at least for now. Thanks again!
Re: Floyd–Steinberg dithering implementation
Reply #4 - Jan 20th, 2010, 12:27pm
 
Replacing 7/16 with 7.0/16 should do the trick as well.

It treats 7 / 16 as an integer division, which yields 0.
Page Index Toggle Pages: 1