使用Java Thumbnailator或Imgscalr调整JPEG图像大小时出现粉红/红色色调

6
我正在尝试使用两个库(thumbnailator和imgscalr)将一张图片转换为另一种格式。我的代码可以处理大部分的图片,但是对于一些图片在转换后会产生粉红/红色的色调。
我想要了解造成这种情况的原因,并欢迎任何建议。
注意 - 这张图片的图像类型为5,即BufferedImage.TYPE_3BYTE_BGR,我使用的是Java 7版本。
以下是需要转换的图片:enter image description here enter image description here 使用Thumbnailator:
  Thumbnails.of(fromDir.listFiles())                
                    .size(thumbnailWidth, thumbnailHeight)
                    .toFiles(Rename.SUFFIX_HYPHEN_THUMBNAIL);

Using imgscalr

    BufferedImage bufferedImage = ImageIO.read(file);
    final BufferedImage jpgImage;

    LOG.debug("image type is =[{}] ", bufferedImage.getType());

     BufferedImage scaledImg = Scalr.resize(bufferedImage, Method.ULTRA_QUALITY, thumbnailWidth, thumbnailHeight, Scalr.OP_ANTIALIAS);


    File thumbnailFile = new File(fromDirPath + "/" + getFileName(file.getName()) +THUMBNAIL_KEYWORD  + ".png");

    ImageIO.write(scaledImg, getFileExtension(file.getName()), thumbnailFile);

    bufferedImage.flush();
    scaledImg.flush();

我认为问题在于JPEGImageReader错误地解释了JPEG数据,并假定它是RGB,而不是实际的YCbCr。如果您尝试从上面的imgscalr代码显示或写入(作为PNG,无需缩放)bufferedImage会发生什么?它是否仍然看起来不正确?还是只有在缩放/存储为JPEG之后才会出现这种情况? - Harald K
@haraldK - 相同的色调。 - rohtakdev
我建议尝试使用ImageIO的JPEG插件。通常情况下,它在确定输出色彩空间时比默认的“JPEGImageReader”做得更好。其中一个提到的库已经预装了旧版本的我的插件,确保您获取最新版本,因为捆绑版本存在关于此问题的错误。 - Harald K
如果有帮助的话,我在这里写了一个更详细的回复,并附上了一些代码示例 - https://dev59.com/rnTYa4cB1Zd3GeqPxq0e - Riyad Kalla
2个回答

6
我经常收到这个问题(imgscalr 的作者)-- 问题几乎总是出在读取/写入不同文件格式时,ALPHA 通道会导致其中一个颜色通道(R/G/B)从生成的文件中被剔除。
例如,如果您读入一个 ARGB(4 通道)文件并将其写成 JPG(3 通道)- 除非您有意地自己操纵图像类型并直接将旧图像渲染到新图像上,否则您将得到一个带有 "ARG" 通道的文件... 或者更具体地说,只有红色和绿色 - 没有蓝色。
PNG 支持 alpha 通道,而 JPG 不支持,请注意这一点。
解决此问题的方法是故意创建适当的 BufferedImage 并使用 destImage.getGraphics() 调用将一个图像呈现到另一个图像之前,然后再将其写入磁盘并重新编码。
Sun 和 Oracle 从未使 ImageIO 库在写入不同文件类型时智能地检测不受支持的通道,因此这种行为经常发生 :(
希望这可以帮到你!

谢谢Riyad。我会尽快尝试这个。 - rohtakdev

2
下面这段代码解决了我的问题:
ByteArrayOutputStream baos = new ByteArrayOutputStream();

  Thumbnails.of(new ByteArrayInputStream(imageByteArray))
    .outputFormat("jpg")
    .size(200, 200)
    .toOutputStream(outputStream);

  return baos.toByteArray();

我正在使用Thumbnailator,代码已经发布在这里:https://github.com/coobird/thumbnailator/issues/23


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