You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

从零构建PNG:如何将扫描线数据转为无压缩zlib流?

嘿,我来帮你理清楚手动构建无压缩zlib流的字节逻辑——其实拆解开来一点都不复杂,咱们一步步来:

核心逻辑铺垫

首先得明确:zlib流本质是对deflate压缩数据的封装,而你要的“无压缩”,对应deflate里的STORED块(完全不压缩的原始数据块)。所以整个zlib流由三部分组成:zlib头部 + deflate STORED块 + ADLER32校验码。


第一步:构造zlib头部(固定2字节)

头部由CMF和FLG两个字节组成,规则如下:

  • CMF(第一个字节):高4位固定为8(表示使用deflate压缩方法,这是zlib唯一标准的压缩方式);低4位是CINFO(窗口大小参数),对于无压缩的STORED块来说,随便选一个合法值就行,比如设为0,所以CMF最终是0x80(二进制10000000)。
  • FLG(第二个字节):必须满足 CMF * 256 + FLG 的结果是31的倍数(这是zlib的校验规则)。以CMF=0x80为例,计算得FLG需要是0x1E(因为0x80*256 + 0x1E = 32798,刚好能被31整除)。

第二步:构造deflate STORED块(无压缩数据块)

STORED块是用来直接存放原始扫描线数据的,结构分四部分:

  1. 块头(1字节):
    • 最低位(第0位)设为1(标记这是最后一个块,PNG的IDAT通常只需要一个块);
    • 第1-2位设为00(表示这是STORED无压缩块);
    • 所以块头最终是0x01。
  2. LEN(2字节):你的扫描线数据的总字节数,用小端字节序存储。比如数据长度是100字节,就写0x64 0x00。
  3. NLEN(2字节):LEN的按位取反值,同样用小端字节序存储。比如LEN=100(0x64),取反后低2字节是0x9C 0xFF。
  4. 原始数据:直接拼接你的扫描线数据(注意PNG扫描线每行开头有个过滤字节,通常是0,这个你应该已经处理好了)。

第三步:添加ADLER32校验码(固定4字节)

zlib流的最后,需要计算整个deflate块(也就是块头+LEN+NLEN+扫描线数据)的ADLER32校验值,用大端字节序拼在末尾。

如果你不想手动计算ADLER32,可以找现成的在线工具,或者参考zlib库的adler32函数实现。


拼接起来就是完整的zlib流

把上面三部分按顺序拼接:
zlib头部(0x80 0x1E) + STORED块 + ADLER32校验码

举个极简例子:假设你的扫描线数据是0x00 0x01 0x02(3字节),最终的zlib流大概是:
0x80 0x1E 0x01 0x03 0x00 0xFC 0xFF 0x00 0x01 0x02 [ADLER32值]

最后可以用zlib的uncompress函数测试一下,看能不能正确解压出你的原始扫描线数据,验证是否正确。

内容的提问来源于stack exchange,提问作者StephenKhoa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 08:00:14