解释PNG像素数据

时间:2014-10-19 23:14:23

标签: binary hex png rgb pixel

查看PNG specification,看来PNG像素数据块以IDAT开头,以IEND结尾(稍微更清楚的解释here)。在中间是对我有意义的价值观。

如何在不使用任何库的情况下(即从原始二进制文件中)获取可用的RGB值?

作为一个例子,我在Photoshop中制作了一个2x2px图像,其中包含4个黑色rgb(0,0,0)像素:
Just four black pixels...

这里是结果数据(在原始二进制输入中,十六进制值和人类可读的ASCII):

BINARY      HEX ASCII
01001001    49  'I'
01000100    44  'D'
01000001    41  'A'
01010100    54  'T'
01111000    78  'x'
11011010    DA  '\xda'
01100010    62  'b'
01100000    60  '`'
01000000    40  '@'
00000110    06  '\x06'
00000000    00  '\x00'
00000000    00  '\x00'
00000000    00  '\x00'
00000000    00  '\x00'
11111111    FF  '\xff'
11111111    FF  '\xff'
00000011    03  '\x03'
00000000    00  '\x00'
00000000    00  '\x00'
00001110    0E  '\x0e'
00000000    00  '\x00'
00000001    01  '\x01'
10000011    83  '\x83'
11010100    D4  '\xd4'
11101100    EC  '\xec'
10001110    8E  '\x8e'
00000000    00  '\x00'
00000000    00  '\x00'
00000000    00  '\x00'
00000000    00  '\x00'
01001001    49  'I'
01000101    45  'E'
01001110    4E  'N'
01000100    44  'D'

1 个答案:

答案 0 :(得分:6)

你错过了两个规范中相当重要的细节:

官方人士:

  

.. IDAT块包含实际图像数据,它是压缩算法的输出流   [...]
  PNG中的Deflate压缩数据流以“zlib”格式存储。

<强>百科:

  

IDAT包含图像,可以在多个IDAT块之间进行分割。这种分割会稍微增加文件大小,但可以以流方式生成PNG。 IDAT块包含实际的图像数据,它是压缩算法的输出流。

两者都声明原始图像数据是压缩。查看您的数据,前2个字节

78 DA

包含RFC1950中指定的压缩标志。其余数据被压缩。

使用通用zlib兼容例程解压缩显示14个字节的输出:

00 00 00 00 00 00 00
00 00 00 00 00 00 00

其中每个第一个字节是PNG行过滤器(两行为0),后面是2个RGB三元组(0,0,0),用于图像的2行。

“不使用任何库”,您需要3个单独的例程:

  1. 读取并解析PNG上层结构;这提供了IDAT压缩数据,以及宽度,高度和颜色深度等基本信息;
  2. zlib部分解压缩为原始二进制数据;
  3. 解析解压缩的数据,根据需要处理Adam-7隔行扫描,并应用行过滤器。
  4. 只有在执行这三个步骤后,您才能访问原始图像数据。其中,你似乎很好地掌握了步骤(1)。步骤(2)更难以“做”自己;就个人而言,我在自己的PNG处理程序中作弊并使用了miniz。再次,步骤3仅仅是决定的问题。所有必要的信息都可以在网上找到,但是需要一段时间才能按顺序排列所有内容。 (就在最近,我在执行极少使用的Paeth行过滤器时发现了一个错误 - 它没有引起注意因为它很少用于'真实世界'图像。)

    请参阅Building a fast PNG encoder issues进行类似的讨论,并Trying to understand zlib/deflate in PNG files深入了解Deflate计划。