【问题标题】:BufferedImage getRGB vs Raster getSampleBufferedImage getRGB 与 Raster getSample
【发布时间】:2014-02-17 06:05:56
【问题描述】:

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

  1. 使用 BufferedImage 的 getRGB 方法:

    pixel = image.getRGB(x,y);

  2. 使用 Raster 的 getSample 方法:

    WritableRaster 光栅 = image.getRaster();
    像素 = raster.getSample(x,y,0);

以上两种方式有什么区别?

【问题讨论】:

    标签: java image-processing javax.imageio


    【解决方案1】:

    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);
        }
    }
    

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

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

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


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

    【讨论】:

    • 非常清晰详细的解释。非常感谢。你清理了我。我有一个简单的查询。通常情况是什么?如果我从互联网下载图像并尝试使用第二种方法,那么它是否返回正常像素。您能否说明一些在正常情况下可能会遇到其他图像类型的实际场景?
    • @BibekSubedi:你下载什么样的图片? :-) 不同的格式以不同的方式存储像素(并且 ImageIO 阅读器插件可能使用不同的表示形式)。 “正常情况”可以是 BufferedImage.TYPE_* 常量中的任何内容。考虑带调色板的 GIF/PNG 与真彩色 PNG 与带 alpha 的 PNG,或 RGB JPEG 与灰色 JPEG。
    • 好的,我明白了。现在我得到了我的答案。再次感谢您。
    猜你喜欢
    • 1970-01-01
    • 2012-11-11
    • 2014-03-22
    • 2015-12-24
    • 1970-01-01
    • 1970-01-01
    • 2017-06-29
    • 2016-01-02
    • 1970-01-01
    相关资源
    最近更新 更多