我一直在研究RFC1951和'puff.c',并且对“长度不完整”的问题有疑问。
我可以说,定义一个“动态”霍夫曼代码表允许比HLIT + 257指定的更多代码将产生错误,至少通过puff.c.例如,如果作为一个简单的调试测试,我使用所有9位代码的霍夫曼表来定义仅257亮/镜头,则'puff.c'会产生错误。这个结果是有目的的还是一个错误?我可以假设任何基于'zlib'库的“充气机”都会产生同样的错误吗?
我在RFC 1951中找不到任何要求使用足够紧密的霍夫曼代码的规范。当然,我可以看到,在压缩方面,使用“订阅不足”的Huffman表可能效率低下,但我不确定为什么禁止使用这样的表。
我的兴趣不仅仅是假设。我真的想使用欠订阅的,仅文字的霍夫曼代码(但不是上面引用的例子)将一些特定应用程序的图像压缩成PNG文件。但我想确保它适用于任何PNG图像查看器。
答案 0 :(得分:0)
RFC指定代码是霍夫曼代码,根据定义,代码是完整代码。 (完成意味着使用所有位模式。)
除了RFC中提到的特殊情况外,zlib将拒绝不完整或超额认购的代码:
如果仅使用一个距离代码,则使用一位编码,而不是 零位;在这种情况下,只有一个代码长度为1 未使用的代码。
允许单个符号的不完整代码0,代码1未使用。
(顺便说一句,那是不必要的。如果只有一个距离符号,那么你就不需要任何位来指定它。你知道那个距离符号必须使用任何长度。如果是这样的话。符号需要额外的比特,然后那些额外的比特紧跟着长度。但是,哦,好吧 - 对于那种情况,Phil Katz在每场比赛中都放了一个无关的零位,现在我们已经坚持了。)
RFC甚至必须注意这一特殊情况这一事实是另一条线索,否则不接受不完整的代码。
deflate有另一种例外,因为固定的文字/长度代码不完整,最后有两个未使用的代码。
底线是,不,您将无法在动态标头中使用不完整的代码(特殊情况除外),并期望zlib或任何兼容的deflate解码器能够解码它。
至于为什么这种严格性是有用的,对动态标题的约束允许快速检测非放气流或损坏的放气流。类似地,zlib不允许没有结束代码的动态头,以避免伪动态头允许任何后续随机位永远可解码的情况,从不检测错误。未使用的固定代码在这方面也有帮助,因为它们最终会在随机输入中触发错误。
顺便说一句,如果你想为你的情况定义一个固定的,完整的霍夫曼代码,那么它非常简单,并且会将几乎所有代码的大小减少一位。只需为符号0..253编码8位,使用该符号编号直接作为代码(当然反转位),使用代码508..511(反转位)使用符号254..257的9位。