摘要:我需要一个PNG编写器,由于各种原因,我必须从头开始制作它。我不需要压缩图像数据,因此我使用了无压缩的deflate算法来实现PNG。对于需要多个deflate块的图像,渲染失败,似乎是因为它忽略了块长度。
问题:当我有一个用单个deflate块编写的微小图像时,生成的图像正是它应该是的(所有像素都正确,在使用pngcheck检查时没有错误)。然而,一旦我使用多个deflate块,生成的图像就会出错,因为deflate块被读取超过了它们的长度(尽管pngcheck仍然没有显示任何错误)。在十六进制编辑器中查看原始数据似乎显示一切都符合规范(根据libpng、RFC 1950和RFC 1951)。
示例数据:我生成了一个3x1 RGBA图像,其中像素颜色从左到右分别为(fb,02,03,fa)
,(01,fc,03,fa)
,(01,02,fd,fa)
。然后我将它们写入文件,其中最大deflate块长度为8字节或64字节。64字节块长度的图像完全正确,可以正确地呈现。
以下是完整的图像内容,以十六进制表示,其中粗体是块长度,斜体是块数据。
8字节块图像(呈现不正确):
89 50 4e 47 0d 0a 1a 0a 00 00 00 0d 49 48 44 52 00 00 00 03 00 00 00 01 08 06 00 00 00 1b e0 14 b4 00 00 00 1d 49 44 41 54 78 9c 00
00 08ff f7
00 fb 02 03 fa 01 fc 0301
00 05ff fa
fa 01 02 fd fa05 ee ac ee a1 e1 2d b9 00 00 00 00 49 45 4e 44 ae 42 60 82
64字节块图像(正确呈现):
89 50 4e 47 0d 0a 1a 0a 00 00 00 0d 49 48 44 52 00 00 00 03 00 00 00 01 08 06 00 00 00 1b e0 14 b4 00 00 00 18 49 44 41 54 78 9c 01
00 0dff f2
00 fb 02 03 fa 01 fc 03 fa 01 02 fd fa05 ee ac ee f8 dc a0 6c 00 00 00 00 49 45 4e 44 ae 42 60 82
每个Deflate块的开头由5个字节组成:0或1(取决于是否为最终块),后跟2字节长度(上面是粗体)和它的2字节补码。在8字节块映像中,第一个块的长度为8,正如它应该的那样。在长度补码后的8个字节(上面是斜体)确实是它们应该是的值,并且第9个字节等于1(并开始最终块)。然而,那个1被解释为颜色值(第二个像素的alpha),而不是下一个块的起始位置!
可能我忽略了Deflate块的结构。我是很傻很天真,还是我误解了规格?