手工制作的PNG文件的问题

问题描述 投票:0回答:1

我已经尝试“从头开始”创建一个 PNG 文件一段时间了,也就是说,逐字节操作数据字节以创建一个可行的文件。

在我的探索过程中,我遇到了一个奇怪的错误,每当原始像素数据以及过滤器类型字节达到256的长度时,图像无法渲染并且所有像素都变成黑色。只是为了澄清这一点似乎不会发生在其他尺寸上,我已经成功地“手工”创建了图像。

这里是图像颜色编码的十六进制数据,用于可视化不同的块: 十六进制数据

为了让我们达成共识,我将为每个块的内容写一个解释。

PNG 初始字节

  • 0x89 0x50 0x4e 0x47 0x0d 0x0a 0x1a 0x0a 这些字节必须位于 PNG 文件的开头才能识别它。

IHDR 块

  • 0x00 0x00 0x00 0x0d 这些字节的值是块的数据部分中包含的数据的长度。
  • 0x49 0x48 0x44 0x52 这些字节是 IHDR 块的标识符。
  • 0x00 0x00 0x00 0xff 这些字节的值是以像素为单位的图像的宽度 (255)。
  • 0x00 0x00 0x00 0x01 这些字节的值是图像的高度(以像素 (1) 为单位)。
  • 0x08 该字节的值是像素中存在的每个颜色通道的位深度(8 位)。
  • 0x00 该字节表示图像的颜色类型,在本例中是一个简单的单通道,灰度
  • 0x00 该字节代表图像的压缩方法0x00是唯一可能的值。
  • 0x00 该字节代表图像的滤镜方法0x00是唯一可能的值。
  • 0x00 该字节表示隔行方式,值为 0x00 表示不隔行。
  • 0x34 0xfb 0x27 0x7f 这些字节是从标识符开头到此处的字节的 CRC-32 值。

IDAT 块

  • 0x00 0x00 0x01 0x0b 这些字节的值是块的数据部分包含的数据的长度。
  • 0x49 0x44 0x41 0x54 这些字节是 IDAT 块的标识符。
  • 0x08这个字节代表zLib压缩数据格式的CMF,指定这里,我用的是256的滑动窗口。
  • 0x1d这个字节代表指定的zLib压缩数据格式的FLG这里,我使用的FLEVEL为0,没有FDICT。
  • 0x80 该字节表示这是最后一个要处理的压缩数据块,因为它是唯一的一个,并且未应用压缩
  • 0x01 0x00这些字节的值是压缩数据256)过滤器类型字节+原始像素数据的长度。
  • 0xfe 0xff 这些字节是前一个字节的否定。
  • 0x00 该字节表示用于该扫描线的过滤器type0x00表示无过滤器
  • 0xff到地址末尾00000120我们有实际的像素数据,因为位深度是8并且颜色类型是灰度每个0xff是一个白色像素。
  • 0x08 0xf1 0xfe 0x02 这些字节是从地址 00000030 开头到地址 00000120 结尾的字节的 ADLER-32 值。
  • 0x33 0xed 0xdb 0x91 这些字节是从标识符开头到此处的十六进制的 CRC-32 值。

IEND 块

  • 0x00 0x00 0x00 0x00 这些字节的值是块的数据部分中包含的数据的长度。 IEND 块中没有数据。
  • 0x49 0x45 0x4e 0x44 这些字节是 IEND 块的标识符。
  • 0xae 0x42 0x60 0x82 这些字节是标识符字节的 CRC-32 值,因为没有数据。

我尝试更改颜色类型和位深度,但只要压缩(实际上未压缩)数据的总和达到 256,文件就无法正确渲染,只是将每个像素替换为黑色像素。我尝试了所有可能的窗口,从 256 到 32768,但没有任何变化。

也许我需要包含一些辅助块,例如 sRGB,即使很难,我也不知道为什么这会有帮助。

hex png zlib
1个回答
0
投票

0x80 这个字节代表这是最后一次压缩的事实 要处理的数据块

不,事实并非如此。放气位从底部开始,而不是顶部。要执行您所描述的操作,该字节需要是

0x01

我已经成功“手工”创建了图像。

请注意,图像渲染并不意味着 PNG 文件是正确的。尝试显示 PNG 图像的软件可以选择相当自由地接受错误输入。

© www.soinside.com 2019 - 2024. All rights reserved.