【问题标题】:LZW compression/decompression under low memory conditions低内存条件下的LZW压缩/解压
【发布时间】:2010-07-08 12:05:20
【问题描述】:

谁能指点我如何在低内存条件下(

【问题讨论】:

  • 环境是什么?
  • 嗯,我需要把这段代码放在一个适当的低端手机中......
  • 我更新了您的标签以添加embedded,这样您就可以接触到使用受限资源(如
  • 约束是瞬态内存使用还是输入/输出大小?

标签: c algorithm embedded compression lzw


【解决方案1】:

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

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

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

如果您发现更好的东西,请在此处发布或通过 stackoverflow 联系我,我也对其他嵌入式解决方案非常感兴趣。我搜索了很多,上面是我发现的唯一有用的一个,我很幸运,我的数据使用该算法压缩得足够好......暂时。

【讨论】:

【解决方案2】:

谁能指点我如何在低内存条件下(

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

我已经非常很久没有接触编码了,但是 IIRC Huffman coding 在内存消耗方面要好一些。

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

【讨论】:

    【解决方案3】:

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

    【讨论】:

      【解决方案4】:

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

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

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

      最大的优点是它是公共领域,因此您可以随心所欲地使用它!

      【讨论】:

        【解决方案5】:

        距离我上一次使用 LZW 压缩算法已经 15 年多了,所以请对以下内容持保留态度。

        考虑到内存限制,这充其量是很困难的。您构建的字典将消耗您可用的绝大多数内容。 (假设代码 + 内存

        为您的字典选择一个小的固定尺寸。说 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 字节的代码可供使用。当然,您可以随意调整字典大小,看看什么对您有好处,但您的代码最终不会有太多空间。由于您看到的代码空间如此之小,我希望您最终会在汇编中进行编码。

        我希望这会有所帮助。

        【讨论】:

        • 是否可以丢弃字典并重新解析以在每次查找时从源中获取所需的条目?当然这会非常慢,但它可能是唯一的方法。
        • @R..:我不这么认为。字典是 en/decoder 的状态。编码流中的位是字典的索引。
        【解决方案6】:

        我最好的建议是检查 BusyBox 源代码,看看他们的 LZW 实现是否足够小,可以在您的环境中工作。

        【讨论】:

        • 可能不是 -- BusyBox 是为资源多得多的系统设计的。
        • 您是否检查过,而不仅仅是说“可能没有”。 BusyBox 中的几乎所有算法都是开发人员能够找到/创建的最小的(无论是代码大小还是工作空间),但通常以牺牲良好的性能为代价。如果性能太差,通常有一个编译时选项可以在性能糟糕的小尺寸和中等尺寸/性能之间进行选择。
        • @tomlogic:我过去见过的大多数 LZW 实现都将字典(主内存)的大小作为编译时定义。值得检查。字典 IIRC 的最小大小为 257+1。但这相当于完​​全没有压缩。
        【解决方案7】:

        lzw 的最低字典是trie onlinked list。请参阅LZW AB 中的原始实现。我已经用 fork LZWS 重写了它。 Fork 与compress 兼容。详细文档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 版本来压缩你的数据。但它不会提供良好的压缩比。你有更多的比特 - 比率更好。

        【讨论】:

          【解决方案8】:
          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);
          

          【讨论】:

          • -1 这应该如何回答这个问题?图书馆的描述或链接在哪里。或有关尺寸或其他信息的信息
          猜你喜欢
          • 2021-02-09
          • 2022-08-18
          • 1970-01-01
          • 2012-10-24
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多