DEFLATE (RFC1951) 动态哈夫曼 "incomplete length"

DEFLATE (RFC1951) dynamic huffman "incomplete length"

一直在研究RFC1951和'puff.c',对"incomplete length"的问题有疑问。

据我所知,定义一个 "dynamic" 霍夫曼代码 table 允许比 HLIT+257 指定的代码更多的代码将产生错误,至少 puff.c 是这样。例如,如果作为简单的调试测试,我将使用所有 9 位代码的 Huffman table 来仅定义 257 lit/lens,那么 'puff.c' 就会产生错误。这个结果是有目的的还是错误?我可以假设任何基于 'zlib' 库的 "inflator" 都会产生相同的错误吗?

我在 RFC 1951 中找不到任何规范要求使用足够严格的霍夫曼代码。当然,我可以看到使用 "under-subscribed" Huffman table 在压缩方面可能效率低下,但我不确定为什么要禁止使用这样的 table。

我的兴趣不仅仅是假设。我真的很想使用一个订阅不足的、纯文字的霍夫曼代码(但不是上面引用的例子)来将一些特定于应用程序的图像压缩到 PNG 文件中。但我想确保它适用于任何 PNG 图片查看器。

RFC 指定代码是霍夫曼代码,根据定义是完整代码。 (完整意味着使用了所有位模式。)

zlib 将拒绝不完整或超额订阅的代码,RFC 中注明的特殊情况除外:

If only one distance code is used, it is encoded using one bit, not zero bits; in this case there is a single code length of one, with one unused code.

允许单个符号的不完整代码0,代码1未使用。

(顺便说一句,这是不必要的。如果只有一个距离符号,那么你不需要任何位来指定它。你知道那个距离符号必须与任何长度一起使用。如果那个符号需要额外的位,然后那些额外的位紧跟在长度之后。但是,哦,好吧——对于这种情况,Phil Katz 在每个匹配项中都放置了一个无关的零位,现在我们坚持使用它。)

RFC 甚至必须注意这种特殊情况的事实是不接受不完整代码的另一个线索。

deflate 中还有一个例外,固定的 literal/length 代码不完整,最后有两个未使用的代码。

最重要的是,不,您将无法在动态 header 中使用不完整的代码(特殊情况除外)并期望 zlib 或任何兼容的 deflate 解码器能够解码它。

至于为什么这种严格性有用,对动态 header 的约束允许快速检测 non-deflate 流或损坏的 deflate 流。类似地,zlib 不允许没有结束代码的动态 header,以避免出现伪动态 header 允许任何后续随机位永远可解码,永远不会检测到错误的情况。未使用的固定代码在这方面也有帮助,因为它们最终会触发随机输入错误。

顺便说一句,如果你想为你的案例定义一个固定的、完整的霍夫曼代码,那非常简单,并且可以将你几乎所有代码的大小减少一位。只需为符号 0..253 编码八位,直接使用该符号编号作为代码(当然反转位),并使用代码 508..511(反转位)为符号 254..257 编码九位。