1

I've put all the black pixels of the image in an array and I want them to get the color of their left neighbor. I run the code without errors but the result is not really what I'm expecting. Where those black stripes comes form? I was expecting it to be all red.

Here's my code and results.

import java.awt.Color;
import java.awt.image.BufferedImage;
import java.util.*;


public class ImageTest {
    public static BufferedImage Threshold(BufferedImage img) {

        int height = img.getHeight();
        int width = img.getWidth();
        BufferedImage finalImage = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);

        int r = 0;
        int g = 0;
        int b = 0;
        List<Integer> blackpixels = new ArrayList<Integer>();



        for (int x = 0; x < width; x++) {
            try {

                for (int y = 0; y < height; y++) {

                    //Get RGB values of pixels
                    int rgb = img.getRGB(x, y); 
                    r = ImageTest.getRed(rgb);
                    g = ImageTest.getGreen(rgb);
                    b = ImageTest.getBlue(rgb);

                    int leftLoc = (x-1) + y*width;

                    if ((r < 5) && (g < 5) && (b < 5)) {
                        blackpixels.add(rgb);
                        Integer[] simpleArray = new Integer[ blackpixels.size() ];
                        System.out.print(simpleArray.length);

                        int pix = 0;

                        while(pix < simpleArray.length) {
                            r = leftLoc;
                            pix = pix +1;   
                        }


                    }

                    finalImage.setRGB(x,y,ImageTest.mixColor(r, g,b));  
                }

                }
            catch (Exception e) {
                    e.getMessage();
            }
    }
    return finalImage;

    }
    private static int mixColor(int red, int g, int b) {
        return red<<16|g<<8|b;
    }

    public static int getRed(int rgb) {
        return (rgb & 0x00ff0000)  >> 16;
    }

    public static int getGreen(int rgb) {
        return  (rgb & 0x0000ff00)  >> 8;
    }

    public static int getBlue(int rgb) {
        return (rgb & 0x000000ff)  >> 0;

    }
}

enter image description here

leonardo
  • 537
  • 1
  • 4
  • 7
  • You have a while loop that is changing the `r` value, might that be the cause of the strips? (fading from black to red). – Eric Sep 05 '14 at 12:41
  • Yes definitely, but I can't figure out how to make it work the way I want – leonardo Sep 05 '14 at 12:46
  • What exactly are you trying to do? What is the expected result? Could you provide the desired output image? – Gabriel Archanjo Sep 11 '14 at 11:57
  • I'm trying to reconstruct the image, saying that black pixels are missing part, so replacing them with neighbours color. My desired output image should be completely red. I've managed to do it in processing using a similar algorithm but in Java it does not work – leonardo Sep 11 '14 at 13:38

1 Answers1

1

The following might work. The main change is that it first collects the locations of ALL dark pixels, then goes over them to assign the colour from their left neighbours.

import java.awt.image.BufferedImage;
import java.util.*;

public class BlackRedImage
{
    public static BufferedImage Threshold( BufferedImage img )
    {
        int height = img.getHeight();
        int width = img.getWidth();
        BufferedImage finalImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);

        List<Integer> blackpixels = new ArrayList<Integer>();

        for ( int x = 0; x < width; x++ )
        {
            for ( int y = 0; y < height; y++ )
            {
                int rgb = img.getRGB(x, y); // Get the pixel in question
                int r = BlackRedImage.getRed(rgb);
                int g = BlackRedImage.getGreen(rgb);
                int b = BlackRedImage.getBlue(rgb);

                if ( (r < 5) && (g < 5) && (b < 5) )
                { // record location of any "black" pixels found
                    blackpixels.add(x + (y * width));
                }

                finalImage.setRGB(x, y, rgb);
            }
        }

        // Now loop through all "black" pixels, setting them to the colour found to their left
        for ( int blackPixelLocation: blackpixels )
        {
            if ( blackPixelLocation % width == 0 )
            { // these pixels are on the left most edge, therefore they do not have a left neighbour!
                continue;
            }

            int y = blackPixelLocation / width;
            int x = blackPixelLocation - (width * y);

            int rgb = img.getRGB(x - 1, y); // Get the pixel to the left of the "black" pixel
            System.out.println("x = " + x + ", y = " + y + ", rgb = " + rgb);
            finalImage.setRGB(x, y, rgb);
        }
        return finalImage;
    }

    private static int mixColor( int red, int g, int b )
    {
        return red << 16 | g << 8 | b;
    }

    public static int getRed( int rgb )
    {
        return (rgb & 0x00ff0000) >> 16;
    }

    public static int getGreen( int rgb )
    {
        return (rgb & 0x0000ff00) >> 8;
    }

    public static int getBlue( int rgb )
    {
        return (rgb & 0x000000ff) >> 0;
    }
}

EDIT: Here is a simpler version (doesn't collect the black pixels)

import java.awt.Color;
import java.awt.image.BufferedImage;
import java.util.*;

public class ColourMove
{
    public static BufferedImage Threshold( BufferedImage img )
    {
        int width = img.getWidth();
        int height = img.getHeight();
        BufferedImage finalImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);

        for ( int x = 1; x < width; x++ ) // Start at 1 as the left most edge doesn't have a left neighbour
        {
            for ( int y = 0; y < height; y++ )
            {
                Color colour = new Color(img.getRGB(x, y));
                int red = colour.getRed();
                int green = colour.getGreen();
                int blue = colour.getBlue();

                if ( (red < 5) && (green < 5) && (blue < 5) )
                { // Encountered a "black" pixel, now replace it with it's left neighbour
                    finalImage.setRGB(x, y, img.getRGB(x - 1, y));
                }
                else
                { // Non-black pixel
                    finalImage.setRGB(x, y, colour.getRGB());
                }
            }
        }
        return finalImage;
    }
}
Eric
  • 1,321
  • 2
  • 15
  • 30
  • I'm getting the error "Coordinate out of bounds!", try to figure out where it goes out of range – leonardo Sep 05 '14 at 13:18
  • There was an logic error in the first version I posted (which would have caused such an error), make sure you try the latest edited version now - I hope it works ;) – Eric Sep 05 '14 at 13:28
  • Yes I'm not getting the error, but the final Image is the same as the starting image, no changes are happening...strange – leonardo Sep 05 '14 at 13:29
  • Add some `System.out` statements to the final `for` loop, to check the x, y co-ordinates and to see what the rgb value is. – Eric Sep 05 '14 at 13:31
  • I've add this line "System.out.println(rgb);" and it return this value multiple times: -131072 – leonardo Sep 05 '14 at 14:02
  • I've also edited the answer above, adding a `System.out` statement. Please try the latest version (copy the whole code again, not just the println statement) and let me know how it goes :) – Eric Sep 05 '14 at 14:12
  • Thanks so much for the help, but still getting the same result. I'm not able to post the output because is too long – leonardo Sep 05 '14 at 15:20
  • all the pixels have this value: x = 480, y = 536, rgb = -16777216 and the last one this: x = 480, y = 537, rgb = -16776960 – leonardo Sep 05 '14 at 15:59
  • @leonardo, I added a simpler version - it "should" work. – Eric Sep 08 '14 at 13:39
  • Thanks for the help you're giving me, but the final image is still the same as the source. It's very strange, your code seems to be very logic – leonardo Sep 08 '14 at 14:16
  • @leonardo, are you sure you're viewing the final image? To check, you could force all pixels to be black `finalImage.setRGB(x, y, 0)` if you add that to the end of the inner (height) loop, the final image must be black, if not you're viewing the wrong result! – Eric Sep 08 '14 at 14:21
  • I've changed the testing image to a simpler one, 10x1 of resolution. The first nine pixels are red and the last one black. Like this your code works, the last pixel turns red. I've then made the first 5 pixels red and the other 5 black and the result is an image fading from red to black – leonardo Sep 08 '14 at 14:30
  • @leonardo, I've made another change to the two methods listed above ... plz, copy and test the second example again. – Eric Sep 09 '14 at 07:22
  • with this code I'm getting the left most edge black and than fading to red and back again to black. What about creating an ArrayList containing black pixels and use it in a while loop? Something like this: while (blackpixels.length > 0) { if ( (r < 5) && (g < 5) && (b < 5) ) { finalImage.setRGB(x, y, img.getRGB(x - 1, y)); } blackpixels.remove(non-blackpixels). What do you think? Because I guess that with your code the pixels are getting the color from their left neighbor even if it's black – leonardo Sep 09 '14 at 08:27
  • @leonardo, you can try but I don't think that will help. Based on your description, I believe the problem lies with the getRGB & setRGB methods. I would test somethings like using a fixed (static) value for setRGB, if it still "fades" when using a fixed value, then you know something is wrong with how you are using that method! – Eric Sep 09 '14 at 09:05
  • you're right, I've used a static value for the method setRGB and I'm still getting that fade, but i can't figure out where that come from. – leonardo Sep 09 '14 at 10:38
  • @leonardo, after doing the static setRGB, do a getRGB on the same pixel, the returned value should be the same ... if the value does change, then you need to find out why? Maybe it has to do with the imageType being used in the constructor? – Eric Sep 09 '14 at 12:02
  • @leonardo, I made another change `BufferedImage.TYPE_INT_ARGB`. Have a look at the following link for details: http://stackoverflow.com/questions/21980794/performing-setrgb-on-bufferedimage-changes-pixel-to-black-instead-of-color – Eric Sep 09 '14 at 12:21
  • I've converted the image into ARGB TYPE and the black pixels turn to white even if I use a static value set to 0. I'm desperate :) – leonardo Sep 09 '14 at 12:54
  • @leonardo, have a read of the link in the last message. I give up now :( good luck with it. – Eric Sep 09 '14 at 12:59