【问题标题】:How to get LZW encode results as from example?如何从示例中获取 LZW 编码结果?
【发布时间】:2020-01-27 14:07:32
【问题描述】:

鉴于http://michael.dipperstein.com/lzw/#example1 页面上 example1 的输入,我无法得到正确的结果:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "lzw.h"

void print_hex(unsigned char str[], int len) 
{
    int idx;

    for (idx = 0; idx < len; idx++)
        printf("%02x", str[idx]);
}

int main()
{
    FILE *fpIn;             /* pointer to open input file */
    FILE *fpOut;            /* pointer to open output file */
    FILE *fptr;

    char test_str_lzw[] = { "this_is_his_thing" };
    fptr = fopen("lzw_in_test.txt", "wb");
    fwrite(test_str_lzw, sizeof(char), strlen(test_str_lzw), fptr);
    fclose(fptr);

    fpIn = fopen("lzw_in_test.txt", "rb");
    fpOut = fopen("lzw_out.txt", "wb");

    LZWEncodeFile(fpIn, fpOut);

    fclose(fpIn);
    fclose(fpOut);

    // Getting the results from file
    if ((fptr = fopen("lzw_out.txt", "rb")) == NULL) {
        printf("Error! opening file");
        // Program exits if file pointer returns NULL.
        exit(1);
    }

    unsigned char lzw_out[256];
    memset(lzw_out, 0, 256);

    size_t num;
    num = fread(lzw_out, sizeof(unsigned char), 256, fptr);


    fclose(fptr);

    unsigned int lzw_size = num;
    printf("LZW out size: %d\n", lzw_size);
    printf("LZW out data: \n");
    print_hex(lzw_out, lzw_size);
    printf("\n");

    return(0);
}

十六进制的预期结果:

0x74 0x68 0x69 0x73 0x5F 0x102 0x5F 0x101 0x103 0x100 0x69 0x6E 0x67

我得到十六进制的结果:

0x74 0x34 0x1A 0x4E 0x65 0xF0 0x15 0x7C 0x03 0x03 0x80 0x5A 0x4D 0xC6 0x70 0x20

谁能帮我获取示例中的输出文件?

问候。

【问题讨论】:

  • 请在您的问题中包含您想要的结果和您得到的结果(或完整的错误消息)。此外,LZWEncodeFile 未定义。谢谢!
  • @mzuther 我已经编辑了我的问题,我已经添加了 lzw.h 包含所以现在 LZWEncodeFile 已定义。我还添加了预期的和我想要的结果。谢谢。
  • @Embedded Aside:sizeof(test_str_lzw) 的大小为 18。strlen(test_str_lzw) 的长度为 17。您要压缩多少 字符串
  • 发布如何从代码中查看结果。 “我得到的十六进制结果”是正确的位流,而不是正确的包装。 (注意 9 位在预期与 8 位在看到)发布minimal reproducible example
  • @chux-ReinstateMonica 我已经编辑了问题,所以现在您可以看到最小的可重现示例以及我如何显示数据。

标签: c compression lzw


【解决方案1】:

LZW 编码器将 9 位代码字序列编码为 8 位字节序列。有一种机制可以根据需要发出增加码字长度的信号,但为了简单起见,我们忽略它,因为它不是编码短输入序列所必需的。

对于 OP 的例子,前八个 9 位代码字是(十六进制):

0x74 0x68 0x69 0x73 0x5F 0x102 0x5F 0x101

或用二进制表示:

001110100 001101000 001101001 001110011 001011111 100000010 001011111 100000001

编码器将每个 9 位码字分成两组 - 位 7 到 0,然后是位 8:

01110100 0 01101000 0 01101001 0 01110011 0 01011111 0 00000010 1 01011111 0 00000001 1

然后将其重新组合为 8 位字节序列:

01110100 00110100 00011010 01001110 01100101 11110000 00010101 01111100 00000011

或以十六进制表示:

0x74 0x34 0x1A 0x4E 0x65 0xF0 0x15 0x7C 0x03

【讨论】:

  • 谢谢@Ian。你解释得很完美,现在我明白了问题所在,我必须编写代码以从 HEX 形式转换为 9 位十六进制字以使我的系统正常工作。当您说“表示长度增加”时,您能告诉我当这种情况发生时输入序列的长度是多少?
  • 您知道如何在 JavaScript 中为此实现反转转换吗?我需要它在 JavaScript 中解压缩。
  • “表示长度增加”在您发布的链接中进行了描述。初始码字长度为 9,允许输出 0 到 510 的码字值,其中 511 是保留码,表示“从现在开始切换到 10 位码”。然后可以输出0到1022的10位码字,其中1023是保留码,意思是“从现在开始切换到11位码”。以此类推,最大码字长度为 20 位(由“lzwlocal.h”中的 MAX_CODE_LEN` 定义)。
  • LZW 的这个实现可能是众多实现之一,不一定使用完全相同的编码方案。
  • 好的。多亏了你,我才能完成我的任务。
猜你喜欢
  • 2017-08-27
  • 2011-09-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-22
  • 2014-11-03
  • 1970-01-01
  • 2019-10-20
相关资源
最近更新 更多