Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
68
Добавлен:
02.05.2014
Размер:
359.94 Кб
Скачать

Варианты группового кодирования

Есть несколько вариантов группового кодирования. Обычно данные изображения кодируются последовательно, причем, с точки зрения группового кодирования, они представляют собой одномерный поток, а не двухмерную таблицу данных. В этом последовательном процессе растр кодируется начиная с верхнего левого угла, а затем — слева направо по линиям развертки (по оси X) к нижнему правому углу. Однако альтернативные схемы RLE позволяют записывать закодированные данные по длине растра (по оси Y), т.е. колонками, кодировать растр двухмерными фрагментами или даже по диагонали, зигзагом (см. рис. 9.2). Правда, "странные" варианты RLE (вроде последнего) применяются лишь в узкоспециализированных программах, т.е. довольно редко.

Еще одним редко встречающимся вариантом RLE является групповое кодирование с потерями. Обычно алгоритмы RLE кодируют без потерь. Однако отбрасывание данных в процессе кодирования (обычно одного иди двух самых младших битов в каждом пикселе, имеющих нулевое значение) может увеличить степень сжатия очень сложных изображений без видимых последствий. Этот вариант RLE хорошо "работает" только с реальными изображениями, содержащими много "тонкостей" в пиксельных значениях.

При программировании собственного RLE-кодировщика сделайте так, чтобы он всегда останавливался в конце каждой строки развертки растровых данных. У такого подхода есть несколько преимуществ: построчное кодирование требует минимального размера буфера и, кроме того, предотвращает проблему, известную как перекрестное кодирование (cross-coding).

Перекрестное кодирование — это слияние строк развертки, происходящее из-за того, что в процессе кодирования различия между ними исчезают. Если такое слияние произошло по вине алгоритма RLE, то точка окончания одной строки развертки и начала другой теряется или же ее бывает очень трудно обнаружить.

Мы советуем избегать перекрестного кодирования, так как помогая "выиграть" несколько байтов при сжатии данных, оно значительно усложняет процесс декодирования и отнимает много времени. В форматах растровых файлов перекрестное кодирование нарушает базовый принцип организации растрового изображения в виде строк развертки. Хотя многие спецификации файловых форматов специально оговаривают тот факт, что каждая строка развертки должна обрабатываться отдельно, многие программы кодируют данные изображения непрерывным потоком, игнорируя границы строк развертки.

Если файл изображения, закодированный с помощью RLE, отображается одной программой, но не воспроизводится другой, то, по-видимому, вы столкнулись с перекрестным кодированием. Чтобы избежать подобной проблемы, ваши программы декодирования и отображения должны учитывать возможность перекрестного кодирования и не предполагать, что закодированная группа будет всегда оканчиваться в конце строки развертки.

Когда программа-кодировщик обрабатывает изображение, она должна помещать в закодированные данные маркеры конца строки развертки, информирующие программу-декодировщика о том, что встретился конец строки развертки. Этот маркер обычно представляет собой уникальный пакет, точно определенный в спецификации RLE, который нельзя спутать с любым другим пакетом данных. Как правило, маркеры конца строки развертки имеют длину всего в 1 байт, что незначительно влияет на размер закодированных данных.

Еще одним преимуществом построчного кодирования является то, что программа может легко воспроизвести любую часть изображения. Предположим, что изображение содержит 512 строк развертки, а нам нужно отобразить только строки со 101 по 110. Если мы не будем знать, где в закодированных данных кончается одна строка развертки и начинается другая, то нашей программе прийдется предварительно декодировать 100 первых строк развертки, прежде чем она найдет нужные ей 10 строк. Естественно, если переходы между строками развертки маркированы легкораспознаваемыми разделителями, то программа просто просмотрит закодированные данные, отсчитает нужное количество маркеров и легко найдет нужные ей строки. Но такой подход не очень эффективен.

Другим способом определения в блоке закодированных данных начальных точек любой строки развертки является создание таблицы строк развертки. Таблица строк развертки обычно содержит по одному элементу для каждой строки развертки изображения, а каждый элемент включает информацию о смещении соответствующей строки развертки. Чтобы найти первый RLE-пакет десятой строки развертки, программа-декодировщик должна выбрать смещение, записанное в десятом элементе таблицы строк развертки. Эта таблица может также содержать данные о количестве байтов, использованных для кодирования каждой строки развертки. Если применить этот метод, то для нахождения первого RLE-пакета десятой строки развертки ваша программа-декодировщик просто сложит значения первых девяти элементов таблицы. Полученный результат будет смещением первого пакета десятой строки развертки от начала данных изображения, закодированных с помощью RLE.

RLE-схемы битового, байтового и пиксельного уровней

Различные алгоритмы группового кодирования отличаются друг от друга своими решениями, касающимися характеристик обрабатываемых данных (например, длины групп данных). RLE-схемы, применяемые для кодирования растровой графики, обычно делятся на классы в зависимости от уровня обрабатываемых данных. Большинством форматов графических файлов используются три класса RLE-схем: битового, байтового и пиксельного уровней.

RLE-схемы битового уровня кодируют в группы биты строк развертки, игнорируя при этом границы байтов и слов. Этот класс схем эффективен только при обработке монохромных (черных и белых) однобитовых изображений, содержащих достаточное количество битовых групп. Типичная RLE-схема битового уровня кодирует в группы от одного до 128 битов, создавая из них однобайтовые пакеты. Семь младших битов этого байта содержат счетчик группы (количество битов в группе минус единица), а самый старший бит — значение группы (0 или 1), как показано на рис. 9.4. Группы длиной более 128 пикселей разбиваются на несколько RLE-пакетов.

RLE-схемы байтового уровня кодируют в группы идентичные байтовые значения, игнорируя отдельные биты и границы слов в строке развертки. RLE-схема байтового уровня в общем виде кодирует группы байтов в двухбайтовые пакеты. Первый байт содержит счетчик группы (от 0 до 255), а второй — значение группы. Кроме того, часто применяется схема двухбайтового кодирования, позволяющая хранить в потоке закодированных данных литералы (незакодированные группы байтов). Согласно этой схеме, семь младших битов первого байта пакета содержат счетчик группы (количество байтов в группе минус единица), а самый старший бит первого байта указывает тип группы, следующей за байтом счетчика группы. Если самый старший бит установлен в 1, то он указывает на закодированную группу. Закодированные группы декодируются посредством чтения значения группы и повторения его столько раз, сколько указано в счетчике группы (плюс единица). Если самый старший бит установлен в 0, то он указывает на литеральную группу, т.е. следующие байты (в количестве, указанном счетчиком группы плюс единица) должны читаться напрямую из закодированных данных изображения (см. рис. 9.4). При этой схеме байт счетчика группы содержит значения в диапазоне от 0 до 127 (количество байтов в группе минус единица). RLE-схемы байтового уровня эффективны для данных изображения, которые хранятся в виде одного байта на пиксель

RLE-схемы пиксельного уровня применяются в тех случаях, когда для хранения одного пиксельного значения используются два или более смежных байтов данных изображения. На пиксельном уровне биты игнорируются, а байты принимаются во внимание только для идентификации каждого пиксельного значения. Размер закодированного пакета зависит от размера пиксельных значений, подлежащих кодированию. Сведения о количестве битов или байтов в пикселе записаны в заголовке файла изображения. Если данные изображения состоят из 3-байтовых пиксельных значений, то группа из таких данных будет кодироваться в виде 4-байтового пакета, где за байтом счетчика группы будут следовать 3 байта значения группы. Этот метод кодирования аналогичен RLE-схеме байтового уровня.

Литеральную пиксельную группу можно задать, используя самый старший бит первого байта пакета (как и в RLE-схеме байтового уровня). Учтите, что в RLE-схемах пиксельного уровня счетчик группы содержит данные о количестве пикселей, а не о количестве байтов в группе.

Выше мы рассмотрели ситуацию, когда строка Xtmprsqyitwifb после применения стандартного метода RLE заняла вдвое больше памяти, поскольку для каждой односимвольной группы после кодирования потребовалось два символа. Можем ли мы, применяя RLE, избежать подобного отрицательного сжатия.

Обычно метод RLE должен анализировать поток исходных данных, чтобы определить целесообразность создания литеральной пиксельной группы. Применение метода литеральной группы при обработке потока данных, содержащих много одно- и двухпиксельных групп, более эффективно, чем кодирование этих групп в виде отдельных пакетов. Однако существует и другой метод, позволяющий включать литеральные группы пикселей в поток закодированных данных без инкапсуляции.

Рассмотрим RLE-схему, использующую для представления группы не два, а три байта (см. рис. 9.5). Первый байт — это флаг, значение которого указывает на то, что следующие два байта являются частью закодированного пакета, причем второй байт — это счетчик группы, а третий — значение группы. Если в процессе кодирования встречается группа, состоящая из одного, двух или трех символов, то эти символьные значения записываются непосредственно в поток сжатых данных. Поскольку никакие дополнительные символы при этом не используются, то нет и издержек.

При декодировании анализируется прочитанный символ. Если это флаговое значение, то читаются и обрабатываются счетчик группы и значение группы, а результат записывается в выходной поток данных. Если же прочитанный символ не является флаговым значением, то он записывается в выходной поток напрямую.

Однако у этого метода есть два потенциальных недостатка:

• Минимальный размер группы, пригодной для кодирования, возрастает с трех символов до четырех. Это может снизить эффективность сжатия данньк некоторых типов.

• Если поток незакодированных данных содержит значение символа, равное флаговому значению, то этот символ должен быть закодирован в трехбайтовый пакет. Таким образом можно предотвратить появление в потоке сжатых данных ошибочных флаговых значений. Если во входном потоке подобных символов много, то результатом кодирования будет плохая степень сжатия. Значит, алгоритм RLE должен применять флаговые значения, которые встречаются в потоке несжатых данных крайне редко.

Соседние файлы в папке Лекции по компьютерной графике