0

I wrote the following simple code to write what should be a small, all black image to disk:

import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;

public class ImageWriteTest {
    public static void main(String[] args) throws IOException {
        BufferedImage img = new BufferedImage(10, 10, BufferedImage.TYPE_INT_ARGB);
        final int PIXEL = 0xFF_00_00_00; // Black
        for(int i = 0; i < 10; ++i) {
            for(int j = 0; j < 10; ++j) {
                img.setRGB(i, j, PIXEL);
            }
         }

         ImageIO.write(img, "jpg", new File("/tmp/testImage.jpg"));

         int sample = img.getRGB(0,0);
         System.out.println((sample & 0x00_00_00_FF) + "\t" 
             + ((sample & 0x00_00_FF_00) >>> 8) + "\t" 
             + ((sample & 0x00_FF_00_00) >>> 16) + "\t"
             + ((sample & 0xFF_00_00_00) >>> 24));

         Color color = new Color(sample, true);
         System.out.println(color.getGreen() 
             + "\t" + color.getBlue() 
             + "\t" + color.getRed() 
             + "\t" + color.getAlpha());
    }
}

The output to the terminal is two lines

0    0    0   255
0    0    0   255

as I expect.

The image file, however, appears to be a small teal square instead of a small black square, as shown.

Output image from program

That was run on Windows 10 and Java version 1.8.0_92, Java HotSpot. I saw similar results earlier on a Linux machine.

I found two questions that seem somewhat related, but in both of these cases the issue seems to be that a file was read into the program from external source and had extra meta data and/or missing headers. In this case, I created the image programmatically, so I'm expecting it to work.

If I change PIXEL = 0x00_00_00_00; then I do get a black square. That's no doubt a clue, but one that I haven't understood yet. What have I done wrong? How do I fix it?

Community
  • 1
  • 1
Brick
  • 3,998
  • 8
  • 27
  • 47
  • @K_7 I liked to that possible duplicate in my original post and explained why my question is different. – Brick Dec 30 '17 at 18:12

1 Answers1

1

I am not an expert but this is due to JPG not supporting alpha channels. Change the same result to PNG and it will be as you expected. To do that, simply use

ImageIO.write(img, "png", file);

After some searching, looks like bug in ImageIO jpeg image color gets drastically changed after just ImageIO.read() and ImageIO.write()

Or maybe not bug after all? Take look here: https://stackoverflow.com/a/39478986/1527544 Comment says, that ARGB for JPG is read as CMYK.

Community
  • 1
  • 1
Antoniossss
  • 31,590
  • 6
  • 57
  • 99
  • I tried both PNG and GIF while I was waiting for an answer and found that both work properly with respect to color - although create much larger files in the real application. The question that you linked, however, seems to point to a bug in `read` rather than `write`. I'm doing no `read`, although it does seem likely that they are somehow related. – Brick May 10 '17 at 21:20
  • @Brick check the edit - looks like it is simply theated as CMYK not RGB values if you save to `jpg` files . – Antoniossss May 10 '17 at 21:24
  • Yeah, the comment there actually says: `//pitfall: in a jpeg file 4 channels will be interpreted as CMYK... this is no good` and that's still on a `write` rather than a `read`. Comments on the other answer indicate that it is a bug in Java. It must be symmetrically wrong between read and write though, so I'm guess I'm stuck.. It is handy to know that it's treating it at CMYK - even if that's not what it's supposed to do! (Documented behavior is for the API to do color model conversion behind the scenes as far as I can tell.) – Brick May 10 '17 at 21:35
  • @Brick and maybe there is the actuall bug. – Antoniossss May 10 '17 at 21:39