- •Сжатие информации Оглавление
- •1. Виды информации
- •2. Количество информации.
- •3. Хранение, измерение, обработка и передача информации
- •4. Базовые понятия теории информации
- •5. Обзор подходов к сжатию информации
- •6. Эффективное посимвольное кодирование для сжатия данных.
- •Сжатие информации с учетом цепочек символов по Лемпелю-Зиву (Велчу).
- •8. Сжатие изображений по блочному алгоритму jpeg.
- •9. Методы сжатия звуковой информации
Сжатие информации с учетом цепочек символов по Лемпелю-Зиву (Велчу).
Очевидно, что посимвольное кодирование не использует резервы сжатия информации, связанные с повторяемостью цепочек символов. Так например, в исходном тексте программы на алгоритмическом языке часто встречаются повторяющиеся наименования операторов или идентификаторы, которые в принципе можно закодировать короткими битовыми последовательностями.
Наиболее удачным алгоритмом сжатия, основанным на таком подходе является алгоритм Лемпеля-Зива, который в разных модификациях используется, в частности, в большинстве программ-архиваторов. Основная идея алгоритма состоит в том, что цепочки символов, уже встреченные ранее кодируются ссылкой на их «координаты» (номер первого символа и длину) в «словаре», где находится уже обработанная часть сообщения.
Суть его в следующем: упаковщик постоянно хранит некоторое количество последних обработанных символов в буфере. По мере обработки входного потока вновь поступившие символы попадают в конец буфера, сдвигая предшествующие символы и вытесняя самые старые. Размеры этого буфера, называемого также скользящим словарем (sliding dictionary), варьируются в разных реализациях (в LHarc 1.13 используется 4-килобайтный буфер, LHA 2.13 и PKZIP 1.10 - 8-килобайтный, а ARJ 2.20 - 16-килобайтный).
Алгоритм выделяет (путем поиска в словаре) самую длинную начальную подстроку входного потока, совпадающую с одной из подстрок в словаре, и выдает на выход пару (length, distance), где length - длина найденной в словаре подстроки, а distance - расстояние от нее до входной подстроки (то есть фактически индекс подстроки в буфере, вычтенный из его размера). В случае, если такая подстрока не найдена, в выходной поток просто копируется очередной символ входного потока.
В первоначальной версии алгоритма предлагалось использовать простейший поиск по всему словарю. Время сжатия при такой реализации было пропорционально произведению длины входного потока на размер буфера, что непригодно для практического использования. Однако, в дальнейшем было предложено использовать двоичное дерево для быстрого поиска в словаре, что позволило на порядок поднять скорость работы алгоритма.
Таким образом, алгоритм Лемпеля-Зива преобразует один поток исходных символов в два параллельных потока length и distance. Очевидно, что эти потоки являются потоками символов в новых алфавитах L и D, и к ним можно применить один из упоминавшихся выше методов (RLE, кодирование Хаффмана, арифметическое кодирование). Так мы приходим к схеме двухступенчатого кодирования, наиболее эффективной из практически используемых в настоящее время (и, в частности, использованной автором). При реализации этого метода необходимо добиться согласованного вывода обоих потоков в один файл. Эта проблема обычно решается путем поочередной записи кодов символов из обоих потоков.
Уточним дополнительно некоторые моменты:
- коды координат цепочки и коды отдельных символов различаются битовыми признаками (например, в первом случае – 1, во втором –0) ;
поскольку цепочки находятся чаще в начале словаря, и чаще бывают короткими, дополнительный выигрыш получают за счет статистического кодирования (по Хаффмену) их «адресов» и «длин»;
«канал» - понятие применимое и к реальному каналу передачи данных, и к файлу, куда данные записываются для хранения. В последнем случае декодер «отрабатывает» при разворачивании сжатого файла;
при ограниченной длине словаря (обычно от 4 до 16 кбайт) новые поступающие символы и цепочки «вытесняют» прежние (текст как бы «вдвигается» в словарь). Разумеется, вначале, когда словарь не заполнен, эффективность сжатия невысока. Рост объема словаря позволяет повысить степень сжатия, но значительно увеличивается трудоемкость поиска цепочек.
Добавим, что алгоритм Лемпеля-Зива используется в большинстве популярных программ-архиваторов (в том числе, например, в zip, rar, arj и их windows – версиях). Различие скорости и эффективности кодирование-декодирование определяются в основном особенностями программной реализации.
Алгоритм Лемпеля-Зива требует большого количества вычислительной работы. Его модификация - алгоритм Лемпеля-Зива-Велча является менее трудоемким, хотя и дает несколько худшие результаты по сжатию.
Алгоритм упаковки Лемпеля-Зива-Велча (Lempel-Ziv-Welch compression, LZW) работает так. Будем предполагать, что входной алфавит состоит из m различных символов.
1. Инициализация словаря. В пустой словарь помещаются все m различных односимвольных строк.
2. Строке P, называемой "префиксом", присваиваем пустое значение.
3. Пусть k - очередной символ входного потока.
4. Ищем строку P+k в словаре.
Если нашли, то P := P+k,
сдвигаем указатель входного потока на следующий символ,
переходим к п. 3.
иначе
выводим номер строки P в словаре в выходной поток,
добавляем строку P+k в словарь,
P := k (строка длины 1),
сдвигаем указатель входного потока на
length(P) символов,
переходим к п.3
конец_если.