BufferedImage getRGB vs Raster getSample

我正在尝试用Java做一些图像处理。 我使用ImageIO库来读写图像。 我可以通过以下两种方式读取图像像素值(可能还有其他方法)。

  1. 使用BufferedImage的getRGB方法:

    pixel = image.getRGB(x,y);

  2. 使用Raster的getSample方法:

    WritableRaster raster = image.getRaster();
    pixel = raster.getSample(x,y,0);

上述两种方法有什么区别?

1:第一种方法将始终以int ARGB格式返回一个像素,并在sRGB颜色空间中返回。 无论图像的内部表示如何。 这意味着除非图像的内部表示是TYPE_INT_ARGB ,否则必须进行一些转换。 这有时是有用的,因为它是可预测的,但同样经常很慢。 例如,色彩空间转换非常昂贵。 此外,如果图像具有比每个样本8比特和/或每像素4个样本更高的精度,则发生精度损失。 根据您的使用案例,这可能是也可能是不可接受的。

2:第二种方法可能会给你一个像素值,但不是在所有情况下,因为它给你带(0,y)的带0(第一个带)的样本值。 对于TYPE_INT_ARGB这将与像素值相同。 对于TYPE_BYTE_INDEXED这将是在查找表中使用的索引(您需要查找它以获取像素值)。 对于TYPE_3BYTE_BGR这将仅为您提供蓝色值(您需要将其与带1和2中的样本组合以获得完整像素值)。 等等其他类型。 对于未在内部表示为int的样本,将发生数据类型转换(在极少数情况下会发生精度损失)。 它可能适合你,但我从来没有太多使用getSample(...)方法。

相反,我建议你研究一下我认为是获取像素数据的最快方法。 那是使用getDataElements方法:

 Object pixel = null; // pixel initialized on first invocation of getDataElements for (y) { for (x) { pixel = raster.getDataElements(x, y, pixel); } } 

这将为您提供数据缓冲区中的“本机”值,而无需任何转换。

然后,您需要对要支持的每种传输类型(请参阅DataBuffer类)进行特殊处理,并且可能是非标准类型的常见回退。

对于像素值与标准化RGB值的方法2,这将具有相同的“问题”,因此您可能需要“手动”转换/查找。


一如既往,更好的方法取决于。 您必须查看每个用例,并确定哪些更重要。 轻松/简单,或最佳性能(或最佳质量?)。