【问题标题】:javax.imageio.ImageIO reading incorrect RGB values on grayscale imagesjavax.imageio.ImageIO 在灰度图像上读取不正确的 RGB 值
【发布时间】:2012-01-24 15:26:57
【问题描述】:

我有一张图片,叫它 grayscale.jpg。现在我在 The Gimp 中打开该图像并将颜色模式更改为 RGB 并将其保存为 color.jpg。如果我在任何图像查看器中查看 grayscale.jpg 和 color.jpg,它们看起来完全一样。但是如果我用javax.imageio.ImageIO打开图片

import javax.imageio.ImageIO;

input = ImageIO.read(new File("grayscale.jpg"));
System.out.format("Grayscale value: %x\n", input.getRGB(200, 200));

input = ImageIO.read(new File("color.jpg"));
System.out.format("Color value: %x\n", input.getRGB(200, 200));

彩色图像将返回正确的值,例如 0xff6c6c6c。灰度图像将返回一个不同的、较浅的、不正确的值,例如 0xffaeaeae。

Grayscale value: 0xffaeaeae // Incorrect (Lighter)
Color value:     0xff6c6c6c // Correct

换句话说,javax.imageio.ImageIO 认为灰度图像比实际要轻得多。如何准确读取灰度图像?

编辑

这里有更多上下文。我的用户上传的图片可能是灰度的。我的 Java 在服务器上运行并进行一些非常复杂的图像处理。所以一个理想的解决方案是只修复我的 Java 代码,而不是用命令行工具拼凑一些东西。

【问题讨论】:

  • 经过更多挖掘,这是stackoverflow.com/questions/6474753/…的副本
  • 刚刚确认这个错误在 2019 年的 Java 8.181 中仍然存在。BufferedImage.getRGB 在使用 BufferedImage.getRaster() 时对灰度字节应用了一个奇怪的变换,使其亮度提高了 30%。 getPixel() 返回正确的颜色。

标签: java image


【解决方案1】:

您的测试无关紧要,因为您使用的是 JPEG,这是有损的。根据压缩,您可能有其他颜色值。因此,请尝试使用无损的 PNG。

您可以使用此图像来测试javax.imageio 的正确性。使用 Gimp 将其转换为灰度,并确保将其保存为 PNG。然后以相同的方式加载两者(这个和转换后的)。并在 for 循环中比较 y 轴的所有颜色。

示例代码:

BufferedImage inputGrayscale = ImageIO.read(new File("grayscale.png"));    
BufferedImage inputColor = ImageIO.read(new File("color.png"));

for (int i = 0; i < 256; ++i)
{
    System.out.printf(i + "Grayscale value: %x\n", inputGrayscale.getRGB(10, i));
    System.out.printf(i + "Color value: %x\n", inputColor.getRGB(10, i));
    System.out.println();
}

【讨论】:

  • 这不仅仅是一个压缩的东西。如果我读取每个像素并将其写入文件,本质上是逐个像素地复制图像,则彩色图像的副本看起来正确,而灰度图像的副本将比输入文件轻得多。
  • 另外,请参阅我的编辑,它添加了更多上下文。这些图片来自我的用户,我不希望他们担心 .png 和 .jpg。他们应该能够直接上传他们的相机输出。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-18
  • 1970-01-01
  • 2020-05-04
  • 2018-02-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多