51

I'm using the following code to write a jpg file:

String url="http://img01.taobaocdn.com/imgextra/i1/449400070/T2hbVwXj0XXXXXXXXX_!!449400070.jpg";
String to="D:/temp/result.jpg";
ImageIO.write(ImageIO.read(new URL(url)),"jpg", new File(to));

But I get the result.jpg is a pink background image:

alt text

Cœur
  • 37,241
  • 25
  • 195
  • 267
Koerr
  • 15,215
  • 28
  • 78
  • 108
  • Not a duplicate but a similiar result with `ImageIO.write()`: http://stackoverflow.com/questions/1830063/problem-converting-png-to-jpg-using-java-imageio-write – Andreas Dolk Dec 08 '10 at 10:36
  • thanks,but `Page not found`,I can't get the answer – Koerr Dec 08 '10 at 10:42
  • Which underlying reader do you use for reading jpeg with the ImageIO wrapper? It could be buggy. – Jules Dec 08 '10 at 12:35
  • 1
    I think it has something to do with a Transparency property. I had the same issue when I was trying to rotate an image. There was a transparency property that was set, once I removed it, all was well. – user489041 Dec 08 '10 at 15:04
  • Possibly related to http://blogs.msdn.com/b/pix/archive/2007/06/05/faq.aspx#q6. – finnw Dec 09 '10 at 14:06
  • This is likely the same bug as http://stackoverflow.com/questions/9340569/jpeg-image-with-wrong-colors and http://stackoverflow.com/questions/7474210/reading-jpegs-imageio-read-messes-up-color-space. – uckelman Feb 24 '13 at 17:32
  • 2
    Possible duplicate of [JPEG image with wrong colors](https://stackoverflow.com/questions/9340569/jpeg-image-with-wrong-colors) – Kartik Chugh Dec 30 '17 at 02:53
  • This should be reopened. It includes the desired behavior (the image on the left), the specific problem or error (the image on the right), and the shortest code necessary to reproduce it in the question itself. It has a clear problem statement (summed up in a picture that doesn't require language, but also described above the image). – Ky - May 26 '18 at 02:57

6 Answers6

40

You can work around this by using Toolkit.createImage(url) instead of ImageIO.read(url) which uses a different implementation of the decoding algorithm.

If you are using the JPEG encoder included with the Sun JDK then you must also ensure that you pass it an image with no alpha channel.

Example:

private static final int[] RGB_MASKS = {0xFF0000, 0xFF00, 0xFF};
private static final ColorModel RGB_OPAQUE =
    new DirectColorModel(32, RGB_MASKS[0], RGB_MASKS[1], RGB_MASKS[2]);

    // ...

String sUrl="http://img01.taobaocdn.com/imgextra/i1/449400070/T2hbVwXj0XXXXXXXXX_!!449400070.jpg";
URL url = new URL(sUrl);
Image img = Toolkit.getDefaultToolkit().createImage(url);

PixelGrabber pg = new PixelGrabber(img, 0, 0, -1, -1, true);
pg.grabPixels();
int width = pg.getWidth(), height = pg.getHeight();

DataBuffer buffer = new DataBufferInt((int[]) pg.getPixels(), pg.getWidth() * pg.getHeight());
WritableRaster raster = Raster.createPackedRaster(buffer, width, height, width, RGB_MASKS, null);
BufferedImage bi = new BufferedImage(RGB_OPAQUE, raster, false, null);

String to = "D:/temp/result.jpg";
ImageIO.write(bi, "jpg", new File(to));

Note: My guess is that the color profile is corrupted, and Toolkit.createImage() ignores all color profiles. If so then this will reduce the quality of JPEGs that have a correct color profile.

finnw
  • 47,861
  • 24
  • 143
  • 221
21

I had similar problems. But then I solved it by using this one

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

   //do something to populate the image
   //such as
   image.setRGB( x, y, pixelValue); //set your own pixels color



   ImageIO.write(image, "jpg", new File("D:\\test.jpg"));

Note that I'm using Java version 1.6.0_25-b06 and It's just works fine.

Maybe you can check the Java version.

Ali Irawan
  • 2,094
  • 2
  • 18
  • 23
  • 8
    that totaly worked ! TYPE_INT_RGB is crucial here - this removes the pink hue - simply clone pixels from source ARGB image to the output RGB images and pink hue is gone ! – gibffe Nov 12 '11 at 16:31
  • 1
    Very similar answer to this one (though the code example on this one was easier to follow) http://stackoverflow.com/questions/1830063/problem-converting-png-to-jpg-using-java-imageio-write#answer-8418291 – RedYeti Mar 14 '13 at 18:09
15

This works for me:

int w = originalImage.getWidth();
int h = originalImage.getHeight();
BufferedImage newImage = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
int[] rgb = originalImage.getRGB(0, 0, w, h, null, 0, w);
newImage.setRGB(0, 0, w, h, rgb, 0, w);
2
  • for me the problem was not the reading but the writing
  • ImageIO will happily write JPG files from ARGB BufferedImages
  • Browsers/other programs then interpret this 4-channel file as CMYK color or something, resulting in the effect described in this question
  • solution for me: make sure that that BufferedImage that is passed to ImageIO.write is of type RGB (not ARGB)
  • this also explains why the problem only appears when saving to jpeg, but not when saving to png
  • this took a long time for me to figure out because my own image tools always convert to ARGB on the fly, so I was always passing an ARGB image to ImageIO.write, without realizing it
Reto Höhener
  • 5,419
  • 4
  • 39
  • 79
1
BufferedImage originalImage = ImageIO.read(getContent());
BufferedImage newImage = new BufferedImage(originalImage.getWidth(), originalImage.getHeight(), BufferedImage.TYPE_3BYTE_BGR);

    for (int x = 0; x < originalImage.getWidth(); x++) {
        for (int y = 0; y < originalImage.getHeight(); y++) {
            newImage.setRGB(x, y, originalImage.getRGB(x, y));
        }
    }

this did the trick for me

1

I faced the same issue when reading and writing images using ImageIO. After reading answers here I changed my JRE - from openjdk version "1.8.0_91" to HotSpot java version "1.8.0_102". The hint was not obvious in finnw's answer but it worth a try ;-)

And thus the issue resolved! So if you are using OpenJDK JRE and free to change your JRE, changing it HotSpot and you won't need to change your code.

Bazi
  • 311
  • 1
  • 4
  • 10