与其他工具相比,从 Java 中的 BufferedImage 获得的 RGB 值不正确
RGB values obtained from BufferedImage in Java incorrect when compared to other tools
我正在尝试跨平台可靠地获取图像像素的 RGB 值。
对于我的测试,我使用的是别人提供给我的 jpg 图像(请参阅下面的 编辑 - 情节变粗 部分)。
在 C# 中,我正在做类似于以下的事情(其中 bmpData 是一个 BitmapData 对象):
PixelData* pScan = (PixelData*)bmpData.Scan0;
...
struct PixelData
{
internal byte r;
internal byte g;
internal byte b;
internal PixelData(byte r, byte g, byte b)
{
this.r = r;
this.g = g;
this.b = b;
}
}
在 Java 中,我尝试了以下操作,其中图像是一个 BufferedImage 对象(从在此实用程序方法中读取的 byte[] 创建:http://docs.oracle.com/javase/7/docs/api/javax/imageio/ImageIO.html#read(java.io.InputStream)):
Raster raster = image.getRaster();
for(x){
for(y){
double[] pixel = raster.getPixel(x, y, new double[3]);
还有这个:
int rgb = image.getRGB(x, y);
int r = (rgb >> 16) & 0xff;
int g = (rgb >> 8) & 0xff;
int b = rgb & 0xff;
还有这个:
Raster raster = image.getRaster();
int r = raster.getSample(x, y, 0);
int g = raster.getSample(x, y, 1);
int b = raster.getSample(x, y, 2);
用我的测试图像,结果总是如下。例如取第一个像素:
C# 结果:
R=16
G=60
B=109
Java 结果(在所有情况下):
R=52
G=160
B=102
所以,我有三个问题:
1.为什么它们如此不同?
2.是不是我做错了?
3.这两种情况有更好的方法吗?
感谢您提供的任何帮助!
编辑 - 2015-10-19
在有人建议我使用图像工具 "pick" 第一个像素的颜色后,我就这样做了。值如下:
微软画图:
R=17
G=61
B=110
GIMP:
R=16
G=60
B=109
所以我的问题变成了:
为什么 Java 的 BufferedImage class 的 RGB 值如此错误?
编辑 - 情节变厚了
我从 GIMP 和 运行 通过相同的程序导出图像,现在 RGB 数字都正确匹配。
GIMP 导出过程中的一些东西改变了它,因此它现在在 Java 库中工作相同。
现在我需要弄清楚发生了什么变化!不幸的是,我在这方面的知识有限。
我已经检查了 alpha 预计算、ColorModel 和 ColorSpace。一切都明显相同。
图片(希望原样):
https://www.dropbox.com/s/9pc4nxwdav5s0za/correctRGBs.jpg?dl=0
https://www.dropbox.com/s/fknlj1n4jcuk4pg/incorrectRGBs.jpg?dl=0
已实施解决方案
在 Anders 的建议下,我首先研究了 twelvemonkeys "plugins",因为它似乎是最干净的解决方案。
我还注意到作者写了一个插件来处理 tiff 文件,这是一个额外的好处,因为我之前通过它们的幻数识别 tiff 并使用 JAI 库转换它们。不用了!
为了让它工作,我只是添加了以下 gradle 依赖项:
compile 'com.twelvemonkeys.imageio:imageio-jpeg:3.1.2'
compile 'com.twelvemonkeys.imageio:imageio-tiff:3.1.2'
刷新并再次运行。当它再次 运行 时,我可以从调试器以及结果中看到图像已正确加载到 BufferedImage 对象中。
那时 RGB 值也是正确的。谢谢!
正如您所说,这个问题与this thread. You can confirm it by reading the image and then writing it to a file. It looks like this中的问题完全相同。
这个问题有多种解决方案。最简单的似乎是包括 TwelveMonkeys' ImageIO jars as dependencies to your project. You don't need to make any code changes. This worked for me.
其他选择:
- Mark Jeronimus 写道 a method 将不良图像转换为正确图像。我在你的示例图像上测试了它并且它有效。但是,您需要找到一种检测是否需要进行转换的好方法。对该答案的评论可能会有所帮助。
- 根据 ludovic 的建议,您可以使用 Toolkit's getImage 而不是
ImageIO
打开图像,因为它没有相同的错误。
我正在尝试跨平台可靠地获取图像像素的 RGB 值。
对于我的测试,我使用的是别人提供给我的 jpg 图像(请参阅下面的 编辑 - 情节变粗 部分)。
在 C# 中,我正在做类似于以下的事情(其中 bmpData 是一个 BitmapData 对象):
PixelData* pScan = (PixelData*)bmpData.Scan0;
...
struct PixelData
{
internal byte r;
internal byte g;
internal byte b;
internal PixelData(byte r, byte g, byte b)
{
this.r = r;
this.g = g;
this.b = b;
}
}
在 Java 中,我尝试了以下操作,其中图像是一个 BufferedImage 对象(从在此实用程序方法中读取的 byte[] 创建:http://docs.oracle.com/javase/7/docs/api/javax/imageio/ImageIO.html#read(java.io.InputStream)):
Raster raster = image.getRaster();
for(x){
for(y){
double[] pixel = raster.getPixel(x, y, new double[3]);
还有这个:
int rgb = image.getRGB(x, y);
int r = (rgb >> 16) & 0xff;
int g = (rgb >> 8) & 0xff;
int b = rgb & 0xff;
还有这个:
Raster raster = image.getRaster();
int r = raster.getSample(x, y, 0);
int g = raster.getSample(x, y, 1);
int b = raster.getSample(x, y, 2);
用我的测试图像,结果总是如下。例如取第一个像素:
C# 结果:
R=16
G=60
B=109
Java 结果(在所有情况下):
R=52
G=160
B=102
所以,我有三个问题:
1.为什么它们如此不同?
2.是不是我做错了?
3.这两种情况有更好的方法吗?
感谢您提供的任何帮助!
编辑 - 2015-10-19 在有人建议我使用图像工具 "pick" 第一个像素的颜色后,我就这样做了。值如下:
微软画图:
R=17
G=61
B=110
GIMP:
R=16
G=60
B=109
所以我的问题变成了:
为什么 Java 的 BufferedImage class 的 RGB 值如此错误?
编辑 - 情节变厚了
我从 GIMP 和 运行 通过相同的程序导出图像,现在 RGB 数字都正确匹配。
GIMP 导出过程中的一些东西改变了它,因此它现在在 Java 库中工作相同。
现在我需要弄清楚发生了什么变化!不幸的是,我在这方面的知识有限。
我已经检查了 alpha 预计算、ColorModel 和 ColorSpace。一切都明显相同。
图片(希望原样):
https://www.dropbox.com/s/9pc4nxwdav5s0za/correctRGBs.jpg?dl=0
https://www.dropbox.com/s/fknlj1n4jcuk4pg/incorrectRGBs.jpg?dl=0
已实施解决方案
在 Anders 的建议下,我首先研究了 twelvemonkeys "plugins",因为它似乎是最干净的解决方案。
我还注意到作者写了一个插件来处理 tiff 文件,这是一个额外的好处,因为我之前通过它们的幻数识别 tiff 并使用 JAI 库转换它们。不用了!
为了让它工作,我只是添加了以下 gradle 依赖项:
compile 'com.twelvemonkeys.imageio:imageio-jpeg:3.1.2'
compile 'com.twelvemonkeys.imageio:imageio-tiff:3.1.2'
刷新并再次运行。当它再次 运行 时,我可以从调试器以及结果中看到图像已正确加载到 BufferedImage 对象中。
那时 RGB 值也是正确的。谢谢!
正如您所说,这个问题与this thread. You can confirm it by reading the image and then writing it to a file. It looks like this中的问题完全相同。
这个问题有多种解决方案。最简单的似乎是包括 TwelveMonkeys' ImageIO jars as dependencies to your project. You don't need to make any code changes. This worked for me.
其他选择:
- Mark Jeronimus 写道 a method 将不良图像转换为正确图像。我在你的示例图像上测试了它并且它有效。但是,您需要找到一种检测是否需要进行转换的好方法。对该答案的评论可能会有所帮助。
- 根据 ludovic 的建议,您可以使用 Toolkit's getImage 而不是
ImageIO
打开图像,因为它没有相同的错误。