我正在尝试用Java做一些图像处理。我使用ImageIO库读取和写入图像。我可以通过以下两种方式读取图像像素值(可能还有其他未知的方法)。
像素= image.getRGB(x,y);
WritableRaster栅格= image.getRaster();
像素= raster.getSample(x,y,0);
以上两种方法有何区别?
最佳答案
1:第一种方法将始终以int ARGB格式和sRGB颜色空间返回像素。无论图像的内部表示如何。这意味着除非图像的内部表示形式为TYPE_INT_ARGB
,否则必须进行一些转换。有时这很有用,因为它是可以预测的,但通常它很慢。例如,色彩空间转换非常昂贵。另外,如果图像的精度高于每个样本8位和/或每个像素4个样本,则会发生精度损失。鉴于您的用例,这可能会接受也可能不会接受。
2:第二种方法可能会为您提供像素值,但并非在所有情况下都为您提供像素值,因为它为频带0(第一个频带)提供了(x,y)处的样本值。对于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);
}
}
这将为您提供数据缓冲区中的“ native ”值,而无需进行任何转换。
然后,您需要对要支持的每种传输类型(请参阅
DataBuffer
类)进行特殊处理,对于非标准类型可能需要进行常见的备用。对于像素值与标准化RGB值,这将具有与方法2相同的“问题”,因此您可能需要“手动”进行转换/查找。
一如既往,哪种方法更好,取决于情况。您必须查看每个用例,然后决定更重要的事情。轻松/简单,或最佳性能(或最佳质量?)。