Данный алгоритм необычайно прост в реализации. Групповое кодирование - от английского Run - один из самых старых и самых простых алгоритмов происходит за счет того, что в исходном изображении встречаются цепочки одинаковых байт. Замена их на пары <счетчик повторений, значение> уменьшает избыточность данных.
Алгоритм декомпрессии при этом выглядит так:
Initialization(...);
do {
byte = ImageFile.ReadNextByte();
if(является счетчиком(byte)) {
counter = Low6bits(byte)+1;
value = ImageFile.ReadNextByte();
for(i=1 to counter) DecompressedFile.WriteByte(value)
}
else {
DecompressedFile.WriteByte(byte)
}
while(!ImageFile.EOF());
В данном алгоритме признаком счетчика ( ) служат единицы в двух верхних битах считанного файла (рис. 5.1):
(рис 5.1) Соответственно оставшиеся 6 бит расходуются на счетчик, который может принимать значения от 1 до 64. Строку из 64 повторяющихся байтов мы превращаем в два байта, т.е. сожмем в 32 раза.
RLE .Алгоритм рассчитан на деловую графику - изображения с большими областями повторяющегося цвета. Ситуация, когда файл увеличивается, для этого простого алгоритма не так уж редка. Ее можно легко получить, применяя групповое кодирование к обработанным цветным фотографиям. Для того, чтобы увеличить изображение в два раза, его надо применить к изображению, в котором значения всех пикселов больше двоичного 11000000 и подряд попарно не повторяются.
RLE . Объясните, почему размер сжатого файла больше размера исходного файла.Данный алгоритм реализован в формате . См. пример в приложении.
Второй вариант этого алгоритма имеет большую
Алгоритм декомпрессии для него выглядит так:
Initialization(...);
do {
byte = ImageFile.ReadNextByte();
counter = Low7bits(byte)+1;
if(если признак повтора(byte)) {
value = ImageFile.ReadNextByte();
for (i=1 to counter) CompressedFile.WriteByte(value)
}
else {
for(i=1 to counter){
value = ImageFile.ReadNextByte();
CompressedFile.WriteByte(value)
}
}
while(!ImageFile.EOF());
Признаком повтора в данном алгоритме является единица в старшем разряде соответствующего байта (рис. 5.2):
(рис 5.2) Как можно легко подсчитать, в лучшем случае этот алгоритм сжимает файл в 64 раза (а не в 32 раза, как в предыдущем варианте), в худшем увеличивает на 1/128. Средние показатели степени компрессии данного алгоритма находятся на уровне показателей первого варианта.
RLE .Похожие схемы компрессии использованы в качестве одного из алгоритмов, поддерживаемых форматом , а также в формате .
Степени сжатия: Первый вариант: 32, 2, 0,5. Второй вариант: 64, 3, 128/129. (Лучшая, средняя, худшая степени)
Класс изображений: Ориентирован алгоритм на изображения с небольшим количеством цветов: деловую и научную графику.
Симметричность: Примерно единица.
Характерные особенности: К положительным сторонам алгоритма, пожалуй, можно отнести только то, что он не требует дополнительной памяти при
Название алгоритм получил по первым буквам фамилий его разработчиков - Lempel, Ziv и Welch. Сжатие в нем, в отличие от , осуществляется уже за счет одинаковых цепочек байт.
Существует довольно большое семейство LZ-подобных алгоритмов, различающихся, например, методом поиска повторяющихся цепочек. Один из достаточно простых вариантов этого алгоритма, например, предполагает, что во входном потоке идет либо пара <счетчик, смещение относительно текущей позиции>, либо просто <счетчик> "пропускаемых" байт и сами значения байтов (как во втором варианте алгоритма ). При разархивации для пары <счетчик, смещение> копируются <счетчик> байт из выходного массива, полученного в результате разархивации, на <смещение> байт раньше, а <счетчик> (т.е. число равное счетчику) значений "пропускаемых" байт просто копируются в выходной массив из входного
(рис 5.3) При этом мы получим увеличение LZ можно отнести чрезвычайную простоту алгоритма декомпрессии.
LZ, в котором на пару <счетчик, смещение> будет выделено 3 байта, и подсчитайте основные характеристики своего алгоритма.Рассматриваемый нами ниже вариант алгоритма будет использовать дерево для представления и хранения цепочек. Очевидно, что это достаточно сильное ограничение на вид цепочек, и далеко не все одинаковые
Процесс сжатия выглядит достаточно просто. Мы считываем последовательно символы входного потока и проверяем, есть ли в созданной нами таблице строк такая строка. Если строка есть, то мы считываем следующий символ, а если строки нет, то мы заносим в поток код для предыдущей найденной строки, заносим строку в таблицу и начинаем поиск снова.
Функция InitTable() очищает таблицу и помещает в нее все строки единичной длины.
InitTable();
CompressedFile.WriteCode(СlearCode);
CurStr=пустая строка;
while(не ImageFile.EOF()){ //Пока не конец файла
C=ImageFile.ReadNextByte();
if(CurStr+C есть в таблице)
CurStr=CurStr+С;//Приклеить символ к строке
else {
code=CodeForString(CurStr);//code-не байт!
CompressedFile.WriteCode(code);
AddStringToTable (CurStr+С);
CurStr=С; // Строка из одного символа
}
}
code=CodeForString(CurStr);
CompressedFile.WriteCode(code);
CompressedFile.WriteCode(CodeEndOfInformation);
Как говорилось выше, функция InitTable() инициализирует таблицу строк так, чтобы она содержала все возможные строки, состоящие из одного символа. Например, если мы сжимаем байтовые данные, то таких строк в таблице будет 256 ("0", "1", ... , "255"). Для кода очистки (ClearCode) и кода конца информации (CodeEndOfInformation) зарезервированы значения 256 и 257. В рассматриваемом варианте алгоритма используется 12-битный код, и, соответственно, под коды для строк нам остаются значения от 258 до 4095. Добавляемые строки записываются в таблицу последовательно, при этом индекс строки в таблице становится ее кодом.
Функция ReadNextByte() читает символ из файла. Функция WriteCode() записывает код (не равный по размеру байту) в выходной файл. Функция AddStringToTable () добавляет новую строку в таблицу, приписывая ей код. Кроме того, в данной функции происходит обработка ситуации InitTable(). Функция CodeForString() находит строку в таблице и выдает код этой строки.
Пример:
Пусть мы сжимаем последовательность 45, 55, 55, 151, 55, 55, 55. Тогда, согласно изложенному выше алгоритму, мы поместим в выходной поток сначала код очистки <256>, потом добавим к изначально пустой строке "45" и проверим, есть ли строка "45" в таблице. Поскольку мы при инициализации занесли в таблицу все строки из одного символа, то строка "45" есть в таблице. Далее мы читаем следующий символ 55 из входного потока и проверяем, есть ли строка "45, 55" в таблице. Такой строки в таблице пока нет. Мы заносим в таблицу строку "45, 55" (с первым свободным кодом 258) и записываем в поток код <45>. Можно коротко представить
"45" - есть в таблице;
"45, 55" - нет. Добавляем в таблицу <258>"45, 55". В поток: <45>;
"55, 55" - нет. В таблицу: <259>"55, 55". В поток: <55>;
"55, 151" - нет. В таблицу: <260>"55, 151". В поток: <55>;
"151, 55" - нет. В таблицу: <261>"151, 55". В поток: <151>;
"55, 55" - есть в таблице;
"55, 55, 55" - нет. В таблицу: "55, 55, 55" <262>. В поток: <259>;
Последовательность кодов для данного примера, попадающих в выходной поток: <256>, <45>, <55>, <55>, <151>, <259>.
Особенность заключается в том, что для декомпрессии нам не надо сохранять таблицу строк в файл для распаковки. Алгоритм построен таким образом, что мы в состоянии восстановить таблицу строк, пользуясь только потоком кодов.
Мы знаем, что для каждого кода надо добавлять в таблицу строку, состоящую из уже присутствующей там строки и символа, с которого начинается следующая строка в потоке (рис. 5.4).
(рис 5.4) Алгоритм декомпрессии, осуществляющий эту операцию, выглядит следующим образом:
code=File.ReadCode();
while(code != СodeEndOfInformation){
if(code = СlearСode) {
InitTable();
code=File.ReadCode();
if(code = СodeEndOfInformation)
{закончить работу};
ImageFile.WriteString(StrFromTable(code));
old_code=code;
}
else {
if(InTable(code)) {
ImageFile.WriteString(FromTable(code));
AddStringToTable(StrFromTable(old_code)+
FirstChar(StrFromTable(code)));
old_code=code;
}
else {
OutString= StrFromTable(old_code)+
FirstChar(StrFromTable(old_code));
ImageFile.WriteString(OutString);
AddStringToTable(OutString);
old_code=code;
}
}
}
Здесь функция ReadCode() читает очередной код из декомпрессируемого файла. Функция InitTable() выполняет те же действия, что и при компрессии, т.е. очищает таблицу и заносит в нее все строки из одного символа. Функция FirstChar() выдает нам первый символ строки. Функция StrFromTable() выдает строку из таблицы по коду. Функция AddStringToTable() добавляет новую строку в таблицу (присваивая ей первый свободный код). Функция WriteString() записывает строку в файл.
Замечание 1. Как вы могли заметить, записываемые в поток коды постепенно возрастают. До тех пор, пока в таблице не появится, например, в первый раз код 512, все коды будут меньше 512. Кроме того, при компрессии и при декомпрессии коды в таблице добавляются при обработке одного и того же символа, т.е. это происходит "синхронно". Мы можем воспользоваться этим свойством алгоритма для того, чтобы повысить степень компрессии. Пока в таблицу не добавлен 512 символ, мы будем писать в выходной битовый поток коды из 9 бит, а сразу при добавлении 512 - коды из 10 бит. Соответственно декомпрессор также должен будет воспринимать все коды входного потока 9-битными до момента добавления в таблицу кода 512, после чего будет воспринимать все входные коды как 10-битные. Аналогично мы будем поступать при добавлении в таблицу кодов 1024 и 2048. Данный прием позволяет примерно на 15% поднять степень компрессии (рис. 5.5):
(рис 5.5) Замечание 2. При сжатии изображения нам важно обеспечить быстроту поиска строк в таблице. Мы можем воспользоваться тем, что каждая следующая подстрока на один символ длиннее предыдущей, кроме того, предыдущая строка уже была нами найдена в таблице. Следовательно, достаточно создать список ссылок на строки, начинающиеся с данной
Заметим также, что реально нам достаточно хранить в таблице только пару <код предыдущей
На практике для хранения таблицы используется такое же быстрое, как в случае списков, но более компактное по памяти решение - key ). Младшие 12 бит этого числа отданы под код, а следующие 8 бит под значение символа.
В качестве
Index(key)= ((key >> 12) ^ key) 8191;
Где >> - побитовый сдвиг вправо ( key >> 12 - мы получаем значение символа), ^ -
Таким образом, за считанное количество сравнений мы получаем искомый код или сообщение, что такого кода в таблице нет.
Подсчитаем лучшую и худшую степень сжатия для данного алгоритма. Лучшее сжатие, очевидно, будет получено для цепочки одинаковых байт большой длины (т.е. для 8-битного изображения, все точки которого имеют, для определенности, цвет 0). При этом в 258 строку таблицы мы запишем строку "0, 0", в 259 - "0, 0, 0", ... в 4095 - строку из 3839 (=4095-256) нулей. При этом в поток попадет (проверьте по алгоритму!) 3840 кодов, включая код очистки. Следовательно, посчитав сумму арифметической прогрессии от 2 до 3839 (т.е. длину сжатой цепочки) и поделив ее на 3840*12/8 (в поток записываются 12-битные коды), мы получим лучшую степень сжатия.
Худшее сжатие будет получено, если мы ни разу не встретим подстроку, которая уже есть в таблице (в ней не должно встретиться ни одной одинаковой пары символов).
ziinset, arj , gz ). Если вы получите сжатие, значит алгоритм генерации написан неправильно.В случае, если мы постоянно будем встречать новую подстроку, мы запишем в выходной поток 3840 кодов, которым будет соответствовать строка из 3838 символов. Без учета замечания 1 это составит увеличение файла почти в 1.5 раза.
реализован в форматах и .
Степени сжатия: Примерно 1000, 4, 5/7 (Лучшее, среднее, худшее сжатие). Сжатие в 1000 раз достигается только на одноцветных изображениях размером кратным примерно 7 Мб.
Класс изображений: Ориентирован на 8-битные изображения, построенные на компьютере. Сжимает за счет одинаковых
Симметричность: Почти симметричен, при условии оптимальной реализации операции поиска строки в таблице.
Характерные особенности: Ситуация, когда алгоритм увеличивает изображение, встречается крайне редко.
Классический алгоритм Хаффмана был рассмотрен в первой части данной книги. Он практически не применяется к изображениям в чистом виде, а используется как один из этапов компрессии в более сложных схемах.
Близкая модификация алгоритма используется при сжатии черно-белых изображений (один бит на пиксел). Полное название данного алгоритма . Это означает, что данный алгоритм был предложен третьей группой по стандартизации Международного Консультационного Комитета по Телеграфии и Телефонии (
Определение: Набор идущих подряд точек изображения одного цвета называется серией. Длина этого набора точек называется длиной серии.
В таблице, приведенной ниже, заданы два вида кодов:
Каждая строка изображения сжимается независимо. Мы считаем, что в нашем изображении существенно преобладает белый цвет, и все строки изображения начинаются с белой точки. Если строка начинается с черной точки, то мы считаем, что строка начинается белой серией с длиной 0. Например, последовательность длин серий 0, 3, 556, 10, ... означает, что в этой строке изображения идут сначала 3 черных точки, затем 556 белых, затем 10 черных и т.д.
На практике в тех случаях, когда в изображении преобладает черный цвет, мы инвертируем изображение перед компрессией и записываем информацию об этом в заголовок файла.
Алгоритм компрессии выглядит так:
for(по всем строкам изображения) {
Преобразуем строку в набор длин серий;
for(по всем сериям) {
if(серия белая) {
L= длина серии;
while(L > 2623) { // 2623=2560+63
L=L-2560;
ЗаписатьБелыйКодДля(2560);
}
if(L > 63) {
L2=МаксимальныйСостКодМеньшеL(L);
L=L-L2;
ЗаписатьБелыйКодДля(L2);
}
ЗаписатьБелыйКодДля(L);
//Это всегда код завершения
}
else {
[Код аналогичный белой серии,
с той разницей, что записываются
черные коды]
}
}
// Окончание строки изображения
}
Поскольку черные и белые серии чередуются, то реально код для белой и код для черной серии будут работать попеременно.
В терминах
((<Б-2560>)*[<Б-сст.>]<Б-зв.>(<Ч-2560>)*[<Ч-сст.>]<Ч-зв.>)+
[(<Б-2560>)*[<Б-сст.>]<Б-зв.>]
Где ()* - повтор 0 или более раз, ()+.- повтор 1 или более раз, [] - включение 1 или 0 раз.
Для приведенного ранее примера: 0, 3, 556, 10... алгоритм сформирует следующий код: <Б-0><Ч-3><Б-512><Б-44><Ч-10>, или, согласно таблице, 00110101 10 0110010100101101 0000100 (разные коды в потоке выделены для удобства). Этот код обладает свойством
(рис 5.6) Изображение, для которого очень выгодно применение алгоритма CCITT-3. (Большие области заполнены одним цветом) - слева. Изображение, для которого менее выгодно применение алгоритма CCITT-3. (Меньше областей, заполненных одним цветом. Много коротких "черных" и "белых" серий) - справа.Заметим, что единственное "сложное" выражение в нашем алгоритме: L2=МаксимальныйДопКодМеньшеL(L) - на практике работает очень просто: L2=(L>>6)*64, где >> - побитовый сдвиг L влево на 6 битов (можно сделать то же самое за одну побитовую операцию - логическое И).
442, 2, 56, 3, 23, 3, 104, 1, 94, 1, 231, размером 120 байт ((442+2+..+231)/8). Подсчитать степень сжатия этой строки алгоритмом CCITT Group 3.Приведенные ниже таблицы построены с помощью классического алгоритма Хаффмана (отдельно для длин черных и белых серий). Значения вероятностей появления для конкретных длин серий были получены путем анализа большого количества факсимильных изображений.
Таблица
| Длина серии | Код белой |
Код черной |
|---|---|---|
| 0 | 00110101 | 0000110111 |
| 1 | 00111 | 010 |
| 2 | 0111 | 11 |
| 3 | 1000 | 10 |
| 4 | 1011 | 011 |
| 5 | 1100 | 0011 |
| 6 | 1110 | 0010 |
| 7 | 1111 | 00011 |
| 8 | 10011 | 000101 |
| 9 | 10100 | 000100 |
| 10 | 00111 | 0000100 |
| 11 | 01000 | 0000101 |
| 12 | 001000 | 0000111 |
| 13 | 000011 | 00000100 |
| 14 | 110100 | 00000111 |
| 15 | 110101 | 000011000 |
| 16 | 101010 | 0000010111 |
| 17 | 101011 | 0000011000 |
| 18 | 0100111 | 0000001000 |
| 19 | 0001100 | 00001100111 |
| 20 | 0001000 | 00001101000 |
| 21 | 0010111 | 00001101100 |
| 22 | 0000011 | 00000110111 |
| 23 | 0000100 | 00000101000 |
| 24 | 0101000 | 00000010111 |
| 25 | 0101011 | 00000011000 |
| 26 | 0010011 | 000011001010 |
| 27 | 0100100 | 000011001011 |
| 28 | 0011000 | 000011001100 |
| 29 | 00000010 | 000011001101 |
| 30 | 00000011 | 000001101000 |
| 31 | 00011010 | 000001101001 |
| 32 | 00011011 | 000001101010 |
| 33 | 00010010 | 000001101011 |
| 34 | 00010011 | 000011010010 |
| 35 | 00010100 | 000011010011 |
| 36 | 00010101 | 000011010100 |
| 37 | 00010110 | 000011010101 |
| 38 | 00010111 | 000011010110 |
| 39 | 00101000 | 000011010111 |
| 40 | 00101001 | 000001101100 |
| 41 | 00101010 | 000001101101 |
| 42 | 00101011 | 000011011010 |
| 43 | 00101100 | 000011011011 |
| 44 | 00101101 | 000001010100 |
| 45 | 00000100 | 000001010101 |
| 46 | 00000101 | 000001010110 |
| 47 | 00001010 | 000001010111 |
| 48 | 00001011 | 000001100100 |
| 49 | 01010010 | 000001100101 |
| 50 | 01010011 | 000001010010 |
| 51 | 01010100 | 000001010011 |
| 52 | 01010101 | 000000100100 |
| 53 | 00100100 | 000000110111 |
| 54 | 00100101 | 000000111000 |
| 55 | 01011000 | 000000100111 |
| 56 | 01011001 | 000000101000 |
| 57 | 01011010 | 000001011000 |
| 58 | 01011011 | 000001011001 |
| 59 | 01001010 | 000000101011 |
| 60 | 01001011 | 000000101100 |
| 61 | 00110010 | 000001011010 |
| 62 | 00110011 | 000001100110 |
| 63 | 00110100 | 000001100111 |
Таблица составных кодов (табл. 5.2):
| Длина серии | Код белой |
Код черной |
|---|---|---|
| 64 | 11011 | 0000001111 |
| 128 | 10010 | 000011001000 |
| 192 | 01011 | 000011001001 |
| 256 | 0110111 | 000001011011 |
| 320 | 00110110 | 000000110011 |
| 384 | 00110111 | 000000110100 |
| 448 | 01100100 | 000000110101 |
| 512 | 01100101 | 0000001101100 |
| 576 | 01101000 | 0000001101101 |
| 640 | 01100111 | 0000001001010 |
| 704 | 011001100 | 0000001001011 |
| 768 | 011001101 | 0000001001100 |
| 832 | 011010010 | 0000001001101 |
| 896 | 011010011 | 0000001110010 |
| 960 | 011010100 | 0000001110011 |
| 1024 | 011010101 | 0000001110100 |
| 1088 | 011010110 | 0000001110101 |
| 1152 | 011010111 | 0000001110110 |
| 1216 | 011011000 | 0000001110111 |
| 1280 | 011011001 | 0000001010010 |
| 1344 | 011011010 | 0000001010011 |
| 1408 | 011011011 | 0000001010100 |
| 1472 | 010011000 | 0000001010101 |
| 1536 | 010011001 | 0000001011010 |
| 1600 | 010011010 | 0000001011011 |
| 1664 | 011000 | 0000001100100 |
| 1728 | 010011011 | 0000001100101 |
| 1792 | 00000001000 | совп. с белой |
| 1856 | 00000001100 | — // — |
| 1920 | 00000001101 | — // — |
| 1984 | 000000010010 | — // — |
| 2048 | 000000010011 | — // — |
| 2112 | 000000010100 | — // — |
| 2176 | 000000010101 | — // — |
| 2240 | 000000010110 | — // — |
| 2304 | 000000010111 | — // — |
| 2368 | 000000011100 | — // — |
| 2432 | 000000011101 | — // — |
| 2496 | 000000011110 | — // — |
| 2560 | 000000011111 | — // — |
Этот алгоритм реализован в формате
Степени сжатия: лучшая стремится в пределе к 213.(3), средняя 2, в худшем случае увеличивает файл в 5 раз.
Класс изображений: Двуцветные черно-белые изображения, в которых преобладают большие пространства, заполненные белым цветом.
Симметричность: Близка к 1.
Характерные особенности: Данный алгоритм чрезвычайно прост в реализации, быстр и может быть легко реализован аппаратно.
Алгоритм разработан группой экспертов ISO (Joint Bi-level Experts Group) специально для сжатия однобитных черно-белых изображений [5.5]. Например, факсов или отсканированных документов. В принципе, может применяться и к 2-х, и к 4-х битовым картинкам. При этом алгоритм разбивает их на отдельные битовые плоскости. JBIG позволяет управлять такими параметрами, как порядок разбиения изображения на битовые плоскости, ширина полос в изображении, уровни масштабирования. Последняя возможность позволяет легко ориентироваться в базе больших по размерам изображений, просматривая сначала их уменьшенные копии. Настраивая эти параметры, можно использовать описанный выше эффект "огрубленного изображения" при получении изображения по сети или по любому другому каналу, пропускная способность которого мала по сравнению с возможностями процессора. Распаковываться изображение на экране будет постепенно, как бы медленно "проявляясь". При этом человек начинает анализировать картинку задолго до конца процесса разархивации.
Алгоритм построен на базе Q-кодировщика [5.6], патентом на который владеет IBM. Q-кодер, так же как и алгоритм Хаффмана, использует для чаще появляющихся символов короткие цепочки, а для реже появляющихся - длинные. Однако, в отличие от него, в алгоритме используются и последовательности символов.
Этот алгоритм разработан группой экспертов в области фотографии ( Joint Photographic Expert Group ). В отличие от JBIG, Lossless JPEG ориентирован на полноцветные 24-битные или 8-битные в градациях серого изображения без палитры. Он представляет собой специальную реализацию JPEG без потерь. Степени сжатия: 20, 2, 1. Lossless JPEG рекомендуется применять в тех приложениях, где необходимо побитовое соответствие исходного и декомпрессированного изображений. Подробнее об алгоритме сжатия JPEG см. следующий раздел.
Попробуем на этом этапе сделать некоторые обобщения. С одной стороны, приведенные выше алгоритмы достаточно универсальны и покрывают все типы изображений, с другой - у них, по сегодняшним меркам, слишком маленькая степень сжатия. Используя один из алгоритмов сжатия без потерь, можно обеспечить
Справедливости ради следует отметить, что и в классических алгоритмах можно использовать идею когерентности. Существуют алгоритмы обхода изображения по "фрактальной" кривой, при работе которых оно также вытягивается в цепочку; но за счет того, что кривая обегает области изображения по сложной траектории, участки близких цветов в получающейся цепочке удлиняются.
RLE ?RLE , для которых файл максимально увеличится в размере.CCITT G-3?CCITT G-3, для которого файл максимально увеличится в размере. (Приведенный в характеристиках алгоритма ответ не является полным, поскольку требует более "умной" реализации алгоритма.)Данный алгоритм необычайно прост в реализации. Групповое кодирование - от английского Run - один из самых старых и самых простых алгоритмов происходит за счет того, что в исходном изображении встречаются цепочки одинаковых байт. Замена их на пары <счетчик повторений, значение> уменьшает избыточность данных.
Алгоритм декомпрессии при этом выглядит так:
Initialization(...);
do {
byte = ImageFile.ReadNextByte();
if(является счетчиком(byte)) {
counter = Low6bits(byte)+1;
value = ImageFile.ReadNextByte();
for(i=1 to counter) DecompressedFile.WriteByte(value)
}
else {
DecompressedFile.WriteByte(byte)
}
while(!ImageFile.EOF());
В данном алгоритме признаком счетчика ( ) служат единицы в двух верхних битах считанного файла (рис. 5.1):
(рис 5.1) Соответственно оставшиеся 6 бит расходуются на счетчик, который может принимать значения от 1 до 64. Строку из 64 повторяющихся байтов мы превращаем в два байта, т.е. сожмем в 32 раза.
RLE .Алгоритм рассчитан на деловую графику - изображения с большими областями повторяющегося цвета. Ситуация, когда файл увеличивается, для этого простого алгоритма не так уж редка. Ее можно легко получить, применяя групповое кодирование к обработанным цветным фотографиям. Для того, чтобы увеличить изображение в два раза, его надо применить к изображению, в котором значения всех пикселов больше двоичного 11000000 и подряд попарно не повторяются.
RLE . Объясните, почему размер сжатого файла больше размера исходного файла.Данный алгоритм реализован в формате . См. пример в приложении.
Второй вариант этого алгоритма имеет большую
Алгоритм декомпрессии для него выглядит так:
Initialization(...);
do {
byte = ImageFile.ReadNextByte();
counter = Low7bits(byte)+1;
if(если признак повтора(byte)) {
value = ImageFile.ReadNextByte();
for (i=1 to counter) CompressedFile.WriteByte(value)
}
else {
for(i=1 to counter){
value = ImageFile.ReadNextByte();
CompressedFile.WriteByte(value)
}
}
while(!ImageFile.EOF());
Признаком повтора в данном алгоритме является единица в старшем разряде соответствующего байта (рис. 5.2):
(рис 5.2) Как можно легко подсчитать, в лучшем случае этот алгоритм сжимает файл в 64 раза (а не в 32 раза, как в предыдущем варианте), в худшем увеличивает на 1/128. Средние показатели степени компрессии данного алгоритма находятся на уровне показателей первого варианта.
RLE .Похожие схемы компрессии использованы в качестве одного из алгоритмов, поддерживаемых форматом , а также в формате .
Степени сжатия: Первый вариант: 32, 2, 0,5. Второй вариант: 64, 3, 128/129. (Лучшая, средняя, худшая степени)
Класс изображений: Ориентирован алгоритм на изображения с небольшим количеством цветов: деловую и научную графику.
Симметричность: Примерно единица.
Характерные особенности: К положительным сторонам алгоритма, пожалуй, можно отнести только то, что он не требует дополнительной памяти при
Название алгоритм получил по первым буквам фамилий его разработчиков - Lempel, Ziv и Welch. Сжатие в нем, в отличие от , осуществляется уже за счет одинаковых цепочек байт.
Существует довольно большое семейство LZ-подобных алгоритмов, различающихся, например, методом поиска повторяющихся цепочек. Один из достаточно простых вариантов этого алгоритма, например, предполагает, что во входном потоке идет либо пара <счетчик, смещение относительно текущей позиции>, либо просто <счетчик> "пропускаемых" байт и сами значения байтов (как во втором варианте алгоритма ). При разархивации для пары <счетчик, смещение> копируются <счетчик> байт из выходного массива, полученного в результате разархивации, на <смещение> байт раньше, а <счетчик> (т.е. число равное счетчику) значений "пропускаемых" байт просто копируются в выходной массив из входного
(рис 5.3) При этом мы получим увеличение LZ можно отнести чрезвычайную простоту алгоритма декомпрессии.
LZ, в котором на пару <счетчик, смещение> будет выделено 3 байта, и подсчитайте основные характеристики своего алгоритма.Рассматриваемый нами ниже вариант алгоритма будет использовать дерево для представления и хранения цепочек. Очевидно, что это достаточно сильное ограничение на вид цепочек, и далеко не все одинаковые
Процесс сжатия выглядит достаточно просто. Мы считываем последовательно символы входного потока и проверяем, есть ли в созданной нами таблице строк такая строка. Если строка есть, то мы считываем следующий символ, а если строки нет, то мы заносим в поток код для предыдущей найденной строки, заносим строку в таблицу и начинаем поиск снова.
Функция InitTable() очищает таблицу и помещает в нее все строки единичной длины.
InitTable();
CompressedFile.WriteCode(СlearCode);
CurStr=пустая строка;
while(не ImageFile.EOF()){ //Пока не конец файла
C=ImageFile.ReadNextByte();
if(CurStr+C есть в таблице)
CurStr=CurStr+С;//Приклеить символ к строке
else {
code=CodeForString(CurStr);//code-не байт!
CompressedFile.WriteCode(code);
AddStringToTable (CurStr+С);
CurStr=С; // Строка из одного символа
}
}
code=CodeForString(CurStr);
CompressedFile.WriteCode(code);
CompressedFile.WriteCode(CodeEndOfInformation);
Как говорилось выше, функция InitTable() инициализирует таблицу строк так, чтобы она содержала все возможные строки, состоящие из одного символа. Например, если мы сжимаем байтовые данные, то таких строк в таблице будет 256 ("0", "1", ... , "255"). Для кода очистки (ClearCode) и кода конца информации (CodeEndOfInformation) зарезервированы значения 256 и 257. В рассматриваемом варианте алгоритма используется 12-битный код, и, соответственно, под коды для строк нам остаются значения от 258 до 4095. Добавляемые строки записываются в таблицу последовательно, при этом индекс строки в таблице становится ее кодом.
Функция ReadNextByte() читает символ из файла. Функция WriteCode() записывает код (не равный по размеру байту) в выходной файл. Функция AddStringToTable () добавляет новую строку в таблицу, приписывая ей код. Кроме того, в данной функции происходит обработка ситуации InitTable(). Функция CodeForString() находит строку в таблице и выдает код этой строки.
Пример:
Пусть мы сжимаем последовательность 45, 55, 55, 151, 55, 55, 55. Тогда, согласно изложенному выше алгоритму, мы поместим в выходной поток сначала код очистки <256>, потом добавим к изначально пустой строке "45" и проверим, есть ли строка "45" в таблице. Поскольку мы при инициализации занесли в таблицу все строки из одного символа, то строка "45" есть в таблице. Далее мы читаем следующий символ 55 из входного потока и проверяем, есть ли строка "45, 55" в таблице. Такой строки в таблице пока нет. Мы заносим в таблицу строку "45, 55" (с первым свободным кодом 258) и записываем в поток код <45>. Можно коротко представить
"45" - есть в таблице;
"45, 55" - нет. Добавляем в таблицу <258>"45, 55". В поток: <45>;
"55, 55" - нет. В таблицу: <259>"55, 55". В поток: <55>;
"55, 151" - нет. В таблицу: <260>"55, 151". В поток: <55>;
"151, 55" - нет. В таблицу: <261>"151, 55". В поток: <151>;
"55, 55" - есть в таблице;
"55, 55, 55" - нет. В таблицу: "55, 55, 55" <262>. В поток: <259>;
Последовательность кодов для данного примера, попадающих в выходной поток: <256>, <45>, <55>, <55>, <151>, <259>.
Особенность заключается в том, что для декомпрессии нам не надо сохранять таблицу строк в файл для распаковки. Алгоритм построен таким образом, что мы в состоянии восстановить таблицу строк, пользуясь только потоком кодов.
Мы знаем, что для каждого кода надо добавлять в таблицу строку, состоящую из уже присутствующей там строки и символа, с которого начинается следующая строка в потоке (рис. 5.4).
(рис 5.4) Алгоритм декомпрессии, осуществляющий эту операцию, выглядит следующим образом:
code=File.ReadCode();
while(code != СodeEndOfInformation){
if(code = СlearСode) {
InitTable();
code=File.ReadCode();
if(code = СodeEndOfInformation)
{закончить работу};
ImageFile.WriteString(StrFromTable(code));
old_code=code;
}
else {
if(InTable(code)) {
ImageFile.WriteString(FromTable(code));
AddStringToTable(StrFromTable(old_code)+
FirstChar(StrFromTable(code)));
old_code=code;
}
else {
OutString= StrFromTable(old_code)+
FirstChar(StrFromTable(old_code));
ImageFile.WriteString(OutString);
AddStringToTable(OutString);
old_code=code;
}
}
}
Здесь функция ReadCode() читает очередной код из декомпрессируемого файла. Функция InitTable() выполняет те же действия, что и при компрессии, т.е. очищает таблицу и заносит в нее все строки из одного символа. Функция FirstChar() выдает нам первый символ строки. Функция StrFromTable() выдает строку из таблицы по коду. Функция AddStringToTable() добавляет новую строку в таблицу (присваивая ей первый свободный код). Функция WriteString() записывает строку в файл.
Замечание 1. Как вы могли заметить, записываемые в поток коды постепенно возрастают. До тех пор, пока в таблице не появится, например, в первый раз код 512, все коды будут меньше 512. Кроме того, при компрессии и при декомпрессии коды в таблице добавляются при обработке одного и того же символа, т.е. это происходит "синхронно". Мы можем воспользоваться этим свойством алгоритма для того, чтобы повысить степень компрессии. Пока в таблицу не добавлен 512 символ, мы будем писать в выходной битовый поток коды из 9 бит, а сразу при добавлении 512 - коды из 10 бит. Соответственно декомпрессор также должен будет воспринимать все коды входного потока 9-битными до момента добавления в таблицу кода 512, после чего будет воспринимать все входные коды как 10-битные. Аналогично мы будем поступать при добавлении в таблицу кодов 1024 и 2048. Данный прием позволяет примерно на 15% поднять степень компрессии (рис. 5.5):
(рис 5.5) Замечание 2. При сжатии изображения нам важно обеспечить быстроту поиска строк в таблице. Мы можем воспользоваться тем, что каждая следующая подстрока на один символ длиннее предыдущей, кроме того, предыдущая строка уже была нами найдена в таблице. Следовательно, достаточно создать список ссылок на строки, начинающиеся с данной
Заметим также, что реально нам достаточно хранить в таблице только пару <код предыдущей
На практике для хранения таблицы используется такое же быстрое, как в случае списков, но более компактное по памяти решение - key ). Младшие 12 бит этого числа отданы под код, а следующие 8 бит под значение символа.
В качестве
Index(key)= ((key >> 12) ^ key) 8191;
Где >> - побитовый сдвиг вправо ( key >> 12 - мы получаем значение символа), ^ -
Таким образом, за считанное количество сравнений мы получаем искомый код или сообщение, что такого кода в таблице нет.
Подсчитаем лучшую и худшую степень сжатия для данного алгоритма. Лучшее сжатие, очевидно, будет получено для цепочки одинаковых байт большой длины (т.е. для 8-битного изображения, все точки которого имеют, для определенности, цвет 0). При этом в 258 строку таблицы мы запишем строку "0, 0", в 259 - "0, 0, 0", ... в 4095 - строку из 3839 (=4095-256) нулей. При этом в поток попадет (проверьте по алгоритму!) 3840 кодов, включая код очистки. Следовательно, посчитав сумму арифметической прогрессии от 2 до 3839 (т.е. длину сжатой цепочки) и поделив ее на 3840*12/8 (в поток записываются 12-битные коды), мы получим лучшую степень сжатия.
Худшее сжатие будет получено, если мы ни разу не встретим подстроку, которая уже есть в таблице (в ней не должно встретиться ни одной одинаковой пары символов).
ziinset, arj , gz ). Если вы получите сжатие, значит алгоритм генерации написан неправильно.В случае, если мы постоянно будем встречать новую подстроку, мы запишем в выходной поток 3840 кодов, которым будет соответствовать строка из 3838 символов. Без учета замечания 1 это составит увеличение файла почти в 1.5 раза.
реализован в форматах и .
Степени сжатия: Примерно 1000, 4, 5/7 (Лучшее, среднее, худшее сжатие). Сжатие в 1000 раз достигается только на одноцветных изображениях размером кратным примерно 7 Мб.
Класс изображений: Ориентирован на 8-битные изображения, построенные на компьютере. Сжимает за счет одинаковых
Симметричность: Почти симметричен, при условии оптимальной реализации операции поиска строки в таблице.
Характерные особенности: Ситуация, когда алгоритм увеличивает изображение, встречается крайне редко.
Классический алгоритм Хаффмана был рассмотрен в первой части данной книги. Он практически не применяется к изображениям в чистом виде, а используется как один из этапов компрессии в более сложных схемах.
Близкая модификация алгоритма используется при сжатии черно-белых изображений (один бит на пиксел). Полное название данного алгоритма . Это означает, что данный алгоритм был предложен третьей группой по стандартизации Международного Консультационного Комитета по Телеграфии и Телефонии (
Определение: Набор идущих подряд точек изображения одного цвета называется серией. Длина этого набора точек называется длиной серии.
В таблице, приведенной ниже, заданы два вида кодов:
Каждая строка изображения сжимается независимо. Мы считаем, что в нашем изображении существенно преобладает белый цвет, и все строки изображения начинаются с белой точки. Если строка начинается с черной точки, то мы считаем, что строка начинается белой серией с длиной 0. Например, последовательность длин серий 0, 3, 556, 10, ... означает, что в этой строке изображения идут сначала 3 черных точки, затем 556 белых, затем 10 черных и т.д.
На практике в тех случаях, когда в изображении преобладает черный цвет, мы инвертируем изображение перед компрессией и записываем информацию об этом в заголовок файла.
Алгоритм компрессии выглядит так:
for(по всем строкам изображения) {
Преобразуем строку в набор длин серий;
for(по всем сериям) {
if(серия белая) {
L= длина серии;
while(L > 2623) { // 2623=2560+63
L=L-2560;
ЗаписатьБелыйКодДля(2560);
}
if(L > 63) {
L2=МаксимальныйСостКодМеньшеL(L);
L=L-L2;
ЗаписатьБелыйКодДля(L2);
}
ЗаписатьБелыйКодДля(L);
//Это всегда код завершения
}
else {
[Код аналогичный белой серии,
с той разницей, что записываются
черные коды]
}
}
// Окончание строки изображения
}
Поскольку черные и белые серии чередуются, то реально код для белой и код для черной серии будут работать попеременно.
В терминах
((<Б-2560>)*[<Б-сст.>]<Б-зв.>(<Ч-2560>)*[<Ч-сст.>]<Ч-зв.>)+
[(<Б-2560>)*[<Б-сст.>]<Б-зв.>]
Где ()* - повтор 0 или более раз, ()+.- повтор 1 или более раз, [] - включение 1 или 0 раз.
Для приведенного ранее примера: 0, 3, 556, 10... алгоритм сформирует следующий код: <Б-0><Ч-3><Б-512><Б-44><Ч-10>, или, согласно таблице, 00110101 10 0110010100101101 0000100 (разные коды в потоке выделены для удобства). Этот код обладает свойством
(рис 5.6) Изображение, для которого очень выгодно применение алгоритма CCITT-3. (Большие области заполнены одним цветом) - слева. Изображение, для которого менее выгодно применение алгоритма CCITT-3. (Меньше областей, заполненных одним цветом. Много коротких "черных" и "белых" серий) - справа.Заметим, что единственное "сложное" выражение в нашем алгоритме: L2=МаксимальныйДопКодМеньшеL(L) - на практике работает очень просто: L2=(L>>6)*64, где >> - побитовый сдвиг L влево на 6 битов (можно сделать то же самое за одну побитовую операцию - логическое И).
442, 2, 56, 3, 23, 3, 104, 1, 94, 1, 231, размером 120 байт ((442+2+..+231)/8). Подсчитать степень сжатия этой строки алгоритмом CCITT Group 3.Приведенные ниже таблицы построены с помощью классического алгоритма Хаффмана (отдельно для длин черных и белых серий). Значения вероятностей появления для конкретных длин серий были получены путем анализа большого количества факсимильных изображений.
Таблица
| Длина серии | Код белой |
Код черной |
|---|---|---|
| 0 | 00110101 | 0000110111 |
| 1 | 00111 | 010 |
| 2 | 0111 | 11 |
| 3 | 1000 | 10 |
| 4 | 1011 | 011 |
| 5 | 1100 | 0011 |
| 6 | 1110 | 0010 |
| 7 | 1111 | 00011 |
| 8 | 10011 | 000101 |
| 9 | 10100 | 000100 |
| 10 | 00111 | 0000100 |
| 11 | 01000 | 0000101 |
| 12 | 001000 | 0000111 |
| 13 | 000011 | 00000100 |
| 14 | 110100 | 00000111 |
| 15 | 110101 | 000011000 |
| 16 | 101010 | 0000010111 |
| 17 | 101011 | 0000011000 |
| 18 | 0100111 | 0000001000 |
| 19 | 0001100 | 00001100111 |
| 20 | 0001000 | 00001101000 |
| 21 | 0010111 | 00001101100 |
| 22 | 0000011 | 00000110111 |
| 23 | 0000100 | 00000101000 |
| 24 | 0101000 | 00000010111 |
| 25 | 0101011 | 00000011000 |
| 26 | 0010011 | 000011001010 |
| 27 | 0100100 | 000011001011 |
| 28 | 0011000 | 000011001100 |
| 29 | 00000010 | 000011001101 |
| 30 | 00000011 | 000001101000 |
| 31 | 00011010 | 000001101001 |
| 32 | 00011011 | 000001101010 |
| 33 | 00010010 | 000001101011 |
| 34 | 00010011 | 000011010010 |
| 35 | 00010100 | 000011010011 |
| 36 | 00010101 | 000011010100 |
| 37 | 00010110 | 000011010101 |
| 38 | 00010111 | 000011010110 |
| 39 | 00101000 | 000011010111 |
| 40 | 00101001 | 000001101100 |
| 41 | 00101010 | 000001101101 |
| 42 | 00101011 | 000011011010 |
| 43 | 00101100 | 000011011011 |
| 44 | 00101101 | 000001010100 |
| 45 | 00000100 | 000001010101 |
| 46 | 00000101 | 000001010110 |
| 47 | 00001010 | 000001010111 |
| 48 | 00001011 | 000001100100 |
| 49 | 01010010 | 000001100101 |
| 50 | 01010011 | 000001010010 |
| 51 | 01010100 | 000001010011 |
| 52 | 01010101 | 000000100100 |
| 53 | 00100100 | 000000110111 |
| 54 | 00100101 | 000000111000 |
| 55 | 01011000 | 000000100111 |
| 56 | 01011001 | 000000101000 |
| 57 | 01011010 | 000001011000 |
| 58 | 01011011 | 000001011001 |
| 59 | 01001010 | 000000101011 |
| 60 | 01001011 | 000000101100 |
| 61 | 00110010 | 000001011010 |
| 62 | 00110011 | 000001100110 |
| 63 | 00110100 | 000001100111 |
Таблица составных кодов (табл. 5.2):
| Длина серии | Код белой |
Код черной |
|---|---|---|
| 64 | 11011 | 0000001111 |
| 128 | 10010 | 000011001000 |
| 192 | 01011 | 000011001001 |
| 256 | 0110111 | 000001011011 |
| 320 | 00110110 | 000000110011 |
| 384 | 00110111 | 000000110100 |
| 448 | 01100100 | 000000110101 |
| 512 | 01100101 | 0000001101100 |
| 576 | 01101000 | 0000001101101 |
| 640 | 01100111 | 0000001001010 |
| 704 | 011001100 | 0000001001011 |
| 768 | 011001101 | 0000001001100 |
| 832 | 011010010 | 0000001001101 |
| 896 | 011010011 | 0000001110010 |
| 960 | 011010100 | 0000001110011 |
| 1024 | 011010101 | 0000001110100 |
| 1088 | 011010110 | 0000001110101 |
| 1152 | 011010111 | 0000001110110 |
| 1216 | 011011000 | 0000001110111 |
| 1280 | 011011001 | 0000001010010 |
| 1344 | 011011010 | 0000001010011 |
| 1408 | 011011011 | 0000001010100 |
| 1472 | 010011000 | 0000001010101 |
| 1536 | 010011001 | 0000001011010 |
| 1600 | 010011010 | 0000001011011 |
| 1664 | 011000 | 0000001100100 |
| 1728 | 010011011 | 0000001100101 |
| 1792 | 00000001000 | совп. с белой |
| 1856 | 00000001100 | — // — |
| 1920 | 00000001101 | — // — |
| 1984 | 000000010010 | — // — |
| 2048 | 000000010011 | — // — |
| 2112 | 000000010100 | — // — |
| 2176 | 000000010101 | — // — |
| 2240 | 000000010110 | — // — |
| 2304 | 000000010111 | — // — |
| 2368 | 000000011100 | — // — |
| 2432 | 000000011101 | — // — |
| 2496 | 000000011110 | — // — |
| 2560 | 000000011111 | — // — |
Этот алгоритм реализован в формате
Степени сжатия: лучшая стремится в пределе к 213.(3), средняя 2, в худшем случае увеличивает файл в 5 раз.
Класс изображений: Двуцветные черно-белые изображения, в которых преобладают большие пространства, заполненные белым цветом.
Симметричность: Близка к 1.
Характерные особенности: Данный алгоритм чрезвычайно прост в реализации, быстр и может быть легко реализован аппаратно.
Алгоритм разработан группой экспертов ISO (Joint Bi-level Experts Group) специально для сжатия однобитных черно-белых изображений [5.5]. Например, факсов или отсканированных документов. В принципе, может применяться и к 2-х, и к 4-х битовым картинкам. При этом алгоритм разбивает их на отдельные битовые плоскости. JBIG позволяет управлять такими параметрами, как порядок разбиения изображения на битовые плоскости, ширина полос в изображении, уровни масштабирования. Последняя возможность позволяет легко ориентироваться в базе больших по размерам изображений, просматривая сначала их уменьшенные копии. Настраивая эти параметры, можно использовать описанный выше эффект "огрубленного изображения" при получении изображения по сети или по любому другому каналу, пропускная способность которого мала по сравнению с возможностями процессора. Распаковываться изображение на экране будет постепенно, как бы медленно "проявляясь". При этом человек начинает анализировать картинку задолго до конца процесса разархивации.
Алгоритм построен на базе Q-кодировщика [5.6], патентом на который владеет IBM. Q-кодер, так же как и алгоритм Хаффмана, использует для чаще появляющихся символов короткие цепочки, а для реже появляющихся - длинные. Однако, в отличие от него, в алгоритме используются и последовательности символов.
Этот алгоритм разработан группой экспертов в области фотографии ( Joint Photographic Expert Group ). В отличие от JBIG, Lossless JPEG ориентирован на полноцветные 24-битные или 8-битные в градациях серого изображения без палитры. Он представляет собой специальную реализацию JPEG без потерь. Степени сжатия: 20, 2, 1. Lossless JPEG рекомендуется применять в тех приложениях, где необходимо побитовое соответствие исходного и декомпрессированного изображений. Подробнее об алгоритме сжатия JPEG см. следующий раздел.
Попробуем на этом этапе сделать некоторые обобщения. С одной стороны, приведенные выше алгоритмы достаточно универсальны и покрывают все типы изображений, с другой - у них, по сегодняшним меркам, слишком маленькая степень сжатия. Используя один из алгоритмов сжатия без потерь, можно обеспечить
Справедливости ради следует отметить, что и в классических алгоритмах можно использовать идею когерентности. Существуют алгоритмы обхода изображения по "фрактальной" кривой, при работе которых оно также вытягивается в цепочку; но за счет того, что кривая обегает области изображения по сложной траектории, участки близких цветов в получающейся цепочке удлиняются.
RLE ?RLE , для которых файл максимально увеличится в размере.CCITT G-3?CCITT G-3, для которого файл максимально увеличится в размере. (Приведенный в характеристиках алгоритма ответ не является полным, поскольку требует более "умной" реализации алгоритма.)Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.