2014-10-19 75 views
3

看着PNG specification,看起来PNG像素数据块开始于IDAT并以IEND结束(稍微更清晰的解释here)。在中间是对我来说没有意义的价值观。解释PNG像素数据

如何从这里获得可用的RGB值,而无需使用任何库(即从原始二进制文件)?

作为一个例子,我在Photoshop与4个黑色rgb(0,0,0)像素由2x2px图像:
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' 

回答

6

你错过了在这两个规格相当关键的细节:

官方之一:

.. IDAT块包含实际的图像数据,它是压缩算法的输出流。
[...]
PNG内的减压数据流以“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上层建筑;这提供了压缩数据以及基本信息,例如宽度,高度和颜色深度;
  2. zlib零件解压缩为原始二进制数据;
  3. 解析解压缩的数据,如果需要处理Adam-7隔行扫描,并应用行过滤器。

只有在执行这三个步骤后,您才能访问原始图像数据。其中,您似乎对步骤(1)有很好的掌握。步骤(2)更难以“自己动手”;个人而言,我欺骗并在我自己的PNG处理程序中使用了miniz。步骤3再一次只是确定的问题。所有必要的信息都可以在网上找到,但需要一段时间才能将所有信息按照正确的顺序排列。 (就在最近,我在很少使用Paeth行筛选器的执行中发现的错误 - 因为这是相当罕见的“真实世界”的图像用它去注意。)

了类似的讨论和Trying to understand zlib/deflate in PNG filesBuilding a fast PNG encoder issues深入了解Deflate方案。

+0

非常非常有帮助 - 谢谢! – JeffThompson 2014-10-20 11:25:40