将 png 扫描线图像数据不压缩地放入 zlib 流?

Put png scanlines image data to zlib stream with no compressing?

我正在从头开始制作一个简单的 png 图像。我有它的扫描线数据。现在我想把它变成 zlib 流而不被压缩。我怎样才能做到这一点?我已阅读“https://www.ietf.org/rfc/rfc1950.txt”处的 "ZLIB Compressed Data Format Specification version 3.3",但仍不理解。有人可以给我一些关于在 zlib 流中设置字节的提示吗?

提前致谢!

如RFC1950中所述,压缩算法的细节在另一个castle RFC中有描述:DEFLATE Compressed Data Format Specification version 1.3 (RFC1951).

我们找到了

  3.2.3. Details of block format

     Each block of compressed data begins with 3 header bits
     containing the following data:

        first bit       BFINAL
        next 2 bits     BTYPE

     Note that the header bits do not necessarily begin on a byte
     boundary, since a block does not necessarily occupy an integral
     number of bytes.

     BFINAL is set if and only if this is the last block of the data
     set.

     BTYPE specifies how the data are compressed, as follows:

        00 - no compression
        [... a few other types]

这是你想要的。这 2 位 BTYPE 与最后一个块标记 BFINAL 相结合,就是您编写 "uncompressed" zlib 兼容数据所需的全部内容:

  3.2.4. Non-compressed blocks (BTYPE=00)

     Any bits of input up to the next byte boundary are ignored.
     The rest of the block consists of the following information:

          0   1   2   3   4...
        +---+---+---+---+================================+
        |  LEN  | NLEN  |... LEN bytes of literal data...|
        +---+---+---+---+================================+

     LEN is the number of data bytes in the block.  NLEN is the
     one's complement of LEN.

所以,伪算法是:

  1. 将前 2 个字节设置为 78 9c ("default compression")。
  2. 对于每个不超过 32768 字节的块ᵃ
    1. 如果是最后一块,写01,否则写00
    2. ...写[<em>块长度</em>][COMP(<em>块长度)</em>]
    3. ...写入立即数
  3. 重复直到写入所有数据。

不要忘记在压缩数据的末尾添加 Adler-32 校验和,以 big-endian 顺序,在 'compressing' 之后这样。 Adler-32校验和用于验证未压缩的原始数据。在 PNG 图像的情况下,该数据已经由其 PNG 过滤器处理并附加了行过滤器字节 - that 是 "the" 被此 FLATE 压缩的数据-兼容算法。


ᵃ 这个是我当时正好方便的一个值;写入大至 65535 字节的块应该是安全的(只是不要尝试 跨越 那条线)。

ᵇ 都是先低字节后高字节的字。简介里简单提到了。