查看PNG specification,看来PNG像素数据块以IDAT
开头,以IEND
结尾(稍微更清楚的解释here)。在中间是对我有意义的价值观。
如何在不使用任何库的情况下(即从原始二进制文件中)获取可用的RGB值?
作为一个例子,我在Photoshop中制作了一个2x2px图像,其中包含4个黑色rgb(0,0,0)
像素:
这里是结果数据(在原始二进制输入中,十六进制值和人类可读的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'
答案 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个单独的例程:
IDAT
压缩数据,以及宽度,高度和颜色深度等基本信息; zlib
部分解压缩为原始二进制数据; 只有在执行这三个步骤后,您才能访问原始图像数据。其中,你似乎很好地掌握了步骤(1)。步骤(2)更难以“做”自己;就个人而言,我在自己的PNG处理程序中作弊并使用了miniz
。再次,步骤3仅仅是决定的问题。所有必要的信息都可以在网上找到,但是需要一段时间才能按顺序排列所有内容。 (就在最近,我在执行极少使用的Paeth行过滤器时发现了一个错误 - 它没有引起注意因为它很少用于'真实世界'图像。)
请参阅Building a fast PNG encoder issues进行类似的讨论,并Trying to understand zlib/deflate in PNG files深入了解Deflate计划。