jpeg image color gets drastically changed after ju

2019-01-06 18:00发布

问题:

I have been using ImageIO.read() and ImageIO.write() methods in javax.imageio.ImageIO for reading and writing images, and I found that some images' color gets changed weirdly.

Even if I change my code to do nothing but just read images and write them (with jpeg, png, gif), all those new images have the same issue.

Do I need to add any other code before/after ImageIO.read/write methods?

Here is the code I used:

    File f = new File("obw.jpg");
    BufferedImage bi = ImageIO.read(f);
    FileOutputStream fos2 = new FileOutputStream("obw2.jpg");
    ImageIO.write(bi, "JPG", fos2);
    FileOutputStream fos3 = new FileOutputStream("obw3.gif");
    ImageIO.write(bi, "GIF", fos3);
    FileOutputStream fos4 = new FileOutputStream("obw4.png");
    ImageIO.write(bi, "PNG", fos4);

My environment:

    java version "1.6.0_35"
    MacOSX 10.8.2

Original Image:

One of images after read and write:

回答1:

Your problem is that ImageIO is misinterpreting the YCbCr data in your JPEG as RBG data. The relevant Java bugs are 4712797 and 4776576, which Oracle wrongly claims were fixed in Java 1.4, but in reality still afflict some Java 5, 6, and 7 JVMs.

In a project I work on, we've dealt with this problem by loading a specially-constructed test JPEG with a single black pixel to see if ImageIO loads it properly. If the pixel comes up green, then ImageIO is misinterpreting the image data, so when we load JPEGs later and we detect the sort of JPEG which causes the problem, we also apply a color correction. (The kind of JPEG which triggers the problem in JVMs which exhibit it has a particular kind of subsampling and no JFIF marker.)

Here's some LGPLv2-licensed code which deals with the problem. The need for code like this to work around dozen-year-old bugs when the whole rest of the world manages to load JPEGs properly is one of the reasons I want Java to die in a fire.



回答2:

seems a colorspace problem, imageIO try to do some encoding/decoding of the image but it seems to fail. Take a look here: Unable to read JPEG image using ImageIO.read(File file)