为什么忽略PNG deflate-block长度?

时间:2015-09-17 14:54:10

标签: compression png zlib libpng deflate

摘要:我需要一位PNG作家,出于各种原因,我必须从头开始。我不需要压缩图像数据,因此我使用无压缩deflate算法实现了PNG。对于需要多个放气块的图像,渲染失败,似乎是因为它忽略了块长度。

问题当我使用单个放气块写入一个小图像时,生成的图像正是它应该是的(所有像素都正确,使用{{3}检查时没有错误})。但是,一旦我使用多个deflate块,结果图像就会出错,因为正在读取deflate块超过它们的长度(尽管pngcheck仍然没有显示错误)。在十六进制编辑器中查看原始数据似乎表明一切都符合规范(根据pngcheck,RFC 1950和RFC 1951)。

示例数据:我生成了一个3x1 RGBA图像,其中像素颜色从左到右依次为(fb,02,03,fa)(01,fc,03,fa)(01,02,fd,fa)。然后我将它们写入文件,最大压缩块长度为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 08 ff f7 00 fb 02 03 fa 01 fc 03 01 00 05 {{ 1}} fa 01 02 fd fa ff fa

64字节块图像(正确渲染):
05 ee ac ee a1 e1 2d b9 00 00 00 00 49 45 4e 44 ae 42 60 82 00 0 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 fb 02 03 fa 01 fc 03 fa 01 02 fd fa ff f2

每个deflate块的开头由5个字节组成:0或1(取决于它是否是最后一个块)后跟2字节长度(上面用粗体表示)和2字节1&#39补充。在8字节块图像中,第一个块的长度是8,正如它应该的那样。长度补码后的8个字节(上面的斜体)确实是它们应该是的值,第9个字节等于1(并开始最后的块)。但是,1被解释为颜色值(第二个像素的alpha)而不是下一个块的开始!

据推测,我有一些关于放气块结构的遗漏。我是愚蠢而犯了错误,还是我误解了这些规格?

1 个答案:

答案 0 :(得分:5)

两个PNG文件都无效,即使有人正确渲染(即使pngcheck没有捕获它)。它们都没有正确终止嵌入的放气流。

查看其中一个deflate流,存储的长度和补充是big-endian而不是little endian。例如。而不是0d 00 f2 ff,它必须是vi file1 xxx xxxxxxxxx xxxxxxxxxx xxxxxxxxxx O48 8.80620265 3.13576702 16.73758145 O49 2.11414472 0.47922554 23.80825532 H1 1.09354199 0.56015908 23.18883965 H2 1.84841487 0.60605486 24.87784867 O50 6.45693524 0.12577435 26.20766069 H3 5.43633251 0.20670789 25.58824502 H4 6.19120539 0.25260367 27.27725405 O51 3.85207272 4.89778259 29.52091127 H5 2.83146999 4.97871613 28.90149560 H6 3.58634288 5.02461191 30.59050463 xx xxxxxxxxx xxxxxxxxx xxxxxxxxx