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

bsc*_*dam 3 compression png zlib deflate libpng

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

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

实施例的数据:我生成一个3×1 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 08 ff f700 fb 02 03 fa 01 fc 03 0100 05 ff 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 0d ff 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字节1的补码.在8字节块图像中,第一个块的长度是8,正如它应该的那样.长度补码后的8个字节(上面的斜体)确实是它们应该是的值,第9个字节等于1(并开始最后的块).但是,1被解释为颜色值(第二个像素的alpha)而不是下一个块的开头!

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

Mar*_*ler 5

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

查看其中一个放气流,存储的长度和补充是big-endian而不是little endian.例如,而不是00 0d ff f2它需要0d 00 f2 ff.

  • 是的,这是问题的字节顺序和坏校验和的组合.还意识到你是_that_ Mark Adler.现在我为实现那个简单的校验和算法的破碎版本而感到非常尴尬...... (2认同)