【发布时间】:2017-01-31 15:16:37
【问题描述】:
我发现我在使用 Java(实际上是 paint.NET)时获得的 RGB 与使用 ImageMagick、Gimp、Python 和 Octave 时不同。最后4个都同意,所以我假设是正确的。
对于这些示例,我使用的是这个测试图像:http://farm3.static.flickr.com/2811/9177301733_9836174725_o.jpg
测试像素x=4144 y=2768
R G B
Java = (125, 107, 69)
Paint.NET = (125, 107, 69)
ImageMagick = (128, 106, 67)
Python = (128, 106, 67)
Octave = (128, 106, 67)
Gimp = (128, 106, 67)
什么给了?
这是一个使用 imagemagick 的快速测试:
convert image.jpg -crop 1x1+4144+2768 -depth 8 txt:
输出:
# ImageMagick pixel enumeration: 1,1,65535,srgb
0,0: (32896,27242,17219) #806A43 srgb(128,106,67)
这里有一些 java 和 python 代码也演示了这个问题:
import org.apache.commons.io.FileUtils;
import org.junit.Test;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
public class ImageIOTest {
@Test
public void can_read_file() throws IOException, InterruptedException, URISyntaxException {
File tempFile = File.createTempFile("image", "jpg");
FileUtils.copyURLToFile(new URL("http://farm3.static.flickr.com/2811/9177301733_9836174725_o.jpg"), tempFile);
BufferedImage image = ImageIO.read(tempFile);
int javaRGB = image.getRGB(4144, 2768);
int javaRed = (javaRGB >> 16) & 0xFF;
int javaGreen = (javaRGB >> 8) & 0xFF;
int javaBlue = (javaRGB >> 0) & 0xFF;
System.out.printf("rgb: (%d, %d, %d)", javaRed, javaGreen, javaBlue);
}
}
这里是对应的python脚本:
from PIL import Image
import sys, urllib, cStringIO
file = cStringIO.StringIO(urllib.urlopen("http://farm3.static.flickr.com/2811/9177301733_9836174725_o.jpg").read())
im = Image.open(file)
pix = im.load()
print pix[4144, 2768]
我尝试过使用this 12monkeys library,希望能解决这个问题,但没有骰子。还有其他想法如何使用java提取正确的RGB值吗?当然我不是第一个遇到这个问题的人!
更新
我尝试了getRaster().getSample(),但得到了同样的无效结果:System.out.println(raster.getSample(4144, 2768, 0)+","+ raster.getSample(4144, 2768, 1)+","+ raster.getSample(4144, 2768, 2)); 输出:125,107,69
更多信息
下面是一些输出,显示了图像左上角的前 9 个(3x3 平方)像素由三种不同工具解码的 RGB 值。如您所见,Python 和 ImageMagick 是一致的。 Java 有时会匹配。我在java不同意的地方放了一个X...:
Tool [x, y] = (R , G , B )
ImageIO : [0, 0] = (86, 90, 93)
Python : [0, 0] = (86, 90, 93)
ImageMagick : [0, 0] = (86, 90, 93)
ImageIO : [1, 0] = (86, 90, 93)
Python : [1, 0] = (86, 90, 93)
ImageMagick : [1, 0] = (86, 90, 93)
ImageIO : [2, 0] = (90, 91, 95) X
Python : [2, 0] = (88, 92, 95)
ImageMagick : [2, 0] = (88, 92, 95)
ImageIO : [0, 1] = (85, 93, 95)
Python : [0, 1] = (85, 93, 95)
ImageMagick : [0, 1] = (85, 93, 95)
ImageIO : [1, 1] = (85, 93, 95) X
Python : [1, 1] = (87, 92, 95)
ImageMagick : [1, 1] = (87, 92, 95)
ImageIO : [2, 1] = (87, 92, 95)
Python : [2, 1] = (87, 92, 95)
ImageMagick : [2, 1] = (87, 92, 95)
ImageIO : [0, 2] = (83, 93, 94)
Python : [0, 2] = (83, 93, 94)
ImageMagick : [0, 2] = (83, 93, 94)
ImageIO : [1, 2] = (83, 93, 94) X
Python : [1, 2] = (84, 92, 94)
ImageMagick : [1, 2] = (84, 92, 94)
ImageIO : [2, 2] = (83, 91, 93)
Python : [2, 2] = (83, 91, 93)
ImageMagick : [2, 2] = (83, 91, 93)
为什么 Java 会为某些像素提供不同的值?或者,是否有另一种(快速)使用本机 Java 代码生成正确值的方法?
2016 年 9 月 26 日更新:
我提交了演示此问题的代码并将其推送到 github (imageio-test),以便我可以轻松地在不同的机器上对其进行测试。事实证明,Java 在 OSX 和 Ubuntu Linux 上是一致的,但不一致的是 Python、ImageMagick 和 Octave。换句话说,在 Linux 机器上,所有工具都相互一致,因此,我现在认为 java 一直都是正确的,而在 OSX 上给出错误结果的是其他工具!我仍然不明白为什么,我也没有任何具体的证据证明哪些值是正确的,但我在某个地方......
【问题讨论】:
-
RGB 不是颜色空间,而是颜色模型(参见color model vs color space)。我知道 Java 总是使用 sRGB 颜色空间,但不确定其他颜色空间。如果色彩空间不同,您可能有不同的 RGB 值,但屏幕上的颜色仍然相同。
-
@haraldK,好地方。据我所知,Python 正在使用 sRGB(但无法证明)。 GIMP 正在使用 sRGB。我使用 imagemagick 添加了一个单线,它也给出了相同的结果,并且还报告说它正在使用 sRGB。
-
我已经用 Paint.NET 打开了它。像素值为 125、107、69(与 Java 相同)。
-
感谢您的帮助。我已经将测试代码推送到github.com/mattburns/imageio-test,如您所见,Linux 和 OSX 的结果不同,这表明 Java 实际上是正确的!蟒蛇公司给了我不同的结果!还是不明白为什么。
-
主要区别在于编解码器 - ImageIO 调用以获取图像数据的本机代码。 Python、GIMP 等使用 libjpeg.9.dylib(在 Mac OSX 上),而 JDK 将使用它们随附的一个(例如:Library/Java/JavaVirtualMachines/jdk1.8.0_102.jdk/Contents/Home/jre/lib/ libjpeg.dylib)。不幸的是,您无法交换和更改它们。潜在地,您可以使用您想要的版本重新构建 Pillow(用于 Python)......虽然没有测试过。
标签: java jpeg rgb javax.imageio