使用ImageIO.write写入jpg文件时出现问题:粉色背景。

51

我正在使用以下代码来写入一个jpg文件:

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));

但我得到的result.jpg是一个粉色背景图像:

alt text


谢谢,但是“页面未找到”,我无法得到答案。 - Koerr
你使用哪个底层阅读器来使用ImageIO包装器读取jpeg?它可能存在漏洞。 - Jules
1
我认为这与透明度属性有关。当我尝试旋转图像时,我遇到了同样的问题。有一个设置了透明度属性,一旦我删除它,一切都好了。 - user489041
这很可能是与https://dev59.com/tmox5IYBdhLWcg3wOx79和https://dev59.com/vlvUa4cB1Zd3GeqPtWtM相同的错误。 - uckelman
2
可能是颜色错误的JPEG图像的重复问题。 - Kartik Chugh
显示剩余3条评论
6个回答

40

您可以通过使用Toolkit.createImage(url)而不是ImageIO.read(url)来解决此问题,因为前者使用了不同的解码算法实现。

如果您正在使用Sun JDK附带的JPEG编码器,则还必须确保将没有alpha通道的图像传递给它。

示例:

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));
注意:我的猜测是颜色配置文件已损坏,并且Toolkit.createImage()会忽略所有颜色配置文件。如果是这样,那么这将降低具有正确颜色配置文件的JPEG图像的质量。

谢谢,真的有效。 - Mr rain

21

我也遇到过类似的问题,不过后来我用了这个方法解决了它。

   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"));

请注意,我正在使用Java版本1.6.0_25-b06,而且它运行得很好。

也许您可以检查一下Java的版本。


8
太好了!在这里 TYPE_INT_RGB 很关键 —— 它可以去除粉红色调 —— 只需将源 ARGB 图像的像素克隆到输出的 RGB 图像中,粉红色调就消失了! - gibffe
1
这个答案与这个非常相似(尽管这个的代码示例更容易理解)https://dev59.com/bUrSa4cB1Zd3GeqPXprU - RedYeti

15

这个对我有效:

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);

感谢您提供这个更完整的代码片段。它可以正常工作。 - daparic

2
  • 对我来说,问题不在于阅读,而在于写作。
  • ImageIO可以从ARGB BufferedImages中愉快地编写JPG文件。
  • 然后浏览器/其他程序将这个4通道文件解释为CMYK颜色或其他东西,导致了这个问题描述中的效果。
  • 解决方法:确保传递给ImageIO.write的BufferedImage是RGB类型(而不是ARGB)。
  • 这也解释了为什么只有在保存为jpeg时才出现问题,而在保存为png时却没有问题。
  • 这花费了我很长时间才发现,因为我的图像工具总是在转换为ARGB时进行转换,所以我总是将ARGB图像传递给ImageIO.write,而没有意识到这一点。

1
感谢您的解释,它与其他答案中提供的工作示例相辅相成。 - daparic

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));
        }
    }

这对我很有用。

尝试过了,但对我没用。 - Sumit Kumar Saha

1
我在使用ImageIO读写图像时遇到了同样的问题。在阅读这里的答案后,我将我的JRE从openjdk version "1.8.0_91"更改为HotSpot java version "1.8.0_102"。虽然finnw的回答并没有明确提到这一点,但值得一试;-)
因此,问题得以解决!所以,如果你正在使用OpenJDK JRE,并且可以自由更改你的JRE,那么将它更改为HotSpot,你就不需要改变你的代码。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接