lb91
lb91

Reputation: 109

BufferedImage is not changing the colour of all white parts of the image

I have a set of black and white Kanji characters images that I am trying to change the colour of. I want all white parts of the white image (i.e., all parts of the image that is not the character) to turn a particular colour. I am doing this with BufferedImages, by using a for loop to loop through every pixel in the image, check if it is white, and then change the white colour to a colour passed to the method. Here is the code for the method in question:

public static void illuminateImage(BufferedImage elementImage, Color elementColor){
    for (int j = 0; j < elementImage.getWidth(); j++){
        for (int k = 0; k < elementImage.getHeight(); k++){
            if(elementImage.getRGB(j, k) == Color.WHITE.getRGB()){//images1.get(0).getRGB(0, 0)){
                elementImage.setRGB(j,k, elementColor.getRGB());
            }
        }
    }
}

The problem is is that not every white pixel is changing color. When I call the method, all parts of the image that are not the Kanji character do not change colour. While most of it changes color, there are some white patches in part. Why is this occurring?

I thought a way around this would be to instead write code that checks if the pixels are not black, and then change them to the given colour if so. However, that doesn't work, and just turns the entire image the given colour, I think because the characters are not strictly in black, even though they look like it. I don't know how to get the colour of the characters. Any help would be appreciated.

Upvotes: 1

Views: 1078

Answers (2)

XaolingBao
XaolingBao

Reputation: 1044

It seems to me that all of your "white" isn;t exactly white, and that all of your black isn't black (from what you said).

What you should be doing is printing out every color in the kanji, to see what's going on.

Something such as.

    public static void illuminateImage(BufferedImage elementImage, Color elementColor)
    {
        for (int j = 0; j < elementImage.getWidth(); j++)
        {
            for (int k = 0; k < elementImage.getHeight(); k++)
           {
              System.out.println(elementImage.getRGB(j, k));
           }
        }
    }

From there your choices are.

  1. Change everything to white and black (not sure where these images are coming from, but you should have them be the correct colors of white and black, so you will have to edit them with a program like Photoshop, or personally manipulate them using code.

  2. Instead of looking for a color, look for a range of colors, or look into finding HUES, granted this might be more difficult for shades of white/black.

IMO I would look into what the range of WHITE is, and then searching that entire range to see if the color is in there i.e., 200,200,200-255,255,255 to cover all possibilties of "white" but would probably be way more than needed, so check some color charts.

Since your Kanji should be black/white, you shouldn't have an issue finding a range and it affecting the rest of your application.

This site should provide some interesting info on Chroma-Keying.

http://www.lac.inpe.br/JIPCookbook/6520-howto-chromakey.jsp

Overall, you will need to figure out what color the other pixels are, then figure out if you will edit them manually, with a program like photoshop, or just test ranges.

Good luck.


Code to find RGB values.

Color c = new Color(elementImage.getRGB(j, k));

  System.out.println(c.getRed() +  " | " + c.getGreen() + " | " + c.getBlue() );

to convert back into integer you look at your values.

B encompasses 0-7 bits, G is 8-15, and R is 16-24.

You will do (2^16*Red) + (2^8 *Green) + (Blue) to get your integer value again.


Just to add to this, we discovered that the OP is using the Alpha channel so his white value is -1, which is correct.

So OP just needs to make sure that he is within a certain threshold using the RGB values in order to select or not, instead of the integer value, which would be harder to figure out.

Upvotes: 2

Kevin.Zhang
Kevin.Zhang

Reputation: 30

   public static void illuminateImage(BufferedImage elementImage, Color elementColor)
    {
        for (int j = 0; j < elementImage.getWidth(); j++)
        {
            for (int k = 0; k < elementImage.getHeight(); k++)
           {
              Color c = new Color(elementImage.getRGB(j, k));
              c.getBlue();
              c.getGreen();
              c.getRed();
           }
        }
    }

public static void illuminateImage(BufferedImage elementImage, Color elementColor){
    int threshold = 300;//You can try other threshold
    for (int j = 0; j < elementImage.getWidth(); j++){
        for (int k = 0; k < elementImage.getHeight(); k++){
            if(elementImage.getRGB(j, k) >= (Color.WHITE.getRGB() + threshold)){//images1.get(0).getRGB(0, 0)){
                elementImage.setRGB(j,k, elementColor.getRGB());
            }
        }
    }
}

This way can get red green blue value

Upvotes: 0

Related Questions