【问题标题】:DEFLATE: how to handle "no distance codes" case?DEFLATE:如何处理“没有距离代码”的情况?
【发布时间】:2021-10-10 13:44:32
【问题描述】:

我主要获得 RFC 1951,但是我不太清楚如何管理(使用动态霍夫曼表时)不需要或不存在距离代码的情况。例如,让我们输入:

abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890987654321ZYXWVUTSR

因为没有长度 >= 3 的重复,所以不可能有反向引用。 根据 RFC 1951,无论如何都必须存在至少一个距离代码,否则将无法对 HDIST - 1 进行编码。根据参考资料,我理解这样的代码应该是零位以表示“没有距离代码” ”。

一个零位的距离码表示没有距离码 完全使用(数据都是文字)。

在 infgen 符号中,我希望看到 dist 0 0

分析 gzip 对 infgen 的作用,但是,我看到为上述输入发出了两个距离代码(每个 1 位长)(即使当时没有实际使用):

! infgen 2.4 output
!
gzip
!
last
dynamic
litlen 48 6
litlen 49 6
litlen 50 6
...cut...
litlen 121 6
litlen 122 6
litlen 256 6
dist 0 1
dist 1 1
literal 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890987654321Z
literal 'YXWVUTSR
end
!
crc
length

那么在这些情况下正确的行为是什么?

【问题讨论】:

    标签: gzip huffman-code deflate


    【解决方案1】:

    如果 deflate 块中没有匹配项,则长度/文字代码中将没有长度,因此解码器将永远不会寻找距离代码。在这种情况下,最有意义的是根本不提供有关距离代码的信息。

    但是格式不允许这样做,因为标头中的 5 位 HDIST 值被解释为 1 到 32 个距离代码,必须在标头中提供长度。您必须在标头中提供至少一个距离码长度,即使它永远不会被使用。

    在这种情况下,您可以做几件有效的事情。 RFC 1951 指出,您可以提供一个长度为零的距离代码(HDIST == 0,表示一个长度),即长度列表中的一个零。

    还允许提供一个长度为 1 的代码,或者您可以像 zlib 一样提供两个长度为 1 的代码。您实际上可以将任何您喜欢的有效距离代码描述放在那里,它仍然会被接受。

    至于为什么 zlib 的 deflate 选择在那里定义两个代码,我只能猜测 Jean-loup 是保守的,写了一些他知道即使是过度简化的充气机也不得不接受的东西。 gzip 和 zopfli 都做同样的事情。当只使用一个距离代码时,它们都做同样的事情。根据 RFC,它们可以仅发出单个一位距离代码,但它们会发出两个单位距离代码,其中一个从未使用过。

    真正正确的做法是编写 RFC 中所述的单个零长度,这将占用标头中的最少位数。我会考虑更新 zlib 来做到这一点,以进行更多的压缩。

    【讨论】:

    • 注意:在 Zopfli 的 deflate.c 中,它是在 PatchDistanceCodesForBuggyDecoders 函数中完成的...
    猜你喜欢
    • 2023-03-04
    • 1970-01-01
    • 2012-03-21
    • 2020-11-06
    • 1970-01-01
    • 2016-07-11
    • 2016-04-29
    • 2017-04-02
    • 2020-04-07
    相关资源
    最近更新 更多