2

我目前正在研究 LZW 压缩的 java 实现。到目前为止,我的编码器工作正常。读取文件并输出将通过管道传送到位打包器的短语编号。

我现在必须将这些短语编号打包到一个文件中,我不确定如何进行此过程。此外,我们为编码设置的最大位为 20。因此,当编码的数字超过编码所需的 20 位时,我们重置特里树并开始构建新的特里树。

所以我们必须打包的第一组数字将是 0-255,然后是 256-511,依此类推,所以我知道有些将被打包为 8 位,然后是 9 位,依此类推。

如果可以就从哪里开始以及查看哪些内容提供任何指导,我们将不胜感激

4

1 回答 1

3

LZW 压缩通常从比符号大小高一的位数开始。因此,如果符号是 8 位值,则初始位大小通常为 9。这对于字面值 0..255 和字典中的前 256 个代码来说已经足够了。通常 LZW 也有一些特殊的预定义代码,例如“清除”代码和“停止”代码,它们作为符号 0x100 和 0x101 附加到符号集。它们不是严格要求的,但非常有用。

此外,您有一个最大位数来限制字典的增长。在您的情况下,它是 20,因此您的字典最多可以容纳 1048576 个条目。要编写可变长度的位代码,您需要使用一个足够宽以容纳最大位计数的寄存器。在您的情况下,32 位或 64 位无符号整数是合适的。(如果您的目标是 64 位处理器,请使用后者。)因此,基本上,您维护一个移位计数器,最初设置为 0,并将位移位/写入寄存器直到它溢出。然后将整个寄存器写入流并移位/复制剩余的位。最后,您必须将寄存器中的最新位刷新到流中(如果有)。

这真的很容易。您不需要任何特殊的位计数处理,因为 LZW 读取器和写入器已就何时增加位计数达成一致。一些 LZW 实现,例如 TIFF 6.0,会在编写适合旧大小的最后一个代码之前增加计数(所谓的“早期更改”)。其他人(例如 GIF)在 AFTERWARDS 之后增加它,这样效率更高。您可以自由选择所写符号的位顺序。只需要编码器和解码器就这一点达成一致。再一次,现有的 LZW 实现使用不同的位顺序:GIF 将它们从最低有效写入最高有效,TIFF 6.0 则相反。LSB-to-MSB 变体通常更容易实现。

请注意,一个常见的误解是字典满了就需要清除。实际上,我发现 LZW 压缩在大多数情况下要好得多,如果你继续填充目录,直到最后发出最大宽度的代码。这是因为字典现在反映了输入流的统计分布并发出有效的代码。仅当分布随时间发生显着变化时才需要清除,因此字典变得不充分。

GIF和TIFF的常见LZW解码器经常在字典填满后自动清除字典,而不是等待清除代码。这是“坏习惯”,甚至在最新的 GIF 规范随附的注释中明确弃用,但可惜的是,如果编码器想要与所有阅读器兼容,它不应该用清晰的代码赌博。

于 2017-08-04T13:50:58.087 回答