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

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

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

如果可以就从何处开始以及如何看待给出任何指导,将不胜感激。

最佳答案

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

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

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

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

用于GIF和TIFF的常见LZW解码器经常在字典填满后立即自动清除它,而不必等待清除代码。这是“坏习惯”,甚至在最新的GIF规范随附的注释中也已弃用,但是可惜,如果编码器希望与所有读者兼容,那么它就不应该赌清楚的代码,这很常见。

关于java - 位打包LZW短语编号,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/23189391/

10-11 03:26