0

I'm trying to implement the Floyd-Steinberg algorithm in java ,but i still have some errors?! in my code that i cant solve.Maybe some of you have an advise how i can solve this.

Here is the method

 public DitheringGUI dith(String fileName) {
DitheringGUI g = new DitheringGUI(fileName);

for(int y = 0 ; y<g.img.getHeight();y++){
    for(int x = 0 ; x < g.img.getWidth();x++){

    Color oldColor = g.img.getColor(x, y);
    Color newColor = palette(oldColor);

    g.img.set(x, y, newColor);



    int quant_Error = oldColor.getRed() - newColor.getRed();


    if(x+1 < g.img.getWidth()) {
        g.img.set(x+1,y,new Color(  g.img.getColor(x+1, y).getRed()+quant_Error*(7/16),
            g.img.getColor(x+1, y).getRed()+quant_Error*(7/16),
            g.img.getColor(x+1, y).getRed()+quant_Error*(7/16)));
    }


    if(x-1 >=0 && y+1 <g.img.getHeight()){
        g.img.set(x-1,y+1,new Color(    g.img.getColor(x-1, y+1).getRed()+quant_Error*(3/16),
            g.img.getColor(x-1, y+1).getRed()+quant_Error*(3/16),
            g.img.getColor(x-1, y+1).getRed()+quant_Error*(3/16)));
    }

    if(y+1 < g.img.getHeight()){
        g.img.set(x,y+1,new Color(  g.img.getColor(x, y+1).getRed()+quant_Error*(5/16),
            g.img.getColor(x, y+1).getRed()+quant_Error*(5/16),
            g.img.getColor(x, y+1).getRed()+quant_Error*(5/16)));

    }



    if(x+1 < g.img.getWidth() && y+1 < g.img.getHeight()){
        g.img.set(x+1,y+1,new Color(    g.img.getColor(x+1, y+1).getRed()+quant_Error*(1/16),
            g.img.getColor(x+1, y+1).getRed()+quant_Error*(1/16),
            g.img.getColor(x+1, y+1).getRed()+quant_Error*(1/16)));
    }

    }
}
return g;
}

the actual problem is that it is just black and white and not dithered,meaning there are no gray-scalings.

My input is this: http://www.directupload.net/file/d/3985/spd2k9wq.png

My output is: http://www.directupload.net/file/d/3985/s24rq7qo.png

Notice that the "dithered" image is over-dithered and is nearly black.

Paul Sasik
  • 79,492
  • 20
  • 149
  • 189
greedsin
  • 1,252
  • 1
  • 24
  • 49
  • 1
    Links to example input and expected output could be very useful. – Paul Sasik May 12 '15 at 14:38
  • 2
    After error distribution your color components can overflow which may lead to incorrect results. When you create the `new Color`, it's better to test that the value falls into 0..255 range. Also the problem might be inside `palette` method. Please add it to the post. – Tagir Valeev May 12 '15 at 14:43
  • private Color palette(Color oldColor) { int avg =oldColor.getRed(); int BoW = avg < 128 ? 0 : 255; Color c = new Color(BoW,BoW,BoW); return c; } – greedsin May 12 '15 at 14:48
  • @PaulSasik before: http://www.directupload.net/file/d/3985/spd2k9wq_png.htm after :http://www.directupload.net/file/d/3985/s24rq7qo_png.htm – greedsin May 12 '15 at 14:50
  • @lolio: I tried to add your images into the body of your question, the prefered way of doing it if your reputation is high enough. There were problems though. The web site does not seem to allow direct links to images or drag drop. I just added links into your question instead. Please use a different image site next time like imgur, – Paul Sasik May 12 '15 at 15:57

2 Answers2

0

You are doing integer division: 7/16, 3/16, 5/16, 1/16...

The results of these divisions is 0 and not some fraction.

Make sure you use floating-point numbers instead, for example: 7.0 / 16, 3.0 / 16 etc.

Jesper
  • 202,709
  • 46
  • 318
  • 350
  • when i change this to floating-point numbers i get this : Exception in thread "main" java.lang.IllegalArgumentException: Color parameter outside of expected range: Red Green Blue – greedsin May 12 '15 at 15:06
0

I think I see the error and it's probably of the cut-and-paste variety:

In each of you code's if block you only ever call getRed() and never getGreen90 or getBlue(). See this in a block below: (reformatted to make issue easier to spot.

if(x+1 < g.img.getWidth()) {
    g.img.set(x+1,y,new Color(  
        g.img.getColor(x+1, y).getRed()+quant_Error*(7/16),
        g.img.getColor(x+1, y).getRed()+quant_Error*(7/16),
        g.img.getColor(x+1, y).getRed()+quant_Error*(7/16)));
}                              /\/\/\/\
                                 here   

Shouldn't this and your other block look like:

if(x+1 < g.img.getWidth()) {
    g.img.set(x+1,y,new Color(  
        g.img.getColor(x+1, y).getRed()+quant_Error*(7/16),
        g.img.getColor(x+1, y).getGreen()+quant_Error*(7/16),
        g.img.getColor(x+1, y).getBlue()+quant_Error*(7/16)));
} 

I am guessing that you're very close and the reason your resulting image looks the way it does is because only the red part of the RGB spectrum is being evaluated.

Paul Sasik
  • 79,492
  • 20
  • 149
  • 189
  • Paul that is right but i do this because i only have grey colors,which means red green and blue are the same.Still thanks – greedsin May 12 '15 at 18:25
  • @lolio - Hmm. I didn't assume that but it makes sense. Is it possible you need a different version of the algorithm since the one you implemented only accounts for RGB colors? – Paul Sasik May 12 '15 at 19:10