java - 4 位调色板的奇怪 BufferedImage 行为

标签 java image png bufferedimage

[参见related]

以下代码打开一个带有 4 位调色板和透明度(TRNS block )的微小 PNG 图像,并打印像素 (1,1) 和 (1,2) 的值。然后它将图像从自动类型转换为 TYPE_4BYTE_ABGR 并打印相同的像素值。

  public static void images() throws IOException {
    File png = new File("c:\\temp\\04ptx.png");

    BufferedImage bi1 = ImageIO.read(png);
    System.out.printf("%s is TYPE_BYTE_BINARY? %s (%d)\n",png, 
        String.valueOf(BufferedImage.TYPE_BYTE_BINARY==bi1.getType()),
        bi1.getType());
    int p1i1 = bi1.getRGB(1, 1);
    int p2i1 = bi1.getRGB(2, 1);
    System.out.printf("im1: p1=%08x %s  p2=%08x %s\n",
         p1i1,formatARGB(p1i1),p2i1,formatARGB(p2i1));

    BufferedImage bi2 = new BufferedImage(bi1.getWidth(), bi1.getHeight(), 
        BufferedImage.TYPE_4BYTE_ABGR);
    bi2.getGraphics().drawImage(bi1, 0, 0, null);
    int p1i2 = bi2.getRGB(1, 1);
    int p2i2 = bi2.getRGB(2, 1);
    System.out.printf("im2: p1=%08x %s  p2=%08x %s\n",
        p1i2,formatARGB(p1i2),p2i2,formatARGB(p2i2));
  }

  public static String formatARGB(int v) {
    return String.format("(%d,%d,%d,%d)", 
        (v>>24)&0xFF,(v>>16)&0xFF,(v>>8)&0xFF,v&0xFF);
  }

我得到的结果是

c:\temp\04ptx.png is TYPE_BYTE_BINARY? true (12)
im1: p1=80e25fb1 (128,226,95,177)  p2=00000000 (0,0,0,0)
im2: p1=80e160b1 (128,225,96,177)  p2=00000000 (0,0,0,0)

(当选择 JAI 的读取器时,会选择 TYPE_BYTE_INDEXED,但像素值相同)。

我有两个问题:

  1. 根据docs 、 TYPE_BYTE_BINARY “表示不透明的字节封装 1、2 或 4 位图像。该图像具有不带 alpha 的 IndexColorModel”。这似乎与结果相矛盾,结果(正确地)显示了两个像素的 alpha 值。

  2. 原始结果 (128,226,95,177) 是正确的(可以使用任何图像查看器进行验证,或者更好的是使用 http://entropymine.com/jason/tweakpng/ 进行验证)。为什么传递给 TYPE_4BYTE_ABGR 会引入这个(小)错误?

图像(4x3,右半部分完全透明)位于:https://dl.dropboxusercontent.com/u/1608708/tech/04ptx.png

我的Java是

java version "1.7.0_17"
Java(TM) SE Runtime Environment (build 1.7.0_17-b02)
Java HotSpot(TM) Client VM (build 23.7-b01, mixed mode, sharing)
<小时/>

最佳答案

我可以尝试回答第1项;该文档有点不精确,我认为的目的是说图像具有 IndexColorModel 并且没有离散 alpha channel 。即:颜色图中只有一个带有索引的 channel 。这与 IndexColorModel 中的颜色本身可能是(半)透明的这一事实并不矛盾。这个解释符合我的经验,但当然,我没有编写 API 或文档...;-)

第 2 项看起来有点奇怪。该误差非常小+/- 1,因此在实践中可能没什么大不了的(大多数人的眼睛看不见)。完全猜测,但我猜想正在使用某种优化循环,这会牺牲一些准确性来提高速度。您是否尝试过使用 setRGB()/getRGB() 来查看是否会产生不同的结果?

关于java - 4 位调色板的奇怪 BufferedImage 行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23707736/

相关文章:

android - 是否可以在Android上控制png编码的图像质量?

java - 如何编码节点或文档字段?

java - 为什么 ActionListener 不起作用?

Java - 理解继承

iphone - 有人有 iOS 上 vImage 处理的示例代码吗?

javascript - 将 PDF 作为图像包含在 HTML 中

php在上传时调整图像大小

iphone - iPhone 是否支持具有 alpha 透明度的 24 位 PNG?

java - 安卓/gradle : not able to use repository

Delphi - 将 bmp 转换为 png 失败