Опубликован: 23.04.2007 | Уровень: специалист | Доступ: платный | ВУЗ: Московский государственный университет имени М.В.Ломоносова
Лекция 13:

Алгоритмы сжатия изображений без потерь

< Лекция 12 || Лекция 13: 12345 || Лекция 14 >

Алгоритм LZW

Данный алгоритм (алгоритм LZW7Алгоритм назван по имени автора Терри Уэлч (Terry Welch) и названия исходного алгоритма LZ78 (также от имен Лемпеля и Зива). Он был опубликован в 1984 году. ) является модификацией другого метода от Абрахама Лемпеля (Abraham Lempel) и Якоба Зива (Jacob Ziv) - LZ78 [56]. Автор модификации - Терри Уэлч (Terry Welch) [51]. Словарь в данном алгоритме представляет собой таблицу, которая заполняется цепочками элементов по мере работы алгоритма. Причем во время декодирования словарь будет построен автоматически, следовательно, нет нужды хранить его вместе со сжатой последовательностью. Обычно таблица инициализируется так, что первые строчки заполнены всеми различными цепочками из одного элемента. В процессе сжатия отыскивается наиболее длинная цепочка, уже записанная в словарь. Каждый раз, когда новая цепочка элементов не найдена в словаре, она добавляется в словарь; при этом записывается код цепочки, для которой есть совпадение со словарем. В теории на размер таблицы не накладывается ограничений, однако ограничение на размер позволяет улучшить степень сжатия, т.к. накапливаются ненужные (возможно, более не встречающиеся) цепочки. Чем больше вхождений имеет таблица, тем больше информации нужно выделять для хранения кодов. Соответственно резервируется специальный код, обозначающий очистку таблицы (точнее, приведение ее к исходному состоянию).

// elem - элемент, chain - цепочка элементов
// in - вход, out - выход
// Table - таблица цепочек
// Table.Find - возвращает код, соответствующий
// цепочке (0 иначе)

str = ""; // пустая цепочка
while( in.Read( elem ) ) // пока есть данные
{
     // проверяем, есть ли уже в таблице новая цепочка
     if( Table.Find( chain + elem ) )
     {   // есть
          // сохраним новую цепочку для будущих проверок
          chain = chain + elem;
     }
     else
     {   // нет
          // запишем код, соответствующий chain
          out.Write( Table.Find( chain ) );
          // добавляем в словарь
          Table.Add( chain + elem );
          chain = elem;
     }
}
//остается одна необработанная цепочка
out.Write( Table.Find( chain ) );
Листинг 13.4. Алгоритм сжатия LZW

Рассмотрим пример сжатия алгоритмом. Будем, как и в предыдущем пункте, сжимать строку "TOBEORNOTTOBE". Пусть таблица инициализирована 256 символами кода ASCII. Предполагаем, что таблица может содержать 512 вхождений, т.е. нам требуется хранить 9 бит для каждого кода; для удобства пусть исходный словарь выглядит так:

строка код
T 1
O 2
B 3
E 4
R 5
N 6
... ...
СLT 256

Здесь CLT означает "очистить (инициализировать) таблицу".

  • самая длинная совпавшая цепочка - "T", выход - {1}, словарь:
    строка код
    T 1
    O 2
    B 3
    E 4
    R 5
    N 6
    ... ...
    СLT 256
    TO 257
  • самая длинная совпавшая цепочка - "O", выход - {2}, словарь имеет следующий вид:
    строка код
    ... ...
    OB 258
    Далее подобным образом в выход записывается последовательность {3}{4}{1}{5}{6}{2}, после этого
  • самая длинная совпавшая цепочка - "T", выход: {1}, словарь имеет следующий вид:
    строка код
    ... ...
    TO 257
    OB 258
    BE 259
    EO 260
    OR 261
    RN 262
    NO 263
    OT 264
    TT 265
  • самая длинная совпавшая цепочка - "TO", выход: {257}, словарь имеет следующий вид:
    строка код
    ... ...
    TOB 266
  • самая длинная совпавшая цепочка - "BE", выход: {259}.

В результате закодированная последовательность выглядит так: {CLT}{1}{2}{3}{4}{1}{5}{6}{2}{1}{257}{259} (обычно в начале закодированной последовательности записывают код очистки таблицы для упрощения декодера). Полученная последовательность имеет объем 108 бит (без учета обозначения конца последовательности), что больше, чем исходная ( 104 бита). В данном случае это обусловлено слишком малой длиной исходной последовательности. Однако уже упоминавшийся рис. 13.1 кодового дерева Хаффмена сжимается при помощи данного алгоритма с исходных 420 килобайт до 290 килобайт.

// chain - цепочка незакодированных элементов
// in - вход, out - выход
// lcode, code - элемент закодированной последовательности
// Table - таблица цепочек
// Table.Get(code) - возвращает цепочку с кодом code
// Table.IsOccupied(code) - есть ли запись в словаре для code
// Firstelem(chain) - возвращает первый элемент цепочки

while( in.Read( code ) ) // пока есть данные
{
     if( code == CLT ) //прочитан код очистки таблицы?
    {    // да
          Table.Init();
          If ( !in.Read(code) ) break; // больше нет информации
          out.Write( Table.Find( code ) );
          lcode = code;
     }
     else
     {   // нет
          if( Table.IsOccupied( code ) )
         {
               out.Write( Table.Find( code ) );
               // заполняем словарь новой цепочкой
               Table.Add( Table.Find( lcode ) +
                                Firstelem(Table.Find( code ) ) );
               lcode = code;
          }
          else
          {    // code не имеет соответствующей цепочки
               chain = Table.Find( lcode ) +
                               Firstelem( Table.Find( lcode ) );
               out.Write ( chain ); // запишем цепочку
               Table.Add ( chain ); // и добавим в таблицу
               lcode = code;
          }
     }
}
Листинг 13.5. Алгоритм декодирования LZW

Декодирование заключается в прямой расшифровке кодов, т.е. в построении словаря и вывода соответствующих цепочек. Словарь инициализируется так же, как и в кодере.

К достоинствам алгоритма можно отнести высокую степень сжатия и достаточно высокую скорость как сжатия, так и разжатия. К недостаткам до недавнего времени относили патентную защищенность алгоритма, однако с середины 2004 года этот недостаток не актуален.

Приведенный выше алгоритм имеет множество модификаций, например: различные варианты представления таблиц и поиска в них, переменная длина кодов и т.д. Модификации LZW используются во множестве архиваторов общего назначения, а также в таких форматах как GIF и TIFF.

< Лекция 12 || Лекция 13: 12345 || Лекция 14 >
Иван Ерохин
Иван Ерохин
Казахстан
Дарья Маслова
Дарья Маслова
Россия