Алгоритм LZW
Алгоритм LZW (Lempel–Ziv–Welch) — это универсальный алгоритм сжатия данных без потерь, основанный на построении динамического словаря (таблицы) последовательностей символов (строк) из входного потока. Алгоритм был разработан в 1984 году Терри Уэлчем (Terry Welch) как усовершенствование алгоритмов LZ77 и LZ78, предложенных Абрахамом Лемпелем и Якобом Зивом. LZW широко применялся в ранних форматах сжатия изображений (GIF, TIFF) и в утилитах архивации (например, compress в Unix).
История
Алгоритмы сжатия семейства LZ (Lempel-Ziv) появились в конце 1970-х годов. В 1977 году Лемпель и Зив опубликовали алгоритм LZ77, использующий скользящее окно для поиска повторяющихся фрагментов. В 1978 году они предложили LZ78, где вместо окна строилась словарная таблица фраз. Однако практическая реализация LZ78 была неэффективной из-за неограниченного роста словаря и сложности кодирования.
В 1984 году Терри Уэлч, работавший в компании Sperry Research Center, опубликовал модификацию LZ78, названную LZW. Основные улучшения Уэлча:
- Инициализация словаря всеми возможными односимвольными строками (обычно 256 байт для 8-битных данных).
- Отказ от кодирования второго символа в выходной поток — теперь кодировались только индексы словаря.
- Механизм «предсказания» следующего символа, что устраняло необходимость в явной передаче новых фраз.
LZW быстро стал популярным благодаря простоте реализации и хорошей степени сжатия для текстовых и графических данных. В 1987 году он был выбран для формата GIF (Graphics Interchange Format), разработанного компанией CompuServe. В 1990-х годах алгоритм использовался в утилите compress (Unix), а также в форматах TIFF и PostScript Level 2. С появлением более эффективных алгоритмов (DEFLATE, LZMA) и патентных ограничений LZW утратил доминирующее положение, но остаётся важным историческим примером.
Принцип работы
Алгоритм LZW сжимает данные, заменяя повторяющиеся последовательности символов (строки) на более короткие коды — индексы из словаря. Словарь строится динамически в процессе сжатия и не требует передачи отдельно: он восстанавливается декомпрессором на основе тех же правил.
Сжатие
Процесс сжатия состоит из следующих шагов:
- Инициализация словаря. В словарь заносятся все возможные односимвольные строки (коды 0–255 для байтовых данных). Каждому символу соответствует его числовое значение.
- Чтение входного потока. Алгоритм последовательно считывает символы из входного потока, накапливая текущую строку
w. - Поиск в словаре. Для каждого нового символа
cпроверяется, есть ли в словаре строкаw + c.
- Если есть — строка
wрасширяется доw + c, и алгоритм переходит к следующему символу. - Если нет — в выходной поток записывается код строки
w(её индекс в словаре), а строкаw + cдобавляется в словарь с новым кодом. Затемwустанавливается равнойc.
- Завершение. После обработки всего потока в выходной поток записывается код последней строки
w.
Таким образом, алгоритм заменяет повторяющиеся последовательности на один код, а новые последовательности добавляет в словарь для будущего использования.
Декомпрессия
Декомпрессия выполняется в обратном порядке, но с той же логикой построения словаря:
- Инициализация словаря теми же односимвольными строками.
- Чтение кодов из сжатого потока. Для каждого кода:
- Если код есть в словаре — в выходной поток записывается соответствующая строка.
- Если код отсутствует (особый случай, возникающий при последовательности вида
cScSc, гдеS— уже известная строка) — строка восстанавливается какпредыдущая_строка + первый_символ_предыдущей_строки.
- Обновление словаря. После записи каждой строки в словарь добавляется новая фраза, состоящая из предыдущей строки и первого символа текущей строки.
Декомпрессор всегда «догоняет» компрессор, так как новые коды добавляются в словарь только после их первого использования.
Пример работы
Рассмотрим сжатие строки «ABABABA» (символы A, B имеют коды 65, 66 соответственно, но для простоты используем условные коды 1 и 2).
Инициализация словаря:
- Код 1: «A»
- Код 2: «B»
Шаги сжатия:
- Читаем «A» → w = «A»
- Читаем «B» → w + c = «AB» нет в словаре → выводим код 1 (для «A»), добавляем «AB» с кодом 3, w = «B»
- Читаем «A» → w + c = «BA» нет → выводим код 2 (для «B»), добавляем «BA» с кодом 4, w = «A»
- Читаем «B» → w + c = «AB» есть (код 3) → w = «AB»
- Читаем «A» → w + c = «ABA» нет → выводим код 3 (для «AB»), добавляем «ABA» с кодом 5, w = «A»
- Читаем «B» → w + c = «AB» есть (код 3) → w = «AB»
- Читаем «A» → w + c = «ABA» есть (код 5) → w = «ABA»
- Конец потока → выводим код 5 (для «ABA»)
Выходной поток: 1, 2, 3, 5 (4 кода вместо 7 символов). Степень сжатия — 4/7 ≈ 57%.
Характеристики и ограничения
Достоинства
- Простота реализации. Алгоритм требует минимум вычислительных ресурсов и памяти.
- Однопроходность. Сжатие выполняется за один проход по данным, без предварительного анализа.
- Адаптивность. Словарь строится под конкретные данные, что обеспечивает хорошее сжатие для повторяющихся структур.
- Симметричность. Декомпрессия не требует дополнительной информации (кроме инициализированного словаря).
Недостатки
- Ограниченный размер словаря. В классической реализации словарь фиксирован (обычно 4096 или 65536 записей). При переполнении словарь либо сбрасывается, либо перестаёт обновляться, что снижает эффективность.
- Плохое сжатие коротких или случайных данных. Для неповторяющихся последовательностей размер сжатых данных может превысить исходный.
- Патентные ограничения. Алгоритм LZW был запатентован в США (патент US4558302A, истёк в 2003 году), что ограничивало его свободное использование в программном обеспечении.
- Чувствительность к ошибкам. Ошибка в одном коде может привести к неверному восстановлению всей последующей последовательности.
Применение
LZW использовался в следующих областях и форматах:
- Формат GIF (Graphics Interchange Format). Основной алгоритм сжатия для изображений с палитрой до 256 цветов. Позволял эффективно сжимать изображения с большими одноцветными областями.
- Формат TIFF (Tagged Image File Format). Один из вариантов сжатия для растровых изображений.
- Утилита compress (Unix). Стандартная программа сжатия в системах Unix, использовавшая LZW.
- Формат PostScript Level 2. Использовался для сжатия данных в языке описания страниц.
- Модемные протоколы. В некоторых протоколах сжатия данных (например, V.42bis) применялись модификации LZW.
В настоящее время LZW в значительной степени вытеснен более эффективными алгоритмами, такими как DEFLATE (используется в PNG, ZIP, gzip) и LZMA (7z, XZ). Однако он остаётся важным для обратной совместимости с устаревшими форматами (GIF, TIFF).
Интересные факты
- Патент на LZW (US4558302A) принадлежал компании Unisys и был предметом судебных разбирательств в 1990-х годах. В 1999 году Unisys потребовала лицензионных отчислений от разработчиков программ, использующих GIF, что вызвало протесты в интернет-сообществе и привело к созданию формата PNG (Portable Network Graphics), не использующего запатентованные алгоритмы.
- Алгоритм LZW является основой для многих учебных примеров по сжатию данных из-за своей наглядности.
- В некоторых реализациях (например, в GIF) используется переменная длина кода (от 9 до 12 бит), что позволяет адаптироваться к размеру словаря.
Источники
- Welch, T. A. (1984). «A Technique for High-Performance Data Compression». IEEE Computer, 17(6), 8–19.
- Nelson, M., & Gailly, J.-L. (1995). The Data Compression Book. M&T Books.
- Salomon, D. (2007). Data Compression: The Complete Reference. Springer.
- RFC 1951 (DEFLATE Compressed Data Format Specification) — содержит описание алгоритмов, заменивших LZW.
BFOmetr — база данных и аналитика по компаниям России.
На главную BFOmetr →