LZ77压缩palmdoc

时间:2013-05-19 08:53:35

标签: compression

我正在尝试创建一个用于生成palmdoc / mobipocket格式电子书文件的实用程序,据说mobi使用LZ77压缩技术来压缩他们的记录,但我发现与标准LZ77存在相当大的偏差,我的主要来源是引用是Calibre电子书创建者with C implementation for palmdoc

在这个文件中,uncompress效果很好,但是我无法使用其他实现或者这个(Calibre代码doent解压缩相同)压缩一个类似的mobi记录。

我发现了一些差异,比如(< - 我的评论在代码中跟随)

static Py_ssize_t <-- can replaced with size_t
cpalmdoc_do_compress(buffer *b, char *output) {
    Py_ssize_t i = 0, j, chunk_len, dist;
    unsigned int compound;
    Byte c, n;
    bool found;
    char *head;
    buffer temp; 
    head = output;
    temp.data = (Byte *)PyMem_Malloc(sizeof(Byte)*8); temp.len = 0;
    if (temp.data == NULL) return 0;
    while (i < b->len) {
        c = b->data[i];
        //do repeats
        if ( i > 10 && (b->len - i) > 10) { <-- ignores any match outside this range
            found = false;
            for (chunk_len = 10; chunk_len > 2; chunk_len--) {
                j = cpalmdoc_rfind(b->data, i, chunk_len);
                dist = i - j;
                if (j < i && dist <= 2047) { <-- 2048 window size instead of 4096
                    found = true;
                    compound = (unsigned int)((dist << 3) + chunk_len-3);
                    *(output++) = CHAR(0x80 + (compound >> 8 ));
                    *(output++) = CHAR(compound & 0xFF);
                    i += chunk_len;
                    break;
                }
            }
            if (found) continue;
        }

        //write single character
        i++;
        if (c == 32 && i < b->len) { <-- if space is encountered skip char & check for next sequence for match otherwise do this, due to this code had wrong result.
            n = b->data[i];
            if ( n >= 0x40 && n <= 0x7F) {
                *(output++) = CHAR(n^0x80); i++; continue;
            }
        }
        if (c == 0 || (c > 8 && c < 0x80))
            *(output++) = CHAR(c);
        else { // Write binary data <-- why binary data? LZ is for text encoding
            j = i;
            temp.data[0] = c; temp.len = 1;
            while (j < b->len && temp.len < 8) {
                c = b->data[j];
                if (c == 0 || (c > 8 && c < 0x80)) break;
                temp.data[temp.len++] = c; j++;
            }
            i += temp.len - 1;
            *(output++) = (char)temp.len;
            for (j=0; j < temp.len; j++) *(output++) = (char)temp.data[j];
        }
    }
    PyMem_Free(temp.data);
    return output - head;
}

这个实现是否正确?

1 个答案:

答案 0 :(得分:1)

PalmDoc compression本质上是字节对压缩,即LZ77的变体