为什么忽略 PNG 放气块长度?

Why are PNG deflate-block lengths being ignored?

总结:我需要一个 PNG 编写器,但出于各种原因我不得不从头开始制作它。我不需要压缩图像数据,所以我使用无压缩 deflate 算法实现了 PNG。需要多个压缩块的图像渲染失败,似乎是因为它忽略了块长度。

问题: 当我用一个 deflate 块写入一个小图像时,生成的图像正是它应该的样子(所有像素正确,检查时没有错误使用 pngcheck). However, as soon as I use multiple deflate blocks the resulting image is wrong because deflate blocks are being read past their lengths (though pngcheck still shows no errors). Looking at the raw data in a hex editor seems to show that everything is to spec (according to libpng、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 0000 08ff f700 fb 02 03 fa 01 fc 0301 00 05ff fafa 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 0100 0dff f200 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 块的结构我遗漏了一些东西。是我太笨而犯了错误,还是我误解了规格?

两个 PNG 文件都是无效的,即使其中一个文件恰好正确呈现(即使 pngcheck 没有捕捉到它)。它们都没有正确终止嵌入式压缩流。

查看其中一个 deflate 流,存储的长度和补码是大端而不是小端。例如。而不是 00 0d ff f2 它需要 0d 00 f2 ff.