2

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

在这个文件中,解压缩效果很好,但是我无法使用其他实现或这个(Calibre 代码不解压缩相同的)来压缩完全相同的 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;
}

这个实现正确吗?

4

1 回答 1

1

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

于 2013-08-25T08:17:18.680 回答