带 Alpha 解码的 PNG 真彩色
Posted
技术标签:
【中文标题】带 Alpha 解码的 PNG 真彩色【英文标题】:PNG True color with Alpha decoding 【发布时间】:2014-07-04 04:23:49 【问题描述】:我正在编写一个 PNG 解码器,但遇到了一些奇怪的问题。通过 PNG 文件格式,我成功地使用颜色索引 + tRNS (alpha) 和 True Color + tRNS (alpha) 正确解码了 PNG。我目前不确定为什么我无法解码带有 Alpha 类型 PNG 的真彩色 PNG。我已经验证我的 IDAT 块膨胀是正确的。下面是块的样子:
Width: 256
Height: 256
Bit Depth: 8
Color Type: 6
Compression: 0
Filter: 0
Interlace: 0
Length: 25
Type: tEXt
Data: 53 6f 66 74 77 61 72 65 00 41 64 6f 62 65 20 49 6d 61 67 65 52 65 61 64 79
CRC: 71c9653c
Length: 20690
Type: IDAT
Data: 78 da ec 7d 09 9c 1c 57 99 df f7 7a a6 e7 3e 5a a3 fb ...
CRC: 21550259
实际数据太长,无法在此处打印。这是我的解码逻辑,如果我错了,请纠正我:
-
膨胀 IDAT 块中给定的所有字节
取消过滤膨胀块。在这种情况下,所有过滤器的类型都是 0,因此,我们只需丢弃过滤器字节。
因为这是颜色类型 6,所以一个像素由 RGBA 通道表示,每个通道有 1 个字节。这意味着我们需要一次解释 4 个字节。使用如下代码:
ByteBuffer image = BufferUtil.getDirectByteBuffer(data.length, ByteOrder.BIG_ENDIAN);
int i = 0;
while(i < data.length)
int color = ( (data[i] & 0xff) << 24) | ( (data[i+1] & 0xff) << 16) | ( (data[i+2] & 0xff) << 8) | (data[i+3] & 0xff);
image.putInt(color);
i += 4;
奇怪的是,我得到的主要是 RRGGBBAA = 0x00000000 数据,导致图像清晰,颜色很少。
【问题讨论】:
【参考方案1】:问题是您忽略了观察每条扫描线的过滤。
从提供的图像来看,解压后的数据看起来像
1 ffffffff 0 0 0 ... 2 0 0 0 0 0 0 ... ..
每行的第一个值符合使用的过滤方法[http://www.w3.org/TR/PNG/#9Filters]
扫描线后处理看起来像
ffffffff ffffffff ffffffff ... ffffffff ffffffff ffffffff ... ...
这里是一些处理方法 0、1 和 2 的示例代码。
private static void processScanLine(byte filterValue, byte[] scanLine, byte[] previousScanLine)
switch(filterValue)
case 0:break;
case 1:
for (int i =4;i<scanLine.length;i++)
scanLine[i] = (byte)(scanLine[i]+scanLine[i-4]);
break;
case 2:
for (int i =0;i<scanLine.length;i++)
scanLine[i] = (byte)(scanLine[i]+previousScanLine[i]);
break;
【讨论】:
你解压压缩数据的短样本sn-p了吗? OP 断言“所有过滤器都是 0 型”。 解压前的二进制数据:dropbox.com/s/20j10fuburid4sy/pre_inflate_data.dat解压后的二进制数据:dropbox.com/s/x35k5df3rpx0tqi/post_inflate_data.dat解压后的一些样本:00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ... 所以看起来过滤字节是0x0。 似乎在前几行扫描之后,过滤器代码可以是非零的。抱歉打扰了。 上一个扫描线和当前扫描线之前的扫描线有什么区别? 我使用发布的图像来测试代码。假设那是正在显示的那个。以上是关于带 Alpha 解码的 PNG 真彩色的主要内容,如果未能解决你的问题,请参考以下文章