0

i wrote a java code to change all the red values of a black and white image to 255, so the output would be a red image. But its not red, instead it outputs a brighter image. What did I do wrong?

 File bwgFile = new File("X:/Java/Documents/NetBeansProjects/colour/input/bwg.png");
BufferedImage bwgImage = ImageIO.read(bwgFile);
int width=bwgImage.getWidth();
int height=bwgImage.getHeight();
for(int w=0; w<width; w++){
  for(int h=0; h<height; h++){
      int pixel = bwgImage.getRGB(w,h);
      Color bwg = new Color(pixel);
      int c=bwg.getRed();
      Color red = new Color(255,c,c);
      int cpixel = red.getRGB();
      bwgImage.setRGB(w,h,cpixel);
  }
}
    ImageIO.write(bwgImage, "png", new File("X:/Java/Documents/NetBeansProjects/colour/output/c.png")); 

input output

EDIT: I have found out what the problem was, apparently when the input is a greyscale image it will try to make the output a greyscale image as well thus making it darker when blue and green colors get removed and brighter when red gets added. not using a grayscale image as input fixed it.

ergoforce
  • 17
  • 5

1 Answers1

0

If I understand what you're trying to do, you're trying to create a greyscale image, except that it is "redscale", using only shades of red. Therefore, you need to compute the greyscale constant of each pixel.

From wikipedia (Greyscale), the luminance of a pixel Y = 0.2126R + 0.7152G + 0.0722B. So, try this

int pixel = bwgImage.getRGB(w,h);
Color bwg = new Color(pixel);
float c = (0.2126f * bwg.getRed() + 0.7152f * bwg.getGreen() + 0.0722f * bwg.getBlue());
int cc = (int)Math.round(c);
Color red = new Color(cc, 0, 0);
int cpixel = red.getRGB();
bwgImage.setRGB(w,h,cpixel);

Alternatively, you can simply retain the red component and set green and blue to 0. This will leave you with just the "redness" of each pixel.

int pixel = bwgImage.getRGB(w,h);
Color bwg = new Color(pixel);
int c=bwg.getRed();
Color red = new Color(c,0,0);
int cpixel = red.getRGB();
bwgImage.setRGB(w,h,cpixel);

NOTE: This solution above only works on images that are not using IndexColorModel. You can check the color model using BufferedImage's getColorModel(). For IndexColorModel, setRGB() does not work directly and instead picks a color in the index closest to the set color, as per HaraldK's comment. To achieve the desired result for images using IndexColorModel, you can create a new BufferedImage with TYPE_INT_ARGB:

BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);

Then, write the calculated pixel colors to this new image and save the new image instead.

nitegazer2003
  • 1,193
  • 5
  • 10
  • Exception in thread "main" java.lang.IllegalArgumentException: Color parameter outside of expected range: Red at java.awt.Color.testColorValueRange(Color.java:310) at java.awt.Color.(Color.java:395) at java.awt.Color.(Color.java:369) at colour.Colour.main(Colour.java:50) C:\Users\Emma\AppData\Local\NetBeans\Cache\8.1\executor-snippets\run.xml:53: Java returned: 1 BUILD FAILED (total time: 0 seconds) – ergoforce Mar 08 '16 at 07:56
  • @ergoforce, sorry, removed the * 255 on the 3rd line. The original values are already between 0 and 255. – nitegazer2003 Mar 08 '16 at 07:58
  • I also tried your second suggestion but I still end up with a greyscale image, notably darker than the input even though the Blue and Green values should be 0 for each pixel. – ergoforce Mar 08 '16 at 08:01
  • Same result with the improved first answer, im getting a darker greyscale image – ergoforce Mar 08 '16 at 08:04
  • I have found out what the problem was although I dont understand why it was a problem, apparently when the input is a greyscale image it will try to make the output a greyscale image as well thus making it darker when blue and green colors get removed and brighter when red gets added. not using a grayscale image as input fixed it. Thanks for your improved code you helped alot! – ergoforce Mar 08 '16 at 08:09
  • @ergoforce I believe it depends on the format of the input image. Try checking the value of bwgImage.getType() and see whether it corresponds to BufferedImage.TYPE_INT_ARGB – nitegazer2003 Mar 08 '16 at 08:11
  • The current accepted answer is incorrect. While you deserve the rep for helping the OP solve his problem, you should at least update the answer to help future readers. :-) The problem is that the `setRGB(...)` methods of `BufferedImage` don't work as intended for grayscale or indexed color models (instead of setting the exact color, it will choose the "nearest" available in the color model). – Harald K Mar 08 '16 at 08:20
  • @haraldK Thanks! Have updated my answer to add a footnote. – nitegazer2003 Mar 08 '16 at 08:30