Алгоритм LZW

Алгоритм LZ78 существовал до 1984 года как математическая абстракция, пока не был усовершенствован Терри Уэлчем. Главной особенностью алгоритма LZW стало удаление второго поля из метки.

Суть LZW в том, что рабочий модуль первоначально должен инициализировать словарь из 256 символов (в общем случае 8-битного алфавита). Символы с номерами от 0 до 255 дадут нам полный набор наиболее часто используемых в текстах знаков, а также русский и английский алфавиты. Таким образом, первый символ сжимаемого текста совершенно точно будет найден в словаре, и метка может состоять всего лишь из указателя.

На следующем шаге второй символ группируется с первым в строку, и эта строка ищется в словаре. Если она там найдена, то процесс удлинения строки продолжается. Если же строка в словаре не найдена, то выполняется следующий набор действий:

1) В выходной файл записывается указатель на предыдущую строку;

2) В конец словаря записывается ненайденная строка;

3) Строка перестает удлиняться, и начинается работа со следующим символом.

 

Поясним на примере. Возьмем строку «топот_копыт» и попробуем сжать ее при помощи LZW.

 

Рабочая строка Присутствие в словаре Запись в словарь Запись в выходной файл
т есть - -
то нет 256-то 226(т)
о есть - -
оп нет 257-оп 222(о)
п есть - -
по нет 258-по 223(п)
о есть - -
от нет 259-от 222(о)
т есть - -
т_ нет 260-т_ 226(т)
_ есть - -
нет 261-_к 32(_)
к есть - -
ко нет 262-ко 218(к)
о есть - -
оп есть - -
опы нет 263-опы 257(оп)
ы есть - -
ыт нет 264-ыт 235(ы)
т есть - -
т, eof нет - 226(т)

 

 

Поясним этот пример. После инициализации словаря мы находим номер первого символа (226). Затем добавляем к нему следующий и видим, что такой строки (то) в словаре нет. Последний символ у нас 255, добавляем «то» под номером 256 в словарь и записываем в выходной файл указатель на «т» - 226. После чего начинаем все заново с символа «о». Если строка из двух символов есть в словаре, точно так же работаем со строкой из трех и более символов, в конце итерации рабочей строке все равно присваивается один символ. Последняя строка «т, eof» в словарь, естественно, не записывается.

Выходной файл будет выглядеть так: 226, 222, 223, 222, 226, 32, 218, 257, 235, 226.

 

2.2.1. Декодирование LZW

LZW очень удобен в плане декодирования. Особенность его в том, что кодер и декодер в состоянии работать синхронно. То есть, при поступлении на вход декодера закодированного файла он просто инициализирует словарь, смотрит по указателям, из которых состоит файл, номера символов в словаре и восстанавливает файл, исходя из этого.

Пошагово декодер работает так:

1) Вводится указатель, извлекается соответствующая строка I из словаря;

2) Строка записывается в выходной файл;

3) Из нее извлекается первый символ, и с предыдущей строкой J заносится в словарь на свободную позицию;

4) I перемещается в J.

 

Поясним работу декодера на нашем примере «топот_копыт». Первым символом входного файла является указатель 226. Он соответствует строке «т», которая извлекается по ссылке из словаря и записывается в разжатый файл. Следующий указатель – 222. Извлекается строка «о», записывается в выходной файл, а строка «о» добавляется к предыдущей, образуя строку «то», которая, также как и в кодере, добавляется на последнюю позицию. Таким образом декодер проходит до конца файла, расжимая текст обратно в «топот_копыт».

 

Резюмируя сказанное, представим достоинства и недостатки алгоритма LZW.

Достоинства:

1) Не требует вычисления вероятностей встречаемости символов или кодов.

2) Для декомпрессии не надо сохранять таблицу строк в файл для распаковки. Алгоритм построен таким образом, что мы в состоянии восстановить таблицу строк, пользуясь только потоком кодов.

3) Данный тип компрессии не вносит искажений в исходный графический файл, и подходит для сжатия растровых данных любого типа.

 

Недостаток: Алгоритм не проводит анализ входных данных, поэтому не оптимален.

 

Опубликование алгоритма LZW произвело большое впечатление на всех специалистов по сжатию информации. За этим последовало большое количество программ и приложений с различными вариантами этого метода.
Этот метод позволяет достичь одну из наилучших степеней сжатия среди других существующих методов сжатия графических данных, при полном отсутствии потерь или искажений в исходных файлах. В настоящее время испольуется в файлах формата TIFF, PDF, GIF, PostScript и других, а также отчасти во многих популярных программах сжатия данных (ZIP, ARJ, LHA).

 

 

Описание функционирования рабочего модуля

В данном разделе описывается построчное функционирование рабочего модуля алгоритма Хаффмана, выполненное в системе Wolfram Mathematica.

Первоначально для работы модуля требуется непосредственно задать кодируемый текст – он задается в виде списка.

 

 

Кодирование Хаффмана предполагает разбивку текста на символы. При помощи функций Flatten и Characters разобьем текст и выведем в виде переменной-списка символов.

 

 

 

Текст становится таким:

 

{"в", "о", "т", ",", " ", "и", "з", "в", "о", "л", "и", "т", "е", "

", "в", "и", "д", "е", "т", "ь", ",", " ", "т", "а", "к", " ", "н",

"а", "з", "ы", "в", "а", "е", "м", "а", "я", " ", "э", "в", "р", "и",

"с", "т", "и", "ч", "е", "с", "к", "а", "я", " ", "м", "а", "ш", "и",

"н", "а"}

 

Для начала необходимо определить частоту вхождения каждого символа в текст. В Mathematica это можно рассчитать с помощью функции Tally (количество копий элементов в списке). Для удобства работы отсортируем список при помощи функций Sort и Transpose:

 

 

 

Получим список:

 

{{1, "ш"}, {1, "ч"}, {1, "р"}, {1, "э"}, {1, "ы"}, {1, "ь"}, {1,

"д"}, {1, "л"}, {2, "с"}, {2, "я"}, {2, "м"}, {2, "н"}, {2,

"к"}, {2, "з"}, {2, ","}, {2, "о"}, {4, "е"}, {5, "т"}, {5,

"в"}, {6, "и"}, {6, " "}, {7, "а"}}

 

Приложение