[P&AM Lab] LZW simple in-memory compression library
Grigoriy A. Sitkarev
sitkarev на komitex.ru
Ср Авг 8 02:46:23 MSK 2012
Приветствую всех.
Я давно забыл, что у нас появилась весьма компактная и простая
библиотечка алгоритма сжатия LZW, про который мы однажды говорили на
нашей лаборатории в связи с обсуждением онлайн-алгоритмов.
Код можно взять или через svn
$ svn co http://wiki.syktsu.ru/svn/libslzw
или смотреть на нашем websvn через HTTP
http://wiki.syktsu.ru/websvn/listing.php?repname=libslzw&path=%2F&sc=0
Большинство известных реализаций LZW не работают in-memory, а
предназначены для сжатия/распаковки файлов. Нам нужна была компактная
версия алгоритма, который мог бы распаковывать и запаковывать поток
данных онлайн, по мере их поступления.
Примеры использования даны в encode.c и decode.c. Функции сжатия и
распаковки весьма похожи на семантику iconv(3). Обе функции принимают 5
аргументов: контекст, указатель на буфер с входными данными и указатель
на из размер, указатель на буфер с выходными данными и указатель на его
размер.
Такой псевдо-пример, иллюстрирующий сжатие:
#define BUFSIZE 2048
unsigned char buffer[BUFSIZE];
unsigned char buffer2[2*BUFSIZE];
const unsigned char *in;
unsigned char *out;
size_t insz, outsz;
int count, rc;
...
while ((count = read(0, buffer, sizeof(buffer))) > 0) {
in = buffer;
insz = count;
while (insz > 0) {
out = buffer2;
outsz = sizeof(buffer2);
rc = lzw_encode(&enc, &in, &insz, &out, &outsz);
if (rc == LZW_OK || rc == LZW_NOSPACE) {
/* Здесь buffer2 содержит (buffer2 - out)
* сжатых байт, которые можно отсылать.
*/
...
} else {
if (rc == LZW_NOMEM) {
/* Не хватило памяти. */
...
} else {
/* Какое-то другое безобразие... */
...
}
}
}
...
}
Финальная посылка сжатых данных должна заканчиваться вызовом
lzw_end_of_data():
rc = lzw_end_of_data(&enc, &out, &outsz);
assert(rc == LZW_OK);
/* В буфер теперь добавлена завершающая последовательность. */
С распаковкой всё проще, пример decode.c в помощь. Кому интересны детали
реализации: исходники снабжены достаточно подробными комментариями. В
любом случае следует сначала разобрать как работает LZW. Дальше всё
встаёт на свои места.
Алгоритм проверялся на наборе данных Calgary и показал результат
коэффициента сжатия ~2.11. Это, безусловно, не самый лучший результат,
но нас он практически устраивал, учитывая простоту реализации и
незамысловатый алгоритм сброса словаря. Сценарий тестовой программы
приведен в test.sh.
Всего наилучшего,
--
Г.А.
Подробная информация о списке рассылки Lab