低内存条件下的LZW压缩/解压缩

时间:2010-07-08 12:05:21

标签: c algorithm embedded compression lzw

任何人都可以指出如何在低内存条件下(< 2k)实现lzw压缩/解压缩。那可能吗?

8 个答案:

答案 0 :(得分:4)

每个人都使用的zlib库在其他问题(对于嵌入式)中臃肿。我很确定它不适合你的情况。我有更多的记忆可能16K并且无法让它适合。它分配和存储大块内存并保存内容的副本等。算法可以做到这一点,但找到现有代码是挑战。

我选择http://lzfx.googlecode.com解压缩循环很小,它是较旧的lz类型压缩依赖于先前的结果,因此您需要访问未压缩的结果...下一个字节是0x5,下一个字节是0x23,接下来的15个字节是15个200字节前的副本,接下来的6个字节是127个前面的副本...较新的lz算法是可变宽度表,可以大或增长取决于如何实施。

我正在处理重复数据并尝试将几K压缩到几百,我认为压缩率约为50%,不是很好,但是工作和减压程序很小。上面的lzfx包很小,不像zlib,就像两个主要函数那样有代码,而不是几十个文件。您可能可能会更改缓冲区的深度,如果您愿意,可能会改进压缩算法。我确实必须修改解压缩代码(可能是20或30行代码)它指针很重,我把它切换到数组,因为在我的嵌入式环境中,指针位于错误的位置。 Burns可能是一个额外的寄存器,取决于你如何实现它和你的编译器。我也这样做,所以我可以抽取字节的提取和存储,因为我将它们打包到不能字节寻址的内存中。

如果你发现更好的东西请在这里发布或通过stackoverflow ping我,我也对其他嵌入式解决方案很感兴趣。我搜索了很多,上面是我发现的唯一有用的,我很幸运,我的数据是这样的,使用该算法压缩得足够好......现在。

答案 1 :(得分:3)

  

任何人都可以指出如何在低内存条件下(< 2k)实现lzw压缩/解压缩。那可能吗?

为什么选择LZW? LZW需要大量内存。它基于哈希/字典,压缩比与哈希/字典大小成正比。更多内存 - 更好的压缩。内存减少 - 输出甚至可能大于输入。

我没有长时间触及非常的编码,但IIRC Huffman coding在内存消耗方面稍微好一些。

但这一切都取决于你想要压缩的信息类型。

答案 2 :(得分:3)

我使用过LZSS。我使用code中的Haruhiko Okumura作为基础。它使用未压缩数据的最后部分(2K)作为字典。如果您在内存中拥有所有未压缩的数据,则可以修改我链接的代码以使用几乎没有内存。通过一些谷歌搜索,你会发现很多不同的实现。

答案 3 :(得分:2)

如果压缩算法的选择不是一成不变的,您可以尝试使用gzip / LZ77。这是我使用和修改过的一个非常简单的实现:

ftp://quatramaran.ens.fr/pub/madore/misc/myunzip.c

你需要清理它读取输入,错误处理等的方式,但这是一个好的开始。如果您的数据和代码需要适合2k,那么它可能也太大了,但至少数据大小已经很小。

大加是它是公共领域,所以你可以随意使用它!

答案 4 :(得分:1)

自从我上次使用LZW压缩算法以来已经超过15年了,所以请注意以下几点。

考虑到内存限制,这将是最困难的。您构建的字典将消耗您可用的绝大部分内容。 (假设代码+内存< = 2k。)

为您的字典选择一个小的固定大小。说1024个条目。

让每个字典条目采用....的形式。

 struct entry {
    intType   prevIdx;
    charType  newChar;
 };

这种结构使字典递归。您需要先前索引处的项目有效才能使其正常工作。这可行吗?我不确定。但是,让我们暂时考虑它是什么,并找出它引导我们的地方....

如果对int和char使用标准类型,则会快速耗尽内存。你会希望尽可能紧密地把东西打包在一起。 1024个条目将需要10位来存储。你的新角色可能需要8位。总计= 18位。

18位* 1024个条目= 18432位或2304个字节。

乍一看,这看起来太大了。我们做什么?利用前256个条目已知的事实 - 典型的扩展ascii集或者你有什么。这意味着我们确实需要768个条目。

768 * 18位= 13824位或1728字节。

这使您可以使用大约320个字节来代码。当然,您可以使用字典大小来查看对您有用的内容,但是您的代码不会占用很多空间。由于您正在寻找如此少的代码空间,我希望您最终会在汇编中进行编码。

我希望这会有所帮助。

答案 5 :(得分:0)

我最好的建议是检查BusyBox来源,看看他们的LZW实施是否足够小,无法在您的环境中使用。

答案 6 :(得分:0)

lzw的最低词典为链表上的尝试。请参见LZW AB中的原始实现。我已经用叉子LZWS重写了它。叉子与ncompress兼容。详细文档here

n位字典需要(2 ** n) * sizeof(code) + ((2 ** n) - 257) * sizeof(code) + (2 ** n) - 257

所以:

  1. 9位代码- 1789 个字节。
  2. 12位代码- 19709 个字节。
  3. 16位代码- 326909 个字节。

请注意,这是字典的要求。堆栈中的状态或变量大约需要100-150个字节。

解压缩器将比压缩器使用更少的内存。

因此,我认为您可以尝试使用9 bit版本压缩数据。但是它不会提供良好的压缩率。您拥有的位数更多-比率更好。

答案 7 :(得分:-3)

typedef   unsigned int     UINT;
typedef   unsigned char    BYTE;

BYTE *lzw_encode(BYTE *input ,BYTE *output, long filesize, long &totalsize);
BYTE *lzw_decode(BYTE *input ,BYTE *output, long filesize, long &totalsize);