Java 1.5.0_16保存jpg图片时颜色损坏

4

我从磁盘加载了一张图像(存储为BufferedImage),我在JPanel上正确显示它,但是当我尝试使用下面的命令重新保存此图像时,图像以红色色调保存。

ImageIO.write(image, "jpg", fileName);

注意!image是一个BufferedImage对象,fileName是指向以“.jpg”结尾的文件名的File对象。
我已经看到早期JDK中存在ImageIO方法的问题,但据我所知,我不在这些版本中。我正在寻找一种在不更新JDK的情况下解决此问题的方法,然而话虽如此,如果我的JDK确实存在这个bug,我还是想知道它是在哪个JDK中修复的。
谢谢。

好的,我找到了更多信息。我尝试将图像保存为png文件,颜色是正确的。所以似乎是jpg编码器不正确。对我来说,将图像保存为jpg文件非常重要,因为png文件很大。有人有进一步的信息吗?也许有另一种机制可以通过工具包将图像保存为jpg文件吗? - Coder
3个回答

5

好的,问题解决了,似乎我需要将图片转换为BufferedImage.TYPE_INT_RGB格式。我认为在某些层面上可能没有正确处理alpha通道。


很高兴听到您已经找到了解决方案。正如您所知,我在我的答案中建议更改缓冲图像类型,但是由于不知道您的图像的具体情况,我无法确定哪种图像类型会起作用。 - mdma
当然,非常感谢。我不确定整个投票过程是如何运作的(我是这个论坛的新手),如果您是在建议这个,那么您已经获得了一个点数。我不知道这个问题的好地方在哪里,但是把它放在这里似乎很合适。正如我所说,我刚加入,但到目前为止,我真的很喜欢这个社区的礼貌和反应能力。很高兴成为其中的一员。 - Coder
如果有帮助,请点赞。我建议您接受@mdma的答案,因为它首先确定了潜在的问题。当然,您也可以给任何有用的答案点赞。 - trashgod

3
我会首先调查是BufferedImage颜色模型有问题还是JPEG编码有问题。您可以尝试更改图像类型(构造函数中的第三个参数),看看是否会产生差异,并直接使用JPEGCodec保存jpeg格式的文件。
例如:
 BufferedImage bufferedImage = ...;  // your image
 out = new FileOutputStream ( filename );
 JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder ( out );
 JPEGEncodeParam param = encoder.getDefaultJPEGEncodeParam ( bufferedImage );
 encoder.setJPEGEncodeParam ( param );
 encoder.encode ( bufferedImage );
 out.close();

编辑:更改文本,您想要更改的是图像类型。请参见构造函数的链接。


谢谢您的建议。 您能提供一些代码片段吗?如果您直接使用编解码器,指的是 Iterator writers = ImageIO.getImageWritersBySuffix("jpeg");, 那么我已经尝试过了,结果是相同的行为。 - Coder
使用上面的代码片段,通过使用编解码器将图像保存为JPEG格式。 - mdma
谢谢,我尝试了你建议的方法(完全复制了你的代码),但是我得到了相同的结果。这是否意味着编码器有问题? - Coder
到目前为止我们无法得出任何结论(编码器可能不是问题,或者在JPEGEncoder和ImageIO中都表现出了问题 - 这是有道理的,因为ImageIO可能在内部使用JPEGEncoder)。你的下一步是尝试调整BufferedImage。 - mdma
如何调整缓冲图像? - Coder
该方法在Java7中会出现错误:包com.sun.image.codec.jpeg不存在;尽管有一些解决方案,但这个类未来可能会被弃用,并不是一个好的选择。 - Zon

1
另一种方法是将图像渲染到一个带有alpha通道的TYPE_INT_ARGB缓冲区中,使用DirectColorModel进行处理,如下所述并建议参考这里
private BufferedImage process(BufferedImage old) {
    int w = old.getWidth();
    int h = old.getHeight();
    BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
    Graphics2D g2d = img.createGraphics();
    g2d.drawImage(old, 0, 0, null);
    g2d.dispose();
    return img;
}

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