Text
                    Дж. Миано
ФОРМАТЫ И АЛГОРИТМЫ
СЖАТИЯ ИЗОБРАЖЕНИЙ
В ДЕЙСТВИИ
ACM Press • SIGGRAPH Series
New York, New York
ADDISON-WESLEY
An imprint of Addison Wesley Longman, Inc.
Reading, Massachusetts • Menlo Park, California • New York
Don Mills, Ontario • Harlow, England • Amsterdam • Bonn
Sydney • Singapore • Tokyo • Madrid • San Juan
Paris • Seoul • Milan • Mexico City • Taipei
Издательство
«ТРИУМФ»
Москва

Si Compressed Image File Formats __MBBgggggig|a|r JPEG, PNG, GIF, XBM, BMP John Miano ACM Press • SIGGRAPH Series New York, New York ▼▼ ADDISON-WESLEY An imprint of Addison Wesley Longman, Inc. Reading, Massachusetts • Menlo Park, California • New York Don Mills, Ontario • Harlow, England • Amsterdam • Bonn Sydney • Singapore • Tokyo • Madrid • San Juan Paris • Seoul • Milan • Mexico City • Taipei
УДК 004 Дж. Мнано Форматы и алгоритмы сжатия изображений в жйпав. М.: Издательство Триумф, 2003 — 336 с.: ил. ISBN 5-89392-078-3 ISBN 0-201-60443-4 (амер.) В книге рассмотрены все самые популярные алгоритмы сжатия и форматы хранения растровых изображений. Исходные тексты программ сопровождаются описанием особенностей цветовых моделей, популярным объяснением математических основ сжатия и демонстрацией эффективных способов программной реализации алгоритмов. Authorized translation from the English language edition, entitled COMPRESSED IMAGE FILE FORMATS: JPEG, PNG, GIF, XBM, BMP, 1st Edition by MIANO, JOHN, published by Pearson Education, Inc, publishing as Addison Wesley, Copyright © 1999 by the ACM Press, a division of the Association for Computing Machinery, Inc. (ACM). Ail rights reserved. No part of this book may be reproduced or transmitted in any form or by any means, electronic or mechanical, including photocopying, recording or by any information storage retrieval system, without permission from Pearson Education, Inc. Russian language edition published by TRIUMPH PUBLISHING (ООО «Издательство ТРИУМФ»), Copyright © 2003. Редактор B.H. Печников. Корректор А Н. Левина. Верстка О.И. Воробьева. Дизайн обложки О.В. Русецкая. Подписано в печать с оригинал-макета 05.05.2003 г. Формат 70 х 100/16. Печать офсетная. Печ. л. 21. Заказ № 9809. Тираж 3 000 экз. ООО «Издательство ТРИУМФ». 125438, г. Москва, а/я 18. Лицензия серия ИД № 05434 от 20.07.01 г. Оптовый отдел: (095) 720-07-65 Отпечатано в полном соответствии с качеством предоставленных диапозитивов в ОАО «Можайский полиграфический комбинат» 143200, г. Можайск, ул. Мира, 93 ISBN 5-89392-078-3 ISBN 0-201-60443-4 (амер.) © Обложка, серия, оформление ООО «Издательство ТРИУМФ», 2003
Краткое содержание Подробное содержание находится в конце книги) ГЛАВА 1. Введение..................................11 ГЛАВА 2. Windows BMP...............................41 ГЛАВА 3. ХВМ.......................................53 ГЛАВА 4. Введение в JPEG...........................57 ГЛАВА 5. Формат файлов JPEG........................73 ГЛАВА 6. Кодирование Хаффмана в JPEG...............91 ГЛАВА 7. Дискретное косинусное преобразование.....109 ГЛАВА 8. Декодирование изображений JPEG, сжатых в последовательном режиме........127 ГЛАВА 9. Создание последовательных файлов JPEG....145 ГЛАВА 10. Оптимизация DCT..........................167 ГЛАВА 11. Прогрессивные изображения JPEG...........199 ГЛАВА 12. GIF......................................225 ГЛАВА 13. PNG......................................249 ГЛАВА 14. Развертывание сжатых данных PNG-изображения.........................283 ГЛАВА 15. Создание PNG-файлов......................305 Глоссарий...............................319 Библиография............................325 Солержание компакт-лиска................336
Предисловие Цель этой книги - служить для читателя руководством по написанию программ с возможностями чтения и записи файлов в различных форматах двумерных изображений. Существует множество книг, посвященных форматам фай- лов. Одни из них описывают разнообразные форматы на высоком научном уровне, в других избегают рассмотрения сложных форматов. Мне же хотелось написать книгу о наи- более распространенных форматах файлов так, чтобы чита- тель мог использовать полученные сведения в собственных разработках. В результате размышлений я остановил свой выбор на форматах файлов изображений, которые поддер- живаются Web-браузерами. Форматы (BMP, ХВМ, JPEG, GIF и PNG), рассматриваемые в этой книге, охватывают огром- ное множество файлов изображений, циркулирующих в Ин- тернете. В них используются разнообразные методы коди- рования, а трудность реализации варьируется от очень про- стой до очень сложной. Желание написать эту книгу возникло от разочарования, по- стигшего меня при поиске информации о том, как реализо- вывать кодеры и декодеры для относительно сложных фор- матов файлов. Большая часть доступной информации была излишне детализованной, многое пропускалось, либо изло- жение было слишком трудно для понимания. Я попытался навести мост между программистом и документацией стан- дартов. В самом начале работы над данным проектом возник вопрос: какой язык программирования использовать для исходного кода примеров? Намерение было написать книгу о форматах графических файлов, а не о том, как разрабатывать програм- мы чтения и записи графических файлов на конкретном язы- ке. Поэтому, в качестве возможного варианта рассматривался простой для восприятия язык (например, Pascal или Ada) или язык, который, вероятно, наиболее употребителен (C++). В конце концов, я сделал вывод, что широкое распростране- ние языка C++ делает его наилучшим выбором. Чтобы при- меры были более понятными для программистов, пишущих на языках? отличных от C++, я тщательно избегал некоторых конструкций языка C++ (например, выражений с побочными эффектами и взаимозаменяемостью целых чисел и булевых выражений), которые могли бы затруднить понимание про- граммного кода.
Предисловие 7 Чтобы сделать процессы кодирования и декодирования мак- симально ясными, я использовал Pascal-подобный псевдо- код. На языке C++ писались законченные реализации функ- ций, а псевдокоды использовались в иллюстративных фраг- ментах. Эти фрагменты, как правило, не содержат контроля на ошибки. Из-за большого объема рабочих исходных кодов форматов они не были включены в текст книги. Вместо этого на при- лагаемый к книге компакт-диск записаны полные исход- ные коды кодеров и декодеров почти для всех обсуждае- мых форматов изображений.1 Приводимый в книге псевдо- код помогает читателю уяснить, как действуют описывае- мые процессы, а примеры на C++, которые содержатся на диске, показывают, как следует реализовывать конкретные процедуры. Обычно по числу выполняемых функций декодеры превос- ходят кодеры. В декодерах я реализовал все средства, не- обходимые для декодирования файлов, которые читатель, с какой-либо вероятностью, может встретить в Интернете. Для достижения большей ясности кодеры, как правило, реализуют сокращенный набор функциональных возмож- ностей. При написании примеров программ предпочтение отдавалось понятности перед эффективностью исполнения и межплат- форменной переносимостью. Исходный программный код примеров компилируется без каких-либо изменений в среде Microsoft Windows с использованием как Borland C++ Builder 3, так и Microsoft Visual C++ 5.0. Другие компиляторы, обычно, требуют некоторой модификации кода. В описаниях кодеров и декодеров для различных форматов файлов часто встречается термин «пользователь», указы- вающий источник определенных входных параметров в процессе кодирования или декодирования. Под ним пони- мается пользователь кодера или декодера, а необязательно лицо, вводящее данные с клавиатуры. Поскольку кодеры и декодеры изображений встраиваются в другие программы, такие как программы просмотра изображений и графиче- ские редакторы, то в этих случаях в качестве «пользовате- ля» будет выступать другая часть программы. Тем не менее, №-за юридических проблем единственным исключением является формат GIF.
Форматы и алгоритмы сжатия изображений в действии во многих ситуациях программа-лпользователь» может по- лучать некоторые из входных параметров непосредственно от человека. Эта книга не претендует быть пособием по программиро- ванию на языке C++, точно также ее не следует рассматри- вать в качестве руководства по программированию в кон- кретной операционной среде. Для получения необходимой информации читателю потребуется книга по его конкрет- ной системе.
Выражение благодарности Такой крупный проект, как издание книги, требует усилий многих людей. Майк Бейли (Mike Bailey), Эрик Хейнс (Eric Haines), Шоун Хили (Shawn Heely) и Глен Рандерс-Персон (Glenn Randers-Pehrson) редактировали рукопись и внесли много ценных предложений. Глен (Glenn) также помог мне получить последние версии стандартов PNG для компакт- диска. Мой знакомый пилот Чарли Бауман (Charlie Baumann) был настолько добр, что предоставил мне ряд фотографий. Ральф Миано (Ralph Miano) и Маргарет Миано (Margaret Miano) помогали в подготовке рукописи. Жан-Луп Гэйли (Jean-Loup Gailey) ответил на все мои вопросы по ZLIB. Аль- берт Коппер (Albert Copper), «кодировщик» (chipster), компи- лировал примеры на системах, к которым у меня не было доступа. Но самая главная роль выпала Елене Голдштейн (Helen Goldstein) из компании AWL, которая осуществляла общее руководство всем процессом подготовки издания от начала до конца. Джон М. Миано (John М. Miano) Саммит, штат Нью-Джерси (Summit, New Jersey) miano@colosseumbuilders. com
ГЛАВА 1. Введение В этой главе рассматриваются фундаментальные вопросы форматов графических файлов. Здесь вы найдете введение в растровые изображения, в способы представления цвета и методы сжатия. Представление изображений В большинстве компьютерных дисплеев экранное изображе- ние формируется из дискретных элементов, называемых пик- селами. Каждый пиксел занимает на экране небольшую пря- моугольную область, которая в любой момент времени ото- бражается в одном цвете. Пикселы упорядочены в виде дву- мерного массива. На экране объекты прорисовываются путем установки цветов отдельных пикселов. На Рис. 1.1 показан идеальный тре- угольник и его представление в виде пикселов. Пиксельное представление отличается зубчатыми краями, не особо ра- дующими глаз. Чем плотнее упакованы пикселы на устройст- ве отображения, тем менее заметна неровность краев. Рис. 1.1. Идеальное изображение и его пиксельное представление За прошедшие годы число пикселов, отображаемых на мони- торах PC, значительно возросло. Не так давно стандартным считалось отображение на экране 640x480 (307200) пикселов. Сейчас обычное разрешение мониторов составляет 1024x768 (786432), 1280x1024 (1310720) пикселов и даже больше. Чис- ло пикселов, которое может отображать компьютерная сис- тема, ограничивается объемом видеопамяти и возможностя- ми монитора и видеоадаптера.
12 Форматы и алгоритмы сжатия изображений в действии Рис. 1.2 служит иллюстрацией состава типичной видеосис- темы. Буфер кадров представляет собой блок видеопамяти, который управляет цветом каждого пиксела на мониторе. В видеопамяти каждому пикселу соответствует ячейка, раз- мер которой обычно варьируется в пределах от 1 до 32 би- тов. Во многих системах допускается как чтение, так и за- пись в видеопамять, точно так же, как для любого другого вида памяти. Программа может изменять цвет, отображае- мый на мониторе, путем простого изменения значения соот- ветствующей ячейки в памяти. Видеоконтроллер преобразу- ет значения в буфере кадров в сигнал, который может ото- бражаться монитором. Рис. 1.2. Простая видеосистема Для вывода изображений используются также компьютерные принтеры. В настоящее время большинство принтеров по своему принципу работы сходны с видеосистемами. Изобра- жение разбивается в принтере на множество пикселов, но с гораздо большей плотностью, чем на компьютерных монито- рах, обычно при печати на офисном принтере на дюйме раз- мещается 300 или 600 точек. Принтеры, спроектированные для систем верстки, печатают с еще большей плотностью. Принтер содержит память, аналогичную буферу кадров, за исключением того, что данные передаются по последова- тельному или параллельному кабелю, а не напрямую по сис- темной шине. Изображение формируется в памяти принтера, а затем переносится на печатную страницу.
Введение 13 Не все принтеры работают по принципу отображения памяти в точки. Плоттеры, применяемые для черчения и других ин- женерных работ, оснащены пером, управляемым командами, такими как рисование линии от одной точки к другой, рисо- вание эллипса внутри заданного прямоугольника или рисова- ние в некотором месте текста с использованием заданного шрифта1. Векторная и растровая графика Рис. 1.3. Простое векторное изображение Так же, как существует два принципа работы устройств ото- бражения, так и форматы графических файлов можно разде- лить на два общих класса: векторные и растровые2. Вектор- ные графические форматы для представления изображения используют последовательности команд рисования. Широко распространенным векторным графическим форматом явля- ется метафайл Windows. На Рис. 1.3 показано простое вектор- ное изображение, созданное с помощью команд рисования двух дуг и прямоугольника. Применение векторных графических форматов не ограничи- вается устройствами вывода, такими, как плоттеры, которые рисуют изображения через посредство команд. Компьютер- ные мониторы и лазерные принтеры обычно оснащены про- граммным обеспечением, преобразующим векторные коман- ды в пикселы. Векторной графике присущи два основных недостатка. Во- первых, они не подходят для воспроизведения фотографий или живописи. Для отображения такой картины, как «Мать» Вистлера (Whistler), потребовались бы десятки тысяч команд рисования - даже просто определение набора команд, необ- ходимых для прорисовки картины, было бы труднейшей за- дачей. Во-вторых, воспроизведение сложных изображений требует много времени. В большинстве систем отображения каждый векторный объект должен преобразовываться в пик- сельное изображение. В В прежние времена по такому же принципу работали графические мониторы. ' Термин «растровый графический формат» представляет собой общепринятый синоним термина «точечный графический формат».
14 Форматы и алгоритмы сжатия изображений в действии Все форматы изображений, рассматриваемые в этой книге, относятся к растровым графическим форматам. В таких фор- матах изображения представляются в виде двумерных масси- вов, где каждый элемент массива определяет цвет, который должен отображаться в заданном местоположении. При вы- воде на экран компьютера каждый элемент массива обычно отображается в один экранный пиксел. Если в устройстве отображения пикселы расположены достаточно плотно, че- ловеческому глазу трудно заметить структуру массива точек, который составляет изображение. Наибольшее преимущество растровых изображений состо- ит в их качестве. По мере увеличения вместе со скоростью процессоров объема дискового пространства и памяти расширяется и использование растровых изображений. Одним из самых заметных примеров этого является от- расль компьютерных игр. В настоящее время даже игры, требующие высокого быстродействия, такие, как авиаци- онные симуляторы и стрелялки используют растровую графику. Сопоставьте графику в таких играх, как Quake или Doom, с векторной графикой танка (Tank) или даже мертвой звезды (Death Star) в оригинальном фильме «Звездные войны» (Star Wars). Основной недостаток растровых изображений в большом объеме данных, необходимых для их воспроизведения. Раз- мер изображения в байтах (без учета избыточных битов) со- ставляет: ширина х высота х число битов на пиксел + 7 8 Таким образом, для отображения или хранения изображения размером 600x800, с 24 битами на пиксел, потребуется 1440000 байтов памяти или дискового пространства. С рос- том объема памяти компьютеров увеличиваются также число и размеры изображейий, которые могут отображаться одно- временно. Для уменьшения пространства, занимаемого фай- лом изображения на диске, обычно применяется сжатие, по- зволяющее хранить большее число изображений.
Введение 15 Другим недостатком растровых изображений является то, что они зависимы от размера и непригодны для обширного ре- дактирования. При работе с векторными форматами про- грамме рисования нетрудно добавлять, удалять и модифици- ровать отдельные элементы. Кроме того, над векторным изо- бражением несложно выполнять преобразования, такие, как построение перспективы, укрупнение и масштабирование. Для растровых изображений даже изменение размера связано с проблемами. При уменьшении размеров часть информации утрачивается; при укрупнении изображения возникают эф- фекты блочности. Рис. 1.4 иллюстрирует проблему, возни- кающую при увеличении размеров растрового изображения путем дублирования пикселов. Существуют методы сглажи- вания, позволяющие улучшать внешний вид масштабирован- ных изображений. Рис. 1.4. Растровое изображение и его увеличение В Таблице 1.1 обобщены преимущества векторной и растро- вой графики. Важно отметить, что ни одному из методов нельзя отдать полного предпочтения - для каждого из них существуют свои области применения. В действитель- ности некоторые программы используют комбинацию двух технологий.
16 Форматы и алгоритмы сжатия изображений в действие Таблица 1.1. Сопоставление растровой и векторной графики Растровая графика Векторная графика Скорость х отображения Качество изображения Использование X памяти Легкость х редактирования Аппаратная независимость Цветовые модели В предыдущем разделе мы видели, что в растровом изобра- жении каждому пикселу соответствует значение, задающее его цвет. Каким же образом числовое значение преобразуется в цвет? Известно множество способов численного представления цве- тов. Система представления цветов называется цветовой моде- лью. Цветовые модели обычно разработаны так, чтобы исполь- зовать достоинства устройств отображения конкретного типа. В большинстве цветных мониторов для каждого пиксела ис- пользуются три люминофора (красный, зеленый и синий) или три светоизлучателя. Настраивая яркости отдельных люми- нофоров, можно управлять цветом пиксела. Когда яркость всех трех люминофоров минимальна, пиксел выглядит чер- ным. При максимальной яркости пиксел выглядит белым. Если активен только красный люминофор, пиксел выглядит красным. Когда активны только красный и зеленый люмино- форы, они комбинируются и образуют оттенки желтого цве- та, а когда все три люминофора светятся в полную яркость, пиксел выглядит белым. Наиболее общепринятая цветовая модель, применяемая в компьютерных программах, известна как RGB (Red-Green- Blue - Красный-Зеленый-Синий). Модель RGB отражает ра- боту компьютерных дисплеев. В модели RGB цвета получа- ются сложением трех компонентов, которые представляют относительные яркости красного, зеленого и синего цветов.
Введение 17 На Рис. 1.5 показана взаимосвязь цветов в цветовой модели RGB. Диапазон цветов, которые могут быть представлены цветовой моделью, называют цветовым пространством. На Рис. 1.5 цветовым пространством RGB является куб, постро- енный на осях диаграммы. Рис. 1.5. иветовая модель RGB При математическом описании цвета, значения компонентов часто представляют в виде действительных чисел, нормиро- ванных относительно диапазона от 0,0 до 1,0. В программи- ровании и форматах изображений в качестве значений ком- понентов почти всегда используют целые числа без знака. Диапазон значений для компонента цвета определяется точ- ностью дискретизации (sample precision), которая равна ко- личеству битов, используемых для представления цветового компонента. Для фотографических изображений чаще всего точность дискретизации равна 8 битам. Тем не менее, обще- употребительны и значения 1, 2, 4, 12 и 16 битов. Целочисленные значения компонентов могут находиться в до 2 - ' ’ -1. Для перехода от представления цвета нормированным действительным чис- лом к представлению целым числом, его следует просто ум- ножить на 2пють-дискретизации-\. В системе Windows точность дискретизации почти всегда равна 8 битам, поэтому операционная система (но не обяза- тельно аппаратура) распознает 256 различных оттенков каж- дого основного цвета. Другие системы могут использовать большую или меньшую точность дискретизации.
18 Форматы и алгоритмы сжатия изображений в действии Полутоновая шкала Некоторые устройства отображения, такие как лазерные принтеры, могут отображать цвета только в оттенках серого цвета. Такие устройства относятся к полутоновым устройст- вам. Оттенки серого цвета могут быть представлены одним компонентом в диапазоне от 0 (черный цвет) до ^точностЪ-дискретизации (белый цвет). щ рис L5 видн0; чт0 от. тенки серого цвета, присутствующие в цветовой модели RGB, располагаются вдоль прямой, для которой R=G=B. Цветовая модель YCbCr Модель RGB не единственная используемая цветовая модель. Некогда в компьютерных системах широко применялась цве- товая модель HSB (Hue-Saturation-Brightness - Цветовой тон- насыщенность-яркость), которая до сих пор используется в некоторых программах обработки изображений. Изображе- ния в формате JPEG почти всегда сохраняются с использова- нием трехкомпонентного цветового пространства, известного как YCbCr. Компонент Y, или яркость (luminance) представ- ляет яркость изображения. Компоненты СЬ и Сг определяют цветность (chrominance). Значение СЬ задает синеву (blueness) изображения, а значение Сг задает его красноту (redness). Цветовая модель YCbCr подобна цветовой модели, исполь- зуемой в телевизионных приемниках, что обеспечивает со- вместимость цветных изображений с черно-белыми теле- визорами. В цветовой модели YCbCr компонент Y сам по себе является полутоновым представлением цветного изо- бражения. Соотношение между цветовыми моделями YCbCr и RGB, ис- пользуемое в формате JPEG, описывается Уравнением 1.1. Уравнение 1.1. Взаимосвязь между цветовыми пространствами YCbCr/RCB Y = 0.2995 + 0.587G + 0.1145 СЬ = -0.16875 - 0.3313G + 0.55 + 2mm“ocmb-ducKpemula'tu"11 Сг = 0.55 - 0.4187G - 0.08135 + 2то'“,ость-'>‘“:кРетю‘п<“‘‘11 R = Y + 1.402Сг q = у _ Q 34414(06 — '2,точиость_^искРвтизации1^ „ о 71414(Сг — 2mo4Mcmb-^UCKPemu3a4uu^ В — у + 1 722 (СЬ — 2точйасть“^иск^‘!ти^ии^)
Введение Рис. 1.6. Цветное изображение, разделенное на компоненты Y, СЬ и С г
20 Форматы и алгоритмы сжатия изображений в действии На Рис. 1.6 показано цветное изображение, разделенное на компоненты Y, СЬ и Сг. Можно заметить, что большую часть информации в изображении определяет компонент Y. В отличие от цветовой модели RGB, где все компоненты примерно равнозначны, цветовая модель YcbCr концентри- рует наиболее важную информацию в одном из компонен- тов. Это позволяет добиться большего сжатия путем вклю- чения большего объема данных по компоненту Y, чем по компонентам СЬ и Сг. Цветовая модель CMYK Еще одной цветовой моделью, достойной упоминания здесь, является четырехкомпонентная модель, упоминае- мая как CMYK (Cyan, magenta, yellow, black - Голубой, пурпурный, желтый, черный). Она часто используется в цветной печати. Большинство печатных работ выполняется на белой бумаге с помощью типографской краски, добав- ляемой для создания более темных цветов. Такой способ получения цвета противоположен методу формирования цвета на компьютерном мониторе. Цветовое пространство CMYK соответствует модели печати (printing model). Ком- поненты представляют четыре краски, обычно употреб- ляемые в цветной печати. Цветовые модели, которые мы рассматривали до сих пор, относятся к аддитивным моделям. Это означает, что ком- поненты добавляют цвет в изображение. Чем выше значе- ние компонента, тем ближе цвет к белому. Однако в моде- ли CMYK большие значения компонентов представляют цвета, более близкие к черному цвету. Такие модели из- вестны как субстрактивные. Голубой, пурпурный и желтый цвета служат дополнениями для красного, синего и зелено- го цветов. Чисто голубая поверхность поглощает весь красный свет, направленный на нее. Если комбинировать желтую и пурпурную краски, .они поглощают зеленый и синий свет, что приводит к красному цвету. При комбини- ровании голубой, пурпурной и желтой красок поглощается весь свет, что приводит к черному цвету - по крайней ме- ре, теоретически.
Введение 21 На практике, при комбинировании голубой, пурпурной и желтой красок на листе белой бумаги не создается чистый черный цвет. Но даже если вы сможете получить хороший оттенок черного цвета путем комбинирования цветов, это по- требует втрое больше краски, по сравнению с использовани- ем одного черного цвета. А поскольку большинство печат- ных работ выполняется в черном цвете, для создания черного цвета и оттенков серого цвета предпочтительно использовать черную краску. Взаимосвязь между цветовыми моделями CMYK и RGB в компьютерном мониторе можно аппроксимировать Уравне- нием 1.2. Уравнение 10.21. Взаимосвязь между цветовыми пространствами CMYK/RCB К = (2. шочность^искретизации/! _ _ MAX(R G В^ — ^точность^дискретизации/! „ Q _ R _ у — ^2точность_дискретизации/2 _ _ (J. _ М = ^2точность_дискретизации/2 _ Q _ Q _ r — ^2 точмость_дискретизт{ии/2 _ Q _ __ G ~ ^2/,,о'1Н1>с"!Ь~<>искРетизачы^‘2 _ Q _ у q = ^2точностъ_дискретизации/2 „ Q _ Когда значения компонентов С, M и Y равны, цвет пред- ставляет собой оттенок серого цвета. Обратите внимание, как при преобразовании цветовых пространств из RGB в CMYK заменяются голубая, пурпурная и желтая краски от- тенками серого цвета, создаваемого черной краской. В ре- зультате такой замены, по крайней мере, один компонент CMY всегда должен быть равен нулю, если данный процесс преобразования выполняется в точности так, как это пока- зано здесь. Цветовая модель CMYK не требует, чтобы зна- чение одного из компонентов равнялось нулю - это просто результат преобразования из RGB. Программы, использую- щие цветовую модель CMYK, должны позволять получать любую комбинацию значений компонентов для обеспечения полного контроля над печатными цветами и возможности варьирования различными типами типографских красок. Еще одно обстоятельство, которое следует отметить в отно- шении цветовой модели CMYK, заключается в том, что меж- ду этой моделью и RGB нет взаимно однозначного соответ- ствия. Напротив, на одно и то же значение RGB отображает- ся множество значений CMYK.
22 Форматы и алгоритмы сжатия изображений в действии Сравнение истинного цвета и палитры В примерах этой книги предполагается, что для отображения изображений устройство вывода использует цветовую мо- дель RGB, и что значение каждого компонента определяется 8 битами и находится в диапазоне 0—256? Данное представ- ление цвета применяется в большинстве систем персональ- ных компьютеров. Такая система может воспроизводить 16777216 (2563) различных цветов. Существуют компьютер- ные системы, которые для представления цвета используют большее число битов, например, для медицинских изображе- ний часто применяется 12-битовая полутоновая шкала. Неко- торые форматы изображений поддерживают данные с более чем 8 битами на компонент (12 для JPEG, 16 для PNG). В ос- тальной части этого раздела предполагается, что вы работае- те с системой, в которой значения компонентов определяют- ся 8 битами. Для назначения пикселу одного из возможных цветов обыч- но используют два способа. Простейший способ заключает- ся в сохранении в сжатых данных цветового значения каж- дого пиксела. Для изображений с 24 битами на пиксел с ка- ждым пикселом связано 3-байтовое значение цвета. Счита- ется, что изображения, использующие 24 или более битов на пиксел, отображаются в истинном цвете (true color), так как для диапазона цветов, воспроизводимых монитором, 24 би- та на пиксел являются тем пределом, при котором получае- мые цветовые оттенки еще могут различаться человеческим глазом. Проблема, присущая 24-битовой графике, заключается в том, что хотя система позволяет отображать 16777216 различных цветов, она может оказаться неспособной выводить все цвета одновременно. В устаревших компьютерах может даже от- сутствовать видеоплата, обеспечивающая работу дисплея в 24-битовом режиме. В более новых компьютерах может не хватать объема видеопамяти, которая требуется для работы в 24-битовом режиме при высоких разрешениях экрана. Дис- плей персонального компьютера, установленный на разреше- ние 1024x768 пикселов, потребует 2359296 (1024x768x3=2,25 Мбайт) видеопамяти для отображения 24-битовых изображе- 3 Чтобы не углубляться чрезмерно в детали реализации конкретных систем, в данной главе работа устройств отображения рассматривается упрощенно.
ведение 23 ний. Если в компьютере установлено только 2 Мбайта видео- памяти, он не сможет выводить на экран 24-битовые изобра- жения при таком высоком разрешении, но сможет делать это при меньшем разрешении 800x600 (800x600x3=1,4 Мбайт). Решение, использовавшееся для представления цветов до то- го, как появились дисплеи, способные отображать изображе- ния с 24 битами на пиксел, заключалось в определении цве- товой палитры, состоявшей из подмножества возможных цветов. В абстрактном виде палитра - это одномерный мас- сив 3-байтовых элементов, которые определяют цвет. Вместо того чтобы напрямую задавать цвет, значение каждого пик- села служит указателем в цветовой палитре. В палитре с са- мым распространенным размером в 256 элементов значение каждого пиксела определяется 8 битами. Большинство со- временных компьютеров могут отображать 8-битовую гра- фику при всех разрешениях дисплея, но в очень старых ком- пьютерах размер палитры ограничивался даже еще меньши- ми размерами. Изображения с 24 или более битами на пиксел никогда не ис- пользуют палитру для указания цвета, так как для определения указателя в палитре потребовалось бы больше битов, чем для прямого указания цвета. По существу, форматы файлов растровых изображений пред- ставляют цвета тем же способом, что и компьютерные дис- плеи. Некоторые задают значение цвета для каждого пиксела, некоторые используют цветовую палитру, а другие поддер- живают оба метода. В Таблице 1.2 показаны методы, исполь- зуемые для представления цветов различными форматами изображений. WiBti 1.2. 'Найгчплы щцрвасввления 1веа Формат С помошью палитры Задание значения цвета BMP X X JPEG X GIF X X PNG X X
24 Форматы и алгоритмы сжатия изображений в действии Форматы файлов, использующие для указания цвета палитру, могут указывать значения пикселов с помощью числа бито1 меньшего 8, чтобы уменьшить размер файла. Для храненш изображения с 4 битами на пиксел требуется вдвое меньше< пространство, чем для изображения того же размера с 8 би- тами на пиксел. Для изображений, с ограниченным числом цветов, таких как мультипликации, простой способ уменьше- ния размера файла состоит в уменьшении точности дискрети- зации (sample precision). Сжатие изображений Поскольку цветные растровые изображения обычно требуки более мегабайта для своего хранения, большинство форматов файлов изображений включают технологии сжатия. Техноло- гии сжатия основаны на повторяемости отдельных участков внутри данных изображения для поиска эквивалентного представления, занимающего меньший объем. Сжатие пол- ностью случайных данных невозможно. Ниже приведено краткое описание технологий сжатия, реа- лизованных в форматах изображений, которые рассматрива- ются в этой книге. В Таблице 1.3 приводятся методы сжатия, используемые каждым форматом. Таблииа 1.3. BMP GIF PNG JPEG используемые RLE X X различными 1 7 форматами файлов Huffman X X DCT X ✓ Метол RLE (Run Length Encoding - Кодирование длин серий), i Последовательные пикселы с одинаковым значением коди- руются с помощью пары чисел, включающих длину серии (run length) и значение пиксела. Например, 9 повторяющихся пикселов со значением равным 8, можно представить в виде 2-байтовой последовательности: 0916 0816 вместо 0816 0816 08]б 0816 0816 08|б 0816 0816
Введение 22 ✓ Кодирование LZ. Программа сжатия ведет словарь, содержа- щий уже встречавшиеся последовательности значений пик- селов. Сжатый поток содержит коды, указывающие элемеь ты словаря. ✓ Кодирование Хаффмана (Huffman). Вместо использования длг представления значений компонентов фиксированного числг. битов, используются коды переменной длины. Значениям которые повторяются чаще, присваиваются более короткие коды. ✓ Метод DCT (Discrete Cosine Transform - Дискретное косинусное преобразование). Блоки пикселов представляются с помощьк косинусных функций с разными частотами. Высокие часто- ты, которые обычно вносят малый вклад в данные изображе- ний, отбрасываются. Эффективность технологий сжатия зависит от типа данш На Рис. 1.7 приведена фотография, а на Рис. 1.8 показан сунок. Фотография содержит много областей с неболыш изменениями цвета, в то время как в рисунке присутств крупные области одинакового цвета. Рис. 1.7. Фотография IRENE.BMP
26 Форматы и алгоритмы сжатия изображений в действии Рис. 1.8. Рисунок STARS.BMP На Рис. 1.9 показаны относительные размеры файлов, по- лучаемых при сжатии фотографии на Рис. 1.7 с использо- ванием разных форматов: несжатый BMP-файл, ВМР-файл с RLE-кодированием, файлы в форматах GIF, PNG и JPEG. Обратите внимание, что форматы BMP-RLE и GIF характе- ризуются очень малой степенью сжатия данных, в то время как PNG и особенно JPEG существенно уменьшают размер файла. Рис. 1.9. Размеры сжатых файлов в процентах относительно размера файла IRENA.BMP BMP BMP-RLE GIF PNG JPEG На Рис. 1.10 показан подобный график, но на этот раз, Рис. 1.8, можно заметить, что для данного изображения другие форма- ты файлов обеспечивают почти такой же уровень сжатия, что и формат JPEG.
Введение 27 Рис. 1.10. Размеры сжатых файлов в процентах относительно размера файла STARS.BMP Сопоставление сжатия без потерь со сжатием с потерями данных Большинство форматов файлов изображений используют так называемое сжатие без потерь. Под этим понимается, что если взять изображение, сжать его, используя техноло- гию сжатия без потерь, и затем восстановить, то получив- шееся изображение будет идентично оригиналу с точностью до бита. Некоторые способы сжатия (особенно JPEG) относятся к ме- тодам сжатия с потерями данных. Используя упомянутую выше последовательность операций сжатия-распаковки, ме- тод сжатия с потерями дает изображение, которое хотя и близко к оригиналу, но не совпадает с ним полностью. То есть, пиксел со значением RGB-цвета равным (128, 243, 118) в исходном (несжатом) изображении после сжатия и восста- новления изображения может измениться до значения цвета (127, 243, 119). При сжатии изображений методы сжатия с потерями используют тот факт, что человеческому глазу трудно различить почти одинаковые цвета. Причина использования методов сжатия с потерями заключа- ется в том, что, в общем случае, они обеспечивают гораздо большую степень сжатия, чем методы сжатия без потерь. Во многих ситуациях небольшие потери данных допустимы и компенсируются ростом степени сжатия.
28 Форматы и алгоритмы сжатия изображений в действии Порядок расположения байтов и битов Все файлы растровых изображений содержат целые числа, хранящиеся в двоичном формате. Для однобайтовых целых чисел проблемы совместимости с процессорами различных типов не существует. Это не так в случае с многобайтовыми целыми числами. При чтении многобайтовых целых чисел возникает вопрос: каким образом расположить в целом числе байты из входного потока данных? Предположим, что файл изображения содержит последовательность из следующих двух байтов: 0 1 1 0 0 0 1 1 (6316) 0 0 0 1 1 1 0 1 (1D16) Самый старший бит Самый младший бит Если эти байты составляют 2-байтовое целое число, то сле- дует ли их интерпретировать как: 00011101 01100011 (1D63,6) 7,52310 или 01100011 00011101 (631D16) 25,373ю Иными словами, где в многобайтовом целом числе должен стоять старший байт: на первом или на последнем месте в файле? Ответ на этот вопрос зависит от типа файла. Некоторые фор- маты требуют, чтобы старший байт сохранялся первым; в других форматах на первом месте хранится младший байт. Почему бы не упорядочить байты в файле изображения так, чтобы простая операция чтения, подобная приводимой ниже, корректно считывала целые числа? unsigned int value ; inputstream.read ((char *) &value, sizeof (value)) ;
Введение 29 Проблема состоит в том, что процессоры различных типов упорядочивают целые числа по-разному, и простое считы- вание необработанных байтов в целочисленную перемен- ную не будет срабатывать для всех типов процессоров. Большинство используемых процессоров, включая семейст- ва Motorola 680x0 и Sun SPARC, хранят целые числа со старшим байтом на первом месте. Этот порядок байтов из- вестен как обратный (big-endian). Он известен также как се- тевой порядок, поскольку используется в протоколе Интер- нета. Процессоры, которые хранят целые числа с младшим байтом на первом месте, известны как процессоры с прямым порядком (little-endian). Самыми распространенными про- цессорами с прямым порядком байтов являются процессоры семейства Intel 80x86, которые используются в персональ- ных компьютерах. В приводимом примере программный код формирует разные выходные данные, в зависимости от того, исполняется ли он в системе с прямым или обратным порядком. #include <iostream> using namespace std ; main () { unsigned short value = 1 ; unsigned char *ptr = (unsigned char *) &value ; if (*ptr == 1) cout << "I'm Little-Endian" << endl ; else cout << "I'm Big-Endian" << endl ; return 0 ; } Преобразование между форматами с прямым и обратным по- рядком заключается всего лишь в перестановке байтов и одинаково в обоих направлениях. Для 2-байтового целого числа преобразование таково: unsigned short SwapBytes (unsigned short source) { unsigned short destination ;
30 Форматы и алгоритмы сжатия изображений в действии destination = ((source & OxFF) << 8) | ((source & OxFFOO) » 8) ; return source ; } А 4-байтовые целые числа преобразуются как: unsigned long SwapBytes (unsigned long source) { unsigned long destination ; destination = ((source & OxOOOOOOFFL) << 24) | ((source & OxOOOOFFOOL) << 8) | ((source & OxOOFFOOOOL) >> 8) | ((source & OxFFOOOOOOL) >> 24); return destination ; } В приведенных примерах программ предполагается, что длинное целое число (long) составляет 32 бита, а короткое целое число (short) - 16 битов. Это верно для большинства операционных систем, но не для всех. Каков бы ни был тип процессора, при обработке всего байта порядок битов внутри байта одинаков. Однако порядок бито- вых строк внутри отдельных байтов является более тонким вопросом. Компьютерные процессоры работают только с полными байтами. При обработке сжатых данных часто тре- буется обрабатывать битовые строки, границы которых не совпадают с границами байтов. Битовые строки могут извле- каться из байтов, но их порядок целиком определяется фор- матом изображения. Предположим, что вам нужно прочитать три 3-битовые стро- ки из 2-байтовой последовательности Первый байт 0001 1 101 Второй байт 01 10001 1
Введение 31 В зависимости от того, читаются ли битовые строки начи- ная от старшего бита к младшему биту, и становятся ли биты второго байта старшими или младшими, итоговая би- товая строка может быть одной из следующих четырех возможных: 1. 000 111 010 2. 000 111 001 3. 101 011 001 4. 101 011 100 Порядок битовых строк внутри байтов определяется форма- том изображения. За исключением формата ХВМ, во всех рассматриваемых в этой книге форматах файлов изображений, которые поддер- живают изображения с менее чем восемью битами на пиксел, старшие биты внутри байта содержат значения крайнего ле- вого пиксела. Порядок расположения битов в этих форматах должен выглядеть как Байт данных |7 65 4|3 2 10| 4 бита на пиксел |7 6 | 5 4 | 3 2 | 1 0| 2 бита на пиксел |7|6|5|4|3|2|1|0| 1 бит на пиксел Крайний левый пиксел згиа Крайний правый пиксел Квантование цвета Форматы JPEG и PNG, рассматриваемые в этой книге, мо- гут содержать данные изображений, использующие 24 и более битов на пиксел. Каким образом можно отобразить 24-битовое изображение в формате JPEG на устройстве вывода, которое поддерживает только 8 битов на пиксел? И еще один схожий вопрос: каким образом можно преоб- разовать файл JPEG в формат GIF, который поддерживает максимум 8 битов на пиксел? Ответ дает процесс, извест- ный как квантование цвета (color quantization) и заклю- чающийся в уменьшении числа цветов, используемых в изображении. Тема квантования цвета выходит за рамки этой книги. Поэтому мы собираемся обсудить ее только в
32 Форматы и алгоритмы сжатия изображений в действии Алгоритм 1.1. Подсчет частот использования цветов в алгоритме усредненного квантования том объеме, который достаточен для того, чтобы вы могли выводить на экран изображения, если ваш дисплей не под- держивает 24-битовые изображения, и преобразовывать данные изображений в форматы с малым числом битов на пиксел. Способ, который мы собираемся использовать, называется усредненным квантованием (median cut quantization). В нем создается трехмерная сумма частот использования каждого цветового значения пиксела. Такая процедура подсчета час- тот может быть похожей на метод, используемый в Алго- ритме l.l. Global FREQUENCIES [0..255][0..255][0..255] Global IMAGE [ 1. .IMAGEHEIGHT][1..IMAGEWIDTH] Procedure GatherFrequencies Begin For II = 1 To IMAGEHEIGHT Do Begin For JJ = 1 To IMAGEWIDTH Do Begin RED = IMAGE [II][JJ].RED GREEN = IMAGE [II][JJ].GREEN BLUE = IMAGE [II][JJ].BLUE FREQUENCIES [RED][GREEN][BLUE] = FREQUENCIES [RED][GREEN][BLUE] + 1 End End End Теперь мы получили кубическую область, содержащую все данные о частотах появления цветов. Следующий шаг, пока- занный в Алгоритме 1.2, заключается в разделении куба на две прямоугольные области так, чтобы каждая часть содержала половину значений частот. Приведенный ниже фрагмент кода делит частоты на половины вдоль оси Blue (Синий).
Введение 33 Алгоритм 1.2. Деление цветового GLOBAL FREQUENCIES [0..255] [0 . . 255] [0..255] Function DivideBluelnHalf пространства пополам Begin COUNT = 0 For BLUECUT = 0 To 255 Do Begin For II = 0 To 255 Do Begin For JJ = 0 To 255 Do Begin COUNT = COUNT + FREQUENCIES [II] [JJ] [BLUECUT] End End If COUNT > IMAGEHEIGHT * IMAGEWIDTH / 2 Then Return BLUECUT End Return 255 End Рис. 1.11. Пример цветового пространства RGB, разделенного с помощью процесса Алгоритма 1.2. Красный
34 Форматы и алгоритмы сжатия изображений в действии На Рис. 1.11 показан результат первого выполнения процесса, реализованного в Алгоритме 1.2. Процесс выполняется ре- курсивно, деля прямоугольные области пополам и используя разные цветовые оси до тех пор, пока не получится 256 бло- ков примерно с одинаковой частотой. На Рис. 1.12 и Рис. 1.13 показаны примеры деления цветового пространства RGB вдоль остальных осей. Рис. 1.12. Цветовое пространство (Рис. 1.11), теперь разделенное также по оси Зеленый (Green) Рис. 1.13. Цветовое пространство (Рис. 1.12), теперь разделенное также по оси Красный (Red) Красный
Введение 35 Учтите, это лишь грубое приближение. Если бы для хранения значений частот использовались 4-байтовые целые числа, массив FREQUENCIES, определяемый в Алгоритме 1.1, соста- вил бы 64 Мбайт. Даже в наше время дешевой памяти это слишком большое число для практической реализации. На самом деле, размер массива FREQUENCIES больше, чем дан- ные пикселов большинства изображений. Поэтому на прак- тике требуется уменьшать точность каждого цветового зна- чения, использовать динамические структуры данных или применять комбинацию обоих методов. Простой способ уменьшения размера массива заключается в отбрасывании из каждого значения компонента нескольких младших битов. Использование 6 битов вместо 8 битов уменьшает размер массива FREQUENCIES до 1 Мбайт (4х2бх2бх2б). Обший формат изображений Типичная программа для просмотра файлов изображений должна позволять читать и сохранять изображения, ис- пользуя несколько форматов файлов, а также преобразовы- вать файлы из одного формата в другой формат. Вместо того, чтобы использовать отдельные функции для про- смотра файлов каждого типа и отдельные функции для ка- ждого возможного преобразования форматов, полезно применять общий формат изображений без сжатия, кото- рый можно использовать для всех типов файлов, поддер- живаемых программой. Используя общий формат без сжатия, требуется написать только одну функцию для отображения общего формата. Ес- ли для каждого формата файлов изображений написаны функция для чтения в общий формат и функция записи из общего формата, то у вас есть все для того, чтобы отобра- жать, сохранять все форматы и выполнять преобразования между ними. Кроме поддержки всех предполагаемых форматов изображе- ний, общий формат изображений идеально прост для отобра- жения и переноса на различные аппаратные платформы. К со- жалению, простота отображения и переносимость до некото- рой степени взаимоисключающи. Нежелательно наличие об- щего формата изображений и отдельного формата отображе- ния. В наших примерах в качестве компромисса используется формат, разработанный так, чтобы быть максимально простым
36 Форматы и алгоритмы сжатия изображений в действии для использования в среде Windows и в то же время скрывать специфику Windows. Он позволяет сохранять изображения, используя 1, 4, 8 и 24 бита на пиксел. Форматы PNG и JPEG являются единственными форматами, которые сохраняют данные, используя другие форматы. PNG-декодер преобразо- вывает данные в один из упомянутых выше форматов; JPEG- декодер читает только файлы с 8-битовыми данными. Определение типа данных Примеры программного кода в этой книге используют опре- деления целых чисел, размер которых, как предполагается, будет соответствовать указанному. В Таблице 1.4 перечисле- ны используемые типы целых чисел. Они определяются в файле datatype.h, который также определяет функцию преоб- разования целых чисел в целые числа с прямым порядком байтов. Существующие определения пригодны для большин- ства 32-битовых систем с прямым порядком байтов, так что при переносе кода в систему другого типа этот файл необхо- димо будет модифицировать первым. Таблица 1.4. Типы, определенные в файле datatype.h Тип Применение BYTE1 Целое 8-битовое число со знаком UBYTE2 Целое 8-битовое число без знака BYTE2 Целое 16-битовое число со знаком UBYTE2 Целое 16-битовое число без знака BYTE4 Целое 32-битовое число со знаком UBUTE4 Целое 32-битовое число без знака Общий класс изображений Общий класс формата изображений называется Bitmapimage. Он определяется в файле bitimage.h. Общий процесс, который выполняют при чтении и записи изображений все кодеры и декодеры, рассматриваемые в этой книге, описывается сле- дующим образом: Bitmapimage image ; XYZDecoder decoder ; XYZEncoder encoder ;
Введение 37 ifstream input ("INPUT.XYZ", ios::binary) ; decoder.Readimage (input, image) ; ofstream output ("OUTPUT.XYZ", ios::binary) ; encoder.Writelmage (output, image) ; где XYZDecoder и XYZEncoder являются классами декодера и кодера для конкретного типа изображения. Реализация данного класса выполнена для Microsoft Windows. Тем не менее, интерфейс разработан так, чтобы скрыть спе- цифические детали конкретной операционной системы. Класс Bitmapimage выполняет хранение двух основных об- ластей данных: карты цветов и данных пикселов (pixel data). Программа может хранить изображение в объекте Bitmapimage путем использования одного из декодеров изо- бражений, описанных в этой книге (или написанного вами самостоятельно), либо с помощью функций SetSize, ColorMap и операторов [ ] для записи сохраняемых необработанных данных изображений. Функиия SetSize Функция SetSize выделяет динамическую память, используе- мую для хранения данных изображений в объекте Bitmapimage. Прежде чем пытаться сохранить данные в этом объекте, программа должна вызывать эту функцию. Функиия ColorMap Функция ColorMap используется для доступа к цветовой па- литре изображения. Для изображений с глубиной цвета 8 и менее битов программа должна заполнять карту цветов. Если глубина цвета изображения равна 24 битам, эту функцию не следует использовать. Оператор [ ] (Индексирования) Оператор индексирования (subscript operator) используется для получения доступа к отдельным байтам в данных пиксе- лов изображений. Формат этих данных зависит от глубины цвета изображения. Для изображений, которые используют 8 битов на пиксел, каждый байт данных является индексом в карте цветов (доступный через посредство функции ColorMap). Если глубина цвета меньше 8 битов, в байты дан- ных упаковывается множество цветовых индексов. Старшие биты содержат значения для крайних левых пикселов. Для 24-битовых изображений каждый пиксел представляется
38 Форматы и алгоритмы сжатия изображений в действии тремя байтами. В 24-битовом изображении цветовые байты обычно располагаются в порядке RGB, но Windows предпо- лагает, что значения цветов упорядочены как BGR. Класс Bitmapimage определяет используемые в примерах программ значения RedOffset, GreenOffset и BlueOffset, чтобы задать по- рядок этих байтов. Если ваша операционная система не ис- пользует порядок BGR, можно изменить значения этих сме- щений (offsets). Другая особенность Windows, скрываемая оператором индек- сирования, заключается в том, что изображения Windows со- храняются, начиная с самой нижней строки. Чтобы макси- мально упростить отображение изображения в Windows, дан- ная реализация класса Bitmapimage сохраняет строки в поряд- ке снизу-вверх, в соответствии с требованиями Windows. Од- нако оператор индексирования изменяет на обратный поря- док строк так, что [0] возвращает самый верхний ряд изобра- жения. Кроме того, в Windows предполагается, что длина ка- ждого ряда изображения должна быть кратна 4 байтам. Опе- ратор индексирования автоматически принимает в расчет это заполнение, так что [N] [0] всегда возвращает первый байт пиксела для N-й строки. Реализуя класс Bitmapimage незави- симым от интерфейса, становится возможным обеспечивать поддержку различных операционных систем путем измене- ния реализации класса, без какого-либо изменения кодеров и декодеров изображения. Существуют две реализации оператора индексирования. Если определен препроцессорный символ CHECK_RANGE, оператор индексирования выполняет контроль попадания в интервал для каждого значения. Если символ CHECK_RANGE не опре- делен, контроль попадания в интервал не выполняется. По- следняя реализация оператора индексирования работает значительно быстрее, но первая удобнее при отладке. Функция GetRGB Функция GetRGB возвращает значение RGB-цвета для ука- занного пиксела изображения. Кодер изображения может ис- пользовать эту функцию для получения значений пикселов, не обращаясь к различным значениям точности дискретиза- ции (sample precision).
Введение 39 Функция EightBitQuantization Функция EightBitQuantization преобразует изображения с 24 битами на пиксел в изображения с 8 битами на пиксел, исполь- зуя процессы разбиения по медиане. Примерно половина ис- ходного кода функции Bitmapimage реализует квантование цвета. В данной реализации функции обработка изображения выполняется за два прохода. В первом проходе функция FindColorUsage создает структуру Colorllsage для каждого цве- та, используемого в изображении. Эти структуры вставляются в три связанные списка, отсортированные по значениям ком- понентов Red (Красный), Green (Зеленый) и Blue (Синий). За- тем рекурсивная функция SplitArealnHalf многократно делит цветовое пространство RGB на две области, которые содержат по половине взвешенных значений цвета оригинала. Здесь мы определили для изображения 256 цветовых облас- тей. Функция CreateColor определяет один цвет, который получается в результате усреднения цвета по блоку. Такая процедура извлекает «наилучшие» цвета для использования в изображении. Наконец, функция QuantizeSourcelmage вы- полняет второй проход по данным изображения, чтобы за- менить цвета в исходном изображении на подходящие цвета из набора 256 цветов, который был определен в предыду- щих проходах. Заключение В этой главе рассмотрены основы форматов растровых изо- бражений. Объяснены различия между форматами растровых и векторных изображений, а также принципы отображения изображений устройствами вывода. Также рассмотрено пред- ставление цвета и описаны некоторые цветовые модели, ис- пользуемые форматами графических файлов. Глава содержит краткое введение в квантование цвета и технологии сжатия, которые используются форматами, рассматриваемыми в дан- ной книге. Фолей (Foley) с коллегами (1996) описывает работу компью- терных дисплеев более подробно, чем это сделано здесь. Там так же прекрасно описаны цветовые пространства. Браун (Brown) и Шеппард (Shepherd) (1995), а также Мюррей (Murray) и Ван Рипер (van Ryper) (1994) дают введение в большое число графических форматов файлов.
40 Форматы и алгоритмы сжатия изображений в действии В данной книге рассматриваются только определенные тех- нологии сжатия, используемые в обсуждаемых форматах файлов. Книга Нельсона (Nelson) (1992) служит наилучшим введением в существующие технологии сжатия и является прекрасным источником по их истории и взаимосвязям меж- ду методами сжатия. Алгоритм деления по медиане (medium cut algorithm) описы- вается Гекбертом (Heckbert) (1982). Линдлей (Lindley) (1995) и Ример (Rimmer) (1993) рассматривают этот алгоритм и предлагают новый подход к его реализации.
ГЛАВА 2. Windows BMP Формат: Windows BMP Разработчик: Microsoft Определение: Windows SDK (Software Development Kit - комплект для разработки программ) Первый формат изображений, который мы собираемся рас- смотреть, относится к числу простейших форматов. Формат Windows BMP является одним из встроенных форматов изо- бражений в операционных системах Microsoft Windows. Он поддерживает изображения с 1, 4, 8, 16, 24 и 32 битами на пиксел, хотя файлы BMP с 16 и 32 битами на пиксел исполь- зуются редко. Для изображений с 4 и 8 битами на пиксел формат ВМР поддерживает также простое RLE-сжатие (Ко- дирование длин серий). Однако сжатие в BMP-формате ока- зывает эффект только при наличии в изображении больших областей одинакового цвета, что ограничивает ценность встроенного алгоритма сжатия. BMP-файлы Windows редко находятся в сжатом виде. На протяжении многих лет существовало несколько разных и несовместимых версий формата BMP. Поскольку устаревшие версии полностью исчезли, проблемы совместимости версий не существует. Здесь рассматривается версия формата BMP, используемая, начиная с третьей версии Windows (общепри- нятый формат), и формат, введенный вместе с операционной системой OS/2 (редкий, но поддерживаемый). Порядок данных В формате Windows BMP многобайтовые целые числа хра- нятся с младшим байтом на первом месте. Данные, сохра- няемые в формате BMP, целиком состоят из полных байтов, поэтому вопрос о порядке битовых строк не возникает.
42 Форматы и алгоритмы сжатия изображений в действии Структура файлов Заголовок файла Заголовок изображения Таблииа цветов Пиксельные данные 1 Рис. 2.1. Структура файла растрового изображения Структура файлов BMP очень проста и демонстрируется на Рис. 2.1. Если вы разрабатываете программы в среде Windows, структуры BMP включаются из заголовочного файла windows.h. Если вы работаете не в Windows, то мо- жете создать свои собственные структуры из таблиц, при- водимых ниже. По каким-то причинам Microsoft настаива- ет на добавлении запутывающих префиксов к именам структурных полей. Чтобы сохранить соответствие с доку- ментацией Microsoft, мы включили эти префиксы в имена полей. Заголовок файла Каждый файл Windows BMP начинается со структуры BITMAPFILEHEADER, которая описывается в Таблице 2.1. Дан- ная структура выполняет роль подписи, которая идентифи- цирует данный формат файлов. Чтобы убедиться, что файл, который вы читаете, является файлом BMP, можно выполнить три проверки: ✓ Первые два байта файла должны содержать ASCII-символы «В» и «м», причем «М» следует за «В». ✓ Если используется файловая система, которая позволяет оп- ределять точный размер файла в байтах, можно сравнить размер файла со значением поля bfSize. ✓ Значения полей bfReservedl и bfReserved2 должны быть ну- левыми. Таблица 2.1. Структура BITMAPFILE- HEADER Имя поля Размер в байтах Описание bfType 2 Содержит символы «ВМ», которые идентифицируют тип файла bfSize 4 Размер файла bfReservedl 2 Не используется bfReserved2 2 Не используется bfOffBits 4 Сдвиг до начала данных пикселов
Windows BMP 43 Заголовок файла указывает также положение в файле дан- ных пикселов. При декодировании файла BMP для опреде- ления смещения начала данных пикселов относительно на- чала файла следует воспользоваться значением поля bfOffbits. Большинство программ располагают данные пик- селов сразу за структурой BITMAPINFOHEADER или палит- рой, если она есть в файле. Однако некоторые программы помещают между этими структурами и данными пикселов байты-заполнители. Поэтому, чтобы определить количест- во байтов между структурой BITMAPFILEHEADER и данны- ми пикселов, необходимо использовать значение поля bfOffbits. Заголовок изображения Заголовок изображения следует сразу за структурой BITMAPFILEHEADER. Он может быть в одном из двух форма- тов, определяемых структурами BITMAPJNFOHEADER и BITMAPCOREHEADER. Структура BITMAPCOREHEADER пред- ставляет формат BMP для OS/2, а структура BITMAPINFOHEADER представляет намного более распростра- ненный формат Windows. К сожалению, в определениях BMP нет поля содержащего версию формата. Единственный спо- соб определения типа структуры изображения, используемой в конкретном файле, заключается в считывании значения по- ля размера структуры, которое занимает первые четыре байта в структурах обоих типов. Размер структуры BITMAPCOREHEADER равен 12 байтам, размер структуры BITMAPINFOHEADER составляет не менее 40 байтов. Описание структуры BITMAPINFOHEADER приводится в Таб- лице 2.2. Эта структура задает размеры и глубину цвета изо- бражения и показывает, сжато изображение или нет. Windows 95 поддерживает формат BMP, который использует расши- ренную версию данного заголовка. Файлы BMP, использую- щие этот формат, создают немногие программы. Тем не ме- нее, декодер должен быть реализован так, чтобы ему было известно о том, что размеры заголовков могут быть больше 40 байтов.
44 Форматы и алгоритмы сжатия изображений в действии Таблица 2.2. Структура BITMAPINFO- HEADER Имя ПОЛЯ Размер Описание BiSize 4 Размер заголовка. Должен быть не менее 40 BiWidth 4 Ширина изображения BiHeight 4 Высота изображения BiPlanes 2 Должно быть равно 1 BiBitCount 2 Число битов на пиксел - 1,4, 8, 16, 24 или 32 BiCompression 4 Тип сжатия - BI_RGB=O, BI_RLE8=1, BI_RLE4=2 или BI_BlTFlELDS=3 BiSizeimage 4 Размер изображения - может быть равен 0, если нет сжатия BiXPelsPerMeter 4 Предпочтительное разрешение в пикселах на метр BiYPelsPerMeter 4 Предпочтительное разрешение в пикселах на метр BiCIrUsed 4 Число фактически используемых элементов карты цветов BiCIrlmportant 4 Число значимых цветов Высота изображения задается значением без знака (unsigned value). Отрицательное значение поля biHeight указывает на то, что данные пикселов располагаются сверху вниз, а не в обычном порядке снизу вверх. Изображений с отрицатель- ным значением поля biHeight могут быть несжатыми. Структура BITMAPCOREHEADER Структура BITMAPCOREHEADER является еще одним форма- том заголовка изображения. Описание данной структуры приводится в Таблице 2.3. Обратите внимание, что число по- лей в данной структуре меньше и всем им соответствуют аналогичные поля в структуре BITMAPINFOHEADER. Если файл использует структуру BITMAPCOREHEADER, а не BITMAPINFOHEADER, данные пикселов не могут быть сжаты.
Windows BMP 45 Таблица 2.3. Структура BITMAPCORE- HEADER Имя ПОЛЯ Размер Описание BcSize 4 Размер заголовка. Должен быть равен 12 BcWidth 2 Ширина изображения BcHeight 2 Высота изображения BcPIanes ч 2 Должно быть равно 1 BcBitCount 2 Число битов - 1,4, 8 или 24 Цветовая палитра Цветовая палитра следует непосредственно за заголовком файла и может быть организована в одном из трех форматов. Первые два формата используются для отображения данных пикселов в значения RGB-цвета, когда число битов на пиксел равно 1, 4 или 8 (поля biBitCount или bcBitCount). Для файлов BMP в формате Windows палитра состоит из массива '1число битов структур RGBQUAD (таблица 2.4). Файлы BMP в формате OS/2 используют массив структур RGBTRIPLE (таблица 2.5). Таблица 2.4. Структура RGBQUAD Поле Размер Описание RgbBlue 1 Значение синего цвета RgbGreen 1 Значение красного цвета RgbRed 1 Значение зеленого цвета Rgb Reserved 1 Должно быть равным нулю Таблица 2.5. Структура RGBTRIPLE Поле Размер Описание rgbtBlue 1 Значение синего цвета rgbtGreen 1 Значение красного цвета rgbtRed 1 Значение зеленого цвета В действительности, конечный формат цветовой палитры вовсе не представляет отображение цветов. Если число би- тов на пиксел равно 16 или 32, значение поля biCompression структуры BITMAPINFOHEADER равно BI_BITFIELDS (3), то место массива структур RGBQUAD за- нимает массив из трех 4-байтовых целых чисел. Эти три значения являются битовыми масками, которые указывают
46 Форматы и алгоритмы сжатия изображений в действии биты, используемые для красного, зеленого и голубого компонентов соответственно. В каждой маске ненулевые биты должны располагаться подряд. Кроме того, битовый набор какой-либо битовой маски не может быть установ- лен ни в какой другой битовой маске. Для изображений с 24 битами на пиксел, а также для 16- и 32-битовых изо- бражений цветовая палитра отсутствует, если поле biCompression не установлено равным BI_BITFIELDS. В 32-битовом изображении три 32-битовых значения 0000000000000000000000111111111 12 Красный 000000000000111111111100000000002 Зеленый 001111111111000000000000000000002 Синий указывают на то, что каждый из этих компонентов представ- ляется 10 битами. Логическое умножение (AND) трех значе- ний должно быть равно нулю, а диапазон ненулевых битов каждого компонента должен быть непрерывным. Данные пикселов Данные пикселов следуют за палитрой или битовыми маска- ми, если они присутствуют. В других случаях они следуют за структурой BITMAPINFOHEADER или BITMAPCOREHEADER. Обычно данные располагаются непосредственно за структу- рами, но могут отделяться и байтами-заполнителями. Чтобы определить смещение данных пикселов относительно струк- туры BITMAPFILEHEADER, следует воспользоваться значением поля bfOffBits в заголовке BITMAPFILE,. Строки пикселов (pixel rows) располагаются в файле снизу вверх. Число строк данных задается в заголовке изображения полями biHeight или bcHeight. Размер строки определяется значениями пары полей biBitCount и biWidth или bcBitCount и bcWidth. Число байтов на строку округляется до числа крат- ного четырем и может быть определено следующим образом (используя целочисленное деление): (ширина У. число битов +7) л - 8 j число байтов на строку = -------------L--
Windows BMP 47 Формат данных пикселов зависит от числа битов на пиксел. ✓ 1 и 4 бита на пиксел. Каждый байт данных подразделяется либо на восемь, либо на два поля, значения которых пред- ставляют указатель в цветовой палитре. Поле старшего бита относится к крайнему левому пикселу. ✓ 8 битов на пиксел. Каждый пиксел в строке описывается одним байтом, который является указателем в цветовой палитре. ✓ 16 битов на пиксел. Каждый пиксел описывается 2-байтовым целым числом. Если значение поля biCompression в структу- ре BITMAPINFOHEADER равно BI_RGB (0), яркость (intensity) каждого цвета представляется 5 битами, причем старший бит не используется. Использование битов, принимаемое по умолчанию, показано на Рис. 2.2. Рис. 2.2. Формат 16 битов, прихоляшихся 15 14 13 12 11 10 9 8 7 6 5Г 4 3 2 1 0 Красный |||sR ' Си ни Й|В,Й#Ж Зеленый на пиксел Если значение поля biCompression установлено равным В1_В1ТМАР, три 4-байтовые битовые маски, которые следуют за структурой BITMAPINFOHEADER, указывают биты, исполь- зуемые для каждого цветового компонента. Битовые маски располагаются в порядке красный, синий, зеленый. ✓ 24 бита на пиксел. Каждый пиксел описывается тремя после- довательными байтами, которые указывают значения синего, зеленого и красного компонентов, соответственно. Обратите внимание на то, что этот порядок обратен тому, что исполь- зуется в большинстве форматов файлов изображений. ✓ 32 бита на пиксел. Каждый пиксел описывается 4-байтовым целым числом. Если значение поля biCompression в структу- ре BITMAPINFOHEADER установлено равным BI_RGB, три младших байта представляют 8-битовые значения синего, зе- леного и красного компонентов в перечисленном порядке. Старший байт не используется. За исключением неисполь- зуемого байта в конце этот формат в точности подобен фор- мату с 24 битами на пиксел. Если поле biCompression содержит значение BLBITFIELD, три 4-байтовые битовые маски, следующие за структурой BITMAPINFOHEADER, указывают биты, которые используются для каждого компонента. Битовые маски расположены в по- рядке красный, синий, зеленый.
48 Форматы и алгоритмы сжатия изображений в действии Сжатие Формат BMP поддерживает простое RLE-сжатие изображе- ний с 4 и 8 битами на пиксел. Изображения с 4 битами на пиксел подвергаются сжатию, если значение поля biCompression структуры BITMAPINFOHEADER равно BI_RLE4 (=2), а изображения с 8 битами на пиксел сжимаются, если значение biCompression равно BI_RLE8 (=1). При любой дру- гой глубине цвета сжатие данных невозможно. Кодирование длин серий (RLE) является одной из простей- ших технологий сжатия. В этом методе данные сохраняются таким образом, что повторяющиеся значения замещаются числом, равным их количеству. Данный тип сжатия подходит только для изображений с множеством повторяющихся зна- чений, например, мультипликационные рисунки. Для изо- бражений многих типов кодирование длин серий (RLE) соз- дает файл, размер которого больше исходного (отрицатель- ное сжатие). Формат сжатых данных зависит от числа битов на пиксел. Метод сжатия RLE8 В методе сжатия RLE8 сжимаемые данные разбиваются на 2- байтовые пары. Первый байт равен количеству повторяю- щихся значений пикселов, а второй байт равен значению пиксела, которое повторяется. В изображении с 8 битами на пиксел байтовая последовательность 0816 0016 разворачивается в следующую последовательность значений пикселов 00|б 0016 0016 0016 0016 0016 00|б 0016 0016 Счетчик повторов равный нулю используется в качестве управляющего кода. Нулевое значение, за которым следует другое нулевое значение, означает переход к следующей строке в изображении. Нулевое значение, за которым следует 1, означает конец изображения. Нуль, за которым следует байт, содержащий значение 2, изменяет текущее положение в изображении. Следующие два байта являются значениями без знака, которые равны, соответственно, числу столбцов и строк, на которые следует выполнить переход в новое поло-
Windows BMP 49 жение. Этот код позволяет пропускать большое число пиксе- лов с нулевыми значениями. Кодовая последовательность 04]б 1516 0016 0016 0216 1 lie 0216 0316 0016 0116 разворачивается в следующие две строки: 151615161516 1516 Hie 1116 0316 ОЗ]6 Конец изображения. Нулевой управляющий код с последующим значением боль- шим двух указывает число литеральных байтов, которые должны быть скопированы в изображение. Литеральные бай- ты следуют непосредственно за счетчиком. Если число- счетчик нечетное, то после байтов данных сохраняется один байт-заполнитель. Этот код используется для хранения не- сжатых данных. Из приведенного описания метода сжатия нетрудно заклю- чить, что если изображение не содержит последовательных байтов с одинаковым значением, итоговый размер данных изображения превысит размер эквивалентных несжатых данных. Метод сжатия RLE4 Формат RLE4 почти идентичен формату RLE8. Основное раз- личие заключается в том, что при кодировании значений цве- та байт данных, который следует за числом-счетчиком, со- держит два значения пикселов. Значение четырех старших битов используется для кодирования первого и всех после- дующих нечетных пикселов в серии, в то время как четыре младших бита используются для кодирования второго и ос- тальных четных пикселов. Таким образом, формат RLE4 по- зволяет кодировать серии одинаковых значений пиксела или два чередующихся значения. Данная закодированная пара 05]б 5616 разворачивается в следующую последовательность 4-бито- вых значений: 5 65 65
50 Форматы и алгоритмы сжатия изображений в действии Все управляющие коды метода RLE4 совпадают с управ- ляющими кодами метода RLE8, за исключением кодирова- ния абсолютных значений. Нулевой управляющий код с по- следующим байтом большим двух задает число абсолютных значений пикселов, которые располагаются за управляю- щим кодом. Каждое из абсолютных значений упаковывается в 4 бита, причем старшие биты располагаются вначале. Если серия не кратна четырем, далее следует заполнить так, что- бы число абсолютных байтов данных (не пикселов) было кратно двум. Заключение Если вы разрабатываете программное обеспечение для чте- ния и записи графических файлов в среде Windows, формат Windows BMP будет наилучшим выбором для тестирования ваших программ. Его несложно реализовать и отладить, и, кроме того, файлы данного формата можно просматривать без использования специальных программных средств. В отличие от всех других форматов, рассматриваемых в этой книге, определение Windows BMP полностью контролируется одной компанией. Можно ожидать, что в будущем компания Microsoft внесет в формат улучшения, для которых будет обеспечена совместимость, начиная с младших версий. Оп- ределение формата можно найти в книге, выпущенной Micro- soft (1993). Книга Мюррея (Murray) и Ван Рипера (van Ryper) (1994) содержит описания формата, включая предыдущие версии BMP. В книге Свана (Swan) (1993) также подробно объясняется формат BMP. На прилагаемом компакт-диске содержится исходный про- граммный код кодера (BmpEncoder) и декодера (BmpDecoder) Windows BMP. Приводимый ниже код служит иллюстрацией того, как данные классы используются для чтения и записи ВМР-файлов: #include "bitimage.h" #include "bmpdecod.h" #include "bmpencod.h"
Windows BMP 51 Bitmapimage image ; ifstrearn input ("INPUT.BMP", ios::binary) ; BmpDecoder decoder ; decoder.Readimage (input, image) ; ofstream output ("OUTPUT.BMP", ios::binary) ; BmpEncoder encoder ; encoder.Writelmage (output, image) ; При чтении или записи двоичных файлов изображений сле- дует открывать их в двоичном режиме (binary mode). В про- тивном случае ваша библиотека может транслировать содер- жимое файлов самым неожиданным образом. Кроме того, компакт-диск содержит исходный код програм- мы под Windows (viewer.cpp), которая отображает ВМР- файлы. Эту программу нетрудно модифицировать, чтобы ис- пользовать декодер для любого другого формата, рассматри- ваемого в данной книге.
ГЛАВА 3. хвм Формат: ХВМ Разработчик: X Consortium Определение: Неофициальный формат ХВМ является простейшим, а также самым необычным фор- матом из рассматриваемых в этой книге. Этот формат, род- ной для системы X Windows и редко используемый вне этой среды, намного более ограничен, чем Windows BMP. Формат ХВМ поддерживает только двухцветные изображения. В дей- ствительности, ХВМ-файл больше похож на файл значка в операционной системе Windows, чем на файл BMP.1 Формат файлов ХВМ-формат файлов изображений совершенно не похож на другие форматы, обсуждаемые в этой книге. Вместо двоич- ных данных этот формат содержит исходный код на языке Си. При написании кода пользовательского интерфейса для системы X Windows можно включать предварительно задан- ные значки в ХВМ-формате путем простого включения в про- грамму файла, содержащего код программы, а затем компи- лируя и связывая изображение с программой. ХВМ-файл вы- полняет примерно ту же функцию, что и файл ресурсов в Windows. Программы, содержащие ХВМ-декодер, такие, как Web-браузеры и графические редакторы, могут читать ХВМ- файлы и отображать изображения, содержащиеся в них, без компиляции и связывания этих файлов. Формат файла ХВМ показан на Рис. 3.1. Строка imagename представляет уникальное имя, присвоенное изображению в программе, которая включает множество различных файлов ХВМ. При считывании файла ХВМ для вывода изображения, это имя не играет никакой роли. В системе X Windows существует похожий формат, но с большими возможностями, называемый ХРМ.
54 Форматы и алгоритмы сжатия изображений в действии Рис. 3.1. ХВМ-формат файлов # define imagename_width 16 # deflne imagename_height 2 # define imagename_hot_x 1 # define imaqename hot v 1 static unsigned char imagename_bits [] = { 0x10, 0x10, 0x10, 0x01 } ; Размеры изображения определяются парой препроцессорных директив #define. Препроцессорные символы с суффиксами _width и _height задают ширину и высоту изображения в пик- селах. Эти определения обязательны. Файлы ХВМ могут определять область активизации (hot spot), которая используется, когда изображение применяется в ка- честве системного значка. Положение области активизации задается двумя директивами #define, которые создают пре- процессорные символы с суффиксами _hot_x и _hot_y. Опре- деление области активизации в ХВМ-файле носит необяза- тельный характер, но данные символы не могут появляться один без другого. Последняя инструкция в определении изображения является байтовым массивом, который задает значения пикселов изо- бражения. Каждый байт представляет значения для восьми пикселов изображения. Данные изображения сохраняются сверху вниз, слева направо; значения пикселов не разбивают- ся по разным строкам. Если ширина изображения не кратна восьми, дополнительные биты в последнем байте каждой строки не используются. Общее число байтов в изображении должно быть равно: _ „ высота + 7 оаиты = высота X-------- 8 используя целочисленное деление. ХВМ-файлы не содержат информации о цвете. Биты, установленные равными нулю, рисуются текущим фоновым цветом, а биты, установленные равными единице, рисуются текущим активным цветом. Порядок расположения байтов Вопрос о порядке расположения байтов в формате ХВМ не возникает, поскольку все данные состоят из одиночных бай- тов. Внутри байта самый младший бит представляет крайний левый пиксел. Такой порядок расположения битов противо- положен порядку используемому в формате Windows BMP (и о всех других форматах, рассматриваемых в данной книге).
хвм 55 Рис. 3.2. Пример изображения в формате ХВМ Пример изображения Приводимый ниже код является примером ХВМ-файла, кото- рый содержит изображение, показанное на Рис. 3.2. #define myimage_height 12 #define nryimage_width 12 static unsigned char nryimage_bits [] = { OxFO, 0x00, OxFO, 0x00, OxFO, 0x00, OxFO, 0x00, OxFF, OxOF, OxFF, OxOF, OxFF, OxOF, OxFF, OxOF, OxFO, 0x00, OxFO, 0x00, OxFO, 0x00, OxFO, 0x00 } ; Синтаксис файла ХВМ-файл изображения является файлом программного кода на языке Си. Тем не менее, никто не собирается реа- лизовывать полный препроцессор Си и синтаксический анализатор для чтения файла изображения. Си является языком свободного формата, что делает его обработку простым анализатором относительно трудной задачей. По- этому файл, соответствующий официальному формату ХВМ (legal file) и ХВМ-файл, отображаемый какой-либо программой просмотра изображений, представляют две разные вещи. К сожалению, различие между этими двумя файлами не оп- ределяется точно, поэтому можно дать только несколько ре- комендаций по созданию ХВМ-файлов: ✓ Не вставляйте пустые строки. ✓ Не используйте комментарии. ✓ Точно следуйте порядку инструкций, приведенному на Рис. 3.1.
56 Форматы и алгоритмы сжатия изображений в действии ✓ Используйте в директивах #define десятичные значения це- лых чисел. ✓ Не вставляйте пробелы между символом # и define. ✓ Используйте шестнадцатеричные значения для целых чисел, представляющих данные пикселов. Нарушение любого из этих правил, даже если это будет син- таксически абсолютно верный код на языке Си, может сде- лать ХВМ-изображение нечитаемым. Интересно, что сущест- вуют ХВМ-декодеры, которые корректно отображают изо- бражения из файлов, содержащих определенные ошибки синтаксиса языка Си. Чтение и запись ХВМ-файлов Создание ХВМ-файлов является тривиальной процедурой. Все, что должен сделать кодер, заключается в формирова- нии простого текстового файла, используя описанный выше формат. С другой стороны, чтение ХВМ-файлов несколько сложнее, особенно учитывая ограниченные возможности этого форма- та. Один из подходов заключается в применении методов на- писания компилятора. Работа декодера логически разделяет- ся на два прохода. В первом проходе файл разбивается на по- следовательность лексем (tokens), тогда как во втором прохо- де выполняется синтаксический анализ лексем, чтобы сфор- мировать изображения. Для генерирования двух проходов можно использовать такие программные инструменты, как LEX и YACC, однако формат достаточно прост для того, что- бы сгенерировать проходы вручную. Заключение Хотя применение формата ХВМ вне среды X Windows весьма ограниченно, он поддерживается всеми основными Web- браузерами. Формат также иллюстрирует необычный подход к сохранению изображения в файле. Описание ХВМ в книге Шейфлера (Scheiffler) и Джеймса (James) (1990) наиболее точно соответствует официальному описанию формата. Най (Nye) (1988) предлагает альтернативное описание.
ГЛ AB A 4. Введение в JPEG Формат: JPEG Разработчик: Объединенный комитет экспертов по машинной обработке фотоизображений (Joint Photographic Experts Group) Определение: ISO 10918-1 JFIF V1.02 JPEG - самый распространенный формат, используемый для хранения фотографических изображений. Но, несмотря на его широкое распространение, внутренние механизмы сжатия JPEG остаются чем-то сродни черной магии. Поскольку JPEG является очень сложным форматом изображений, мы разделили материал по JPEG на восемь глав. В этой главе мы обсудим основы формата. В последующих главах объясня- ются специфические вопросы. JPEG является аббревиатурой от «Joint Photographic Experts Group» (Объединенный комитет экспертов по машинной об- работке фотоизображений). Эта организация под руково- дством международных комитетов по стандартизации созда- ла стандарт сжатия изображений. Стандарт JPEG весьма сложен, поскольку он описывает не столько формат файлов изображений, а определяет множество связанных с ним тех- нологий сжатия изображений. Мощь формата JPEG заключается в том, что для фотографи- ческих изображений он обеспечивает максимальное сжатие по сравнению с любыми другими общепринятыми формата- ми растровых изображений. Фотографию, для хранения ко- торой в виде файла Windows BMP требуется 1 Мбайт, в фор- мате JPEG обычно можно сжать до 50 Кбайт. Хотя формат JPEG требует значительных вычислений, его выдающиеся возможности по сжатию изображений обычно перевешивают недостаток, связанный с большими затратами времени на об- работку данных. Но как бы ни был хорош формат JPEG, для некоторых при- ложений он непригоден. Все методы сжатия, обычно исполь- зуемые в JPEG, относятся к технологиям сжатия с потерями, что делает этот формат непригодным в качестве формата
58 Форматы и алгоритмы сжатия изображений в действии промежуточного хранения, когда требуется многократно по- вторно редактировать файл изображения. Кроме того, при сжатии текста и рисунков формат JPEG не так хорош, как при сжатии фотографий. Режимы сжатия JPEG Первоначальный стандарт JPEG определял четыре режима сжатия: иерархический (hierarchical), прогрессивный (pro- gressive), последовательный (sequential) и без потерь (lossless). Кроме того, для этих режимов стандарт определял несколько процессов кодирования. На Рис. 4.1 показаны взаимосвязи основных режимов сжатия JPEG и процессов кодирования. Хотя между методами сжатия есть некоторая общность, по большей части их следует реализовывать как совершенно разные технологии. ill М-ЛОН.1П JPEG 1 2-би г Арифмети- ческий 8-бит 12-бш Прогрессивный Без потерь Иерархи- ческий Хаффмана Арифмети- ческий Оригина- льный без потерь JPEG-LS 8-би 1 12-бит 8-бит 12-бит Рис. 4.1. Режимы JPEG Последовательный режим Последовательный режим является простейшим режимом JPEG. Как ясно из его названия, последовательный режим сжатия обеспечивает кодирование изображения сверху вниз. Последовательный режим поддерживает дискретизацию дан- ных с точностью 8 и 12 битов. В последовательном JPEG каждый цветовой компонент пол- ностью кодируется в один скан - блок сжатых данных, кото- рый содержит результаты одного прохода по изображению для одного или нескольких компонентов. В большинстве форматов все сжатые данные пикселов хранятся в одной не- прерывной области файла. В формате JPEG каждый проход по изображению сохраняется в отдельном блоке данных, на- зываемом сканом.
Введение в JPEG 59 В рамках метода последовательного сжатия стандарт JPEG определяет два альтернативных процесса кодирования эн- тропии (entropy encoding). Один использует кодирование Хаффмана (Huffman), а в другом применяется арифметиче- ское кодирование. Вскоре мы обсудим подробнее оба этих процесса. Почти в каждом файле JPEG, который может вам встретиться, используется последовательный JPEG с кодированием Хаффмана и 8-битовые дискретизованные данные. Стандарт JPEG определяет также еще один процесс последо- вательного сжатия, который использует кодирование Хафф- мана. Это базовый процесс, разновидность последовательно- го режима с кодированием Хаффмана. Декодер, который мо- жет выполнять расширенный процесс, должен обеспечивать прозрачную обработку в базовом режиме. В изображениях, сжатых в базовом режиме, могут присутствовать только 8- битовые дискретизованные данные, и они ограничиваются меньшим числом таблиц Хаффмана и квантования1, чем изо- бражения, обработанные методом расширенного последова- тельного сжатия (extended sequential images). Прогрессивный режим В JPEG-изображениях с прогрессивным сжатием компонен- ты кодируются в множестве сканов. Сжатые данные для каж- дого компонента помещаются не менее, чем в 2, и не более, чем в 896 сканов, хотя фактическое их число почти всегда находится на нижней границе этого диапазона. Начальные сканы создают грубую версию изображения, тогда как после- дующие сканы улучшают его качество. Изображения с про- грессивным сжатием предназначены для просмотра во время их декодирования. Они удобны, когда изображение загружа- ется по сети или просматривается в Web-браузере, поскольку позволяют пользователю получить представление о содержа- нии изображения после передачи как минимально возможно- го количества данных. Таблица Хаффмана и таблицы дискретизации описываются, начиная со следующей главы.
60 Форматы и алгооитмы Рис. 4.2 Пример изображения с прогрессивным методом сжатия
Введение в JPEG 61 На Рис. 4.2 показано изображение, которое было закодирова- но в четыре скана методом прогрессивного JPEG. Можно ви- деть, что с каждым сканом изображение становится все более отчетливым. Обратите внимание, уже после первого скана можно сказать, что это изображение самолета. Скажем, вы хотите загрузить через медленное сетевое соединение изо- бражение автомобиля. Используя прогрессивный JPEG, вы смогли бы определить, что получили не тот рисунок, кото- рый вам нужен, уже после передачи сравнительно небольшо- го объема данных. Основные недостатки прогрессивного режима заключаются в том, что его труднее реализовать, чем последовательный ре- жим, а также в том, что если изображение просматривается по мере его загрузки, требуется значительно больший объем обработки. Прогрессивный JPEG наиболее выгоден тогда, когда относительная вычислительная мощность превышает относительную скорость передачи изображения. В целом, размеры файлов изображений, сжатые в прогрессивном и по- следовательном режимах, примерно одинаковы. Прогрессивный режим используется редко, но в настоящее время все чаше встречаются изображения с 8-битовыми дискретизо- ванными данными, кодированные по методу Хаффмана. Иерархический режим Иерархический (hierarchical) JPEG представляет собой супер- прогрессивный режим, в котором изображение разделяется на множество фрагментов, называемых кадрами.2 Кадр пред- ставляет собой группу из одного или нескольких сканов. В иерархическом режиме первый кадр создает версию изо- бражения с низким разрешением. Остальные кадры улучша- ют качество изображения путем повышения разрешения. Сторонники этого метода утверждают, что при низкой скоро- сти передачи данных иерархический режим лучше, чем про- грессивный режим. Если нужно получить только изображе- ние с низким разрешением, для достижения желаемого ре- зультата достаточно использовать только часть из всех суще- ствующих кадров. * Прочие режимы используют один кадр на изображение.
62 Форматы и алгоритмы сжатия изображений в действии Очевидным недостатком иерархического режима является его сложность. Его реализации иерархического режима при- сущи все сложности других режимов плюс ряд дополнитель- ных. Иерархический JPEG определенно требует намного большего объема обработки, чем другие режимы, а использо- вание множества кадров увеличивает количество данных, ко- торые должны передаваться. Неудивительно, что иерархический режим JPEG используется редко. Режим сжатия без потерь Первоначальный стандарт JPEG определял режим сжатия без потерь, который всегда сохраняет точное исходное изобра- жение. Режим без потерь никогда не может достичь такого же сжатия, как режим сжатия с потерями. Более того, в большинстве случаев применения он не обеспечивал такого же сжатия, как форматы, существовавшие на тот момент, по- этому не было побудительных причин для его использования. В настоящее время разработан новый метод сжатия без по- терь, известный как JPEG-LS, что сделало первоначальный формат сжатия без потерь морально устаревшим для всех практических сфер применения. Какая часть JPEG рассматривается в данной книге? Стандарт JPEG настолько обширен, что нельзя надеяться рассмотреть его полностью в одной книге. К счастью, обще- употребительна только небольшая часть стандарта JPEG. Именно эту часть мы рассмотрим в следующих главах: по- следовательный и прогрессивный JPEG с кодированием Хаффмана и 8-битовыми дискретизованными данными. 12-битовые данные используются в некоторых специализи- рованных приложениях, например, при получении медицин- ских снимков (хотя такая разрядность данных не использу- ются для обмена рисунками в Интернете). Наши описания структур JPEG включают информацию по элементам, харак- терным для 12-битовых данных, однако они не реализованы в примерах, поскольку это потребовало бы либо дублирования 12-битовых версий многих функций, либо условной компи-
Введение в JPEG 63 ляции. Структура программ из примеров такова, что если по- требуется использовать 12-битовые данные, вам несложно будет внести необходимые изменения в программный код. Стоит указать некоторые причины, почему широко использу- ется такая малая часть стандарта JPEG, особенно учитывая, насколько широко применяются некоторые его части. Основ- ная причина заключается в том, что стандарт JPEG просто определяет слишком много способов решения одной и той же задачи. Декодер, который мог бы обрабатывать любой воз- можный поток данных JPEG, был бы чрезмерно большим. Еще одна важная причина состоит в том, что режимы ариф- метического кодирования защищены патентами, и чтобы их использовать, необходимо платить за лицензию владельцам патентов. Кодирование Хаффмана и арифметическое кодиро- вание используются разными процессами для выполнения идентичных функций. Если два метода делают одно и то же, но применение одного из них требует лицензионных выплат, а применение второго - нет, который из них вы бы выбрали? Помимо вопросов оплаты лицензии, патенты делают невоз- можным создание общедоступных (бесплатных) реализаций некоторых функций JPEG. Это составляет важнейшую причину того, почему большинство режимов кодирования JPEG редко используются на практике. Для того чтобы формат графического файла получил всеобщее признание, кто-то должен разработать программное обеспече- ние для работы с этим форматом и сделать его доступным для других пользователей.3 Формат изображений, который нельзя использовать для обмена данными между множеством различ- ных программ, малополезен. Проблема реализации усложняется тем, что стандарт JPEG бесплатно не доступен. Стандарты всех других основных форматов графических файлов обращаются свободно, но с JPEG это не так.4 Вы должны приобрести копию стандарта у своего национального представителя международ- ной организации по стандартизации (ISO), а это недешево. Если формат слишком сложен, обладает ограниченным значением или требуется плата за лицензию, маловероятно, что кто-либо возьмет на себя хлопоты по написанию для него программного кода и сделает этот код общедоступным. ,.е с JPEG основной движущей силой по его разработке была независимая группа JPEG, агастся, что за стандарт JPEG надо платить. Однако документы по стандартам JPEG _ о найти в Интернете.
64 Форматы и алгоритмы сжатия изображений в действии Что такое файлы JPEG? Самым удивительным в отношении стандарта JPEG, особен- но с учетом его широкого распространения, является то, что он не определяет формат файлов. Стандарт JPEG не указыва- ет, что должна сделать программа, чтобы создать изображе- ния, которыми можно обмениваться между разными про- граммами. Например, в нем ничего не сообщается о том, как представляются цвета, а рассматриваются только вопросы хранения значений компонентов. Нет в нем также никаких определений того, каким образом значения компонентов ото- бражаются в цветовом пространстве. Разработчику про- граммного обеспечения JPEG не сообщается, является ли первый компонент красным цветом, второй - зеленым цве- том, третий - синим цветом, и даже неизвестно, применяется ли вообще цветовая модель RGB. Хотя стандарт, независи- мый от цветового пространства, универсален, его невозмож- но реализовать. Природа не терпит пустоты, и свободное место занял формат JFIF (JPEG File Interchange Format - Формат для обмена фай- лами стандарта JPEG), созданный Эриком Гамильтоном (Eric Hamilton). Данная спецификация заполняет пробел, остав- ленный стандартом JPEG в определении файлов, которыми можно обмениваться между программами. Аббревиатура «JFIF» стала синонимом фразы «JPEG File» (файл JPEG). То- гда как другие форматы файлов, такие как TIFF, используют JPEG-сжатие, файлы с расширением JPG или JPEG неизмен- но относятся к формату JFIF. Именно формат JFIF мы соби- раемся рассмотреть в данной книге. Формат файлов SPIFF Организация JPEG недавно выпустила стандарт формата файлов, называемый SPIFF (Still Picture Interchange File For- mat - Формат обмена файлами статических изображений), который задумывался как замена формата JFIF. К сожале- нию, формат SPIFF, вероятно, слишком запоздал. Формат JFIF используется уже так долго, что, по всей видимости, со- хранит свое значение и в дальнейшем.
Введение в JPEG 65 Для разработчиков программного обеспечения JPEG формат SPIFF представляет некоторые проблемы, просто потому, что в него слишком много чего включено. Большинство исполь- зуемых форматов поддерживают только одну цветовую мо- дель. Формат SPIFF поддерживает тринадцать моделей цвета, включая три разновидности модели YCbCr. Способны ли де- кодеры JPEG реализовать так много цветовых пространств? Ясно, что нет, но тогда какое подмножество SPIFF должно быть реализовано для обмена изображениями между боль- шинством программ? Поскольку формат JPEG уже широко используется, маловероятно, что предполагаемое для исполь- зования подмножество SPIFF будет развиваться отдельно, само по себе. С практической точки зрения, JFIF остается лучшим форматом файлов для разработчиков программного обеспечения JPEG. Порядок расположения байтов Целые числа хранятся в JPEG-файлах со старшим байтом на первом месте, т.е. в обратном порядке (big-endian). Битовые строки кодируются внутри байтов, начиная со старших би- тов. Когда битовая строка пересекает границу байта, биты в первом байте являются более значимыми, чем биты во вто- ром байте. Частота дискретизации В формате JPEG частота дискретизации представляет собой относительную частоту, с которой выполняется оцифровка компонента. Возможно, это проще всего понять в контексте преобразования фотографии в растровое изображение. В от- личие от изображения на дисплее компьютера, на фотогра- фии могут присутствовать области непрерывного изменения цвета. Чтобы преобразовать фотографию в цифровое изобра- жение, выполняется сканирование изображения и измерение значений компонентов через регулярные интервалы. На Рис. 4.3 показана непрерывная функция, а также дискретиза- ция этой функции при разных частотах. Можно видеть, что чем выше частота дискретизации, тем лучше аппроксимация исходного изображения. 3—9809
66 Форматы и алгоритмы сжатия изображений в действии Рис. 4.3. Аналоговый сигнал, оцифрованный с разными частотами Так зачем же беспокоиться о частоте дискретизации, если, очевидно, она влияет только на разрешение изображения? Поскольку большинство программ работают только с уже от- сканированными данными, казалось бы, нет необходимости рассматривать частоту дискретизации.
Введение в JPEG 67 В большинстве форматов графических файлов дискретизация значений всех цветовых компонентов осуществляется с оди- наковой частотой. Формат JPEG позволяет выполнять дис- кретизацию значений отдельных компонентов с разными частотами. При сжатии изображений частоты дискретизации позволяют изменять объем информации, вносимой каждым компонентом. В Главе 1 вы видели, что в цветовой модели YCbCr важнейшим является компонент Y. Уменьшение объ- ема информации от компонентов СЬ и Сг является простей- шим способом уменьшения размера сжатого изображения. Предположим, что вы создали файл JPEG из цветного изо- бражения. Путем настройки частот дискретизации вы мог- ли бы включить в сжатые данные значения компонента Y для всех пикселов и по 1 значению других компонентов для каждых 4 пикселов. Вместо хранения 12 значений для каждых 4 пикселов вы могли бы хранить 6 значений - 50% уменьшение. Дискретизация значений компонента Y необязательно должна выполняться с большей частотой, чем дискретизация значений компонентов СЬ и Сг. Можно создать файл JPEG, в котором час- тота дискретизации компонента СЬ или Сг будет больше, чем час- тота дискретизации компонента Y. При программировании, связанном с графическими файлами, частоты дискретизации могут запутать, так как данные, с ко- торыми вы работаете, уже оцифрованы. В программировании JPEG понятие дискретизации обычно используется для уменьшения объема данных от одного или нескольких ком- понентов, а не для преобразования аналоговых данных в цифровые. В большинстве программ с помощью частот дис- кретизации фактически выполняется сжатие или растягива- ние значений компонентов по множеству пикселов. Когда изображение сжимается с использованием JPEG, каж- дому компоненту назначается частота дискретизации по го- ризонтали и вертикали. Любая из этих частот может изме- няться в диапазоне от 1 до 4. Чем выше частота дискретиза- ции, тем больше объем данных данного компонента. Количе- ство дискретизованных значений компонента связано с мак- симальной частотой дискретизации по каждой оси измерения изображения.
68 Форматы и алгоритмы сжатия изображений в действии Допустим, например, что для компонента Y частота дискре- тизации по горизонтали равна 4, для компонента СЬ - 2, а для компонента Сг - 1. Это означает, что в горизонтальном на- правлении на каждое значение СЬ приходится 2 значения компонента Y, а на каждое значение Сг приходится 4 значе- ния компонента Y. Если для каждого компонента частота дискретизации по вертикали была бы равна частоте дискре- тизации по горизонтали, тогда каждое значение компонента Y отображалось бы на один пиксел, каждое значение компо- нента СЬ - на 4 пиксела, и каждое значение компонента Сг - на 16 пикселов. Пример такой дискретизации показан на Рис. 4.4. .... Рис. 4.4. Частоты лискретизаиии компонентов Y; Н=4, V=4 Cb: Н=2, V=2 Сг: Н=1, V=1 Y: Н=4, V=4 Cb: Н=4, V=2 Сг: Н=2, V=2 Процесс уменьшения количества данных, вносимых компо- нентом в файл изображения, называется субдискретизацией (down-sampling). Кодер может реализовать субдискретиза- цию путем кодирования только каждого второго, третьего или четвертого пиксела, либо вычисляя среднее значение. Обратный процесс размножения субдискретизованных пик- селов называют сверхдискретизацией (up-sampling). Про- стейший способ реализации сверхдискретизации заключается в повторении одного и того же значения для множества пик- селов. Иногда для уменьшения эффектов блочности приме- няется процесс фильтрования. Обратите внимание, что существует вполне реальная воз- можность создать изображение, в котором субдискретизация компонента Y выполняется при сжатом изображении. Обыч- но так не делают, за исключением экспериментов, поскольку субдискретизация в этом случае приводит к образованию де- фектов изображения, которые проявляются после распаковки сжатого изображения. Еще одна ловушка процесса дискрети- зации связана с тем, что стандарт JPEG не запрещает такие
Введение в JPEG 69 комбинации частот дискретизации, которые приводят к необ- ходимости определения дискретизованных значений для до- лей пикселов. Предположим, что для компонента Y частота дискретизации по вертикали равна 3, а для компонента СЬ - 2. Это означает, что каждое значение данных компонента СЬ в вертикальном направлении приходится на Р/г пикселов. Большинство JPEG-программ не допускают выполнение та- кого рода дробной дискретизации. Функционирование JPEG На Рис. 4.5 показаны этапы кодирования JPEG. Ниже приве- дены краткие описания каждого этапа. ✓ Дискретизация (Sampling). На первом этапе JPEG- кодирования выполняется дискретизация. На этом шаге дан- ные пикселов преобразуются из цветового пространства RGB в цветовое пространство YCbCr и выполняется субдискрети- зация (down sampling). ✓ Дискретное косинусное преобразование (DCT - Discrete Cosine Transform). Изображения JPEG сжимаются в блоки 8x8 пик- селов, называемые единицами данных (data units). Дискрет- ное косинусное преобразование преобразует значения еди- ниц данных в сумму косинусных функций. ✓ Квантование (Quantization). В процессе JPEG-сжатия изобра- жения на этапе квантования отбрасываются коэффициенты дискретного косинусного преобразования, которые несуще- ственны для восстановления изображения, достаточно близ- кого к оригиналу. Квантование - основной процесс, при вы- полнении которого теряются данные в методе JPEG-сжатия. ✓ Кодирование Хаффмана (Huffman Coding). На стадии кодиро- вания Хаффмана кодируются коэффициенты дискретизации (DCT), при этом исключаются серии нулевых значений. В стандарте JPEG эта фаза называется кодированием энтро- пии (entropy coding), поскольку стандарт JPEG допускает вместо кодирования Хаффмана использование арифметиче- ского кодирования (arithmetic coding).
70 Форматы и алгоритмы сжатия изображений в действии Рис. 4.5. Блок-схема JPEC-кодирования Чересстрочные и построчные сканы Выше в этой главе мы говорили, что скан может содержать данные одного или нескольких компонентов. Скан с одним компонентом называется построчным сканом (noninterleaved scan). В построчном скане единицы данных кодируются по одной строке за один раз, сверху вниз, слева направо. Если скан содержит данные нескольких компонентов, он на- зывается чересстрочным сканом (interleaved scan). Чересст- рочные сканы кодируются как группы единиц данных, из- вестные в качестве минимальных кодированных блоков или MCUs (Minimum Coded Units). Частота дискретизации ком- понента по вертикали задает число строк единиц данных, ко- торые приходятся на данный компонент в MCU, а частота по горизонтали задает число столбцов. (В построчном скане MCU всегда равен 1-ой единице данных). Внутри MCU еди- ницы данных для каждого компонента кодируются сверху вниз, слева направо. В пределах MCU чересстрочное разме- щение компонентов не используется. На Рис. 4.6 показано, каким образом кодировались бы едини- цы данных в MCU на примере изображения с тремя компо- нентами и с горизонтальной и вертикальной частотами дис- кретизации равными 4x2, 2x4 и 1x1. Каждый маленький квадратик представляет один пиксел. Прямоугольники с тол- стой рамкой показывают, каким образом при дискретизации пикселы группируются в единицы данных. Числа показыва- ют порядок, в котором кодируется каждая единица данных внутри MCU.
Введение в JPEG 71 Рис. 4.6. Порялок расположения MCU Максимальные значения частот дискретизации по горизонта- ли и вертикали одинаковы и равны 4, так что каждый MCU будет представлять собой блок пикселов 32x32 (8x4 на 8x4). Частоты дискретизации для каждого компонента задают взаимосвязь компонента с MCU. Для первого компонента частота дискретизации по вертикали равна 4, так что ему со- ответствует 4 столбца единиц данных. Частота дискретиза- ции по вертикали равна 2, так что компоненту соответствует 2 строки единиц данных. Сканы всегда кодируются с помощью полных MCUs. Если высота или ширина изображения не кратны размеру MCU, в данные изображения вставляются дополнительные значения пикселов, с тем, чтобы сжатые данные всегда содержали полные MCUs. Для заполнения неполных единиц данных стандарт JPEG рекомендует выполнять дублирование по- следнего столбца или последней строки пикселов. Помните, что число строк и столбцов MCU определяется максималь- ными частотами дискретизации компонентов в изображении, а не максимумом в скане. Допустим, есть изображение размером 129x129 пикселов. Если бы нам надо было закодировать это изображение так, чтобы для одного компонента частоты дискретизации по вер- тикали и горизонтали были равны 4, а для других компонен- тов частоты дискретизации по вертикали и горизонтали были равны 1, тогда каждый MCU представлял бы блок из 32x32 пикселов. Для кодирования изображения потребовалось бы четыре полные строки и столбца MCUs, а также одна дробная строка и один дробный столбец MCU. Поскольку дробные
72 Форматы и алгоритмы сжатия изображений в действии MCUs не допускаются, для кодирования изображения при- шлось бы использовать пять строк и пять столбцов MCUs. Для кодирования первых компонентов в построчном скане, каждый MCU должен состоять из 1-ой единицы данных. Для первого компонента каждая единица данных представляет блок из 8x8 пикселов, поэтому для кодирования скана потре- бовалось бы 17 строк и столбцов. Каждая единица данных для других компонентов представляет блок из 32x32 пиксе- лов, поэтому потребовалось бы 5 строк и столбцов единиц данных. Заключение В этой главе рассмотрены основные понятия формата JPEG: частоты дискретизации, сканы, единицы данных, MCUs, и построчное чередование.(interleaving). Формат JPEG - это не отдельный метод, а скорее набор родственных технологий сжатия. На практике широко используется только небольшая часть стандарта JPEG. Из-за ограничений, накладываемых авторскими правами, официальный стандарт JPEG (JPEG 1994) не включен на прилагаемый к книге компакт-диск. Стандарт состоит из двух частей: самого стандарта и информации об испытаниях на соответствие стандарту. Для реализации JPEG необхо- дима только первая часть. (Более того, существует десять патентов, относящихся к арифметическому кодированию, которые приводятся в приложении L этого документа). До- кументацию можно заказать у вашего местного представи- теля международной организации по стандартизации [ISO] (в США это ANSI). Помимо информации о режимах JPEG, не приведенной в данной книге, Пенбейкер (Pennebaker) и Митчел (Mitchell) (1993) включили в свою книгу копии чер- новых спецификаций (draft specifications) обеих частей стандарта JPEG. В настоящее время стандарт JPEG-LS находится на стадии разработки и не включен ни в один из источников, упомяну- тых выше. Из-за ограничений, накладываемых авторскими правами, мы не смогли включить на компакт-диск копию проекта данного стандарта. Однако проект стандарта JPEG- LS доступен в Интернете по адресу www.jpeg.org.
ГЛАВА 5. Формат файлов JPEG В данной главе продолжается обсуждение формата JPEG. Мы обсудим структуру файлов JPEG, которая включает все части файла, за исключением сжатых данных. Приводимые здесь описания принимают во внимание только ту часть JPEG, которая обсуждается в этой книге, поэтому вы обна- ружите некоторые отличия от стандарта JPEG. Маркеры Маркеры используются для разбиения потока данных JPEG на структуры компонентов. Длина маркера равна 2 байтам, причем значение первого байта всегда равно FF,6. Второй байт содержит код, который указывает тип маркера. В каче- стве символов-заполнителей перед началом любого маркера может располагаться произвольное число байтов со значе- ниями FF16- Байт в потоке JPEG со значением FF16, за кото- рым следует еще один байт со значением FFie, всегда игно- рируется. Маркеры JPEG можно сгруппировать по двум основным ти- пам. Одиночные маркеры (stand-alone markers) не содержат никаких данных, кроме своих 2 байтов. За маркерами, которые стоят не в одиночку, сразу же следует значение длиной 2 бай- та. Оно указывает число байтов данных, которые содержит маркер. Счетчик длины (length count) включает 2 байта длины, но не длину самого маркера. Одиночные маркеры JPEG пере- числены в Таблице 5.1, а маркеры с данными описаны в Таб- лице 5.2. Как можно видеть из таблиц, большинство маркеров не используются в режимах, с которыми мы работаем. Таблица 5.1. Одиночные маркеры JPEG Значение Символ, используемый Описание в стандарте JPEG FFO1* ТЕМ Временно для арифме- тического кодирования FFD0-FFD7 RST0-RST7 Маркер перезапуска FFD8 SOI Начало изображения FFD9 EOI Коней изображения *Не используется ни в одной из технологий, описываемых в этой книге.
74 Форматы и алгоритмы сжатия изображений в действии Таблииа 5.2. Маркеры JPEG с данными Значение Символ, используемый в стандарте JPEG Описание FFCO SOF0 Начинает кадр, базовый метод FFC1 SOF, Начинает кадр, расширенный последовательный FFC2 sof2 Начинает кадр, прогрессивный FFC3* SOF3 Начинает кадр, метод сжатия без потерь FFC4 DHT Определяет таблицу Хаффмана FFC5* SOFs Начинает кадр, дифференциальный последовательный метод FFC6* SOF6 Начинает кадр, дифференциальный прогрессивный метод FFC7* sof7 Начинает кадр, дифференциальный метод без потерь FFC8* JPg Резервный FFC9* sof9 Начинает кадр, расширенный последовательный метод, арифметическое кодирование FFCA* SOF10 Начинает кадр, прогрессивный метод, арифметическое кодирование FFCB* SOFn Начинает кадр, метод без потерь, арифметическое кодирование FFCC* DAC Определяет условия арифметиче- ского кодирования FFCD* SOF13 Начинает кадр, дифференциальный последовательный метод, арифме- тическое кодирование FFCE* sof,4 Начинает кадр, дифференциальный прогрессивный метод, арифметиче- ское кодирование FFCF* sof15 Начинает кадр, дифференциальный метод без потерь, арифметическое кодирование FFDA SOS Начинает скан
Формат файлов JPEG 75 Таблица 5.2. Продолжение Значение Символ, используемый в стандарте JPEG Описание FFDB DQT Определяет таблицы дискретизации FFDC* DNL Определяет число строк FFDD DRI Определяет интервал перезапуска FFDE* DHP Определяет иерархическую прогрессию FFDF* EXP Раскрывает справочные компоненты FFEO-FFEF арр0-арр,5 Специфические данные программы FFFE СОМ Комментарий FFFO-FFFD* JPG0-JPG13 Резервный FFO2-FFBF* RES Резервный *Не используется ни в одной из технологий, описываемых в этой книге. Стандарт JPEG достаточно гибок в том, что касается распо- ложения маркеров внутри файла. Его строжайшее правило предписывает, чтобы файл начинался с маркера SOI и закан- чивался маркером EOI. В большинстве остальных случаев маркеры могут появляться в любом порядке. Основное требование заключается в том, что если данные из одного маркера нужны для обработки второго маркера, пер- вый маркер должен располагаться до второго. Конкретные правила, касающиеся расположения маркеров, рассматрива- ются в следующем разделе. Нижний индекс п используется для ссылки на совокупность ряда маркеров. Например, RST„ означает любой из маркеров переза- пуска от RST0 до RST7; SOFn указывает на любой маркер начала кадра.
76 Форматы и алгоритмы сжатия изображений в действии Сжатые данные 4- Сжатые данные компонентов являются единственной частью файла JPEG, которые не встречаются внутри маркера. Сжа- тые данные всегда следуют сразу после маркера SOS. По- скольку в нем нет информации о длине, необходимо проска- нировать данные до следующего маркера (отличного от RSTn), чтобы найти конец сжатых данных без их восстанов- ления. Маркеры RSTn являются единственными маркерами, которые встречаются внутри сжатых данных, и они не могут помещаться куда-нибудь еще.1 2 Метод JPEG-сжатия разработан так, что он редко создает в сжатых данных значение (compressed value) FF]6. Когда тре- буется присутствие такого значения в сжатых данных, оно кодируется как последовательность 2-х байтов, в которой за FF16 следует 0016. Это облегчает программам сканирование файлов JPEG с целью поиска конкретных маркеров. Типы маркеров В этом разделе описываются все маркеры, используемые ре- жимами JPEG, с которыми мы работаем. В таблицы, которые иллюстрируют структуру маркеров, не включены 2-байтовый маркер и 2-байтовое поле длины (length field). Описания отдельных маркеров указывают, где маркер может встретиться в файле. В описаниях не повторяются следую- щие ограничения: ✓ В сжатых данных могут появляться только маркеры RST и DNL. ✓ Изображение должно начинаться с маркера SOI, за которым следует маркер АРР0." 1 Стандарт JPEG разрешает появление в сжатых данных маркеров DNL. Маркеры DNL использу- ются для определения или переопределения размеров изображения внутри сжатых данных, а не внутри маркера SOFn. На практике маркеры DNL не используются и большинство программ не могут их обрабатывать. Поэтому в дальнейшем маркеры DNL не будут рассматриваться. 2 Расположение маркера АРРо непосредственно за маркером SOI является требованием формата JFIF. Некоторые программы, такие как Adobe Illustrator, могут создавать файлы JPEG, формат которых отличен от формата JFIF.
Формат файлов JPEG 77 ✓ Последним маркером в файле должен быть маркер EOI, и он должен следовать сразу после сжатых данных из последнего скана изображения. Маркеры АРР„ Маркеры АРРо—АРР15 содержат специфические данные про- граммы. Эти маркеры используются программами редакти- рования изображений для сохранения дополнительной ин- формации, помимо той, что задается стандартом JPEG. Фор- мат этих маркеров зависит от конкретной программы. Поле длины, располагающейся после маркера, может использо- ваться для пропуска данных маркера. За исключением марке- ров АРРо, используемых форматом JFIF, программа может игнорировать маркеры АРР, которые она не распознает. Если программе необходимо сохранить информацию, выходящую за пределы возможностей форматов JPEG и JFIF, то для со- хранения этой информации программа может создать марке- ры АРРп. Внутри файла JPEG маркеры АРРП могут появляться где угодно. По соглашению, программы, которые создают маркеры АРРП, сохраняют свое имя (заканчивающееся нулем) в начале мар- кера, с целью предотвращения конфликтов с другими про- граммами. Программа, обрабатывающая маркеры АРРП, должна проверять не только идентификатор маркера, но так- же имя программы, записавшей маркер. ; ‘ Маркеры СОМ Маркер COM (Comment - Комментарий) используется для хранения строк комментариев, например, информации об ав- торских правах. Их интерпретация зависит от конкретной программы, однако JPEG-кодер должен предполагать, что декодер будет игнорировать эту информацию. Именно мар- кер СОМ, а не маркер АРРП, должен использоваться для хра- нения простого текста комментария. В файле JPEG он может появляться где угодно.
78 Форматы и алгоритмы сжатия изображений в действии Маркеры DHT Маркер DHT (Define Huffman Table - Определение таблицы Хаффмана) определяет (или переопределяет) таблицы Хафф- мана, которые идентифицируются типом (АС или DC3) и числом. Один маркер DHT может определять множество таб- лиц, однако базовый режим ограничен двумя таблицами каж- дого типа, а прогрессивный и последовательный режимы ог- раничены четырьмя таблицами. Единственное ограничение на размещение маркеров DHT состоит в том, что если скан требует наличия особого идентификатора таблицы или типа, идентификатор должен быть определен ранее в файле марке- ром DHT. Структура маркера DHT показана в Таблице 5.3. Каждая таб- лица Хаффмана представляет собой 17 байтов фиксирован- ных данных, за которыми следует поле переменной длины, включающее до 256 дополнительных байтов. Первый фикси- рованный байт содержит идентификатор таблицы. Следую- щие 16 байтов образуют массив из 1-байтовых целых чисел без знака, элементы которого задают число кодов Хаффмана для каждой возможной длины кода (1—16). Сумма из 16 длин кодов представляет собой число значений в таблице Хаффмана. Каждое значение равно 1 байту и за ним следуют, согласно порядку кода Хаффмана, счетчики длины (length counts). Подробнее структура таблиц Хаффмана описывается в Главе 6. Таблица 5.3. Формат маркера DHT Размер поля Описание 1 байт 4 старших бита определяют тип таблицы. Значение 0 указывает на таблицу DC, значение 1 указывает на таблицу АС. 4 младших бита определяют иден- тификатор таблицы. Значение этого идентифика- тора равно 0 или 1 для кадров базового метода и 0, 1, 2 или 3 для кадров прогрессивного и расши- ренного методов 16 байтов Счетчик кодов Хаффмана длиной от 1 до 16. Каждый счетчик хранится в 1 байте Переменный 1 -байтовые символы, сортированные по коду Хаффмана. Число символов равно сумме 16 счетчиков кода 3 Обозначения АС и DC поясняются в Главе 7.
Формат файлов JPEG 79 Число таблиц Хаффмана, указываемое маркером DHT, оп- ределяется из поля длины. Программа должна поддержи- вать ведение счетчика, который инициализируется значе- нием длины поля минус 2. Каждый раз, когда считывается таблица, из счетчика вычитается длина этой таблицы. Ко- гда значение счетчика достигнет нуля, все таблицы будут прочитаны. В маркере DHT не допускается наличие запол- нителей, поэтому если значение счетчика становится отри- цательным, то это служит указателем недостоверности файла. Маркеры DRI Маркер DRI (Define Restart Interval - Определение интервала перезапуска) задает число MCUs между маркерами переза- пуска (restart markers) внутри сжатых данных. Значение поля длиной 2 байта, следующего за маркером, всегда равно 4. В маркере есть только одно поле данных - 2-байтовое значе- ние, которое определяет интервал перезапуска (restart interval). Если интервал равен нулю, это означает, что марке- ры перезапуска не используются. Маркер DRI с ненулевым значением интервала перезапуска может применяться для по- вторной активизации маркеров перезапуска далее в изобра- жении. Маркеры DRI могут появляться в любом месте файла для оп- ределения или переопределения интервала перезапуска, ко- торый сохраняет свое действие до конца изображения или пока другой маркер DRI не изменит его. Чтобы маркеры пере- запуска были включены в сегмент сжатых данных, в файле должен присутствовать где-нибудь маркер DRI. Маркеры перезапуска помогают в нейтрализации ошибок. Если декодер находит искаженные данные скана, он может использовать идентификатор (ГО) маркера перезапуска и ин- тервал перезапуска для определения места, с которого будет возобновлено декодирование изображения. Число пропускаемых MCUs можно определить с помощью следующей формулы: Число пропускаемых MCUs = Интервал перезапуска х ((8 + + Идентификатор текущего маркера - Идентификатор последнего маркера)ЪАОТдЪ)
80 Форматы и алгоритмы сжатия изображений в действии Пример: Предположим, что интервал перезапуска равен 10. После того, как были декодированы 80 MCUs, из входного потока считывается маркер RST7. Если декодер встречает искаженные данные до того, как присту- пит к чтению следующего маркера перезапуска (RST0), он прекращает декодирование и сканирует входной поток в поисках следующего мар- кера перезапуска. Если следующим маркером является RST3, декодер пропускает 40 MCUs (= 10 х ((8 + 3 - 7)MOD8)), начиная с последней известной точки (80). Декодер возобновляет декодирование со 121-го MCU в изображении. Маркеры DQT Маркер DQT (Define Quantization Table - Определение таблиц квантования) определяет (или переопределяет) таблицы квантования, используемые в изображении. Маркер DQT мо- жет определять несколько таблиц квантования (до 4). Опре- деление таблиц квантования следует за полем длины марке- ра. Значение поля длины равно сумме размеров таблиц плюс 2 (для учета поля длины). Формат определения таблиц квантования показан в Табли- це 5.4. Каждая таблица начинается с 1-го байта, который со- держит информацию о таблице. Если 4 старших бита ин- формационного байта равны нулю, каждое значение табли- цы квантования равно 1 байту, а длина всего определения таблицы составляет 65 байтов. Если значение 4 старших би- тов равно 1, размер каждого значения таблицы квантования равен 2 байтам и длина определения таблицы составляет 129 байтов. Двухбайтовые значения квантования могут ис- пользоваться только с 12-битовыми дискретизованными данными. Таблица 5.4. Определение таблиц квантования в маркере DQT Размер поля Описание 1 байт 4 младших бита являются идентификатором таблииы (0, 1,2 или 3). 4 старших бита задают размер значения квантования (0 = 1 байт, 1 = 2 байта) 64 или 128 байтов 64 1- или 2-байтовых значений квантования без знака
Формат файлов JPEG 81 4 младших бита определяют числовой идентификатор табли- цы, который может быть равен 0, 1, 2 или 3. За информаци- онным байтом следуют 64 значения квантования, которые хранятся в JPEG в зигзагообразном порядке (определяемом в Главе 7). В файле изображения маркеры DQT могут появляться где угодно. Единственное ограничение состоит в том, что если скану требуется таблица дискретизации, она должна быть определена в предшествующем маркере DQT. Маркеры EOI Маркер EOI (End of Image - Конец изображения) отмечает конец JPEG-изображения и должен находиться в конце JPEG-файла. В файле допускается присутствие только одно- го маркера EOI, за которым не может располагаться ни один из прочих маркеров. Маркер EOI стоит в одиночку. Маркеры RST„ Маркеры перезапуска RST0-RST7 используются для марки- ровки блоков независимо кодированных сжатых данных ска- на. В этих маркерах отсутствуют поле длины и данные, а са- ми маркеры могут встречаться только внутри сжатых данных скана. Маркеры перезапуска могут использоваться для нейтрализа- ции ошибок. Интервал между маркерами перезапуска опре- деляется маркером DRI (Define Restart Interval - Определение интервала перезапуска). Таким образом, если интервал пере- запуска равен нулю, то маркеры перезапуска не используют- ся. В данных скана маркеры перезапуска встречаются в по- следовательности RSTo, RST1, ... RST7, RSTo .... Маркеры SOI Маркер SOI (Start of Image - Начало изображения) отмечает начало JPEG-изображения. Он может находиться в самом начале файла и во всем файле может быть только один такой маркер. Маркер SOI стоит в одиночку.
82 Форматы и алгоритмы сжатия изображений в действии Маркеры SOFn Маркер SOFn (Start of Frame - Начало кадра) определяет кадр. Хотя существует множество типов кадров, у всех у них оди- наковые форматы. Маркер SOF состоит из фиксированного заголовка следующего после поля длины маркера. Далее рас- полагается список структур, которые определяют каждый компонент, используемый в кадре. Структура фиксированно- го заголовка показана в Таблице 5.5, а структура компонента приводится в Таблице 5.6. Таблииа 5.5. Фиксированная часть маркера SOF Размер поля Описание 1 байт Точность дискретизации в битах (может быть равной 8 или 12) 2 байта Высота изображения в пикселах 2 байта Ширина изображения в пикселах 1 байт Число компонентов в изображении Таблииа 5.6. Область маркера SQF, зависяшая от компонента Размер поля Описание 1 байт Идентификатор компонента. В соответствии с форматом JPEG значение этого поля может изме- няться от 0 до 255. Формат JFIF ограничивает значения идентификатора величинами 1 (Y), 2 (СЬ) или 3 (Сг) 1 байт 4 старших бита задают для компонента частоту дискретизации по горизонтали. 4 младших бита задают частоту дискретизации по вертикали. В соответствии со стандартом, как для вертикаль- ной, так и для горизонтальной частот дискретиза- ции допускается любое из значений: 1, 2, 3 или 4. В приводимом нами коде не поддерживается зна- чение 3 1 байт Идентификатор таблицы квантования для компо- нента. Соответствует идентификатору маркера DQT. Может быть равным 0, 1,2 или 3 Компоненты идентифицируются целым числом в диапазо- не от 0 до 255. Стандарт JFIF накладывает большие огра- ничения и указывает, что компоненты должны определять- ся в порядке {Y, СЬ, Сг} с помощью идентификаторов {1, 2, 3}, соответственно. К сожалению, некоторые кодеры не следуют стандарту и назначают компонентам другие идеи-
Формат файлов JPEG 83 тификаторы. Для декодера всеобъемлющим способом дос- тижения соответствия между компонентом цветового про- странства и идентификатором заключается в том, чтобы следовать порядку, в котором определяются компоненты, и принимать в обработку любой идентификатор, назначен- ный кодером. В файле JPEG может быть только один маркер SOFn и он должен предшествовать любому из маркеров SOS. Маркеры SOS Маркер SOS (Start of Scan - Начало сканирования) отмечает начало сжатых данных для скана в потоке JPEG. Его струк- тура иллюстрируется в Таблице 5.7. После счетчика компо- нента располагаются дескрипторы для каждого компонента (описание дескриптора компонента показано в Таблице 5.8). Далее следуют 3 байта данных, используемых только в про- грессивном режиме. Сжатые данные скана следуют непо- средственно за маркером. Таблица 5.7. Структура Размер поля Описание 1 байт 2 байта счетчика компонентов (component count) 1 байт 1 байт 1 байт Счетчик компонентов Дескрипторы компонентов скана (см. Таблицу 5.8) Начало спектрального выделения (0—63) Коней спектрального выделения (0—63) Последовательное приближение (два 4-битовых поля, каждое со значением в диапазоне 0—13) маркера SOS Таблица 5.8. Описание лескриптора скана в маркере SOS Размер поля Описание 1 байт Идентификатор компонента 1 байт 4 старших бита задают таблицу Хаффмана DC, а 4 младших бита задают таблицу Хаффмана АС
84 Форматы и алгоритмы сжатия изображений в действии Дескрипторы компонентов располагаются в той же после- довательности, в которой компоненты располагаются в MCUs данных скана. Хотя не все компоненты из маркера SOFn могут быть в наличии, порядок компонентов в маркере SOS должен совпадать с порядком компонентов в маркере SOFn. Идентификатор компонента в дескрипторе скана дол- жен соответствовать значению идентификатора компонента, определяемому в маркере SOFn. Идентификаторы таблиц Хаффмана АС и DC должны совпадать с идентификаторами таблиц Хаффмана, определяемыми в предшествующем мар- кере DHT. Стандарт JPEG допускает присутствие в скане от 1 до 4 компонентов, но существует ряд других ограничений, накладываемых на число компонентов. Формат JFIF огра- ничивает изображение тремя компонентами. В прогрес- сивных сканах может присутствовать только 1 компонент, если начало спектрального выделения отлично от нуля. Стандарт JPEG также устанавливает для количества еди- ниц данных, которое может быть в MCU, достаточно низ- кий предел равный 10, что может ограничивать число ком- понентов в скане. В последовательном скане начало спектрального выделения должно быть равно нулю, конец спектрального выделения - 63, а последовательное приближение - нулю. Если в прогрес- сивном скане начало спектрального выделения равно нулю, то конец спектрального выделения тоже должен быть равен нулю. В остальных случаях значение конца спектрального выделения должно быть не меньше, чем значение начала спектрального выделения. Эти параметры будут объясняться подробнее в главе 10. В файле маркер SOS должен появляться после маркера SOFn. Ему должны предшествовать маркеры DHT, которые опреде- ляют все таблицы Хаффмана, используемые в скане, и мар- керы DQT, которые определяют все таблицы квантования, ис- пользуемые компонентами скана.
Формат файлов JPEG 85 I 1111 Формат JFIF Рис. 5.1. Структура файла JFIF Для всех практических целей выражение «файл JPEG» озна- чает «файл JPEG в формате JFIF». Стандарт JFIF определяет следующие характеристики формата: ✓ Сигнатуру для идентификации файлов JPEG; ✓ Цветовое пространство; ✓ Плотность пикселов для аппаратно независимого отображения изображения; ✓ Миниатюры изображений; Взаимосвязь пикселов с частотой дискретизации. Обобщенная схема файла JFIF показана на Рис. 5.1. По- скольку вся специфичная для JFIF информация хранится в маркерах АРР0, файлы JFIF полностью совместимы со стан- дартом JPEG. Стандарт JFIF требует, чтобы за маркером SOI, который начинает файл, сразу следовал маркер АРР0 в формате, показанном в Таблице 5.9. Стандарт JFIF предписывает использование цветового про- странства YCbCr. Преобразование между RGB и YCbCr, оп- ределяемое стандартом JFIF, обсуждалось в Главе 1. В цвет- ных изображениях должны присутствовать все три компонента, идентификаторы компонентов изображений должны быть равными Y=l, Cb=2 и Сг=3. Полутоновые изображения должны содержать только компонент Y. Файл JFIF может быть идентифицирован путем считывания первых 11 байтов и проверки того факта, что первые 4 байта равны FFi6 D8i6 FFi6 E0i6 (маркер SOI, за которым следует маркер АРРо). После пропуска 2 байтов, следующие 5 байтов должны быть равными J, F, I, F, 00!6, причем байт 00i6 распо- лагается последним. Маловероятно, что файл, начинающийся указанной выше записью, будет не JFIF-файлом, а файлом какого-нибудь другого формата. За заголовком JFIF АРРо может следовать другой маркер АРРо, используемый для вставки миниатюры в формате, от- личном от трехцветного RGB-формата, определяемого заго- ловком. Расположенная за полем длины структура данных для дополнительного (необязательного) заголовка АРР0, по- казана в Таблице 5.10.
86 Форматы и алгоритмы сжатия изображений в действии Имя поля Размер Описание Идентификатор 5 байтов Строка JFIF, завершаемая нулем Основной код (ID) версии 1 байт Основной идентификационный код (ID) версии файла. Для текущей версии JFIF (1.2) это значение равно 1 Дополнительный код (ID) версии 1 байт Дополнительный идентификационный код (ID) версии файла. Для текущей версии JFIF (1.2) это значение равно 2 Единицы измерения 1 байт Единицы измерения плотности пикселов по горизонтали и вертикали. Нуль означает, что никакие плотности не ис- пользуются. Следующие два поля указывают пропорцию. Единица означает, что следующие два поля указывают плотность в пикселах на дюйм. Двойка означает, что поля указывают плотность в пикселах на сантиметр Xdensity 2 байта Плотность пикселов по горизонтали Ydensity 2 байта Плотность пикселов по вертикали Xthumbnail 1 байт Ширина дополнительной (необязательной) миниатюры изображения. Эта величина может быть равной 0 Ythumbnail 1 байт Высота дополнительной (необязательной) миниатюры изо- бражения. Эта величина может быть равной 0 Миниатюра Пере- менный Дополнительная (необязательная) миниатюра изображе- ния. Размер этого поля равен 3xXthumbnailxYthumbnail. Изображение сохраняется с 3 байтами на пиксел, цвета располагаются в RGB-порядке Таблица 5.9. Формат заголовка маркера JFIFAPPo Если заголовок расширения JFIF включает поле exten- sion_code, равное 1016, то поле extension_data содержит изо- бражение, кодированное в формате JPEG. Цвета кодируются в соответствии со стандартом JFIF, но сжатые данные не со- держат заголовка JFIF АРР0. Формат поля extension_data при значении поля extension_code равном 11]6 показан в Таб- лице 5.11; формат при значении поля extension_code равном 1216 показан в Таблице 5.12. Ваши программы должны избегать создания маркеров АРРо от- личных от тех, что определяются стандартом JFIF. Кроме АРРо, в стандарте предусмотрены также еще пятнадцать других мар- керов АРРЛ, и этого должно быть достаточно для любой мысли- мой ситуации. При создании маркеров АРРП программа должна размещать свое имя в начале области данных. Это позволяет идентифицировать программу-создателя маркера.
Формат файлов JPEG 87 Таблииа 5.10. Формат дополнительного (необяза тел ьного) Имя поля Размер Описание Идентификатор 5 байтов Строка JFXX, завершаемая нулем заголовка АРР0 JFIF extension_code 1 байт Определяет формат поля extension_data, следующего ниже. Значение 1016 означает, что миниатюра кодируется с использованием JPEG. Значе- ние 11 is означает, что миниа- тюра кодируется с разрешени- ем один байт на пиксел. Зна- чение 1216 означает, что ми- ниатюра кодируется с разре- шением 3 байта на пиксел. extension_data Переменный Таблииа 5.11. Формат поля extension_data Имя поля Размер Описание Xthumbnail 1 байт Ширина миниатюры для расширения JFIF типа 1116 Ythumbnail Палитра 1 байт 768 байтов Высота миниатюры Массив 3-байтовых значений цветовых кодов RGB Пикселы Переменный (Xthumbnail х Ythumbnail) Индексы в палитре для каждого пиксела миниатюры Таблииа 5.12. Имя поля Размер Описание Формат поля extension_data Xthumbnail 1 байт Ширина миниатюры для расширения JFIF типа 12is Ythumbnail 1 байт Высота миниатюры RGB Переменный (3 х Xthumbnail х Ythumbnail) Коды цветов RGB для каждого пиксела изображения Хотя большинство структур в стандарте JFIF определяют формат миниатюр изображений, данные структуры используются редко.
88 Форматы и алгоритмы сжатия изображений в действии Заключение После прочтения этой главы вы должны уяснить внутрен- нюю структуру файла JPEG. По мере чтения следующих глав, рассматривающих стандарт JPEG, вам, возможно, по- требуется часто обращаться к данной главе. Первоначальный стандарт JPEG не определял формат файлов, однако в каче- стве такого формата общепринят неофициальный формат JFIF. Текст стандарта JFIF и текст официального стандарта SPIFF включены на прилагаемый к книге компакт-диск. Ос- тальные положения формата JPEG определяет стандарт JPEG (1994). В оставшихся главах этой книги, посвященных JPEG, обсуждаются сжатые данные в маркерах SOS. Прилагаемый компакт-диск содержит исходный код про- граммы JPEGDUMP, которая анализирует структуру файла JPEG. Программа выводит текстовую версию содержимого маркеров файла JPEG. До некоторой степени она поддержи- вает все маркеры JPEG, даже те, которые не обсуждались в этой главе. Однако было бы крайне удивительно, если вам когда-либо встретится любой из этих маркеров в реальном JPEG-файле. Чтобы запустить программу JPEGDUMP, введите jpegdump somefile.jpg в командную строку. На Рис. 5.2 показан пример выходных данных программы JPEGDUMP для цветного изображения. Приводимые вы- ходные данные вполне типичны для большинства изобра- жений JPEG, которые могут вам встретиться. Обратите внимание, таблицы квантования и Хаффмана определяют- ся попарно, и что компонент Y использует одну из таблиц в каждой паре, а компоненты СЬ и Сг совместно использу- ют другую таблицу. Такое применение таблиц не опреде- ляется стандартом, но представляет обычную практику их использования. Рис. 5.2. Пример выходных данных программы JPEGDUMP { Start Of Image } { АРРО Marker Length: 16 Version: 1.1 Density Unit: (pixels per inch) X Density: 72 Y Density: 72 Thumbnail Width: 0 Thumbnail Height: 0
Формат файлов JPEG 89 { Define Quantization Table Length: 132 Table Index: 0 Table Precision: i 0 Table Values: 6 4 4 4 5 4 5 6 9 6 5 6 8 6 6 8 11 : 11 10 10 12 6 5 9 11 12 10 10 16 12 12 12 12 12 12 16 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 Table Index: 1 Table Precision: Table Values: 7 7 7 13 12 16 24 20 14 0 13 24 16 14 14 20 20 14 14 14 14 20 17 12 12 12 12 12 17 17 12 12 12 12 12 12 17 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 { Start Of Frame Type: Baseline (Huffman) Length: 17 Precision: 8 Height: 383 Width: 262 Component Count: 3 Component 1 Horizontal Frequency: 2 Vertical Frequency: 2 Quantization Table: 0 Component 2 Horizontal Frequency: 1 Vertical Frequency: 1 Quantization Table: 1 Component 3 Horizontal Frequency: 1 Vertical Frequency: 1 Quantization Table: 1 } { Define Huffman Table Length: 418 Table Index 0 Table Class: DC Code Counts: 0 0 7 1 11110 0 0 0 0 0 0 0 Code Values: 4 5 3 2 6 1 0 7 8 9 a b Table Index 1 Table Class: DC Code Counts: 0 2 2 3 11111 0 0 0 0 0 0 0 Code Values: 1 0 2 3 4 5 6 7 8 9 a b
90 Форматы и алгоритмы сжатия изображений в действии Table Index 0 Table Class: AC Code Counts: 021332426734262 73 Code Values: 1 2 3 11 4 0 5 21 12 31 41 51 6 13 61 22 71 81 14 32 91 al 7 15 Ы 42 23 cl 52 dl el 33 16 62 £0 24 72 82 £1 25 43 34 53 92 a2 b2 63 73 c2 35 44 27 93 аЗ ЬЗ 36 17 54 64 74 c3 d2 e2 8 26 83 9 a 18 19 84 94 45 46 a4 b4 56 d3 55 28 la £2 e3 £3 c4 d4 e4 £4 65 75 85 95 a5 b5 c5 d5 e5 £5 66 76 86 96 аб Ь6 сб d6 еб £6 37 47 57 67 77 87 97 a7 b7 c7 d7 e7 £7 38 48 58 68 78 88 98 a8 b8 c8 d8 e8 £8 29 39 49 59 69 79 89 99 a9 b9 c9 d9 e9 £9 2a 3a 4a 5a 6a 7a 8a 9a aa ba ca da ea fa Table Index 1 Table Class: AC Code Counts: 022123554564833 6d Code Values: 1 0 2 11 3 4 21 12 31 41 5 51 13 61 22 6 71 81 91 32 al Ы £0 14 cl dl el 23 42 15 52 62 72 £1 33 24 34 43 82 16 92 53 25 a2 63 b2 c2 7 73 d2 35 e2 44 83 17 54 93 8 9 a 18 19 26 36 45 la 27 64 74 55 37 £2 аЗ ЬЗ сЗ 28 29 d3 еЗ £3 84 94 a4 b4 c4 d4 e4 £4 65 75 85 95 a5 b5 c5 d5 e5 £5 46 56 66 76 86 96 аб Ь6 c6 d6 e6 £6 47 57 67 77 87 97 a7 b7 c7 d7 e7 £7 38 48 58 68 78 88 98 a8 b8 c8 d8 e8 £8 39 49 59 69 79 89 99 a9 b9 c9 d9 e9 £9 2a 3a 4a 5a 6a 7a 8a 9a aa ba ca da ea fa } { Start Of Scan Length: 12 Scan Count: 3 Component ID: 1 AC Entropy Table: 0 DC Entropy Table: 0 Component ID: 2 AC Entropy Table: 1 DC Entropy Table: 1 Component ID: 3 AC Entropy Table: 1 DC Entropy Table: 1 Spectral Selection Start: 0 Spectral Selection End: 63 Sucessive Approximation High: 0 Sucessive Approximation Low: 0 } { End Of Image }
ГЛАВА 6. Кодирование Хаффмана в JPEG В данной главе мы продолжим обсуждение формата JPEG, сосредоточив внимание на кодировании Хаффмана - одной из технологий сжатия, используемой в JPEG. Хотя конкретно в этой главе обсуждается применение кодирования Хаффма- на в формате JPEG, оно используется также и в PNG-формате изображений. Частота использования В английском языке некоторые буквы употребляются намно- го чаще других. Например, буквы Е и Т используются очень часто, в то время как буквы X и Q встречаются довольно ред- ко. В Таблице 6.1 приведены нормированные частоты ис- пользования всех букв, используемых в версии Библии Кинга Джеймса (King James). Можно видеть, что буква Е, исполь- зуемая чаще всех других букв, встречается примерно в пять раз чаще, чем буквы U и М, стоящие в середине списка, и примерно в 400 раз чаще, чем буква Q, которая завершает список. Таблииа 6.1. Частота использования Частота Буква Частота Буква Частота Буква 0,1272 Е 0,0489 D 0,0151 В букв в Библии 0,0981 Т 0,0401 L 0,0133 Р Кинга Джеймса (King James) 0,0875 н 0,0258 F 0,0094 V 0,0852 А 0,0257 и 0,0069 к 0,0750 О 0,0247 М 0,0027 J 0,0695 N 0,0202 W 0,0009 Z 0,0598 I 0,0181 Y 0,0004 X 0,0587 S 0,01 70 G 0,0003 Q 0,0525 R 0,0169 С Частота употребления букв учитывалась при разработке кода Морзе (Таблица 6.2), в котором чаще встречаемым буквам присвоены более короткие коды. Так, буквам Е и Т соответ- ствуют 1-символьные коды, в то время как буквам, исполь- зуемым реже, присвоены 4-символьные коды.
92 Форматы и алгоритмы сжатия изображений в действии Таблица 6.2. Кол Морзе Код Морзе Буква Код Морзе Буква Код Морзе Буква Е D - . . . В Т . L Р Н . F . . .- V А и к О М J N W . Z 1 Y X S G Q R С В мире компьютеров наборы символов в латинских алфави- тах почти всегда представляют путем применения методов кодирования с фиксированной длиной кода (fixed-length en- coding methods), таких как ASCII или EBCDIC, которые не принимают в расчет частоту использования. Каждый символ кодируется постоянным числом битов, независимо от того, как часто он встречается. Это весьма эффективно для дости- жения наивысшей скорости вычислений. Однако в таких приложениях, как сжатие изображения, где размер данных играет важную роль, есть смысл использовать коды перемен- ной длины. Наиболее широко известный метод генерирования кодов пе- ременной длины для символов, на основе частоты их упот- ребления, называется кодированием Хаффмана (Huffman cod- ing). Этот метод предложен Хаффманом в 1952 году. Проце- дура формирования кодов Хаффмана для набора значений, на основе частот их употребления, достаточно проста. Она включает создание двоичного дерева, содержащего символы, начиная снизу вверх, причем символы, которые встречаются реже всего, находятся дальше всех от корня. Сначала созда- ется пул (pool), который содержит или значения, или узлы дерева. Первоначально этот пул содержит все значения и не содержит узлов. Приводимая ниже процедура повторяется до тех пор, пока пул не будет содержать один узел дерева, и в нем не будет ни одного символа.
Кодирование Хаффмана в JPEG 93 1. Найдите два значения или узла дерева с наименьшей час- тотой появления и удалите их из пула. Если есть несколь- ко элементов с наименьшей частотой использования, связь можно разорвать с помощью произвольного выбора.1 2. Создайте новый узел дерева и сделайте элементы из пре- дыдущего шага его двумя ветвями. 3. Присвойте новому узлу дерева частоту равную сумме час- тот отходящих от него ветвей. 4. Добавьте вновь созданный узел в пул. После того как все значения будут объединены в одно дере- во, для каждого узла дерева назначается значение 0 одной его ветви и значение 1 другой ветви узла. Код Хаффмана для ка- ждого кодируемого значения определяется проходом по пути от корня дерева до данного значения, и добавлением в общий код кода каждой ветви, встречаемой по мере продвижения. Помните, что при работе с кодами Хаффмана оперируют би- товыми строками. Код Хаффмана состоит из переменного числа битов. Иными словами, это строка переменной длины, которая может состоять из нулей или единиц. Множество ко- дируемых значений и связанных с ними кодов образуют так называемую таблицу Хаффмана. Пример кодирования Хаффмана Чтобы продемонстрировать кодирование Хаффмана на при- мере, воспользуемся следующим палиндромом (палиндро- мом называется строка, читаемая одинаково в обоих направ- лениях). Палиндром состоит из восьми разных символов с частотами употребления, приведенными в Таблице 6.3. A MAN A PLAN A CANAL PANAMA. Таблииа 6.3. Частоты Значение Частота Значение Частота А 10 N 4 употребления СИМВОЛОВ С 1 Р 2 в палиндроме L 2 Пробел 6 М 2 . (точка) 1 Выбор, выполняемый для разрыва связи, влияет только на коды, генерируемые для кодируемых значений и не влияют на степень сжатия.
94 Форматы и алгоритмы сжатия изображений в действии Как видно из Таблицы 6.3, символы «С» и точки («.») встре- чаются реже всех. Чтобы начать процесс кодирования Хафф- мана, возьмем эти символы для создания узла дерева. Назна- чим этому узлу значение частоты равное сумме частот отхо- дящих от узла ветвей. A L М N Р <space> । 1 1 10 2 2 4 1 6 2 С 1 1 Четыре из оставшихся в пуле элементов связаны с низшей частотой равной 2. Берем Р и узел дерева, соединяем их друг с другом, чтобы создать новый узел дерева с суммарной час- тотой равной 4. A L М N <space> । 1- 10 2 2 4 6 4 1 1 Теперь из оставшихся символов наименьшая частота встре- чается у букв L и М. Поскольку всем доступным ветвям де- рева назначены большие частоты, следует создать новый, не соединенный с деревом узел, используя эти буквы. А I---1---1 N <space> ।-1---- 10 4 4 6 4 L М Р ।-------1 2 2 2 2 С 1 1 Теперь есть два узла дерева и буква N, связанные с наимень- шей частотой равной 4. Мы выбираем букву N и присоединя- ем ее к дереву. А I--1---1 <space> ।-1- 10 4 6 8 L М N 2 2 4 С 1 1 1
Кодирование Хаффмана в JPEG 95 Из оставшихся элементов наименьшие частоты встречаются у символа пробела и узла дерева L-M, поэтому они соединя- ются в одно дерево. А I-।---- I—।— 10 10 8 <space> I----1 N ।------- 6 4 4 L М Р I----1 2 2 2 С 1 1 1 Теперь остались два узла дерева и буква А. Мы произвольно решаем соединить два узла дерева, а не букву с одним из этих узлов. А ------------------J- 10 18 10 8 <space> 6 L М Р 2 2 2 1 1 Наконец, добавляем букву А, чтобы завершить построение дерева, а затем помечаем каждую левую ветвь 0 (нулем), а каждую правую ветвь 1 (единицей).
96 Форматы и алгоритмы сжатия изображений в действии Код Хаффмана для каждого кодируемого символа создается путем присоединения к коду 0 или 1, при прохождении по пути от корня к кодируемому символу. В Таблице 6.4 при- ведены коды Хаффмана, полученные для каждого символа. Используя коды Хаффмана, показанные в Таблице 6.2, па- линдром можно закодировать с помощью 74 битов, а если бы применялись коды постоянной длины, то это потребова- ло бы использования 3 битов для кодирования каждого сим- вола и 84 (3x28) бита для кодирования всей строки. Хотя в данном примере получено скромное сжатие на 12%, не за- бывайте, что мы работали с достаточно коротким текстом и между частотами символов нет большой разницы. Вы не получите разброса частот порядка 300:1 в текстовой строке из 28 символов. Таблииа 6.4. Колы Хаффмана лля символов палинлрома Значение Код Хаффмана Длина кода Частота использования символов Использовано битов А 0 1 10 10 С 11110 5 1 5 L 1010 4 2 8 М 1011 4 2 8 N 110 3 4 12 Р 1110 4 2 8 Пробел 100 3 6 18 . (точка) 11111 5 1 5 Всего 74 Обратите внимание, что в Таблице 6.4 ни один из кодов не является префиксом к любому другому коду. Например, бук- ве N присвоен код 110, и ни один из кодов в таблицы не на- чинается с битовой строки 110. Данное положение верно и для всех остальных кодов. Это очень важное свойство, по- скольку без него оказалось бы невозможным декодировать строку, закодированную по методу Хаффмана.
Кодирование Хаффмана в JPEG 97 Кодирование Хаффмана с использованием длин кодов Хотя древовидная структура облегчает понимание принципов кодирования Хаффмана, это не самый простой путь получе- ния кодов Хаффмана. Другой метод состоит в генерировании для всех символов длин кодов (code length) и формировании на их основе кодов Хаффмана. В этом методе используются символы, связанные с длинами кодов и списки значений со связанными с ними частотами. Первоначально кодируемому значению присваивается длина кода равная 0, и каждое зна- чение помещается в отдельный список, которому назначается частота, равная частоте кодируемого значения из этого спи- ска. Для палиндрома данный метод образует следующую структуру: |У 0110 Гс~0~| 1 ElU г |~М~0~| 2 f~N~01 4 | Р 0 | 2 I 0 I 6 □И 1 Для получения длин кодов соединим два списка с самыми низкими частотами. При объединении двух списков частота нового списка равна сумме частот двух прежних списков. Каждый раз, при присоединении списка, частота каждого символа в списке увеличивается на единицу. Процесс повто- ряется до тех пор, пока не получится один список кодов. При наличии нескольких списков с наименьшей частотой, из них всегда выбирается тот список, который расположен ближе всех к концу. Наименьшие частоты принадлежат спискам с точкой и бук- вой С, поэтому мы объединяем эти списки и увеличиваем на единицу длины кодов для двух символов. 4 - 9809
98 Форматы и алгоритмы сжатия изображений в действии В результате получаются четыре списка с наименьшей часто- той равной 4. Мы выбираем два списка, ближайших к низу, и объединяем их, получая: Повторяя описанную выше процедуру, получаем следующие структуры:
Кодирование Хаффмана в JPEG 99 Если рассортировать символы по длине кода, получим длины кодов, приведенные в Таблице 6.5. Используя Алгоритм 6.1, можно сгенерировать из отсортированного списка коды Хаффмана. Входными данными для этой функции будет мас- сив длин кодов Хаффмана, подобных тем, что приведены в Таблице 6.5, и число элементов массива. На выходе функции получается массив кодов Хаффмана, сгенерированных для длин кодов. На Рис. 6.1 показан процесс генерирования кодов Хаффмана из отсортированного списка длин кодов Хаффма- на, приведенного в Таблице 6.5. Таблииа 6.5. Символы палиндрома, отсортированные по длине кода Символ Код длины А 1 Пробел 3 N 3 L 4 М 4 Р 4 С 5 . (точка) 5 Алгоритм 6.1 Генерирование колов Хаффмана по ллинам колов Procedure GenerateHuffmanCodes (NUMBEROFCODES, CODELENGTHS[0..NUMBEROFCODES-1], CODES [0..255]) Begin HUFFMANCODECOUNTER = 0 CODELENGTHCOUNTER = 1 For INDEX = 0 TO NUMBEROFCODES - 1 Do Begin If CODELENGTHS [INDEX] = CODELENGTHCOUNTER Then Begin CODES [INDEX] = HUFFMANCODECOUNTER HUFFMANCODECOUNTER = HUFFMANCODECOUNTER + 1 End Else Begin HUFFMANCODECOUNTER = HUFFMANCODECOUNTER Leftshift 1 CODELENGTHCOUNTER = CODELENGTHCOUNTER + 1 End End End
100 Форматы и алгоритмы сжатия изображений в действии Рис. 6.1. Генерирование кодов Хаффмана по длинам кодов
Кодирование Хаффмана в JPEG 101 Счетчик длин кодов = 4, Счетчик кодов Хаффмана = 1100 | Индекс А Длина кода = 1 N Длина кода = 3 _ Длина кода = 3 L Длина кода = 4 М Длина кода = 4 Р Длина кода = 4 С Длина кода = 5 . Длина кода = 5 Код Хас Код Хас Код Хас )( ЗС X змана - 0 змана = 100 змана = 101 Счетчик длин кодов = 4, Счетчик кодов Хаффмана = 1101 | Индекс [-»- А Длина кода = 1 N Длина кода = 3 _ Длина кода = 3 L /клина кода = 4 М Длина кода = 4 Р Длина кода = 4 С Длина кода = 5 . Длина кода = 5 Кол Хас Код Хас Код Хас Кол Хас X X X X змана = 0 ' змана = 100 змана = 101 змана = 1100 Счетчик длин кодов = 4, Счетчик кодов Хаффмана = 1110 | Индекс А Длина кода = 1 N Длина кода = 3 _ Длина кода = 3 L Длина кода = 4 М Длина кода = 4 Р Длина кода = 4 С Длина кода = 5 . Длина кода = 5 Код Хас Код Хас Код Хас Код Хас Код Хас X X X X X змана = 0 змана = 100 змана = 101 змана = 1100 змана = 1101 Счетчик длин колов = 4, Счетчик кодов Хаффмана = 1111 [Индекс [->- А Длина кода = 1 N Длина кода = 3 _ Длина кода = 3 L Длина кода = 4 М Длина кода = 4 Р Длина кода = 4 С Длина кода = 5 . Длина кода = 5 Кол Хас Код Хас Код Хас Код Хас Код Хас Код Хас X X X X X X змана = 0 змана = 100 змана = 101 змана = 1100 змана = 1101 змана = ню Счетчик длин кодов = 5, Счетчик кодов Хаффмана = 11110 А Длина кода = 1 N Длина кода - 3 _ Длина кода = 3 L Длина кода = 4 М Длина кода = 4 Р Длина кода = 4 Код Хас Код Хас Код Хас Код Хас Кол Хас Код Хас X X X X ЗС зс змана - 0 змана - 100 змана - 101 змана = 1100 змана = 1101 змана = 1110 [Индекс [-»- С Длина кода = 5 . Длина кода = 5 Счетчик длин кодов = 5, Счетчик кодов Хаффмана = 11111 [Индекс [-► А Длина кода = 1 N Длина кода = 3 _ Длина кода = 3 L Длина кода = 4 М Длина кода = 4 Р Длина кода = 4 С Длина кода = 5 . Длина кода = 5 Код Хас Код Хас Кол Хас Код Хас Код Хас Код Хас Код Хас X X X X X X X змана = 0 змана = 100 змана - 101 змана = 1100 змана = 1101 змана = 1110 змана =11110 Счетчик длин кодов = 5, Счетчик кодов Хаффмана = 100000 А Длина кода = 1 Код Хас X змана = 0 N Длина кода = 3 Кол Хас X змана = 100 Длина кода = 3 Код Хас X змана = 101 L Длина кода = 4 Код Хас X змана - 1100 М Длина кода = 4 Код Хас X змана = 1101 Р Длина кода = 4 Код Хас X змана = 1110 С Длина кода = 5 Код Хас X змана = 11110 Длина кода = 5 Код Хас X змана « 11111
102 Форматы и алгоритмы сжатия изображений в действии Алгоритм 6.2 Преобразование ллин колов в счетчики ллины Таблииа 6.6. Счетчик ллины колов для символов палиндрома Можно видеть, что коды Хаффмана на Рис. 6.1 не совпадают полностью с кодами из Таблицы 6.4, но это не важно. Для кодирования палиндрома с помощью любой из таблиц Хаффмана требуется одинаковое количество битов. Различие в значениях кодов является следствием произвольных выбо- ров, которые выполняются во время процесса кодирования. Число значений Хаффмана должно быть больше, чем длина самого длинного кода. Длины кодов можно представить в более компактном виде, если вместо хранения длины кода для каждого кодируемого значения будет сохраняться счет- чик кодов для каждой длины кода. Как показано в Алгоритме 6.2, преобразование списка длин кодов Хаффмана в список, содержащий счетчики кодов заданной длины, является про- стой задачей. Procedure LengthsToCounts (CODELENGTHS [1..CODECOUNT], CODECOUNT, LENGTHCOUNTS [1..16]) Begin For INDEX = 1 TO CODECOUNT Do Begin LENGTHCOUNTS [CODELENGTHS [INDEX]] = LENGTHCOUNTS [CODELENGTHS [INDEX]] + 1 End End Коды, сгенерированные в соответствии с Рис. 6.1, формиру- ют счетчики длины кодов, показанные в Таблице 6.6. Длина кода Счетчик 1 1 2 0 3 2 4 3 5 2 Как показано в Алгоритме 6.3, обратное преобразование счетчиков длины кода в список длин кодов представляет со- бой простую процедуру.
Кодирование Хаффмана в JPEG 103 Алгоритм 6.3 Преобразование счетчиков ллины кола в список ллин колов Procedure CountsToLengths (LENGTHCOUNTS [1..MAXIMUMLENGTH], MAXIMUMLENGTH, CODELENGTHS [0..2 5 5]) Begin INDEX =1 For II = 1 To MAXIMUMLENGTH Do Begin For JJ = 1 TO LENGTHCOUNTS [II] Do Begin CODELENGTHS [INDEX] = II INDEX = INDEX + 1 End End End В главе 5 мы видели, каким образом таблицы Хаффмана хра- нятся в файле JPEG. Каждая таблица в маркере DHT хранится с 16-байтовым списком счетчиков кодов, за которыми следу- ет список переменной длины, содержащий значения Хафф- мана, отсортированные по возрастанию кодов Хаффмана. Используя Алгоритмы 6.1 и 6.3, можно преобразовать ин- формацию, хранимую в маркере DHT, в коды Хаффмана и длины кодов. Кодирование Хаффмана в JPEG В режимах JPEG, которые мы будем использовать в этой книге, возможные значения Хаффмана являются целыми числами от 0 до 255. Вы уже видели, что, в зависимости от способа применения алгоритма Хаффмана, из одних и тех же значений символов и частотных данных могут быть сгенери- рованы различные коды. Стандарт JPEG не указывает точ- ный способ генерирования кодов Хаффмана. Коды Хаффма- на для кодируемых значений в файлах JPEG не обязательно должны быть оптимальными. В действительности, как мы вскоре увидим, в некоторых случаях коды не могут быть оп- тимизированы. Можно определить таблицы Хаффмана так, что значениям, используемым реже всего, будут присвоены самые короткие коды. Результатом такого кодирования было бы ужасное сжатие, но оно полностью соответствует требо- ваниям стандарта.
104 Форматы и алгоритмы сжатия изображений в действии Стандарт JPEG налагает два ограничения на коды Хаффмана. Кодированная по Хаффману битовая строка, целиком со- стоящая из единиц, должна быть префиксом к более длинно- му коду. Это означает, что ни один код Хаффмана не может целиком состоять из единиц. Как видно из Таблицы 6.4 и Рис. 6.1, единственный код, полностью состоящий из еди- ниц, это код, сгенерированный для символа точки («.»). Ес- ли бы мы исключили точку, проблема с кодами, полностью состоящими из единиц, была бы устранена. При использовании Алгоритма 6.1, единственный код, ко- торый будет полностью состоять из единиц, это код для последнего значения, когда значения отсортированы по длине кода. Если в начале процедуры кодирования Хафф- мана вставить фиктивное значение с частотой использова- ния равной 1 и отсортировать значения так, чтобы фиктив- ное значение попало в конец списка, то фиктивное значе- ние будет единственным значением, которому будет при- своен код полностью состоящий из единиц. В конце про- цесса кодирования мы просто отбрасываем фиктивный код. В примере с палиндромом нашим фиктивным кодом является точка. Ограничение длин кодов Ограничение длин кодов 16 битами немного труднее, хотя на практике процесс генерирования кода Хаффмана редко приводит к кодам длиннее 16 битов. В тех редких случаях, когда алгоритм Хаффмана генерирует более длинные коды, следует использовать код меньший, чем при оптимальном кодировании. Наибольшая длина кода Хаффмана, сгенерированного на- ми для палиндрома, была равна 5. Предположим, однако, что нам необходимо ограничить максимальную длину кода величиной 4. Этого легко добиться путем сдвига узлов в дереве. На Рис. 6.2, где представлено дерево, созданное в соответствии с процедурой иллюстрируемой Рис. 6.1, также показано каким образом можно было бы перемес- тить узлы дерева, чтобы уменьшить максимальную длину кода до 4.
Кодирование Хаффмана в JPEG 105 Рис. 6.2. Сдвиг узлов дерева для уменьшения длины кода Преобразование, показанное на Рис. 6.2, намного проще вы- полнить над массивом счетчиков длины, чем над реальной структурой дерева. Основной метод заключается в поиске символа с длиной кода, которая была бы, по крайней мере, на 2 меньше длины кода, которую вы хотите уменьшить. Символ заменяется ветвью, а затем более длинные коды сдвигаются в поперечном направлении. Полный процесс реа- лизован в Алгоритме 6.4. Алгоритм 6.4. Ограничение длин кодов 16 битами Procedure LimitTol6Bits (LENGTHCOUNTS [1..32]) Begin For II = 32 DownTo Begin While LENGTHCOUNTS [II] <> 0 Do Begin JJ = II - 2 While LENGTHCOUNTS [JJ] = 0 Do JJ = JJ - 1 // Замена узла дерева значением. LENGTHCOUNTS [II] = LENGTHCOUNTS [II] - 2 LENGTHCOUNTS [II - 1] = LENGTHCOUNTS [II-l] + 1 // Замена значения узлом дерева. LENGTHCOUNTS [JJ + 1] = LENGTHCOUNTS [JJ + 1] + 2 LENGTHCOUNTS [JJ] = LENGTHCOUNTS [JJ] - 1 End End End
106 Форматы и алгоритмы сжатия изображений в действии Декодирование кодов Хаффмана При считывании файла изображения JPEG, получают набор счетчиков для всех кодов Хаффмана и список значений сим- волов, отсортированных по коду Хаффмана. На основании этой информации требуется сформировать таблицы для пре- образования кодов Хаффмана, считываемых из входного по- тока данных, в корректные символы. Поскольку коды Хафф- мана варьируются по длине, необходимо выполнять побито- вое считывание кодов. Первая проблема состоит в определе- нии момента считывания полного кода Хаффмана. Очевидный способ декодирования кодов Хаффмана состоит в создании двоичного дерева, содержащего значения, упорядо- ченные в соответствии с их кодами. Обход начинается от корня дерева и, используя значения битов, считываемые из входного потока данных для определения пути, выполняется поиск в дереве декодируемых значений. Более простой для реализации метод заключается в использо- вании списка декодируемых значений, отсортированных по коду Хаффмана в сочетании с массивом структур данных, где на каждое значение длины кода Хаффмана приходится один элемент. Каждая структура содержит минимальный и макси- мальный код Хаффмана для заданной длины и индекс первого значения с кодом Хаффмана этой длины в отсортированном массиве значений. На Рис. 6.3 показано, как выглядели бы эти структуры для таблицы Хаффмана, показанной на Рис. 6.1. Рис. 6.3. Данные для декодирования кодов Хаффмана Отсортированные значения 1. А 2. N 3. <space> 4. L 5. М 6. Р 7. С 8. . Длина Минимальный код Максимальный код Первое значение 1 0 0 1 2 3 100 101 2 4 1100 1110 4 5 11110 11111 7
Кодирование Хаффмана в JPEG *• ? • 107 Алгоритм 6.5 показывает, каким образом с помощью данной структуры данных можно декодировать значения, кодиро- ванные по методу Хаффмана. Алгоритм основывается на упорядоченности кодов Хаффмана для заданной длины. Алгоритм 6.5. Декодирование колов Хаффмана GLOBAL VALUES [256] GLOBAL MINCODE [1..16] GLOBAL MAXCODE [ 1..16] GLOBAL FIRSTDATA [1.16] FUNCTION HuffmanDecode Begin CODE = 0 CODELENGTH = 1 While CODELENGTH <- 16 Do Begin CODE = CODE LeftShift 1 CODE = CODE Or NextBitFromlnput () CODELENGTH = CODELENGTH + 1 If CODE <= MAXCODE [CODELENGTH] Then Begin INDEX = FIRSTCODE [CODELENGTH] + CODE - MIN- CODE [CODELENGTH] Return VALUES [INDEX] End End // Переход сюда соответствует ошибке End Используя коды Хаффмана из Рис. 6.3, предположим, что во входном потоке данных присутствуют биты 110100. Во время выполнения следующих циклов, кодовые значения и макси- мальные длины кодов будут такими: Длина Код Максимум 1 1 0 2 11 3 110 101 4 1101 1110 После считывания 4-х битов, кодовое значение не превышает максимального значения для длины 4. Это означает, что мы прочитали полный код Хаффмана. Поскольку минимальное значение кода длиной 4 равно 11002, значение 11012 является вторым кодом Хаффмана длиной 4(11012- 11002 = 1). Первое значение с кодом Хаффмана длиной 4 является четвертым значением в массиве значений, поэтому значением, которое мы ищем, является пятый элемент, то есть буква М. Если вер- нуться к Рис. 6.1, то увидим, что буква определена верно.
108 Форматы и алгоритмы сжатия изображений в действии Заключение В этой главе мы ознакомились с кодированием Хаффмана и рассмотрели его реализацию в технологии JPEG-сжатия. Ко- дирование Хаффмана используется также для сжатия данных в формате PNG, причем основной метод сжатия одинаков для обоих форматов. В Главе 14 будут рассматриваться специфи- ческие требования, предъявляемые к реализации кодирова- ния Хаффмана в PNG. Нельсон (Nelson) (1992) приводит бо- лее общее описание кодирования Хаффмана. В работе Хаффмана (Huffman) (1952) содержится первоначальное опи- сание метода кодирования. Стандарт JPEG (1994) является источником требований, предъявляемых к кодированию Хаффмана стандартом JPEG. На прилагаемом компакт-диске для этой главы содержится исходный программный код классов кодирования Хаффмана в JPEG (JpegHuffmanEncoder и JpegHuffmanDecoder). Кроме того, на компакт-диск записана программа HUFFCOMP для сжатия файлов с использованием кодирования Хаффмана, которая командой HUFFCOMP SOURCE-FILE COMPRESSED-FILE создает на выходе сжатый файл. Эта программа уменьшает размер Библии Кинга Джеймса (King James) примерно на 44 процента. Компакт-диск содержит соответствующею программу для восстановления файла, команда которой HUFFDECO COMPRESSED-FILE DESTINATION-FILE восстанавливает исходный файл, сжатый программой HUFFCOMP.
ГЛАВА 7. Дискретное косинусное преобразование Дискретное косинусное преобразование (Discrete Cosine Transform- DCT) является ключевым методом сжатия в формате JPEG. В этой главе обсуждается прямое и обратное дискретное косинусное преобразование (DCTs), их использо- вание в JPEG и выполнение этих преобразований с помощью матричных операций. Преобразование представляет собой операцию, которая ото- бражает элементы одного множества на элементы другого множества.1 Простым примером является отображение букв на целые числа с помощью кодов ASCII; более сложным примером служит вращение геометрических фигур вокруг оси z. Входными данными для преобразования DCT служит множе- ство числовых значений, а выходные данные представляют собой множество такого же размера. Преобразование DCT относится к обратимым преобразованиям. Это означает, что его выходные коэффициенты (output coefficients) могут быть использованы для восстановления исходных входных значе- ний. Преобразование, обратное DCT, называется обратным дискретным косинусным преобразованием (Inverse Discrete Cosine Transform - IDCT). Преобразование DCT часто назы- вают прямым DCT (Forward DCT - FDCT). Преобразование DCT преобразует набор входных значений в набор коэффициентов косинусных функций с возрастающи- ми частотами. Каждое из исходных значений преобразуется в сумму косинусов. В этом отношении преобразование DCT тесно связано с преобразованием Фурье. Преобразование DCT обычно используется для обработки данных, упорядоченных в одном или двух измерениях. Коли- чество входных значений обычно равно степени двух. В фор- мате JPEG преобразования DCT и IDCT всегда выполняются в двух измерениях над данными, сгруппированными в блоки размером 8x8. Чтобы показать, как действуют преобразова- ния DCT и ГОСТ, рассмотрим одномерный случай. 1 В математике преобразование и отображение неотличимы от функции. В компьютерном мире под функцией мы обычно понимаем операцию, которая возвращает одно числовое значение.
110 Форматы и алгоритмы сжатия изображений в действии Преобразование DCT в одном измерении Одномерное преобразование DCT массива V из чисел N в массив Т из N чисел определяется как Уравнение 7.1. Одномерное дискретное косинусное преобразование л =0 где с(0) = = yJl.k^O Для обратного процесса используется одномерное преобра- зование IDCT. Оно определяется как Уравнение 7.2. Одномерное обратное дискретное косинусное преобразование K[z] = 2 с(Л)Т[й] cos Приводимые ниже примеры программного кода содержат определения DCT и ГОСТ, представленные в виде, более при- вычном для программистов. void DCT (unsigned int NN, double input [], double output []) { double co = 1.0 / sqrt (NN) ; for(unsigned int ii = 0 ; ii < NN ; ++ ii) { output [ii] = 0 ; for(unsigned int jj =0 ; jj < NN ; ++jj) { output[ii] += co * (input [jj]) * cos ((2*jj+l)*ii * M_PI/2.0/NN) } cc = sqrt (2.0/NN) ; } return ; } .<j-;•'-«tw: молтн void IDCT (unsigned int NN, double input [], double output []) < for (unsigned int ii = 0 ; ii < NN ; ++ ii) { double cc = 1 / sqrt (NN) ; output [ii] =0.0 ;
Дискретное косинусное преобразование 111 for (unsigned int jj =0 ; jj < NN ; ++jj) { output [ii] += co * input [jj] * cos((2*ii+l)*jj*M_₽I/2.0/NN) ; cc = sqrt (2.0/NN) ; ) ) return ; } Значение функции у = cos (хтг) показано на Рис. 7.1. Косинусная функция относится к цик- лическим функциям, так что при возрастании х значения функции начинают возрастать заново каждый раз, когда х достигает значения кратного 2л. Частота, с которой повторя- ются значения косинусной функции, можно изменить путем включения в функцию константы п. у = cos (хптт) Рис. 7.1. Косинусная функиия Чем больше значение п, тем чаще повторяются значения ко- синусной функции. Таким образом, если п = 2, функция по- вторяется вдвое чаще, чем при п = 1. Путем умножения косинусной функции на другое значение можно настраивать амплитуду косинусоиды. Поскольку зна- чения функции косинуса лежат в диапазоне от -1 до 1, для функции у = A cos (хптт) постоянное значение А является амплитудой косинусоиды. Если выполнить подстановку 2х 2N И А = с(п)Т[п]
112 Форматы и алгоритмы сжатия изображений в действии в Уравнение 7.2 для функции IDCT, можно увидеть, что IDCT представляет собой сумму косинусных функций, час- тота которых растет вместе с порядковым номером косинус- ной функции, а коэффициенты DCT определяют амплитуды соответствующих косинусных функций в общей сумме. На Рис. 7.2 показана группа из придуманных восьми входных значений и итоговые коэффициенты DCT. Данные сопровож- даются расчетом IDCT для п = 1. Рис. 7.2. Аискретные значения, их одномерные DCT- и IDCT- коэффиииенты для п=1 и Вхо.1 DCT 181.0 71 cos (0) + 0.0 71 cos($ + 136.6Д cos(^) + 0.0 yjj cos ($ п Вход DCT 4 0 0.0 7 128 0.0: + 0.07t «>s(~) + 0.07i cos(^) + 4.6V| cos«) + 0.0^ cos ftf) = 64.0 + 0.0 + 26.1 + 0.0 + 0.0 - 2.1 + 0.0 = 88.0 В режимах JPEG, которые мы будем использовать в этой книге, дискретизованные значения представляются с помо- щью 8 битов, поэтому значения могут изменяться в диапазо- не от 0 до 255. Стандарт JPEG требует, чтобы до выполнения расчетов DCT из всех входных значений вычиталось 128, чтобы диапазон изменения находился от -128 до 127. Это приводит к уменьшению значения первого коэффициента DCT, но не влияет на значения всех остальных коэффициен- тов. После выполнения преобразования ГОСТ необходимо добавить 128, чтобы вернуть результаты обратно в правиль- ный диапазон. Если преобразования DCT и ГОСТ выполняются последова- тельно, с абсолютной точностью, результат всегда будет сов- падать с входными данными. К сожалению, компьютеры не работают с абсолютной точностью. Более того, во время сжа- тия JPEG все значения DCT округляются до целых чисел, а это означает, что процесс преобразования DCT, используе- мый в формате JPEG, вносит ошибку округления, когда изо- бражение сжимается, а затем восстанавливается. Эта ошибка невелика, но, тем не менее, она есть.
Дискретное косинусное преобразование 11. В Таблице 7.1 приведен набор из восьми дискретизованны: значений, извлеченных из строки в середине изображение IRENE.JPG (Рис. 7.3) и коэффициенты DCT, рассчитанные nt ним. Мы можем использовать коэффициенты DCT для вос- создания исходных дискретизованных значений (с ошибкамг округления), но они займут не меньше места, чем коэффици- енты DCT. Тогда зачем вообще использовать DCT в сжатии изображений? Таблица 7.1. Значения коэф- фициентов DCT, рассчитанные по дискретным значениям, взятым в изображении IRENE.JPG Входные данные 190 184 186 182 167 123 63 38 п 0 1 2 3 4 5 6 7 Коэффи- циенты DCT 38,5 143,81 -67,76 -16,33 7,42 -4,73 5,49 0,05 Рис. 7.3. Изображение из файла IRENE.JPG Ключ к пониманию ценности DCT можно увидеть в умг шении абсолютных значений коэффициентов в Таблице .. С увеличением п абсолютные значения коэффициенте, уменьшаются. Графическое представление ГОСТ должно еще больше про- яснить назначение преобразования DCT в формате JPEG. hi Рис. 7.4 показаны восемь графиков функции ГОСТ, значения
114 Форматы и алгоритмы сжатия изображений в действии которой рассчитаны с использованием от 1 до 8 коэффициен- тов DCT из Таблицы 7.1. Для построения первого графика используется только первый коэффициент DCT. Для по- строения второго графика берутся первые два коэффициента, а для последнего графика задействованы все восемь коэффи- циентов DCT. Рис. 7.4. Значения IDCT для набора дискретных значений из фотографии IRENE.JPC
Дискретное косинусное преобразование 115 Обратите внимание, на первом графике Рис. 7.4 функция IDCT представляет собой горизонтальную прямую, в то время как все остальные графики являются кривыми линия- ми. Первый коэффициент DCT известен как коэффициент DC; все остальные называются коэффициентами АС. (Эти названия пришли из электротехники. DC-ток [DC - Direct
116 Форматы и алгоритмы сжатия изображений в действии Current - постоянный ток] протекает при постоянном на- пряжении, тогда как АС-напряжение [АС - Alternating Cur- rent - переменный ток] изменяется по синусоиде). В процес- се сжатия JPEG коэффициенты DC и АС кодируются по- разному. В Главе 5 вы встречали ссылки на таблицы Хафф- мана DC и АС в маркерах DQT и SOS. Именно оттуда появи- лись названия DC и АС. При переходе от первого графика к последнему, функция IDCT становится все ближе и ближе к исходным данным. На первом графике функция IDCT проходит через середи- ну всей области, содержащей точки данных, не пересекая ни одну из них. На последнем графике функция IDCT сле- дует точно через середину всех точек данных. Интересно, что на третьем графике функция IDCT проходит весьма близко ко всем точкам графика. Далее, начиная с четверто- го графика, последующие уточнения на глаз почти неза- метны. Это обстоятельство и есть ключ к пониманию процесса сжатия JPEG. Поскольку коэффициенты DCT более высо- кого порядка, как правило, вносят в изображение меньшую часть информации, их можно отбросить и, несмотря на это, получить очень точное приближение к оригиналу. Исполь- зуя данные Таблицы 7.1, можно отбросить половину коэф- фициентов DCT и, тем не менее, получить хороший ре- зультат. Всегда ли это работает? Можем ли мы в любом наборе дан- ных отбросить коэффициенты высшего порядка и сохранить хорошее приближение к исходным данным? Если бы все бы- ло так просто. В Таблице 7.2 показаны набор входных данных и коэффици- енты DCT, рассчитанные по входным данным. На графиках Рис. 7.5 показаны входные данные, наложенные на функции IDCT с использованием семи и восьми коэффициентов DCT. Можно видеть, что для приведенных входных данных невоз- можно отбросить какой-либо из коэффициентов DCT и полу- чить при этом хорошее приближение.
Дискретное косинусное преобразование 117 Таблииа 7.2. Коэффициенты DCT, рассчитанные для произвольно выбранного набора ланных Входные 0 0 255 255 255 О О О данные п 0 123 4567 Коэффи--91,57 70,84 -384,4 -125,1 90,1 24,87 20,21 106,0 ниенты DCT Рис. 7.5. Входные данные из Таблицы 7.2, наложенные на функции IDCT Какие данные более типичны для реальных изображений: приведенные в Таблице 7.1 или в Таблице 7.2? Это зависит от изображения. В фотографических изображениях резкие из- менения данных, как у входных данных из Таблицы 7.2, не- обычны. В рисунках же такие резкие скачки данных могут встречаться часто. Это одна из причин, по которым формат JPEG сжимает фотографии лучше, чем рисунки. В рисунках компромисс между сжатием и качеством изображения дости- гается труднее, поэтому для рисунков, в общем случае, луч- ше воспользоваться другим форматом изображений, напри- мер, PNG.
118 Форматы и алгоритмы сжатия изображений в действии Преобразование DCT в двух измерениях Как оказывается, с помощью DCT можно добиться большего сжатия, если одновременно учитывать корреляцию между пикселами по горизонтали и по вертикали. В Главе 4 описа- но, каким образом в JPEG изображение разбивается на квад- ратные блоки размером 8x8, называемые единицами данных. Первый шаг в сжатии единицы данных состоит в выполнении двумерного преобразования DCT, которое для квадратной матрицы размером N определяется как Уравнение 7.3. Лвумерное преобразование DCT Щ Л = с(/, ЛX X] cos cos где c(bj) = jj, i и у>0 c(i,j) = jj, i или j = 0 Двумерное преобразование IDCT описывается следующим уравнением: Уравнение 7.4. Лвумерное преобразование IDCT У[у- л Д 20с(г>У)Ллу] COS (у cos ( ^У В JPEG-сжатии значение N всегда равно 8. Двумерное преобразование DCT удобнее выполнять с помо- щью умножения матриц. Прямое преобразование DCT выра- жается как Уравнение 7.5. Лвумерное преобразование Т = MVMT DCT А обратное преобразование DCT выражается так Уравнение 7.6. Лвумерное преобразование V = МтТМ IDCT где V представляет собой матрицу единицы данных размером 8x8, а М - матрица, показанная в Уравнении 7.7.
Дискретное косинусное преобразование 119 Уравнение 7.7. Матрица дискретного косинусного преобразования М = । 1 1 । । । 1 1 Vs Vs Vs Vs Vs Vs Vs Vs I COS-j^TT I COS-j^TT | COS 7jTT I COS-j^TT | COS yy77 | COS у|тт | COS ||t7 | COS “77 I COS -^77 I COS yj'TT I COS 77 77 | COS 77 77 | COS у|тГ | COS у|т7 jCOS ||t7 | COS у|т7 5 COS-^77 | COS yj?7 у COS “77 | COS у|т7 | COS 77 77 | COS у|т7 у COS 7777 | COS у|т7 7 COS Лт7 7 COS “77 7 COS t?77 7 COS 7? 77 | COS 7777 7 COS 7777 7 COS 7777 7 COS 7?77 2 io 2 In 2 lo 2 lo 2 lo 2 lo 2 lo 2 lo I COS yj77 | COS Ц77 I COS Ц77 I COS 77 77 | COS у|т7 | COS yj77 у COS у|т7 у COS “77 | COS-^77 J COS у|т7 | COS у|т7 у COS у|т7 | COS “77 | COS у|т7 у COS “77 | COS у|т7 I COS 7777 I COS T777 7 COS 7777 7 COS 7777 7 COS 7777 7 COS 7777 7 COS 7777 7 COS -77-77 2 lo 2 Io 2 lo 2 lo 2 io 2 lo 2 lo 2 lo Основные операции с матрицами Для читателей, не знакомых с матрицами, мы предоставляем краткое введение в этот предмет. Дополнительную информа- цию можно найти в учебниках по началам линейной алгебры. Матрица представляет собой просто массив чисел. Обычно под матрицей подразумевают двумерный массив. По тради- ции, при задании размерности матрицы сначала указывается число строк. МатрицаNxM содержит Nстрок и М столбцов. Элементы внутри матрицы указываются с помощью нижних индексов. Таким образом, AMN означает элемент, располо- женный на пересечении строки А и столбца М в матрице А. Одномерный массив чисел известен как вектор, над которым часто выполняется операция скалярного умножения. В опе- рации скалярного умножения в качестве входных данных бе- рутся два вектора с одинаковой размерностью, а на выходе получают число. Для выполнения скалярного умножения двух векторов, перемножаются соответствующие элементы этих векторов и все полученные произведения складываются. Вот пример вычисления скалярного произведения двух век- торов А и В:
120 Форматы и алгоритмы сжатия изображений в действии А = [2 2 4] В = [3 1 2] Я-В = 2хЗ + 2х 1+4x2 = 16 Матрицы можно перемножать только тогда, когда они со- вместимы. Две матрицы совместимы, если число столбцов в первой матрице равно числу строк во второй матрице. Все матрицы, которые будут нам встречаться, являются квадрат- ными матрицами с размерами 8x8, поэтому проблем с со- вместимостью в данном случае нет. Умножение матриц вы- полняется путем разделения каждой матрицы на набор век- торов. Каждая строка в первой матрице образует вектор, ка- ждый столбец во второй матрице тоже образует вектор. Что- бы создать элемент на пересечении строки N и столбца М ре- зультирующей матрицы (destination matrix), выполняется скалярное умножение векторов У-ой строки первой матрицы и М-го столбца второй матрицы. Вот пример умножения мат- риц А и В с размерами 2x2: А = Г1 Л [2 -3] В = Г-1 -21 L 0 3J [1 4]-[-10] [1 4] • [-2 3] 1 [2 -3] • [-1 0] [2 -3] • [-2 3] Г-1 101 [-2 -13] Умножение матриц не обладает свойством коммутативности. Если А и В являются матрицами, то нельзя утверждать, что АВ = ВА. Г[-1 -2] • [1 2] [-1 -2]-[4 -3]1 _ Г-5 21 [0 3] • [1 2] [ 0 3] [4 -3]] " [ 6 -9] Умножение матриц обладает свойством ассоциативности. Если А, В а С являются матрицами, то (АВ)С = А (ВС) Операция транспонирования матрицы обозначается как АТ. Если В = А , то для каждого элемента в В, BNM = Amn как в следующем примере.
Дискретное косинусное преобразование 121 ’1 2 3 4 5 6 7 8 9 Ат = 1 4 7 2 5 8 3 6 9 Матрица умножается на число путем умножения каждого элемента матрицы на это число. А = 10 х Л = Г1 31 L2 4J Г10 301 [20 40] Это все, что нам понадобится из линейной алгебры для из- ложения оставшегося материала данной главы. Однако пре- жде чем двигаться дальше, мне бы хотелось указать инте- ресное свойство матрицы М в преобразовании DCT, пока- занном ранее. Матрица М относится к так называемым ор- тогональным матрицам. Скалярное произведение любой строки на саму себя или любого столбца на самого себя бу- дет равно 1. Скалярное произведение любой строки на лю- бую другую строку или любого столбца на любой другой столбец будет равно 0. Если умножить М на ее транспози- цию, в результате получится 10000000' 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 ММТ= 00010000 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 Любая квадратная матрица с единицами на диагонали, иду- щей из верхнего левого угла в нижний правый угол, и всеми остальными значениями равными 0 называется единичной матрицей. При умножении любой матрицы А на единичную матрицу в результате получается матрица А.
122 Форматы и алгоритмы сжатия изображений в действии Использование прямого двумерного преобразования DCT Теперь вернемся к изображению IRENE.JPG, чтобы показать, что происходит с изображением при использовании двумер- ного преобразования DCT. На Рис. 7.6 показаны дискретные данные компонента Y в виде блока 8x8, взятые из области вокруг глаза Ирены (Irene), и коэффициенты двумерного преобразования DCT, рассчитанные для этих дискретных данных. • ! ’ Рис. 7.6. Выборкаелинииы данных из файла IRENEJPC и коэф- фициенты DCT, рассчитанные для выбранных данных Дискретизированнные 58 45 29 27 24 19 17 20 данные компонента Y 62 52 42 41 38 30 22 18 из изображения 48 47 49 44 40 36 31 25 IRENE.BMP 59 78 49 32 28 31 31 31 98 138 116 78 39 24 25 27 115 160 143 97 48 27 24 21 99 137 127 84 42 25 24 20 74 95 82 67 40 25 25 19 Коэффициенты DCT -603 203 11 45 -30 -14 -14 -7 -108 -93 10 49 27 6 8 2 -42 -20 -6 16 17 9 3 3 56 69 7 -25 -10 -5 -2 -2 -33 -21 17 8 3 -4 -5 -3 -16 -14 8 2 —4 -2 1 1 0 -5 -6 -1 2 3 1 1 8 5 -6 -9 0 3 3 2 На рисунке коэффициенты с большими абсолютными значе- ниями концентрируются в верхнем левом углу. Общая тен- денция такова: чем дальше располагается коэффициент от коэффициента DC в верхнем левом углу, тем меньше абсо- лютное значение этого коэффициента DCT. Коэффициент DC почти в три раза больше любого коэффициента АС. Квантование На примере одномерного преобразования DCT мы видели, что в обратном преобразовании DCT не всегда необходимо использовать все коэффициенты DCT, чтобы восстановить с достаточно высокой точностью исходные данные. Мы также видели, что в некоторых ситуациях требуется использовать если не все, то большинство коэффициентов для получения точной аппроксимации исходных данных. Все эти положения справедливы и в отношении двумерного преобразования DCT. После расчета DCT следующий шаг включает поиск и
Дискретное косинусное преобразование 123 отбрасывание коэффициентов, вклад которых в формирова- ние изображения минимален. Для решения этой задачи стандарт JPEG определяет простой механизм именуемый квантованием (quantization), представ- ляющим, в свою очередь, условное название для (division). Чтобы выполнить квантование коэффициентов DCT, доста- точно просто разделить их на другое значение и округлить до ближайшего целого числа: _ ( Коэффициент ) Квантованное значение = Округление}------------- ( Значение кванта I Чтобы обратить процесс, следует выполнить умножение: Коэффициент = Квантованное значение х Значение кванта При выборе в качестве значения кванта числа 20, более поло- вины коэффициентов на Рис. 7.6 было бы преобразовано в нули. Чтобы определить значения квантов для изображения, в формате JPEG используется массив из 64 элементов, на- зываемый таблицей квантования (quantization table). Таб- лицы квантования определяются в маркере DQT, описанном в Главе 5. Можно использовать несколько таблиц квантова- ния с тем, чтобы все компоненты, которые должны быть квантованными, не использовали одинаковые значения. Ка- ждое значение таблицы квантования используется для кван- тования соответствующего коэффициента DCT. Стандарт JPEG не определяет значения квантования, которые должны использоваться. Это остается за конкретной про- граммой. Тем не менее, стандарт все же предоставляет в ка- честве примера пару таблиц квантования, которые, как ут- верждается в стандарте, были проверены на опыте и показали хорошие результаты. Эти таблицы показаны на Рис. 7.7. На Рис. 7.8 показаны результаты квантования дискретных значений из Рис. 7.6, выполненного с помощью показанной на Рис. 7.7 таблицы квантования для компонента Y. После квантования только 19 из 64 коэффициентов DCT значения отличны от нуля. В Главе 8 объясняется, каким образом в формате JPEG сжимаются серии нулевых значений коэффи- циентов АС.
124 Форматы и алгоритмы сжатия изображений в действии Рис. 7.7. Таблица квантования 16 11 10 16 24 40 51 61 Примеры таблиц компонента Y 12 14 12 13 14 16 19 24 26 40 58 57 60 69 55 56 квантования 14 17 22 29 51 87 80 62 из стандарта 18 22 37 56 68 109 103 77 JrtCi 24 35 55 64 81 104 113 92 49 64 78 87 103 121 120 101 72 92 95 98 112 100 103 99 Таблииа квантования 17 18 24 47 99 99 99 99 компонентов СЬ и Сг 18 21 26 66 99 99 99 99 24 26 56 99 99 99 99 99 47 66 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 Рис. 7.8. -38 18 1 -3 -1 0 0 0 Результаты -9 -8 1 3 1 0 0 0 квантования -3 -2 0 1 0 0 0 0 дискретных 4 4 0 -1 0 0 0 0 значений -2 -1 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 Размещение в зигзагообразном порядке Для того чтобы сгруппировать максимально возможное чис- ло квантованных нулевых коэффициентов для создания как можно более длинных серий нулевых значений, коэффициен- ты АС в единицах данных кодируют с использованием зигза- гообразного пути. На Рис. 7.9 показан зигзагообразный порядок, определяе- мый стандартом JPEG. Этот порядок кратко упоминался в Главе 5, в разделе, посвященном маркеру DQT. Квантован- ные значения в таблице квантования хранятся в JPEG- файлах тоже с использованием такого зигзагообразного по- рядка. Вот каков порядок расположения квантованных ко- эффициентов АС на Рис. 7.8.: 18-9-3-8 1-3 1 -24-24 0 3-1 0 1 1 0-1 -1 0 00-1 (39 нулей)
Дискретное косинусное преобразование 125 Рис. 7.9. Зигзагообразный порядок расположения коэффициентов АС Заключение В данной главе описано дискретное косинусное преобразова- ние (Discrete Cosine Transform - DCT) и квантование. Преоб- разование DCT используется для представления блока 8x8 дискретных значений в виде суммы косинусных функций. Коэффициент DCT в верхнем левом углу представляет по- стоянное значение и носит название коэффициента DC. Все остальные коэффициенты называются коэффициентами АС. Для расчета преобразования DCT и обратного ему преоб- разования мы использовались операции с матрицами. В Главе 10 мы вернемся к рассмотрению преобразования DCT и покажем, каким образом его можно ускорить. Более полную информацию о преобразовании DCT можно найти в книге Рао (Rao) и Уипа (Yip) (1990), этой теме по- священа вся их книга. Нельсон (Nelson) (1992) представляет упрощенную версию DCT-сжатия, подобную той, что приме- няется в JPEG. Примеры таблиц квантования в этой главе взяты из стандарта JPEG (1994). Любая книга по введению в линейную алгебру, например, книга Антона (Anton) (1981), содержит более полную информацию по основным операци- ям с матрицами. Для этой главы приводятся исходные программные коды классов для представления таблиц квантования и единиц данных во время процедуры сжатия. Для реализации DCT эти классы используют матричные операции.
ГЛАВА 8. Декодирование изображений JPEG, сжатых в последовательном режиме В предыдущих главах мы рассмотрели большинство предва- рительных вопросов, относящихся к формату JPEG. В этой главе мы сложим все части воедино и покажем, каким обра- зом реализуется декодер последовательного JPEG. Мы обсудим кадры SOFo (базовое преобразование DCT) и подмножество кадров SOFi (расширенный последовательный режим DCT). Они идентичны, за исключением того, что рас- ширенные последовательные кадры (extended sequential frames) могут использовать 12- или 8-битовые дискретизо- ванные данные и до четырех таблиц Хаффмана DC или АС, а основное преобразование DCT в JPEG поддерживает толь- ко 8-битовые образцы и до двух таблиц Хаффмана DC и АС. Если ограничиться 8-битовыми дискретными данными и раз- решить до четырех таблиц Хаффмана DC или АС, эти два ти- па кадров декодируются совершенно одинаково. Размеры MCU Сжатые данные JPEG состоят из последовательности коди- рованных MCUs, упорядоченных сверху вниз, слева направо. Первый шаг в декодировании данных скана заключается в определении числа единиц данных в каждом скане, которые образуют каждый MCU, и определении числа MCUs, необхо- димых для кодирования скана. Для любого компонента число пикселов, составляющих еди- ницу данных, равно: Pixelsx = 8 х г* Pixels,, = 8 х — У Ff где Fx = Частота выборки компонента по горизонтали; Fxmax = Максимальная частота дискретизации компонен- та по горизонтали; Fy = Частота дискретизации компонента по вертикали;
128 Форматы и алгоритмы сжатия изображений в действии Fy max = Максимальная частота дискретизации компонен- та по вертикали. Если скан построчный (т.е. он содержит только один компо- нент), каждый MCU в скане состоит из 1 единицы данных. Число MCUs в скане равно MCUsx х MCUsy где Ширина-изображения + пикселы_по_х - 1 MCusx =-------------------------------------- пикселы _по_х Высота-изображения + пикселы_по-У - 1 MCus =------------------------------------------ у пикселы _по_у Если скан чересстрочный, MCUsx и MCUsy равны - Ширина_изображения + 8 х Fxmax - 1 IVj. (_/ О „ —г - Л Я х F ° А г х max Высота изображения + 8 xF - 1 Помните, что для чересстрочного скана Fxmax и Fymax пред- ставляют собой максимальные частоты дискретизации всех компонентов в изображении, а не максимальные частоты всех компонентов в скане. В чересстрочном скане число единиц данных, соответствую- щих каждому компоненту в MCU, равно произведению час- тот дискретизации компонента. Предположим, есть цветное изображение с компонентом Y, для которого частоты дискре- тизации по вертикали и горизонтали равны 2, и компоненты СЬ и Сг, для которых вертикальные и горизонтальные часто- ты дискретизации равны 1. Если чересстрочный скан содер- жит все три компонента, то в каждом MCU находится, в об- щей сложности, 6 единиц данных. Стандарт JPEG устанавливает для MCU довольно низкий предел в 10 единиц данных. Это накладывает ограничения на частоты дискретизации и расположение компонентов внутри сканов. Предположим, что для компонента Y горизонтальная и вертикальная частоты дискретизации были равны 4. В че- ресстрочном скане на один этот компонент приходилось бы в каждом MCU 16 единиц данных, и, тем самым, допустимый предел JPEG на размер MCU был бы превышен. При исполь- зовании такой дискретизации компонент Y должен был бы находиться в построчном скане.
Декодирование изображений JPEG, сжатых в последовательном режиме 129 Рис. 8.1. Соотношение размеров MCU и изображения Внутри скана не существует неполных MCUs или единиц данных. Если размеры изображения не кратны размеру MCU, сжатые данные содержат заполнитель для округления до сле- дующего целого числа MCU. Рис. 8.1 иллюстрирует взаимное расположение MCUs и изо- бражения. На рисунке показано изображение размером 50x50 пикселов, частота дискретизации компонента Y по го- ризонтали и вертикали равна 2, частота дискретизации про- чих компонентов равна 1. Если для компонента Y использу- ется построчный скан, то скан состоит из 7 строк MCU и 8 столбцов MCU, причем каждый MCU состоит из 1 единицы данных. Область изображения, покрываемая каждым MCU, очерчена белыми линиями. Ширина изображения Ширина изображения, отображаемого в построчном режиме Ширина изображения, отображаемого в чересстрочном режиме В чересстрочном скане находятся 4 строки и 4 столбца MCUs. Область изображения, покрываемая каждым MCU, очерчена тонкой черной линией. В этом примере последняя строка и ряд MCU представляют собой, в основном, пустую зону. 5 - 9809
Алгоритм 8.1. Деколирование MCU Катай MCU «пифии в та* посжятавсжаосхв сятап данных. Компоненты MCU вояцрувясв в том нордов, в ко- тором они перечислены в маркере SOS. и не является черес- строчными. Единицы данных из каждого компонента упоря- дочены сверху вниз, слева направо. Алгоритм 8.1 показывает процедуру декодирования MCUs в скане. For Each MCU In The Scan Begin For Each Component In the Scan Begin For I = 1 To Component Vertical Sampling Frequency Begin For J = 1 To Component Horizontal Sampling Frequency ’• Begin Decode Data Unit End End End End Декодирование единиц данных После определения числа MCUs и единиц данных в каждом скане следующий шаг заключается в декодировании отдель- ных единиц данных. Фактически, для каждой единицы дан- ных кодируются квантованные коэффициенты DCT. Таким образом, первый шаг состоит в получении значений коэффи- циентов DCT. Сначала с помощью кодирования Хаффмана кодируется коэффициент DC. Затем, используя кодирование Хаффмана и кодирование длин серий (RLE), кодируются в виде группы коэффициенты АС. Коэффициенты DC и АС ко- дируются с помощью разных таблиц Хаффмана, в соответст- вии с определениями в маркере SOS. Декодирование коэффициентов DC Коэффициенты DC хранятся в файле JPEG в виде разности между предыдущим значением DC, кодированным для ком- понента, и текущим значением коэффициента DC. Преиму- щество использования разности заключается в том, что для кодирования меньших значений используется меньшее число
Декодирование изображений JPEG, сжатых в последовательном режиме 131 битов. Если при переходе от одной единицы данных к сле- дующей единице данных коэффициент DC не изменяется слишком резко, то разрядность разности между соседними коэффициентами DC, обычно меньше разрядности значений самих коэффициентов DC. Для каждого компонента последнее значение коэффициента DC инициализируется нулем в начале скана и сбрасывается в ноль при каждом считывании маркера перезапуска. Это озна- чает, что первое значение DC в скане и первое значение, сле- дующее за маркером перезапуска, представляют собой абсо- лютные значения коэффициентов DC. Коэффициенты DC кодируются двумя частями. Первая часть представляет собой кодированное по методу Хаффмана 1- байтовое значение, которое определяет разрядность разности между коэффициентами DC. В Таблице 8.1 приводятся коды разрядности для разности коэффициентов DC и соответст- вующие значения коэффициентов DC. Чтобы преобразовать значение разрядности в фактическое значение разности коэффициентов DC, декодер должен про- читать во входном потоке данных множество некодирован- ных литеральных битов. Число литеральных битов равно значению разрядности. Когда значение разрядности равно нулю, дополнительные биты отсутствуют. Таблица 8.1. Колы разрядности разностей коэффициентов DC и диапазоны значений коэффициентов DC Коды разрядности Диапазон значений коэффициентов DC 0 0 1 -1, 1 2 -з, -2, 2, 3 3 -7 . . -4, 4 . . 7 4 -15.. -8, 8 . . 15 5 -31 . .-16, 16 . . 31 6 -63 .. -32, 32 . . 63 7 -127.. -64, 64 . . 127 8 -255 . .-128, 128 . . 255 9 -511 . .-256, 256 . . 511 10 -1023 . .-512, 512 ..1023 11 -2047..-1024, 1024..2047
132 Форматы и алгоритмы сжатия изображений в действии Первый бит, следующий за значением разрядности разности коэффициентов DC, указывает знак значения разности. Зна- ковый бит, равный нулю, означает отрицательную разность, знаковый бит, равный единице, означает положительную разность. Алгоритм 8.2 определяет функцию для преобразо- вания значения разрядности и дополнительных битов в зна- чение разности коэффициентов DC. Данная функция являет- ся результатом перевода положений стандарта JPEG на язык программирования. Алгоритм 8.2. Функция ExtendO Function Extend (ADDITIONAL, MAGNITUDE) Begin vt = 1 LeftShift (MAGNITUDE - 1) If ADDITIONAL < vt Then return ADDITIONAL + (-1 LeftShift MAGNITUDE) + 1 Else return ADDITIONAL End В Алгоритме 8.3 приведен весь процесс декодирования ко- эффициентов DC. Алгоритм 8.3. Аеколирование коэффициентов DC Global LASTDC Function DecodeDC Begin CODE = HuffmanDecode () BITS = ReadBits (code) DIFFERENCE = Extend (BITS, CODE) DC = DIFFERENCE + LASTDC LASTDC = DC Return DC End Декодирование коэффициентов AC Декодирование значений коэффициентов АС немного слож- нее, чем декодирование коэффициентов DC. Коэффициенты АС в каждой единице данных хранятся в зигзагообразном порядке, описанном в Главе 7. Для декодирования 1- байтового значения декодер использует таблицу Хаффмана АС. В отличие от разностей коэффициентов DC, это значение делится на два 4-битовых поля. 4 младших бита содержат значение разрядности (magnitude value), а 4 старших бита со- держат число нулевых коэффициентов, которые следует про- пустить прежде, чем записать данный коэффициент. Напри- мер, кодированное по методу Хаффмана значение 5616 пока-
Декодирование изображений JPEG, сжатых в последовательном режиме 133 зывает, что следующие пять коэффициентов АС равны нулю, а за ними следует ненулевой коэффициент с разрядностью 6 битов. В Таблице 8.2 перечислены возможные значения разрядности коэффициентов АС и соответствующие им диапазоны значе- ний коэффициентов АС. Обратите внимание, что для разряд- ности равной 0 отсутствуют значения коэффициентов АС. Это обусловлено тем, что нулевые коэффициенты АС коди- руются с помощью нулевых серий. Значения разрядности ко- эффициентов АС преобразуются в значения коэффициентов путем чтения необработанных битов (raw bits) и использова- ния функции Extend(), точно так же, как для коэффициентов DC. Единственное отличие состоит в том, что для коэффици- ентов АС кодируются их фактические значения, а не раз- ность коэффициентов АС. Таблица 8.2. Колы разрядности коэффициентов АС и диапазоны значений коэффициентов АС Код разрядности коэффициента АС Диапазон значений коэффициентов АС 1 -1, 1 2 -3, -2, 2, 3 3 -7 ..-А, 4 . . 7 4 -15.. -8, 8 . . 15 5 -31 . . -16, 16..31 6 -63 . . -32, 32 . . 63 7 -127 . .-64, 64.. 127 8 -255 . .-128, 128..255 9 -511 . .-256, 256 . . 511 10 -1023 . .-512, 512.. 1023 Для кодирования значений коэффициентов АС применяются два специальных кода. Код 0016 используется, когда все ос- тавшиеся коэффициенты АС в единице данных равны нулю. Код FOie представляет собой серию из 16 нулевых коэффици- ентов АС. Ни за одним из этих специальных кодов не распо- лагаются необработанные биты (raw bits). Для каждой единицы данных процесс декодирования коэф- фициентов АС повторяется до тех пор, пока не будут декоди- рованы все коэффициенты АС. Процедура декодирования единицы данных считается завершенной, когда декодируется код конца блока либо когда декодирован последний коэффи-
134 Форматы и алгоритмы сжатия изображений в действии циент АС. Процесс декодирования коэффициентов АС еди- ницы данных показан в Алгоритме 8.4. Алгоритм 8.4. Декодирование коэффициентов АС For II = 1 то 63 Do COEFFICIENTS [II] = О II = 1 While II <=63 Do Begin VALUE = DecodeUsingACTable () LOBITS = VALUE And 0F16 HIBITS = (VALUE And F016) Rightshift 4 If LOBITS <> 0 Then Begin EXTRABITS = ReadRawBits (LOBITS) II = II + HIGHBITS COEFFICIENTS [II] = Extend (EXTRABITS, LOBITS) II = II + 1 End Else Begin If HIGHBITS = F16 Then II = II + 16 // Run of 16 Zeros Else If HIGHBITS = 0 Then II = 64 // All Done End End Пример декодирования На Рис. 8.2 и 8.3 показаны примеры декодирования двух пер- вых единиц данных для компонента в скане. На Рис. 8.2, ко- торый показывает декодирование первой единицы данных, последнее значение коэффициента DC для скана инициали- зируется нулем. Сначала декодируется коэффициент DC. Ис- пользуя таблицу Хаффмана DC для компонента, найдем, что следующее значение, кодированное по методу Хаффмана, равно 0416. Это значение разрядности указывает, что необхо- димо считать из входного потока данных 4 необработанные бита (10Юг). Значение коэффициента DC равно сумме ре- зультата функция Extend() (10) и значения последнего коэф- фициента DC (0).
Декодирование изображений JPEG, сжатых в последовательном режиме 135 Коэффициенты DC Блок Декодирование Необрабо- Разность таблицы DC танные коэффици- енты ентов DC Последнее значение коэффициента DC Новое значение коэффициента DC А 0416 10102 10 0 10 Коэффициенты АС А Блок Декодирование Нулевая Необрабо- Значение таблицы АС серия танные биты коэффициента q В Эр z0' ,Q' В 0316 0 0102 -1 С 0416 0 10012 9 и D ЕЗХ6 14 1002 8 Е F016 16 Нет Нет F F016 16 Нет Нет Е С du 12 12 1 Н 0116 0 02 -1 F О Сэ "o ‘ О О to 4o 4. iaS ® о Ъ О I О Рис. 8.2. Декодирование первой единицы данных компо- нента в скане Теперь декодируем коэффициенты АС, используя таблицу Хаффмана АС для компонента. Следующее значение, кодиро- ванное по методу Хаффмана, равно 0316- Четыре старших бита задают серию (0) повторяющихся нулей, младшие биты зада- ют значение разрядности коэффициента (3). Затем, из входно- го потока данных считываются следующие три необработан- ных бита (01 От) и вызывается функцию Extend(), которая воз- вращает -3 в качестве значения первого коэффициента АС. Декодирование второго коэффициента АС почти идентично декодированию первого коэффициента. Третий процесс деко- дирования по методу Хаффмана возвращает значение Е316, ко- торое определяет серию из 14 повторяющихся нулей, за кото- рой следует коэффициент с разрядностью 3 бита. Из входного потока данных считываются следующие 3 необработанные би- та (1002) и вызывается функция ExtendQ, которая возвращает 8. Следующие 14 коэффициентов АС устанавливаются равными нулю, затем следует коэффициент со значением 8. Следующие два значения, декодируемые с помощью таблицы Хаффмана АС, являются специальным кодом F016. За этим кодом не располагаются дополнительные биты. Каждый раз при считывании данного специального кода последующие 16 коэффициентов АС устанавливаются равными 0.
136 Форматы и алгоритмы сжатия изображений в действии Следующий код во входном потоке данных и необработан- ные биты, расположенные за ним, сообщают, что требуется установить очередные 12 коэффициентов АС равными нулю, затем установить коэффициент АС равным 1. Далее следует последовательность, которая определяет следующий коэф- фициент АС равным -1. Поскольку этот коэффициент явля- ется 63-м коэффициентом АС, декодирование единицы дан- ных завершается. На Рис. 8.3 показан процесс декодирования следующей еди- ницы данных для компонента. Если бы это был чересстроч- ный скан (interleaved scan), тогда, в зависимости от частоты дискретизации компонента, единицы данных для других компонентов должны были бы декодироваться до декодиро- вания этого компонента. Сначала мы декодируем для едини- цы данных коэффициент DC. Используя таблицу Хаффмана DC, найдем, что следующее значение разрядности равно ну- лю. Это означает, что дополнительные необработанные биты отсутствуют. Разность коэффициентов DC просто равна ну- лю. Добавим значение разности к значению последнего ко- эффициента DC (10), в результате получим значение коэф- фициента DC равное 10. Последний коэффициент DC остает- ся равным 10. Коэффициенты DC Блок Декодирование Необрабо- Разность Последнее Новое таблицы DC танные коэффици- значение значение биты ентов DC коэффициента DC коэффициента DC A 0016 Нет 0 10 10 Коэффициенты АС Блок Декодирование Нулевая таблицы АС серия В 0216 0 102 2 С 0116 0 02 -1 D 0016 Конец Нет Нет блока 'У Q''$ zz0z JO'V'j3'У 0z z0Zz0" P'ZpZzOZzOZP' -0Z tf p'p'O' 0' p'o' z0 z0 Z 0Z 0Z z0"z0zzO; '.q'z0z tf q' q' q' tf 0zz0z (Xj/ Необрабо- Значение танные биты коэффициента Рис. 8.3. Декодирование второй един ины данных компо- нента в скане D
Декодирование изображений JPEG, сжатых в последовательном режиме 137 Первые два коэффициента АС декодируются также, как пре- жде. При использовании таблицы АС для декодирования значения разрядности следующего коэффициента АС, мы считываем специальный код 0016, который указывает устано- вить оставшиеся коэффициенты АС равными нулю. Теперь декодирование единицы данных завершено. Обработка коэффициентов DCT После считывания всех коэффициентов DCT для единицы данных, необходимо выполнить деквантизацию (dequantiza- tion) и преобразование IDCT единицы данных так, как описа- но в Главе 7. Деквантизация сводится к простому умножению значения каждого коэффициента на соответствующий эле- мент таблицы квантования. После этого для коэффициентов выполняется преобразование ГОСТ, в результате которого получают дискретные значения. Сверхдискретизация На данном этапе значения YCbCr суб дискретизованы (down- sampled). По ним необходимо создать RGB-изображение. Для полутонового изображения работа уже закончена, поскольку значение Y соответствует индексу в цветовой палитре, в ко- торой красный цвет = зеленый цвет = синий цвет. Для цвет- ного изображения первое, что необходимо сделать - это вы- полнить сверхдискретизацию (up-sampling). Если для какого-либо компонента дискретизация значений, либо по горизонтали, либо по вертикали, выполнена относи- тельно числа пикселов в соотношении меньше, чем 1:1 (ины- ми словами, любая из частот дискретизации, по вертикали или по горизонтали, меньше максимальной частоты дискре- тизации для всех компонентов), компонент должен подвер- гаться сверхдискретизации (up-sampled). Под этим понимает- ся увеличение разрешения данных компонента. Если отобран какой-нибудь компонент - либо по вертикали, либо по горизонтали - не менее 1:1 (иными словами, обе час- тоты выборки меньше, чем максимальное значение всех ком- понентов в изображении), компонент должен быть сверхдис- кретизован.
138 Форматы и алгоритмы сжатия изображений в действии Предположим, что есть сжатое цветное изображение JPEG, в котором для компонента Y вертикальная и горизонтальная частоты дискретизации равны 2, а для компонентов СЬ и Сг частоты дискретизации равны 1 по обоим направлениям. При сжатии изображения на каждый пиксел приходилось одно дискретизованное значение компонента Y, а для компонентов СЬ и Сг одно дискретизованное значение приходилось на ка- ждые четыре пиксела. После восстановления изображения необходимо распределить (spread) значения компонентов СЬ и Сг по множеству пикселов. Это можно сделать несколькими способами. Простейший способ, который мы собираемся использовать в примере про- граммы, состоит в том, чтобы просто продублировать значе- ния компонентов СЬ и Сг так, чтобы дискретизованное зна- чение было присвоено множеству примыкающих пикселов. Недостаток этого метода заключается в том, что он создает эффекты блочности. В альтернативном варианте следует применять алгоритм фильтрации в процессе сверхдискрети- зации (up-sampling process). После сверхдискретизации (up-sampling) каждое дискретизо- ванное значение компонентов Y, СЬ и Сг приходится на один пиксел цветного изображения. Последний этап состоит в конвертировании компонентов YCbCr в RGB с помощью преобразований, описанных в Главе 1. Обработка маркеров перезапуска В предыдущем обсуждении мы опустили одну небольшую операцию - обработку маркеров перезапуска. Если послед- ний маркер DRI (Define Restart Interval - Определение интер- вала перезапуска) во входном потоке данных перед маркером SOS определил ненулевое значение для интервала перезапус- ка, между данными скана должны быть вставлены маркеры перезапуска (RST0-RST7). Интервал перезапуска определяет число MCUs между маркерами перезапуска. JPEG-декодер должен поддерживать ведение счетчика MCUs, обработанных между маркерами перезапуска. Каж- дый раз, когда значение счетчика достигает величины интер- вала перезапуска, декодер должен считывать из входного по- тока данных маркер перезапуска.
Декодирование изображений JPEG, сжатых в последовательном режиме 139 Маркеры перезапуска помещают на границах байтов. До прочтения маркера перезапуска все неиспользованные биты дробных частей во входном потоке данных отбрасываются. После прочтения маркера перезапуска выполняется единст- венная операция - сброс в ноль значений разностей коэффи- циентов DC для всех компонентов в скане. Если декодер не находит маркер перезапуска на заданном интервале перезапуска, поток данных искажается. Декодер должен проверять, что маркеры перезапуска располагаются в порядке RSTo, RST1, ... RST7, RSTo, RST1, ... RST7. Обзор декодирования в JPEG Процесс декодирования отдельных единиц данных рассмот- рен от начала до конца. Теперь мы собираемся вернуться на шаг и взглянуть в целом на процесс декодирования изобра- жений JPEG, сжатых в последовательном режиме. Помните, что поскольку мы не поддерживаем иерархический режим JPEG, мы не делаем различий между кадром и изображени- ем. В целом процесс декодирования файла JPEG включает. 1. Чтение маркеров SOI и JFIF АРРо для проверки работоспо- собности файла и его принадлежности к формату JPEG. 2. Чтение маркеров DRI, DQT и DHT и использование их для определения интервала перезапуска, таблиц квантования и таблиц Хаффмана. 3. Чтение маркера SOF и использование его для определения размеров изображения. 4. Чтение всех маркеров SOS и обработка данных сканов, следующих за ними. 5. Чтение маркера EOI. Эта общая схема должна позволять справляться с возможны- ми отклонениями. Маркеры SOI и JFIF АРРо должны нахо- диться в начале файла, а маркер EOI должен присутствовать в конце файла. Маркеры SOS должны располагаться после маркера SOF, а маркеры DRI, DQT и DHT могут встречаться в любом месте файла до маркера EOI.
140 Форматы и алгоритмы сжатия изображений в действии Заключение В этой главе рассмотрено представление сжатых данных изо- бражения внутри маркеров SOS в JPEG-файле с последова- тельным режимом сжатия. Официальным источником фор- мата JPEG служит стандарт JPEG (1994). Исходный про- граммный код JPEG содержит многочисленные ссылки на данный документ, благодаря этому можно по номерам разде- лов в исходном программном коде найти соответствующие разделы в стандарте. В этой главе приводится пример программного кода для функционального JPEG-декодера, который может считывать файлы JPEG, созданные в базовом и расширенном режимах и преобразовывать их в файлы формата Windows BMP. Некото- рые компоненты этого декодера были представлены в преды- дущих главах, поэтому здесь они не будут повторяться. Данной программе присущи два ограничения в типах после- довательных файлов JPEG, которые она может обрабатывать, но оба эти ограничения не создают больших проблем. Преж- де всего, не поддерживаются маркеры DNL. Однако, посколь- ку они используются редко, это ограничение несущественно. Во-вторых, не поддерживается дискретизация данных для дробных частей пикселов. Если кодируется цветное изобра- жение с компонентом, для которого частота дискретизации по горизонтали или по вертикали равна 3, а для всех осталь- ных компонентов соответствующие частоты отличны от 1, это приведет к необходимости дискретизации значений для долей пикселов. На практике дробная дискретизация не ис- пользуется, поэтому отсутствие ее поддержки программой является малозначительной проблемой. Класс компонентов Для представления одного компонента декодер использует класс JpegDecoderComponent. Этот класс поддерживает мас- сив (data_units), который содержит декодированные единицы данных компонента. Можно реализовать последовательный декодер без буферизации всех единиц данных. Однако, буфе- ризация требуется для декодирования прогрессивного JPEG. Для того чтобы добиться максимальной унификации с деко- дером прогрессивного JPEG, описанным в Главе И, декодер последовательного JPEG тоже буферизует данные.
^кодирование изображений JPEG, сжатых в последовательном режиме 141 DecodeSequen tial Функция-член DecodeSequential декодирует следующую еди- ницу данных во входном потоке данных и сохраняет значе- ние в массиве data_units. Эта функция выполняется после процесса декодирования, представленного ранее в этой главе. Upsample Функция Upsample присваивает дискретизованные данные компонента путем дублирования значений. Объем дублиро- вания зависит от отношения частот дискретизации компонен- тов к максимальной частоте дискретизации изображения. Существуют две ветви выполнения функции. При выполне- нии одной ветви обрабатывается простейший случай, когда частоты дискретизации по горизонтали и по вертикали равны максимальным частотам дискретизации изображения. При выполнении другой ветви осуществляется растягивание дис- кретизованных значений компонентов компонентов. Преобразование цвета Функция RGBConvert преобразует дискретизованные значе- ния YCbCr трех компонентов в эквивалентные значения RGB и сохраняет их в объекте Bitmapimage. Поскольку преобразо- вание в RGB требует трех отдельных компонентов, функция RGBConvert статическая. Функция GrayscaleConvert делает то же самое при преобразовании изображений в полутоновые. Для обеспечения единообразия эта функция тоже статиче- ская, хотя использует всего один компонент. Класс декодера Класс JpegDecoder является JPEG-декодером. Он считывает изображение JPEG из входного потока данных и сохраняет его в объекте Bitmapimage. Readimage Функция Readimage считывает JPEG-изображение из входно- го потока данных. Для обработки маркеров входного потока данных она повторно вызывает функцию ReadMarker до тех пор, пока не прочитает маркер EOI. Функция ReadMarker оп- ределяет тип маркера, а затем вызывает функции, которые декодируют конкретные маркеры.
142 Форматы и алгоритмы сжатия изображений в действии ReadQuantization Функция ReadQuantization обрабатывает маркер DQT. Объек- ты JpegDecoderQuantizationTable считывают из входного по- тока данных фактические таблицы квантования. Маркер DQT может указывать несколько таблиц квантования, поэтому данная функция определяет, сколько таблиц содержит маркер и идентифицирует каждую из них. ReadHuffmanTable Данная функция весьма похожа на функцию ReadQuantization, за исключением того, что считывает маркеры DHT. Сами дан- ные таблиц Хаффмана считываются объектами JpegHuffmanDecoder. Эта функция считывает таблицы Хафф- мана до тех пор, пока в маркерах остаются данные. ReadStartOfFrame , Функция ReadStartOfFrame считывает маркеры SOFn. Формат всех маркеров SOFn одинаков, поэтому для считывания мар- керов всех типов используется одна и та же функция. Чтобы определить, поддерживается ли декодером маркер SOFn, де- кодер использует функцию ReadMarker. ReadStartOfScan Функция ReadStartOfScan считывает во входном потоке дан- ных маркер SOS и определяет компоненты, которые состав- ляют скан, а затем сохраняет список указателей на соответст- вующие объекты JpegDecoderComponent в массиве scan_components. ReadSequentiallnterleavedScan и ReadSequentialNonlnterleavedScan Функции ReadSequentiallnterleavedScan и ReadSequentialNonln- terleavedScan управляют чтением единиц данных во входном потоке данных. Первая функция используется в том случае, когда текущий скан содержит более чем один компонент, вторая функция находит применение, когда в скане содер- жится только один компонент. Отдельные объекты компо- нентов считывают коэффициенты DCT в единицах данных. Однако эта функция определяет порядок расположения ком- понентов и какие единицы данных считываются для каждого компонента. Кроме того, функции отслеживают число счи- танных единиц данных и сравнивают его с интервалом пере-
^кодирование изображений JPEG, сжатых в последовательном режиме 143 запуска, чтобы определить, когда должен считываться маркер перезапуска. Использование класса декодера Класс JpegDecoder используется точно так же, как и другие классы декодера, представленные в книге. Следующий фраг- мент программного кода иллюстрирует, каким образом ис- пользуется класс JpegDecoder для преобразования JPEG- файла в файл Windows BMP. #include "jpgdecod.h" ^include "bmpencod.h" ifstream input ("INPUT.JPG", ios::binary) ofstream output ("OUTPUT.BMP", ios::binary) ; Bitmaplmage image ; JpegDecoder decoder ; decoder.Readimage (input, image) ; BmpEncoder encoder ; encoder.Writelmage (output, image) ; Программа декодирования Программа DECODER преобразует JPEG-изображение в формат BMP. Командная строка для запуска данной про- граммы: DECODER input.jpg output.bmp Чтобы считать входной файл в объект Bitmapimage, програм- ма DECODER создает объект JpegDecoder, а затем вызывает функцию Readimage. Программа DECODER создает файл BMP путем вызова функции Writelmage, принадлежащей объекту BmpEncoder.
ГЛАВА 9. Создание последовательных файлов JPEG В этой главе рассматривается реализация кодеров последова- тельных JPEG-файлов. В целом, процесс создания файла JPEG обратен процессу декодирования. Основное отличие между кодированием и декодированием заключается в том, что при кодировании существует несколько вариантов созда- ния файла, в то время как при декодировании обрабатывается заданный файл. При кодировании выбираются параметры сжатия, генерирование кода Хаффмана и порядок располо- жения блоков. Параметры сжатия При сжатии изображения в последовательном режиме JPEG существует несколько альтернативных вариантов. К ним от- носятся: ✓ Структура и число таблиц квантования, а также назначение таблиц компонентам. ✓ Число таблиц Хаффмана, их назначение компонентам и ме- тод создания этих таблиц. ✓ Число сканов и компонентов в каждом скане. ✓ Частота маркеров перезапуска. ✓ Частота дискретизации компонентов. ✓ Создание цветного или полутонового изображения. ✓ Использование базовых или расширенных кадров. Кодер может выбирать эти варианты либо отдельно для каж- дого изображения, либо глобально для всех изображений. Для последовательного JPEG-файла с кодированием Хаффмана могут использоваться кадры двух типов: базо- вый последовательный кадр (SOFo) или расширенный по- следовательный кадр (SOFi). Единственное различие меж- ду этими двумя кадрами состоит в том, что базовый после- довательный кадр поддерживает только 8-битовые дискре- тизованные данные, и максимум две таблицы Хаффмана DC и АС, а расширенный последовательный кадр поддер- живает 8- и 12-битовые дискретизованные данные и до че-
146 Форматы и алгоритмы сжатия изображений в действии тырех таблиц Хаффмана DC и АС. Базовый последова- тельный режим представляет собой режим JPEG, реализо- ванный в большинстве JPEG-декодеров. Поэтому, в целях обеспечения максимальной совместимости, кодер, по воз- можности, должен использовать этот режим. Кодер, опи- сываемый в конце данной главы, кодирует только 8-бито- вые дискретизованные данные и, поскольку в этом случае нет необходимости использовать более двух таблиц Хаффмана каждого типа, кодер работает в базовом после- довательном режиме. Расширенный последовательный режим совместим снизу вверх с базовым последовательным режимом JPEG. Если бы кодер про- сто заменил маркер SOFo на маркер SOFi, то в результате полу- чился бы абсолютно достоверный расширенный последователь- ный JPEG-файл. Таблицы Хаффмана Поскольку цветные изображения содержат три компонента, а базовый режим позволяет работать только, максимум, с двумя таблицами Хаффмана каждого типа, кодер должен распределить таблицы Хаффмана между' компонентами, либо разделить компоненты между несколькими сканами. Наш ко- дер всегда использует таблицы Хаффмана с идентификато- ром 0 для кодирования компонента Y и таблицу с идентифи- катором 1 для кодирования компонентов СЬ и Сг. Если ком- поненты СЬ и Сг кодируются внутри одного скана, они ис- пользуют таблицу Хаффмана совместно. Если изображение разделяется на два или более сканов, кодер может назначить для каждого скана разные таблицы Хаффмана. Наш кодер назначает разные таблицы Хаффмана компонентам СЬ и Сг, только тогда, когда они кодируются в разных сканах. Ес- ли они кодируются внутри одного скана, даже если компонент Y не является частью скана, они используют таблицы Хаффмана совместно.
Создание последовательных файлов JPEG 147 Таблицы квантования Как базовый, так и расширенный последовательный режимы позволяют определять для изображения до четырех таблиц дискретизации. Наш кодер работает только с двумя таблица- ми. Одна таблица (ID=0) используется для компонента Y, а вторая таблица (ID=1) используется для компонентов СЬ и Сг. Назначения этих таблиц носят произвольный характер. Следующая проблема заключается в способе создания таб- лиц квантования. Мы могли бы предоставить пользователю задавать все элементы таблицы квантования, однако это сделало бы несколько утомительным использование деко- дера, особенно людям, не знакомым с внутренними меха- низмами JPEG. Использование постоянного набора значе- ний квантования также нельзя назвать удачной идеей, по- скольку разные типы изображений требуют разных значе- ний квантования для восстановления сжатого изображения без заметных дефектов. Наше решение основано на использовании библиотеки JPEG независимой группы JPEG (Independent JPEG Group). Мы начнем со значений квантования, которые приводятся в стандарте JPEG в качестве примера (Рис. 7.7), затем про- масштабируем эти значения в сторону уменьшения для по- лучения более высокого уровня качества изображения и по- сле этого промасштабируем значения в сторону увеличения для получения изображения более низкого уровня качества. Пользователь выбирает значение качества в диапазоне от 1 до 100. Для уровня качества 50 используются не модифици- рованные значения квантования из стандарта JPEG. При уровне качества меньше 25 значения квантования настолько большие, что итоговое сжатое изображение будет совер- шенно черным. При уровне качества около 100 значения квантования близки к 1 и обеспечивают крайне незначи- тельное сжатие. Чтобы рассчитать коэффициент масштабирования для значе- ний квантования, в нашем примере кодирования использует- ся такая формула: , Г « 6 • (50 - качество) log 2х—--------- Коэффициент _ масштабирования =е 50 '
148 Форматы и алгоритмы сжатия изображений в действии За данной формулой не стоят какие-либо выкладки. Это эм- пирическая формула, которая просто дает коэффициент мас- штабирования равный 1 для уровня качества 50 и обеспечи- вает умеренное масштабирование для диапазона качества 1- 100. При реализации JPEG-кодера вы можете сами задавать собственное масштабирование или использовать любой дру- гой желаемый метод генерирования значений квантования. Например, можно использовать значения качества в диапазо- не от 1 до 4, и выбирать из четырех наборов предварительно заданных таблиц квантования. Важное положение, которое следует уяснить из этого обсужде- ния, уровень качества - относительная величина. В стандарте JPEG отсутствует понятие «значение качества». Данная концеп- ция возникла при реализации JPEG-кодеров. При использовании разных кодеров одно и то же значение качества с большой долей вероятности приведет к разным результатам, даже если диапазон значений качества будет одинаков. Сканы В последовательном JPEG-файле данные по каждому компо- ненту хранятся в одном скане. Для цветного изображения можно использовать от одного до трех сканов. На Рис. 9.1 показаны пять возможных вариантов группирования компо- нентов. Отдельные сканы могут кодироваться в любом по- рядке. Это означает, что реально существует тринадцать раз- ных способов группирования и расположения компонентов в последовательном изображении. Естественно, в полутоновом изображении будет только один скан. Рис. 9.1. Возможные варианты группирования компонентов цветного изображения А В С D Е 1 Сканы< 2 3 ч. \СЬ Сг' 1> . У СЬ Сг \сь Сг к J ' У Сг СЬ к J У СЬ Сг к > Для разделения кодером изображения на множество сканов есть несколько причин. Если изображение передается по сети и отображается «с ходу», кодирование в первом скане одного компонента Y позволяет пользователю просмотреть его по- лутоновую версию до приема всех данных. Это обеспечивает
Создание последовательных файлов JPEG 149 ряд преимуществ, свойственных прогрессивному JPEG без трудностей его реализации. Раздельные сканы позволяют преодолеть ограничения по разрешенному числу таблиц Хаффмана. Базовый режим JPEG позволяет использовать только две таблицы Хаффмана каждого типа. Если по какой-то причине для каждого компо- нента нужна отдельная таблица, можно задействовать не- сколько сканов. На Рис. 9.2 показан порядок маркеров, кото- рый обеспечивает для цветного изображения в базовом ре- жиме JPEG использование разных таблиц для каждого ком- понента. Рис. 9.2. Порядок маркеров в базовом DHT Определяет таблицу 0 режиме JPEG, SOS Компонент Y использует таблицу 0 для которого DHT Переопределяет таблицу каждому компоненту DHT Определяет таблицу 1 назначаются SOS Компонент СЬ использует таблицу 0, разные таблицы компонент Сг использует таблицу 1 Хаффмана Кодер может предоставлять пользователю возможность зада- вать группирование компонентов в сканах, или же он может использовать предварительно заданное группирование. Ре- шение о действующем варианте зависит от того, что пред- почтительнее: универсальность или простота применения. Если пользователю не разрешается задавать группирование компонентов, кодеру необходимо автоматически разделять компоненты на множество сканов, когда это требование обу- словлено частотами дискретизации. Частоты дискретизации Наш кодер позволяет пользователю назначать частоты дис- кретизации по горизонтали и по вертикали (1—4) для каждо- го компонента, но это не является обязательным требовани- ем. Более простой способ, который почти всегда дает хоро- шие результаты, состоит в предоставлении пользователю возможности задавать частоты дискретизации для компонен- та Y, и в то же время использовать в кодере для компонентов СЬ и Сг частоты дискретизации равные 1.
150 Форматы и алгоритмы сжатия изображений в действии Если пользователю разрешено задавать любую возможную частоту дискретизации для любого компонента, то в этом случае кодер должен уметь справляться с проблемой дроб- ной дискретизации (fractional sampling). Если все частоты дискретизации равны степеням 2 (1, 2, 4), то при субдиск- ретизации (down-sampling) на отдельное дискретизованное значение будет отображаться целое число (1, 2, 4, 8 или 16) пикселов. С другой стороны, если для какого-то компонен- та горизонтальная или вертикальная частота дискретиза- ции равна 3, а для всех остальных компонентов соответст- вующая горизонтальная или вертикальная частота дискре- тизации равна 2 или 4, то в процессе субдискретизации на каждое дискретизованное значение будет отображаться дробное число пикселов. Хотя дробное отношение общего числа пикселов к общему количеству дискретизованных значений не противоречит требованиям стандарта JPEG, на практике такие случаи крайне редки. Если вы создаете изображения, которые используют дробную дискретиза- цию, весьма вероятно, что они не будут читаться многими другими программами. JPEG-кодер из нашего примера во время сжатия генерирует ошибку, если пользователь задал дробную дискретизацию. Стандарт JPEG (Раздел В.2.3) определяет, что MCU внутри скана может содержать максимум 10 единиц данных: HFy х VHY + HFCb х VHa + HFCr x VHCr < 10 Это серьезное ограничение, но его легко упустить из виду. Поэтому кодер должен проверять, чтобы этот предел не был превышен, иначе формируемые кодером файлы не бу- дут читаться декодерами, соответствующими стандарту JPEG. Предположим, что для компонента Y частот дискре- тизации по горизонтали и по вертикали равны 4. Посколь- ку в чересстрочном скане MCU включал бы 16 единиц данных компонента Y, то при указанных частотах дискре- тизации компонент Y должен был бы кодироваться в по- строчном скане. Кодер из нашего примера выдает ошибку, если пользователь пытается создавать сканы с более чем 10 единицами данных на каждый MCU. В альтернативном варианте кодер должен был бы ограничивать частоту дискретизации теми значения- ми, при которых данный предел не превышается. Например, кодер мог бы предоставлять пользователю возможность ус-
Создание последовательных файлов JPEG 151 танавливать все частоты дискретизации равными 1 (по 3 еди- ницы данных на каждый MCU) или назначать для компонен- та Y частоту дискретизации равную 2, а для других компо- нентов - частоту дискретизации равную 1 (по 6 единиц дан- ных на MCU). Еще одна возможность - автоматическое на- значение кодером компонентов в раздельные сканы, если число единиц данных в MCU слишком велико. Маркеры перезапуска Маркеры перезапуска используются для создания независимо кодированных блоков MCUs. В файле JPEG, создаваемом в последовательном режиме, кодируется разность коэффици- ентов DC, а не их абсолютные значения. Когда файл изобра- жения не содержит маркеров перезапуска, правильность де- кодирования любого MCU, кроме первого, зависит от пра- вильности кодирования предыдущего MCU.1 Если кодиро- ванные данные для MCU искажаются (например, во время передачи файла по телефонной линии), каждый последую- щий MCU будет декодироваться некорректно. Если файл изображения содержит маркеры перезапуска, де- кодер может использовать их для восстановления процесса декодирования после встречи искаженных сжатых данных. Поскольку маркеры перезапуска помещаются в выходном потоке последовательно, декодеры могут сравнивать послед- ний маркер, прочитанный до начала искаженных данных, и, используя интервал перезапуска, определять, с какого места в изображении следует продолжить декодирование. Этот метод восстановления процесса декодирования срабатывает до тех пор, пока протяженность искажения в сжатом потоке данных не распространится на восемь маркеров перезапуска. Если это произойдет, декодер не сможет сопоставить оставшиеся неискаженными сжатые данные с их корректным местополо- жением внутри изображения. Очевидно, чем меньше интервал перезапуска, тем скорее де- кодер сможет исправить последствия ошибки. Чрезмерно большой интервал перезапуска, когда в скан помещаются всего один или два маркера перезапуска, малополезен. Нель- зя назвать хорошей идеей и использование слишком малого интервала перезапуска. Каждый маркер перезапуска добавля- ет в сжатый поток два дополнительных байта информации, 1 В прогрессивном JPEG также могут быть зависимости единиц данных от коэффициентов АС.
152 Форматы и алгоритмы сжатия изображений в действии что может уменьшить степень сжатия данных, особенно в прогрессивном режиме JPEG. Кроме того, малый интервал перезапуска увеличивает вероятность того, что искажение выйдет за пределы восьми маркеров перезапуска. При создании файлов JPEG в отдельно стоящей системе или в надежной сети, надобность в маркерах перезапуска возникает редко. Если маркеры перезапуска нужны для восстановления декодирования после ошибок, хорошим интервалом переза- пуска можно считать число MCUs, входящих в состав одной строки. Цвет или серая шкала Стандарт JFIF позволяет создавать либо трехкомпонентные цветные изображения, либо однокомпонентные (Y) полу- тоновые изображения. JPEG-кодер можно написать так, чтобы он всегда использовал три компонента, но недоста- ток такого подхода заключается в том, что полутоновые изображения в этом случае будут немного больше, и объем вычислений, необходимый для их декодирования, станет значительно больше необходимого. В цветовом простран- стве RGB оттенки серого цвета представляются значения- ми компонентов, связанных соотношением R = G = В (красный = зеленый = синий). Если внимательно взглянуть на функции преобразования RGB в YCbCr, то можно заме- тить, что при 8-битовых дискретизованных данных для любого оттенка серого цвета (R = X, G = X, В = X), соот- ветствующим цветовым представлением в YcbCr-модели будут координаты Y = X, СЬ = 128, Сг = 128. Поскольку перед выполнением преобразования DCT из значений ком- понентов вычитается 128, все коэффициенты для компо- нентов СЬ и Сг в полутоновом изображении будут равны нулю. В полутоновом изображении компоненты СЬ и Сг сжимаются очень сильно, поскольку для кодирования каж- дой единицы данных требуется всего 2 бита, не считая до- полнительной информации о маркерах. И хотя объем сжа- тых данных компонентов СЬ и Сг относительно невелик, эти данные совершенно бесполезны. Кодер может автоматически определять, является ли входное изображение полутоновым, проверяя соблюдение соотноше- ния R = G = В (красный = зеленый = синий) для RGB- значений цвета каждого пиксела. Проблема возникает, если изображение содержит близкие, но не равные друг другу
Создание последовательных файлов JPEG 153 RGB-компоненты. Например, значение RGB, равное (101, 100, 102), на экране будет выглядеть серым. Вместо проверки равенства кодер может сравнивать разность компонентов с малой величиной (А): abs(R-B) < \ abs(R — G)<\ abs(G - В) < А Однако в этом случае возникает вопрос, насколько большой должна быть величина разности компонентов, и, что более важно, захочет ли пользователь преобразовывать в полутоно- вые те изображения, цвета которых близки к чисто серому цвету. Возможно, самый надежный способ работы с полуто- новыми изображениями - включить в пользовательское меню кодера выбор режима сжатия: сжимать как цветное изобра- жение или сжимать как полутоновое изображение. Структура выходных файлов Рис. 9.3. Порядок расположения блоков кодером Стандарт JPEG достаточно гибок в том, что касается распо- ложения маркеров внутри выходного потока данных. Необ- ходимо соблюдать три основные ограничения, накладывае- мые на порядок размещения маркеров: ✓ Файл должен начинаться маркером SOI, за которым следу- ет маркер JFIF АРРо, и заканчиваться маркером EOI. ✓ В режимах JPEG, используемых нами, может быть только один маркер SOF, и он должен располагаться до любого маркера SOS. ✓ Все таблицы Хаффмана и таблицы квантования, исполь- зуемые в скане, должны определяться маркерами DHT и DQT, которые находятся перед маркером SOS. На Рис. 9.3 показан порядок расположения блоков в файле JPEG, который будет встречаться в большинстве случаев. JPEG-кодер из нашего примера располагает блоки в соответ- ствии с этой схемой. Кодеры, которые сохраняют информа- цию, зависящую от конкретной программы, должны встав- лять в выходной файл блоки АРР„, содержащие эти данные.
154 Форматы и алгоритмы сжатия изображений в действии Процесс кодирования Проверка достоверности Первый шаг в создании файла JPEG состоит в проверке пара- метров сжатия. Кодер должен удостовериться, что: ✓ для используемых частот дискретизации MCUs в сканах со- держатся не более 10 единиц данных; ✓ частоты дискретизации не соответствуют дробной дискрети- зации; ✓ все компоненты изображения записываются в один из сканов. Вывод блоков За исключением процесса формирования сжатых данных, ко- торые следуют за маркером SOS, и генерирования таблиц Хаффмана для маркеров DHT, процесс создания маркеров представляет собой простое заполнение значениями полей, рассмотренных в Главе 5. Единственная трудная задача со- стоит в сжатии данных, которой мы займемся в следующих разделах. Субдискретизация Первый шаг в процессе сжатия состоит в субдискретизации (down-sampling). Иными словами, если для компонента час- тота дискретизации по горизонтали или по вертикали мень- ше, чем максимальное значение частоты дискретизации для всех его компонентов, он сжимается (shrunk). Предположим, что есть цветное изображение, у компонентов которого сле- дующие частоты дискретизации: Y СЬ Сг По горизонтали 2 1 1 По вертикали 2 11
Создание последовательных файлов JPEG 155 Это означает, что для каждых двух дискретизованных значе- ний, полученных для компонента Y в каждом направлении, получается одно дискретизованное значение для компонен- тов СЬ и Сг. Еще один способ рассмотрения суб дискретиза- ции заключается в преобразовании частот дискретизации в интервалы, где каждый интервал равен максимальному зна- чению частоты дискретизации, деленному на значение часто- ты дискретизации компонента. Для предыдущего примера интервалы по горизонтали и вертикали равны: Y СЬ Сг По горизонтали 1 2 2 По вертикали 1 2 2 В общем случае процесс субдискретизации компонента мог бы быть таким: For II = 0 То IMAGEHEIGHT - 1 Step VERTICALINTERVAL Begin For J J = 0 To IMAGEWIDTH - 1 Step HORIZONTALINTEVAL Begin COMPONENTDOWNSAMPLE [II/VERTICALINTERVAL] [JJ/HORIZONTALINTERVAL] = COMPONENTPIXELDATA [II][JJ] End End Эта процедура делит пиксельные данные компонента на бло- ки, размеры которых равны интервалам дискретизации, и из каждого блока берется одно дискретизованное значение. Хо- тя этот способ и работает, лучше вычислять среднее дискре- тизованное значение для каждого блока вместо того, чтобы брать дискретизованное значение для одного пиксела. Как видно из предыдущего примера, все данные компонен- та, подвергнутые субдискретизации, помещаются в буфер, размеры которого, на самом деле, не отличаются от форма- та 8x8. Если процесс субдискретизации организован так, что одна единица данных формируется целиком за один раз, преобразование DCT и процесс дискретизации, опи- санные в Главе 7, могут выполняться сразу, исключая не- обходимость в буферизации субдискретизованных данных компонента.
156 Форматы и алгоритмы сжатия изображений в действии В этой точке процесс кодирования, реализуемый кодером, может выполняться по одному из двух путей. Процесс ко- дирования может быть структурирован так, что сразу после преобразования DCT и квантования будет выполняться ко- дирование единицы данных. Или, в другом варианте, все коэффициенты DCT для компонентов в пределах скана мо- гут сохраняться в буфере, а затем в отдельном проходе бу- дет выполняться чередование (interleaving) строк и кодиро- вание единиц данных. Преимущество первого варианта состоит в том, что для его реализации требуется значительно меньше памяти, чем для осуществления второго варианта. Применение второго вари- анта оправдано только тогда, когда кодер должен поддержи- вать прогрессивный режим JPEG (Глава 10). В этом случае кодер должен поддерживать ведение буфера, содержащего все коэффициенты DCT для компонента, иначе ему придется повторно выполнять субдискретизацию и преобразование - r DCT для одних и тех же данных. Применение буферизации всех коэффициентов DCT для компонентов не лишено смыс- ла, если необходимо, чтобы как можно большая часть про- граммного кода, реализующего кодер, была общей для по- следовательного и прогрессивного режимов JPEG. Кроме то- го, буферизация коэффициентов DCT скана позволяет гене- рировать таблицы Хаффмана по частотам использования ко- эффициентов DCT. В оставшейся части рассматриваемого материала предпо- лагается, что кодер буферизует коэффициенты DCT. При поддержке кодером двумерного массива буферов, содер- жащих 8x8 коэффициентов DCT, общий размер массива будет равен: Ширина-изображения + 8 х Интервал _дискретизации_по_горизонтали -1 Ширина _ буфера = --------------------------------------------------------- 8 х Интервал _ дискретизации _по _ горизонтали Высота _ изображения + 8 х Интервал _ дискретизации _по_ вертикали - 1 Высота _ буфера =---------------------------------------------------------- 8 х Интервал _дискретизации_по _вертикали
Создание последовательных файлов JPEG 157 Чередование Алгоритм 9.1. Кодирование построчного скана На данном этапе кодер уже создал буферы, содержащие ко- эффициенты DCT для компонентов в скане. Следующий шаг состоит в определении порядка, в котором кодируются еди- ницы данных в буферах. Если скан построчный (т.е. он со- держит один компонент), порядок размещения данных будет простым, как это демонстрирует Алгоритм 9.1. Global RESTARTINTERVAL Procedure EncodeNonlnterleaved Begin RESTARTCOUNTER = 0 For II = 0 To BUFFERHEIGHT - 1 Do Begin For JJ = 0 To BUFFERWIDTH - 1 Do Begin If RESTARTINTERVAL <> 0 And RESTARTCOUNTER = RESTARTINTERVAL Then Begin OutputRestartMarker () RESTARTCOUNTER = 0 End EncodeDataUnit (BUFFER [II][JJ]) RESTARTCOUNTER = RESTARTCOUNTER + 1 End End End Если скан чересстрочный, декодеру необходимо определить число строк и столбцов MCU, составляющих изображение. Процедура почти совпадает с той, что использовалась для де- кодирования JPEG-изображений в Главе 8. Единственное от- личие состоит в том, что при декодировании частоты дискре- тизации считываются из файла JPEG, тогда как при кодиро- вании частоты дискретизации являются входными парамет- рами. Число строк и столбцов MCU определяется с помощью частот дискретизации всех компонентов, которые составляют изображение, а не только компонентов текущего скана. Порядок расположения единиц данных в чересстрочном ска- не рассматривался в Главе 5. Алгоритм 9.2 иллюстрирует, ка- ким образом упорядочивание реализуется в кодере. Порядок компонентов в скане соответствует порядку их перечисления в маркере SOS.
158 Форматы и алгоритмы сжатия изображений в действии Алгоритм 9.2. Кодирование построчного MCU Global RESTARTINTERVAL Procedure Encodelnterleaved (COMPONENTCOUNT, COMPO- NENTS [1..COMPONENTCOUNT]) Begin RESTARTCOUNT = 0 For II = 0 To MCUROWS - 1 Do Begin For JJ = 0 To MCUCOLUMNS - 1 Do Begin // Данный блок обрабатывает одиночный MCU If RESTARTINTERVAL <> 0 And RESTARTCOUNT = RESTARTINTERVAL Then Begin OutputRestartMarker () RESTARTCOUNT = 0 End For KK = 0 To COMPONENTCOUNT - 1 DO Begin For LL = 0 To COMPONENTS [KK] . VERTI- CALFREQUENCY - 1 Do Begin For MM = 0 To COMPONENTS [KK]. HORIZONTALFREQUENCY - 1 DO Begin ROW = II * COMPONENTS [KK].VERTICALFREQUENCY + LL COLUMN = JJ * COMPONENTS [KK].HORIZONTALFREQUENCY + MM EncodeDataUnit (COMPONENTS [KK].BUFFER [ROW][COLUMN]) End End End RESTARTCOUNT = RESTARTCOUNT + 1 End End End Кодирование единиц данных Процесс кодирования единиц данных, по существу, обратен процессу декодирования, рассмотренному в Главе 8. При де- кодировании функция Extend() преобразует значение разряд- ности плюс дополнительные биты в значение коэффициента. Функция ReverseExtend() выполняет противоположное дейст- вие, преобразуя значение коэффициента в величину разряд- ности и дополнительные биты. void ReverseExtend (int value, unsigned int &magnitude, unsigned int &bits)
Создание последовательных файлов JPEG 159 if (value >= 0) { bits = value ; } else { value = -value ; bits = -value } magnitude = 0 ; while (value !- 0) { value >>= 1 ; ++ magnitude ; } return ; Для каждой единицы данных сначала кодируется коэффици- ент DC, затем кодируются в зигзагообразном порядке коэффи- циенты АС. Кодированное значение коэффициента DC в дей- ствительности является разностью между значением коэффи- циента DC в текущей единице данных и значением коэффици- ента DC из последней единицы данных, обработанной для то- го же компонента. Коэффициент DC кодируется в виде значе- ния разрядности, кодированного по методу Хаффмана (Табли- ца 9.1), за которым следует строка некодированных битов (un- encoded bits). Значение разрядности задает число литеральных битов, которые должны следовать за значением разрядности. Таблица 9.1. Коды разрядности для значений разности коэффициентов DC и диапазоны разности коэффициентов DC Кодированное Диапазон значений разности значение разрядности коэффициентов DC 0 0 1 -1, 1 2 -3, -2, 2, 3 3 -7 . . -4, 4 . . 7 4 -15.. -8, 8 . . 15 5 -31 . .-16, 16 . . 31 6 -63 . . -32, 32 . . 63 7 -127 . .-64, 64 . . 127 8 -255 . .-128, 128 . . 255 9 -512 . .-256, 256 . . 511 10 -1023 . .-512, 512 ..1023 11 -2047 . .-1024, 1024..2047
160 Форматы и алгоритмы сжатия изображений в действии Кодируются только ненулевые коэффициенты АС. Они хра- нятся в виде значения байта, кодированного по методу Хаффмана, за которым следует определенное количество ли- теральных битов. Кодированный байт разбивается на два 4- битовых поля, причем 4 младших бита определяют значение разрядности коэффициента (Таблица 9.2), а 4 старших бита задают число пропускаемых нулевых коэффициентов. Когда все оставшиеся коэффициенты АС нулевые, оба битовых по- ля устанавливаются равными нулю. Для представления серии из 16 нулевых коэффициентов используется код FOie, за ко- торым не располагаются литеральные биты. Таблииа 9.2. Коды разрядности коэффиииентов АС и диапазоны значений разности коэффиииентов АС Кодированное значение Диапазон значений разности разрядности коэффиииентов АС 1 -1, 1 2 -3, -2, 2, 3 3 -7 . . -4, 4 . . 7 4 -15.. -8, 8 . . 15 5 -31 . . -16, 16 . . 31 6 -63 . . -32, 32 . . 63 7 -127 . . -64, 64 . . 127 8 -255. .-128, 128 . . 255 9 -51 1 . .-256, 256 . . 511 10 -1023 . . -512, 512 ..1023 Алгоритм 9.3 показывает, каким образом единица данных кодируется в последовательном режиме JPEG. Входным па- раметром служит массив квантованных коэффициентов DCT, расположенных в зигзагообразном порядке JPEG. Алгоритм 9.3. Кодирование единии данных в последовательном режиме JPEG Global LAST_DC_VALUE Procedure EncodeDataUnit (DATAUNIT [0..63]) Begin DIFFERENCE = DATAUNIT [0] - LAST_DC_VALUE LAST_DC_VALUE = DATAUNIT [0] ReverseExtend (DIFFERENCE, MAGNITUDE, BITS) HuffmanEncodeUsingDCTable (MAGNITUDE) WriteRawBitS (MAGNITUDE, BITS) ZERORUN = 0 II = 1 While II < 64 Do Begin
Создание последовательных файлов JPEG 161 Алгоритм 9.3. Продолжение If DATAUNIT [II] О 0 Then Begin While ZERORUN >= 16 Do Begin HuffmanEncodeUsingACTable (F016) ZERORUN = ZERORUN - 16 End ReverseExtend (DATAUNIT [II], MAGNITUDE, BITS) HuffmanEncodeUsingACTable ((ZERORUN Leftshift 4) Or MAGNITUDE) WriteRawBits (MAGNITUDE, BITS) End Else Begin ZERORUN = ZERORUN + 1 End End If ZERORUN <> 0 Then Begin HuffmanEncodeUsingACTable (0016) End End Генерирование таблиц Хаффмана В программном коде из предыдущего раздела используется кодирование Хаффмана, но откуда берутся таблицы Хафф- мана, применяемые для кодирования коэффициентов? Стан- дарт JPEG не определяет процедуру генерирования таблиц Хаффмана. Допускается использование произвольного набо- ра кодов Хаффмана, в котором длина любого кода не превы- шает 16 битов и ни один из кодов не состоит целиком из еди- ниц. В стандарте отсутствует требование, чтобы коды, при- сваиваемые значениям, основывались на частотах использо- вания этих значений. Таким образом, простейший метод ко- дирования Хаффмана состоит в применении предварительно заданной таблицы Хаффмана. Стандарт JPEG включает в ка- честве примера два набора кодов Хаффмана для кодирования коэффициентов DC и АС,2 и реализация кодера может ис- пользовать таблицы Хаффмана из стандарта JPEG или любой другой набор предварительно заданных таблиц. Тем не ме- нее, хотя такой метод обладает достоинствами быстроты и простоты реализации, он, очевидно, не обеспечивает такого сжатия данных, какое достигается при использовании кодов Хаффмана, основанных на частотах повторения значений. 2 Раздел К.З в стандарте JPEG
162 Форматы и алгоритмы сжатия изображений в действии Если скорость сжатия не является главным требованием, вполне оправдано генерировать таблицы Хаффмана на ос- нове частот повторения значений, при этом кодер выпол- няет два прохода по коэффициентам DCT в скане. Очевид- ный способ реализации заключается в использовании от- дельных функций для сбора статистики и для вывода ко- дов. К недостаткам этого метода относится требование на- личия двух наборов почти идентичных функций, которые должны точно соответствовать друг другу. При малейшем изменении программного кода в одном из наборов функ- ций требуется внесение соответствующих изменений в другой набор, что превращает обслуживание программного кода в кошмар. Лучшее решение заключается в использовании отдельных функций для обработки отдельных кодов. Кодер мог бы реа- лизовать две пары процедур подобных тем, что показаны в Алгоритме 9.4. Алгоритм 9.4. Функции кодирования коэффициентов АС и DC Procedure GatheгDC (VALUE, EXTRABITS) Begin // EXTRABITS is not used IncrementFrequency (VALUE) End Procedure PrintDC (VALUE, EXTRABITS) Begin FindHuffmanEncode (VALUE, CODE, CODELENGTH) WriteRawBitS (CODELENGTH, CODE) If VALUE <> 0 Then WriteRawBitS (VALUE, EXTRABITS) End Procedure GatherAC (VALUE, EXTRABITS) Begin // EXTRABITS is not used IncrementFrequency (VALUE) End Procedure PrintAC (VALUE, EXTRABITS) Begin FindHuffmanEncode (VALUE, CODE, CODELENGTH) WriteRawBitS (CODELENGTH, CODE) If (VALUE And 0F16) <> 0 Then WriteRawBitS (VALUE And 0F16, EXTRABITS) End
Создание последовательных файлов JPEG 163 Каждая процедура использует идентичный интерфейс, по- этому программный код процесса кодирования может быть модифицирован так, чтобы быть похожим на процедуры в Алгоритме 9.5, где DCPROCEDURE представляет собой указа- тель (pointer) либо на процедуру GatherDC, либо на процедуру PrintDC, a ACPROCEDURE является указателем либо на проце- дуру GatherAC, либо на процедуру PrintAC. Применение указателей на процедуры позволяет задейство- вать одну и ту же функцию как для сбора статистики по ис- пользованию кода Хаффмана, так и для кодирования самих данных. Алгоритм 9.5. Кодирование единиц данных С ПОМОЩЬЮ указателей функций Global LAST_DC_VALUE Procedure EncodeDataUnit (DATAUNIT [0..63], DCPROCE- DURE, ACPROCEDURE) Begin DIFFERENCE = DATAUNIT [0] - LAST_DC_VALUE LAST_DC_VALUE = DATAUNIT [0] ReverseExtend (DIFFERENCE, MAGNITUDE, BITS) DCPROCEDURE (MAGNITUDE, BITS) ZERORUN = 0 II = 1 While II < 64 Do Begin If DATAUNIT [II] <> 0 Then Begin While ZERORUN >= 16 Do Begin ACPROCEDURE (F016, 0) ZERORUN = ZERORUN - 16 End ReverseExtend (DATAUNIT [II], MAGNITUDE, BITS) ACPROCEDURE ((ZERORUN LEFTSHIFT 4) Or MAGNITUDE), BITS) End Else Begin ZERORUN = ZERORUN + 1 End End If ZERORUN <> 0 Then Begin ACPROCEDURE (0016) End End
164 Форматы и алгоритмы сжатия изображений в действии Заключение В этой главе обсуждался процесс кодирования изображений JPEG в последовательном режиме. Процесс кодирования файлов в базовом и расширенном последовательном режимах для 8-битовых изображений в целом одинаков, за исключе- нием ограничений на число определяемых таблиц. Стандарт JPEG (JPEG 1994) содержит примеры таблиц Хаффмана и таблиц квантования. В данной главе приведен пример исходного программного кода кодера, сохраняющего изображение в последовательном JPEG-файле. Кодер является простейшей программой преоб- разования файлов Windows BMP в последовательные JPEG- файлы. Команда в формате ENCODER input.bmp output.jpg используется для создания файла цветного изображения JPEG, а команда ENCODER -g input.bmp output.jpg формирует файл полутонового изображения. Класс компонентов Класс JpegEncoderComponent представляет в процессе коди- рования один компонент. Его основные функции заключают- ся в дискретизации и кодировании единицы данных. Функция-член EncodeSequential кодирует единицы данных. Два из ее параметров являются указателями на функции- члены, которые обрабатывают коды, сгенерированные по данным изображения. Это позволяет использовать одну и ту же функцию как для сбора статистики, необходимой при ге- нерировании кодов Хаффмана, так и для кодирования данных по методу Хаффмана. Эти параметры будут служить указате- лями или на функции GatherDcData и GatherAcData, или на функции PrintDcData и PrintAcData. Первая пара функций со- бирает статистические данные по повторяемости значений, вторая пара функций записывает кодированные по методу Хаффмана значения в выходной поток.
Создание последовательных файлов JPEG 165 Класс кодеров Классом кодеров является JpegEncoder. Две его функции- члена управляют сжатием изображения. Баланс между степе- нью сжатия и качеством задается с помощью функции SetQuality. Значение качества может находиться в диапазоне 1-100 и определяет величину масштабирования эталонных значений из таблицы квантования. Функция SetSamplingFre- quency задает частоты (1—4) дискретизации компонента по горизонтали и по вертикали. По умолчанию кодер помещает все компоненты в один скан. Для размещения компонентов в разные сканы может приме- няться функция-член SetScanAttributes. Последние два пара- метра этой функции используются только для прогрессивно- го режима JPEG (Глава 10). В данном случае они всегда должны быть равны нулю. Функции InterleavedPass и NoninterleavedPass составляют ос- новную часть кодера. Они управляют порядком, в котором кодируются единицы данных, и осуществляют запись марке- ров перезапуска. Эти функции используют указатели на функции-члены; поэтому их можно использовать как для сбора информации по повторяемости кодов Хаффмана, так и для кодирования значений по методу Хаффмана.
ГЛАВА 10. Оптимизация DCT В начале книги мы уже подчеркивали, что будем стремиться скорее к простоте и ясности создаваемого программного ко- да, чем к его эффективности. Эта глава - единственная, в ко- торой рассматриваются вопросы эффективности работы про- грамм. Вычисление ГОСТ представляет собой одну из наибо- лее трудоемких и длительных процедур, выполняемых при декодировании файлов изображений JPEG. Следовательно, эти процедуры в наибольшей степени нуждаются в оптими- зации, позволяющей ускорить работу программ. Методы оп- тимизации вычисления ГОСТ применимы также и для опти- мизации вычисления DCT. Однако скорость вычислений бо- лее важна при декодировании JPEG-файлов, чем при решении задачи кодирования. При оптимизации вычислений ГОСТ и DCT предпочтение будет отдаваться математическим, а не программным мето- дам. Базовые знания линейной алгебры и тригонометрии бу- дут весьма полезны для понимания выполняемых выкладок. Многие люди теряют нить рассуждений, когда при рассмот- рении математических вопросов опускаются промежуточные этапы, поэтому наше обсуждение будет достаточно подроб- ным. Если вы не интересуетесь математикой или считаете ее скучной темой, можно просто перейти к концу главы и озна- комиться с окончательными результатами. Разложение на множители матрицы DCT В главе 6 уже сообщалось, что две матрицы умножаются пу- тем скалярного умножения строк первой матрицы на столбцы второй матрицы. При вычислении IDCT с помощью матрицы используется Уравнение 10.1, где М~ это матрица преобра- зования (transform matrix), а Т - это входные данные, подле- жащие преобразованию. Уравнение 10.21. у = МтТМ Инверсия DCT Поскольку произведение матриц обладает свойством ассо- циативности, две операции произведения могут выполнять- ся в любом порядке. Для определенности, в этой главе опе- рации умножения будут выполняться в следующем порядке:
168 Форматы и алгоритмы сжатия изображений в действии V = Мт(ТМ). Другими словами, для получения промежуточ- ной матрицы строки матрицы Т умножаются на столбцы матрицы М. Далее умножаются столбцы промежуточной матрицы на строки матрицы Мт. При умножении ТхМ каждая строка результата зависит только от соответствующей строки матрицы Т, поэтому можно рассматривать вычисления каждой строки по от- дельности. Аналогично, при перемножении Мт и промежу- точной матрицы, каждый столбец в результирующей матри- це зависит только от соответствующего столбца промежу- точной матрицы. Матрица преобразования DCT, первоначально приведенная в главе 7, повторяется в Уравнении 10.2 с подстановкой 1 12 ,, _ — = J— . Каждое скалярное произведение строки на столбец состоит из 8 операций умножения и 7 операций сложения; поэтому для преобразования каждой строки требуется 64 операции умножения и 56 операций сложения. Уравнение 10.2. 1 7§ 1 7s 1 78 1 vl 1 vl 1 Л 1 1 vi COS VI COS & VI cos & VI cos 17- VI cos 17- VI cos H- X s cos £- li cos H- л COS VI COS VI cos VI cos 17- VI cos il- VI cos 17- VI cos n- cos 30 й77 м = л cos 1б— л COS & VI cos H- VI cos й- VI cos VI cos n- V s cos n- /I V 8 cos 45 1677 л cos & VI cos VI cos 20 16 77 VI cos fl- VI cos 36_ 1677 VI cos \ s cos 17- 7 cos vi cos fa /I V 8 cos #- VI cos 25 _ 1677 VI cos #- VI cos 45 — 1677 VI cos n- VI cos 65 Тб77 7 cos л cos & 71 cos H- VI cos VI cos 42 — 1677 VI cos 54 1677 VI cos 66 Тб77 VI cos 78 Тб77 7 cos 90 й77 л cos & 7 cos VI cos 17- VI cos 1677 VI cos 1677 VI cos VI cos 21^. 1677 7 cos 1P5^ 16 77 Заметьте, что для этой матрицы характерно множество сим- метрий. Мы воспользуемся симметричностью для разложе- ния матрицы преобразования DCT на множители, представ- ляющие собой несколько разреженных матриц.
Оптимизация DCT 169 Первое преобразование, которое мы намереваемся выполнить, состоит в вынесении за скобки из каждого элемента констан- ты -|=, и переопределении IDCT с помощью эквивалентного л/8 представления из уравнения 10.3. Уравнение 10.3. V=-MTTM 8 На время мы отбросим коэффициент — и будем работать 8 только с матрицей, представленной в уравнении 10.4. Уравнение 10.4. 1111111 41 COS 7777 42 COS -~77 41 COS Лт7 4i COS 7777 72 COS 7777 72 COS 7777 72 cos 7777 * lo * |о ’ lo ’ lo ’ lo ’ lo ’ lo 1 72 COS Ц77 72 cos far 41 cos far 42 cos 7777 72 cos -7577 72 cos -ffir 72 cos far 42 cos 2|t7 72 COS 7777 М = 41 cos Л77 72 cos far 42 cos 77-77 72 cos 7777 72 cos far 42 cos 7777 72 cos 7777 ’ lo ’ lo ’ lo ’ lo ’ lo ’ lo ’ lo 42 COS -far 42 COS -Цтг 72 COS 7777 72 COS 7777 72 cos 7777 72 COS 777т 72 cos ^77 72 COS Ц77 72 COS 7^77 72 cos far 42 cos Ц77 72 cos т|тг 72 cos tItt 72 cos tjtt <2 cos ^77 <'2 cos у|т7 72 COS 7J77 42 COS fa 42 COS —7Г 42 COS у|т7 72 COS 7J7T 72 cos 7^77 72 cos ^7T 72 cos 7^77 72 cos 7I77 72 COS 7^77 72 COS ~77 72 COS ^77 72 COS yf77 72 COS ^77 72 COS -^77 72 cos 7^77 72 COS -7^77 Несколько последующих упрощений используют симметрич- ность значений функции косинуса для уменьшения числа не- одинаковых значений в матрице преобразования. Свойства функции косинуса можно найти в любой книге по основам математики. Из Рис. 10.1 видно, что изменения функции косинуса носят периодический характер, так что Уравнение 10.5. cosx = cos(x + 27T)
170 Форматы и алгоритмы сжатия изображений в действии Используя уравнение 10.5, заменим в Уравнении 10.5 все ко- N mod 32 16 , , N эффициенты — на , получив в результате уравне- ние 10.6. Уравнение 10.6. 1 11 1 1 1 1 1 72 cos -j^ir 72 cos -jjzr 72 cos ^zr 72 cos ^zr 72 cos for 72 cos -Ц-тг 72 cos Цтг 72 cos Цтг 72 cos -^zr 72 cos -^zr 72 cos -^zr 72 cos ]|zt 72 cos -Цтг 72 cos ^ir \ 2 cos —zr 72 cos ^zr 72 COS ^ZT 72 COS for 72 cos 2|тг 72 cos f|zr 72 COS ^ZT 72 COS for 72 COS ^ZT 72 COS 2|тт M = 72 COS -j^TT 72 COS -Jf-ZT 72 COS yfzT 72 COS j|zT 72 COS for 72 COS for \ 2 COS j|zT 72 cos y|zT 72 cos ^zr 72 cos Цтг 72 cos y|zr 72 cos -^zr 72 cos -j|zt 72 cos for \2 cos -fo 72 cos Цтг 72 COS ~TT 72 COS ~7T 72 COS YJTT 72 cos -jj7T 72 cos 7“7T 72 cos \2 COS Цтг 72 cos 7“7T 72 COS-for COS ^1T 72 COS -^ir 72 COS 72 COS 2Ljr 72 COS -^zr COS Hzr 72 COS -^zr I Снова обратившись к Рис. 10.1, заметим, что функция коси- нуса симметрична вдоль оси х, так что Уравнение 10.7. costt + х — cos л х Используя Уравнение 10.7, заменим все элементы матрицы в Уравнении 10.6, у которых аргументы функций косинуса больше л, и получим Уравнение 10.8.
Оптимизация DCT 171 Уравнение 10.8. 1 1 1 1 1 1 1 1 Л cos fa Ji cos -far 72 cos -^tt 72 cos far Ji COS -^TT 72 COS ]|7T 72 cos -Цтт 72 cos -Цтт Л cos fa Ji cos fa Ji cos -jjTT Ji cos fa Ji cos Цтт 72 COS 7I7T Ji cos fa 72 cos far Л cos fa Ji cos fa Ji COS -ЦтГ \li cos Цтт Ji COS -^TT 72 COS fa Л COS -^TT 72 cos -J|it M = Л COS ^7T Ji cos Цтг 72 cos Цтт 72 COS ~7T 72 cos ^7T Л cos fa Ji COS -Цтт 72 cos fa Л cos fa Ji COS 72 cos -^tt Ji cos far 72 COS Цтг Ji COS -^TT Ji COS -j^TT Ji COS J|7T Л cos fa Ji COS -^TT 72 cos far Ji COS ]|7T Ji cos ^rr 72 COS -^TT 14 V2 cos -^тг 72 cos fa Л cos far 72 COS 7J7T Ji cos -fa 72 COS -Цтг Ji cos fa Ji COS ]|7T \[2 COS “7Г Ji cos fa Функция косинуса также симметрична вдоль оси Y, так что Уравнение 10.9. r cos—F х = cos-х 2 2 Используя Уравнение 10.9, заменим в Уравнении 10.8 все ар гументы функции косинуса со значениями больше у и по лучим Уравнение 10.10. Уравнение 10.10. 11111111 72 cos ^тг 72 cos -^тт 72 cos -^тт 72 cos - 72 cos -^тт- 72 cos -^тт- 72 cos -—тт- 72 cos -jju 72 cos fa 72 cos -72 cos —тт-72 cos ^тт-72 cos ^7T-72 cos fa 72 cos fa Ji cos fa Л cos к”’ cos ^TT-72 cos -^тг-72 cos fa 72 cos ~тг 72 cos fa 72 cos fa -72 cos М = 4 72 cos ~тт - 72 cos ~тт- 72 cos -j-n- 72 cos fa 72 cos fa - 72 cos fa-72 cos fa 72 cos ^tt 72 cos ^7T -72 cos far 72 cos far 72 cos far -72 cos fa-Л cos far 72 cos far -Л cos fa 72 cos fa -72 cos fa 72 cos fa -72 cos fa-72 cos —zr 72 cos fa -72 cos fa 72 cos fa Л cos ‘ie'”’ -72 cos fa 72 cos fa -72 cos fa 72 cos fa -72 cos fa Ji cos fa - Ji cos fa
172 Форматы и алгоритмы сжатия изображений в действии Значение функции косинуса для аргумента ~ хорошо из- вестно. Уравнение 10.11. п cos— 4 Подстановка уравнения 10.11 в Уравнение 10.10 дает Урав- нение 10.12. Уравнение 10.12. 11111111 72cOS-j^TT 72 COS-^17 72 COS ^77 \'2 COS ^77 -^2 COS ^77-72 COS-^77-у2 COS-^77-v2 COS-^77 м = 72 COS -"7Г 72 COS ^77 -72 COS -^ТГ-72 COS ^77-72 COS -^77-72 COS far 72 COS ^77 72 cos far 72 COS-^77 -72 COS 7~7Т-Т2 COS —77-T2 COS-j—77 72 COS ~77 J2 COS far <2 COS far -72 COS ^77 1-1-11 1-1-11 72 COS -^77 -72 COS ^77 72 COS ^77 JI COS ^77 -72 COS far-j2 COS J£77 \2 COS ~77 -JI COS ^77 72 COS -^77 -72 COS ^77 JI COS ^77 - JI COS far-j2 COS ^77 JI COS -^77 -J2 COS ^77 J2 COS -~77 72 COS TftTT -5/2 COS J^TT 5/2 COS far -5/2 cos far JI cos far -5/2 cos far \2 COS -j^77 -72 cos far Если отвлечься от знаков, то в матрице преобразования оста- лось только семь различных элементов. Теперь, после упро- щения матрицы преобразования, мы разложим матрицу в произведение нескольких разряженных матриц. Главная цель разложения на множители матрицы преобразования состоит в получении матриц-сомножителей, содержащих максималь- но большое число нулевых элементов. Второстепенной це- лью является получение матриц со значениями элементов, равными +/-1. С точки зрения оптимизации нулевые значения наиболее предпочтительны, единичные оказывают слабое влияние, а остальные значения оказывают отрицательный эффект на оптимизацию.
Оптимизация DCT 173 Процедура, используемая для разложения матрицы на множители, называется Гауссовым исключением (Gaussian elimination). Метод Гаусса (исключение по главным эле- ментам) исключение не входит в круг вопросов, обсуждае- мых в этой книге. Однако мы попытаемся включить в наше изложение достаточное число шагов этой процедуры, что- бы читатель, обладающий базовыми знаниями по линейной алгебре, смог уяснить, как получаются множители при разложении матриц. Следующие примеры операций умножения матриц иллюстрируют принципы уменьшения числа строк, используемые для разложения матрицы DCT на множители. . _ Перестановка строк Сложение строк Перестановка столбцов Сложение столбцов Заметим, что если матрицу в Уравнении 10.12 разделить по вертикали пополам, то левая половина каждой строки пред- ставляет собой или зеркальное изображение правой полови- ны строки, или отрицательное (со знаком минус) зеркальное изображение правой половины строки. Матрицу можно раз- ложить на множители так, чтобы объединить в одну группу строки с зеркальным изображением своих правых половин, а в другую группу строки с отрицательным зеркальным изо- бражением своих правых половин (Уравнение 10.13). Это первое разложение на множители служит только для объяснения последующих выкладок.
174 Форматы и алгоритмы сжатия изображений в действии Уравнение 10.13. 1 0 0 0 0 0 0 О' 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 м= 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 о о 0 0 0 0 0 1 1 1 1 11111 1 -1 -1 1 1-1-11 \'l cos тг Д’cos 7T -Д cos - Д cos far- Д COS fa- Д cos far Д cos ^тт Д cos far Д cos -fair - Д COS -Ц7Г Д cos -^тг - Д cos far- Д cos far Д cos fa - Д COS -Д7Т Д COS fa X Дсов-^тт Дсов^ТГ ДсО8~!Т Д COS ^7Г - Д COS “Г7Г-Д COS ~7Т-Д COS-^7Г-Д COS-^7Т Д COS far - Д COS Лтг Д COS -fa Д COS ~ТТ - Д COS Лтг-Д COS 4тТ Д COS -j^TT - Д COS far Д COS ^7Г - Д COS 7^7Г-Д COS ^7Т-Д COS-^7Г Д COS-~7Г ДсОЗ^Т \ 1 cos —7T -Д cos far Д COS -j^TT - Д COS-far Д COS far - Д COS -far Д COS far - Д COS far \ 1 COS ^7T - Д COS -j^TT С помощью разложения на множители в Уравнении 10.14 удаляются половины строк из матрицы Уравнения 10.13, ко- торые являются зеркальными изображениями остающихся половин строк.
Оптимизация DCT 175 Уравнение 10.14. м= 10 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 10 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 10 0 1 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 0 1 -1 -1 1 0 0 0 0 72 cos ^тг 72 cos -^тг -72 cos far -72 cos ~7Г 0 0 0 0 72 cos ^тт -72 cos -^тг 72 cos -^тт -72 cos far 0 0 0 0 0 0 0 0 72 COS 72 COS ^7T 72 cos far 72 COS 0 0 0 0 72 cos far 72 COS -j^TT -72 cos far 72 cos -^тг 0 0 0 0 -72 cos -^тг - 72 COS -j^TT -72 cos ^тг 72 COS far 0 0 0 го» iV- 0 - 72 COS 72 cos far -72 cos 72 COS far 1 0 0 0 0 0 0 1 0 1 0 0 0 0 1 0 0 0 1 0 0 10 0 0 0 0 1 1 0 0 0 ООО 1-1000 0 0 1 0 0 -1 0 0 0 1 0 0 0 0 -1 0 1 0 0 0 0 0 0 -1 Можно заметить, что в Уравнении 10.14 ненулевые элементы в верхнем левом углу центральной матрицы образуют такую же зеркально симметричную структуру, что и строки матри- цы в Уравнении 10.13. Мы выполним разложение этой струк- туры описанным выше способом, чтобы упростить эту часть матрицы (Уравнение 10.15). Взгляните на подматрицу 4x4 в нижнем правом углу второй матрицы в Уравнении 10.15 и в Уравнении 10.16.
176 Форматы и алгоритмы сжатия изображений в действии Уравнение 10.15. I 0 0 0 0 0 0 o' 0 0 0 0 I 0 0 0 0 0 I 0 0 0 0 0 м= 0 0 0 0 0 0 I 0 0 I 0 0 0 0 0 0 0 0 0 0 0 I 0 0 0 0 0 I 0 0 0 0 .0 0 0 0 0 0 0 I I I 0 0 0 0 0 0 I -I 0 0 0 0 0 0 0 0 72 cos 7^ 72 cos 0 0 0 0 0 0 -72 cos far 72 cos 0 0 0 0 X 0 0 0 0 72 COS ^7T 72 COSfar -72 cos far 72 COS ^7T 0 0 0 0 72 cos 72 COS -72 cos 72 COS far 0 0 0 0 -72 cos ~ir -72 cos -<2cos ~-тг 72 COS ^TT 0 0 0 0 COS ±1T 72 COS fat -72 cos ^тг 72 COS ~^ТГ 1 0 0 1 0 0 0 0 0 1 1 0 0 0 0 0 0 1 -1 0 0 0 0 0 1 0 0 -1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 0 1 0 0 0 0 1 0 0 0 1 0 0 1 0 0 0 0 0 1 1 0 0 0 ООО 1-1000 0 0 1 0 0 -1 0 0 0 1 0 0 0 0 -1 0 1 0 0 0 0 0 0 -1 Уравнение 10.16. S = 72 cos -^тт 72 cos ^тг JI COS ^7T >/2 COS ~7T -72 cos -72 cos 72 COS -^TT 72 COS -72 cos —тг 72 cos -fair -72 COS -j^TT 72 COS jgTT ~72 COS JJTT 72 COS ~7T -72 COS -j^TT 72 cos ^7T Эта матрица может быть дальше разложена на множители, если воспользоваться приводимыми ниже уравнениями, ко- торые можно найти в любом справочнике по математическим функциям.
Оптимизация DCT 177 Уравнение 10.17. cos a + cos /3 = 2 cos у (a + /3) cos ^(a - (3) cos a - cos /3 = 2 sin ~^(a + /3) sin ±(a - (3) Используя Уравнение 10.17, найдем, что . Др. Уравнение 10.18. cos 1677 = ^(cos ^7Г + cos и77) 3 1 I 1 7 > cos 77 = v5lcos ii77 + cos 1777! 5 I I I 7 3 C0S T777 = ^(.C0S Тб77 “ C0S Тб77/ 7 I / 3 5 3 cos 1777 = ^(cos le77 - cos Те77] Вывод из Уравнения 10.18. Другие значения выводятся подобным образом. 1(2 cos ^тт + 2 sin -777 = cos ^-тг + sin ^тт 2\ 16 16 / 16 16 3 5 = COS — 77 + COS — 77 Уравнение 7.11 = 2 COS 1(:гг7Т + -Лтт) COS 4('^7T - Атт) Уравнение 7.20 z \ ю io / z\io lb/ * = 2 cos f cos(-^) = 2 cos J cos = 2f cos £ = 2 cos -77т Подставляя Уравнения 10.18 в Уравнение 10.16, получим Уравнение 10.19. Уравнение 10.19. Ji COS ^77 ^(>/2 COS ±1T- V2 cos ^77) 75(^COS ^77+ V2C0S ^77) V2cos-^T7 VI COS ^77 ^(72 COS ^77- 72 COS ^77) (V2 COS ^77 + 72 COS ^77) 72 COS -^77 -VI COS ^77 COS ^77 + \'I COS ~7r) -^(V2 cos A77- V2 cos ^77) VI COS -^77 -^2 COS -j^TT ^(V2 COS 7J7T + 72 cos -^tt) C0S Зб77- cos Зб77) V 2 cos -far
178 Форматы и алгоритмы сжатия изображений в действии Раскладывая Уравнение 10.19 на множители, можно полу- чить Уравнение 10.20. Уравнение 10.20. 72 cos ~тг 0 0 72 COS 7J7T 0 72 cos ^тг 72 COS -^TT 0 1-11 0 11-10 S = 0 -V2cos^7T 72 COS ^7T 0 X 0-1-1 1 0 111 -у[2 COS -j^TT 0 0 72 COS -j^TT 10 0 0 0^00 0 0^0 0 0 0 1 3 Уравнение 10.20 может быть дополнительно разложено на множители, как показано в Уравнении 10.21. Уравнение 10.21. 72 COS -j^TT 0 0 72 COS -jjTT 0 72 cos -^тг 72 COS -^1T 0 1 1 -1 0 1 0 o' 0 5 = 0 -72 cos -j^Tr -72 cos -^тг 0 72 COS -j^Tr 0 0 72 COS j^TT X 0 0 0 -1 0 1 1 1 10 0 0 0 1-10 0 110 0 0 0 1 10 0 0 0^00 0 0 f2 ° 0 0 0 1 С помощью подстановки Уравнения 10.21 в Уравнение 10.15 получаем матрицу, представленную в Уравнении 10.22.
Оптимизация DCT 179 Уравнение 10.22. 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 -1 1 0 0 0 0 0 0 1 -1 0 0 0 0 0 0 0 0 72 cos -^тг 72 cos -^тг 0 0 0 0 0 0 -72 cos -j^Tr 72 cos -^тг 0 0 0 0 к 0 0 0 0 72 cos -^тг 0 0 72 COS -jjTr 0 0 0 0 0 72 cos 4б7г 72 cos fe7Г 0 0 0 0 0 0 —72 cos ^тг 72 cos -jjTr 0 0 0 0 0 -72 COS -^rir 0 0 72 COS ^7T 1 0 0 0 0 0 0 0 0 10 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 1 0 0000 1-100 0 0 0 0 1 1 0 0 0 0 0 0 0 0 -1 1 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 -1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 T20 0 0 0 0 0 0 0 i0 .0 0 0 0 0 0 0 1 1 0 0 1 0 0 0 0 0 1 1 0 0 0 0 0 0 1 -1 0 0 0 0 0 1 0 0 -1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 0 1 0 0 0 0 1 0 0 0 1 0 0 1 0 0 0 0 0 1 1 0 0 0 ООО 1-1000 0 0 1 0 0 -1 0 0 0 1 0 0 0 0 -1 0 1 0 0 0 0 0 0 -1
180 Форматы и алгоритмы сжатия изображений в действии Уравнение 10.22 на первый взгляд более сложно, чем исход- ное уравнение 10.2, но на самом деле для его расчета требу- ется гораздо меньшее число операций. Умножение вектор- строки на матрицу М состоит из 64 операций умножения и 56 операций сложения. В матрицах, полученных разложени- ем исходной матрицы на множители, число операций умно- жения равно количеству ненулевых элементов не равных +/-1, а число операций сложения, приходящихся на каждый столбец, на единицу меньше количества ненулевых элемен- тов в столбце. Нулевое значение в множителе означает отсут- ствие операции, а в полученной нами матрице почти все мат- ричные элементы равны нулю. В Таблице 10.1 приведено число операций, которые необходимо выполнить при умно- жении на каждую из матриц, полученных при разложении исходной матрицы на множители. Таблииа 10.1. Число операций, необходимых для Матрица Число операций сложения Число операций умножения 1 0 0 перемножения матриц, получен- ных в результате 2 8 12 разложения 3 4 0 на множители исхолной 4 2 0 матрицы 5 0 2 6 4 0 7 8 0 Всего 26 14 В большинстве процессоров операция умножения выполняет- ся дольше, чем операция сложения. Например, в моей системе преимущество в скорости характеризуется соотношением 4:1 в пользу сложения. Поэтому, в общем случае, операции умно- жения выгодно заменять операциями сложения. В разложен- ной на множители матрице большинство операций умножения группируются в формулы Уравнения 10.23. Уравнение 10.23. X = A cos a + В sin a Y = A sin a - В cos a
Оптимизация DCT 181 Эти формулы хорошо известны в компьютерной графике, по- скольку применяются при вычислении поворота точки (А, В) на определенный угол. Для описания вращения используются четыре операции умножения и две операции сложения, но если выполнять расчет согласно Уравнению 10.24, потребу- ется три операции умножения и пять операций сложения. Ес- ли применить данный метод для умножения матриц, общее число операций, выполняемых при умножении строки на матрицу DCT, составит 11 операций умножения и 29 опера- ций сложения. Уравнение 10.24. Т = cos a(A + В) X =Т - (cos a - sin a)B У = -T + (cos a + sin O') A Ниже представлен программный код функции ГОСТ, выпол- няющей разложение матрицы на множители согласно урав- нению 10.22. На приводимом примере можно ознакомится с тем, как реализуется в программном коде перемножение мат- риц, полученных в результате разложения на множители ис- ходной матрицы. typeclef double MATRIX [8] [8] ; const double Cl = (sqrt (2.0) * cos (M_Pl/16.0)) ; const double C2 = (sqrt (2.0) * cos (2.O*M_PI/16.0)) ; const double C3 = (sqrt (2.0) * cos (3.O*M_PI/16.0)) ; const double SI = (sqrt (2.0) * sin (M_Pl/16.0)) ; const double S2 = (sqrt (2.0) * sin (2.0*M_Pl/16.0)) ; const double S3 = (sqrt (2.0) * sin (3.0*M_Pl/16.0)) ; const double SQRT2 = (1.0 / sqrt(2.0)) ; unsigned int Limit (double input) { double value = input + 128.5 ; if (value < 0) return 0 ; else if (value > 255) return 255 ; else return (unsigned int) value ; } void ZnverseDCT (MATRIX input, MATRIX output) < double tmp[Samplewidth][Samplewidth] ; for (int row = 0 ; row < 8 ; ++ row) < double aO - input[row][0] ; double al = input[row][4] ; double a2 = input[row][2] ; double a3 = input[row][6] ;
182 Форматы и алгоритмы сжатия изображений в действии double а4 = double а5 = double аб = double а7 = input [row] [1] input [row] [5] input[row][3] input[row][7] double bO = double Ы = (aO + (aO - al) ; al) ; // b2 = S2 * 2 - C2 * a3 ; // ЬЗ = C2 * a2 + S2 * аЗ ; double rO = S2 * (a2 + a3) double b2 = rO - (S2+C2) * double ЬЗ = rO - (S2-C2) * a3 ; a2 ; // b4 = SI * a4 - Cl * a7 ; // b7 = Cl * a4 + SI * a7 ; double rl = SI * (a4+a7) ; double b4 = rl - (Sl+Cl) * double b7 = rl - (Sl-Cl) * // Ь5 = C3 * a5 - S3 * аб ; // Ьб = S3 * a5 + C3 * аб ; double r2 = C3 * (a5 + аб) double b5 = r2 - (C3+S3) * double Ьб = r2 - (C3-S3) * a7 ; a4 ; аб ; a5 ; double cO = bO ; double cl = Ы ; double c2 = b2 ; double сЗ = b3 ; double c4 = Ь4 + b5 ; double c5 = Ь5 - b4 ; double сб = Ь7 - Ьб ; double c7 = Ь7 + Ьб ; double dO double dl double d2 double d3 double d4 double d5 double d6 double d7 = cO ; = cl ; = c2 ; = c3 ; = c4 ; = сб + c5 = сб - c5 = c7 ; double eO a dO ; double el s dl ; double e2 = d2 ; double e3 «S3 ; double e4 s d4 ; double e5 = SQRT2 * d5 double еб 8 SQRT2 * d6 double e7 S <37 ;
Оптимизация DCT 183 double fO a e0 + e3 t double fl = el + e2 ! double f2 a el — e2 Г double f3 a eO — e3 t double f4 s e4 / double f5 a e5 / double f6 a еб f double f7 a e7 / tmp [row][0] = (fO + f7) tmp [row] [1] = (fl + f6) tmp [row] [2] = (f2 + f5) tmp [row][3] = (f3 + f4) tmp [row][4] = (f3 - f4) tznp [row][5] = (f2 - f5) tmp [row][6] = (fl - f6) tmp [row][7] = (fO - f7) for (int col = 0 ; col < 8 ; ++ col) ( double aO = tznp [0] [col] ; double al = tznp [4] [col] ; double a2 = tmp [2][col] ; double a3 = tznp [6] [col] ; double a4 = tznp [1] [col] ; double a5 = tznp [5] [col] ; double аб = tznp [3] [col] ; double a 7 = tznp [7] [col] ; double bO = (aO + al) ; double Ы = (aO - al) ; И Ь2 = S2 * a2 - C2 * a3 ; // ЬЗ = C2 * a2 + S2 * аЗ ; double rO = S2 * (a2 + a3) ; double b2 = rO - (S2+C2) * a3 ; double ЬЗ = rO - (S2-C2) * a2 ; И Ь4 = SI * a4 - Cl * a7 ; II b7 = Cl * a4 + SI * a7 ; double rl = SI * (a4+a7) ; double b4 = rl - (Sl+Cl) * a7 ; double b7 = rl - (Sl-Cl) * a4 ; // Ь5 = C3 * a5 - S3 * аб ; И Ьб = S3 * a5 + СЗ * аб ; double r2 = СЗ * (а5 + аб) ; double Ь5 = r2 - (C3+S3) * аб ; double Ьб = r2 - (C3-S3) * а5 ;
184 Форматы и алгоритмы сжатия изображений в действи double cO = bO t double cl = Ы f double c2 = b2 ! double c3 = b3 double C4 = b4 + b5 ; double c5 = b5 - b4 ; double c6 = b7 - b6 ; double c7 = b7 + Ьб ; double dO = cO r double dl = cl f double d2 = c2 } double d3 = c3 f double d4 = c4 double d5 = сб + c5 ; double d6 = сб - c5 ; double d7 = c7 f double eO = dO + (128*8) ; double el = dl + (128*8) ; double e2 = d2 ; double e3 = d3 ; double e4 = d4 ; double e5 = SQRT2 * d5 ; double еб = SQRT2 * d6 ; double e7 = d7 ) double fO = еО + еЗ ; double fl = el + е2 ; double f2 = el - e2 ; double f3 = eO - e3 ; double f4 = e4 ; double £5 = e5 ; double f6 = еб ; double f7 = e7 ; double gO = £0 + f7 r double gi = fl + £6 double S2 = £2 + f5 double S3 = £3 + £4 ! double g4 £3 — £4 в double g5 s £2 — £5 в double g6 = fl — £6 Г double g7 = fO - f7 в
Оптимизация DCT 185 output [0][col] = Limit (g0/8.0) output [1][col] = Limit (gl/8.0) output [2][col] = Limit (g2/8.0) output [3][col] = Limit (g3/8.0) output [4][col] = Limit (g4/8.0) output [5][col] = Limit (g5/8.0) output [6][col] = Limit (g6/8.0) output [7][col] = Limit (g7/8.0) Арифметика масштабированных целых чисел В большинстве процессоров арифметические операции с плавающей запятой выполняются медленнее, чем целочис- ленные операции. Поэтому еще одним методом ускорения вычислений при преобразованиях ГОСТ и DCT является ис- пользование только целочисленных операций. Для представ- ления вещественных чисел применяются масштабированные целочисленные значения, полученные умножением вещест- венных чисел на степень числа 2. Если промасштабировать все значения с коэффициентом 2, тогда с помощью целых чисел можно было бы представить значения ... -2, -1.5, 1, -0.5, 0, 0.5, 1, 1.5, 2 ... При масшта- бировании с коэффициентом 4, можно представить в виде целых чисел значения ...-1.25, -1, -0.75, -0.5, -0.25, 0, 0.25, 0.5, 0.75, 1, 1.25. Чем больше коэффициент масштабирования чисел, тем больше точность вычислений. К сожалению, если масштабировать числа с помощью слишком большого мно- жителя, возникает ошибка переполнения разрядов и полу- ченный результат будет неправильным. Приведенный ниже программный код иллюстрирует исполь- зование масштабированных целых чисел. В этом примере це- лые значения масштабируются с коэффициентом 25 путем операции левого сдвига разрядов. Для обратного преобразо- вания масштабированного целого в обычное целое число применялся бы правый сдвиг числа в соответствии с величи- ной коэффициента масштабирования. С целью сохранения дробной части здесь для преобразования значений в числа с плавающей запятой используется операция деления.
186 Форматы и алгоритмы сжатия изображений в действии const int scale = 5 ; long vl = 2 << scale ; long v2 = 3 << scale ; // Сложение (Addition) long v3 = vl + v2 ; // Умножение (Multiplication) long v4 = (vl * v2) >> scale ; // Деление (Division) long v5 = (vl « scale) / v2 ; cout << (double) v3 / (1 << scale) cout << (double) v4 / (1 << scale) cout << (double) v5 / (1 << scale) << endl ; << endl ; << endl ; Проблема, связанная с использованием масштабированных целых чисел вместо чисел с плавающей запятой, заключается в том, что если система не работает с 64 разрядными целыми числами, точность вычислений, обеспечиваемая числами с плавающей запятой, всегда будет выше точности вычислений с целыми числами. В общем случае, разница между двумя методами вычислений невелика, но она существует и может приводить к большим ошибкам округления. При разработке программы, работающей с изображениями JPEG, возможно, вы пожелаете использовать числа с пла- вающей запятой в процедуре сжатия изображения, и масштабированные целые числа в процессе развертывания сжатого изображения. Как правило, скорость играет боль- шую роль при просмотре изображения, а не при сжатии. Это позволило бы обеспечить более высокую точность при фор- мировании файла изображения и достичь большей скорости его просмотра. Объединение квантования и преобразования DCT При подсчете операций, приведенных в Таблице 10.1, не учи- 1 £ тывалось наличие множителя — , вынесенного за скобки 8 уравнения расчета IDCT. Как видно из Уравнения 10.3, с множителем связаны еще 64 дополнительные операции ум- ножения, выполняемые в конце расчетов. Если ГОСТ реали- зуется с помощью масштабированных целых чисел, то деле- ние на 8 может быть выполнено как побитовый сдвиг, кото- рый может быть объединен с процедурой обратного масшта- бирования окончательного результата. К сожалению, опи- санный метод не применим для чисел с плавающей запятой.
Оптимизация DCT 187 Другой способ исключения множителя - состоит в объеди- 8 нении этого коэффициента со значениями квантования. В действительности, если разложить матрицу DCT на мно- жители немного по-другому, можно исключить более 64 опе- раций, связанных с вышеуказанным множителем. Для данно- го разложения матрицы DCT мы выполним те же самые ша- ги, которые выполнялись в предыдущем разложении вплоть до получения Уравнения 10.15. Далее алгоритм реализуется по другой ветви. Формула, которая будет играть ключевую роль в разложении на множители, является произведением функций косинуса, представленным в Уравнении 10.25. Уравнение 10.25. Уравнение 10.26. cos a cos /3 = — (cos (a + /3) + cos (a - /3)) В матрице, полученной разложением на множители в Урав- нении 10.15, выражения с косинусом в каждой строке или столбце могут объединяться в пары 1 7 V 2 6 Y3 5 --7Г,--7Г L --7Г,--7Г --Л,---Л 16 16 Г 16 16 16 16 у которых сумма аргументов косинусов равна —, а значение функции косинуса от этого аргумента равно нулю. Если извлечь эту подматрицу из Уравнения 10.15 (Уравне- ние 10.26) и воспользоваться формулой для суммы косину- сов из Уравнения 10.25, то подматрица может быть разло- жена на множители в соответствии с Уравнением 10.27. эбооопз моннве « • Г 6 Г- 2 V2 cos—л V 2 cos—л 16 16 гт 2 гт 6 - V2 cos —л V2 cos —л 16 16
188 Форматы и алгоритмы сжатия изображений в действии Уравнение 10.27. 72 COS "^17 72 cos -^17 -72 cos Л-тт 72 cos Л-77 72 cos^TT о 72 cos £-тт 2 COS Т2ТГ COS Т7ТГ 2 cos far cos 1777 Io 16 10 JO -2 cos far cos 2 cos ^77 cos 7^77 72 cos far 0 0 72 COS ЛтГ COS far COS far + cos (0) - COS -j^-TT - COS 77-77 + cos (0) 72 2 COS -^7T 0 0 72 COS far COS -^77 COS ^77 + 1 -COS -—77 -COS 7777+1 Хитрость в данном способе разложения на множители состо- ит в выборе коэффициентов масштабирования для строк, со- держащих выражения с косинусами так, чтобы матричные элементы cos(O) располагались в одном столбце. При создании еще одной подматрицы для оставшихся выра- жений с косинусами в Уравнении 10.15 можно воспользо- ваться похожей процедурой разложения на множители (Уравнение 10.28).
Оптимизация DCT 189 Уравнение 10.28. V'2 COS 7^77 72 COS 77:77 72 COS ^77 72 COS 7^77 72 COS -^77 72 COS 7^77 -72 COS 7^77 72 COS ^77 -72 COS -^77 -72 COS 7^77 -72 COS 7^77 72 COS -^77 —72 COS 7^77 \/2 COS -^77 -72 COS -^77 72 COS 7^77 72 0 72 0 0 2 COS 7^77 0 2 COS -^77 0 0 72 0 2 COS -^77 0 0 0 72 2 COS -jg-77 2 cos ±тт cos -—it 2 COS -j^TTCOS ^тт -2 COS 7^'77 cos -~7Г —2 COS Т77Г COS 7777 2 COS -^-77 COS -—77 2 COS 77:77 COS ^77 -2 COS 77:77 COS 7^77 2 COS 7^77 COS 7^77 2 COS 7^77 COS -^77 -2 COS 77:77 COS 7^77 -2 COS ^77 COS 7^77 -2 COS -^77 COS 77:77 -> I I 2 COS 7^77 COS 7^77 2 COS 77:77 COS -^77 2 COS 77:77 COS 77:77 2 COS 77777 COS 77777 Таблица 10.2. Матрица Число операций Число операций Количество операций, сложения умножения 1 0 6 выполняемых при перемножении матриц, 2 0 0 получаемых 3 6 0 в новом способе Л 9 9 разложения на множители 5 2 0 исхолной матрицы 6 2 3 7 1 0 8 4 0 9 4 0 10 8 0 Итого 29 11
190 Форматы и алгоритмы сжатия изображений в действии Повторим, что коэффициент масштабирования для выраже- ний с косинусом выбирается так, чтобы все матричные эле- менты cos(O) располагались в одном столбце. Уравне- ние 10.29 описывает оставшуюся часть процедуры разложе- ния на множители. Уравнение 10.29. 2 COS ^77 COS -j^77 2 COS COS ^77 2 COS ^77 COS -^77 2 COS ^77 COS ]^77 ~ 5 3 2 COS -j^77 COS -^77 2 COS ~TT COS ^77 -2 COS -^77 COS ^77 2 COS -^ir COS ^77 -2 COS -^77 COS -^77 -2 COS -^77 COS ^77 -2 COS -^77 COS -j^77 2 COS 7^77 COS -^77 —2 COS -j^77 COS ^77 2 COS -j^TT COS yj77 -2 COS -j^77 COS ^77 2 COS -j^77 COS ^77 COS ~7ТГ COS -Г7ТТ + COS Лт7 lo lo 16 COS Лт7 COS Л-П--COS 7777 lo lo io —COS —COS Л77—COS Лт7 lo lo lo -COS -j^-77 -COS -jj77 + COS —77 COS -^77 + COS -^77 COS ^77 6 4 6 -COS 7777 — COS 7777 -COS Т71Г io lo IO COS JJ77 - COS ^77 COS ^77 -COS 7777+ COS T7TT -COS T777 lo lo Io COS -^77 COS ^77 COS -^77 COS -^77 10 0 1' 0 -COS 4t7 -COS 7777 1 0 110 X 10 16 0 1-10 2 2 6 6 . -10 0 1 COS -^77 COS -^77 -COS -^77 -COS TgTT 0 COS -^77 COS ~7T 1 COS T7TT COS 7777 COS Л77 COS Л77 16 16 16 lo 10 0 1 1 0 0 0' A 0 110 x 0-101 X 0 COS T£77 COS -^77 0 0 1-10 0 0 10 A -10 0 1 .° 1 0 1 COS 7777 COS 7777 -COS 7?77 -COS 77 16 16 16 16 77 0 0 0 1 COS ^77 0 COS -^77 0 1 0 0 1 10 0 0 л 4 1 1 0 0 — 0 110 X 0-101 X 0 COS y£77 0 0 X 0 1 1 0 0 1-10 0 0 10 9 6 ~ 0 0 1 1 -10 0 1 0 10 1 COS -^77 U -COS ^77 U 0 0 0 1 0 0 0 1
Оптимизация DCT 191 Уравнение 10.30. Процедуру разложения на множители можно повторить для матриц, содержащих выражения с функциями косинуса, по- лучив в результате Уравнения 10.30. cos far 0 cos far 0 0 cos т^тг 0 О1 COS far 0 -COS у£77 0 0 0 0 1 1 0 0 0 2 COS ^77 0 1 0 0 0 0 1 0 а 6 2 COS -£7Т 0 0 0 1 2 cos ^77 cos fa о 2 cos far cos far 0 0 2 cos far cos far 0 COS ^77 0 0 0 -2 COS -^77 COS -^77 0 0 0 1 2 cos far COS 7777 0 2 cos far COS -^77 0 16 16 16 16 0 COS -j^77 0 0 2 COS 7777 COS farr 0 -2 COS far COS 7777 0 16 16 16 16 0 0 0 1 COS -^77 + COS -^77 0 COS -^77 + COS (0) 0 0 COS -^77 0 0 COS -j“77 + COS -^77 0 COS -^77 - COS (0) 0 0 0 0 1 COS fa 0 COS -^77 + 1 0 0 COS ^77 0 0 COS ^77 0 COS 3777- 1 0 0 0 0 1 1 0 1 0 0 0 COS ^77 0 0 X 0 1 0 0 0 1 10 10 0 10 0 0 0 10 0 0 0 1 Суммируя проделанное, подставим Уравнение 10.27, Урав- нение 10.28 и Уравнение 10.30 в Уравнение 10.15 и получим Уравнение 10.31.
192 Форматы и алгоритмы сжатия изображений в действии Уравнение 10.31. 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 2 cos -jjTr [10000000] 0 0 0 -— ^-r— 0 0 0 0 0 0 0 0 1 0 0 0 2 COS ^77 0 0 1 0 0 0 0 0 м _ 00000010 х 0 0 0 0 —0 0 0 01000000 2 cos 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 о о -- , - 0 0 0 0 0 0 0 0 0 1 2 COS ^77 0 0 0 0 0 0 5^3— 0 2 cos far 0 0 0 0 0 0 0 — 2 COS ^77 — 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 ’10000000' 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 Ц— 0 0 0 х 00000010 х 0 0 -1 1 0 0 0 0 2 cos -jjir 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 1 1 0 0 0 0 0 0 -1 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 1 -I 0 0000 0 0 Ц— 0 [00000001] [о 0 0 0 -1 0 0 1 2 cos 0000 0 1 0 1_ Г i i о о о 0 0 0 Г 1 0 0 0 0 0 0 01 1-1 0 0 0 0 00 [10000000] 0 1 0 0 0 0 0 0 0 0 cos far 0 0 0 00 01000000 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 00010000 0 0 0 1 0 0 00 00010000 0 0 0 0 1 0 1 0 х 0 0 0 0 cos - fa о 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 1 0 0 6 0 0 0 0 0 1 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 cos —тг 00 00000010 0 0 0 0 0 0 0 1 00000001 0 0 0 0 0 0 1 0 .00 0 0 0 0 0 1_ 1 0 0 0 0 0 0 О’ Г 1 0 0 1 0 0 0 0 [10000001] 0 1 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 1 1 0 0 0 0 0 1 -1 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 1 0 0 0 0 1 0 0 -1 0 0 0 0 0 0 0 1 1 0 0 0 * 00001100 х 0 0 0 0 1 0 0 0 0 0 0 1 -1 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 0 0 0 0 1 0 0 -1 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 0 0 1 0 0 0 0 -1 0 0 0 0 0 0 0 0 1 [00000001 [ 1 0 0 0 0 0 0 -1
Оптимизация DCT 193 Уравнение 10.32. 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 ^5— 0 0 0 0 0 2 cos -[jir '10 0 0 0 0 0 0] 0 0 0 0 0 0 0 0 0 0 0 10 0 0 2 cos 1(;7Г 0 0 10 0 0 0 0 (Ч 0 0 0 0 0 0 10 0 0 0 0 „ , 0 0 0 0 10 0 0 0 0 0 2 COS ^77 0 0 0 0 0 10 0 0 0 0 1 0 0 0 0 0 0 0 0 0 i-j— 0 0 [о 0 0 0 0 0 0 1 ] 2 cos 7^77 0 0 0 0 0 0 „ v23 0 2 COS ^77 /2 0 0 0 0 0 0 0 — 2 COS -^77 1 0 0 0 0 0 0 72 2 cos -j^tt 0 0 0 0 0 0 72 0 0 0 2 cos -far 0 0 0 0 0 0 72 0 1 0 0 X 2 COS -j^77 0 0 0 0 0 0 72 2 cos 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ' 1 0 0 0 0 0 0 o' 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 00000010 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 о о 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 T26 2 COS -^77 0 0 T2? 2 cos 7^77 Поскольку Уравнение 10.32 истинно, умножение матриц мо- жет быть переупорядочено так, чтобы при вычислении ГОСТ масштабирование выполнялось на первом шаге, а при вычис- лении FDCT (прямое преобразование DCT) - на последнем шаге. Подстановка Уравнения 10.32 в Уравнение 10.31 дает Урав- нение 10.33. Число операций, выполняемых при перемножении матриц, полученных в результате разложения на множители в Урав- нении 10.33, приводится в Таблице 10.2 (выше в этой главе).
194 Форматы и алгоритмы сжатия изображений в действии Уравнение 10.33. 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 cos far 0 0 V2 0 0 0 0 0 2 COS -^77 м = 0 0 0 0 0 0 у2 2 cos 7^77 0 0 1 0 0 0 0 0 0 0 0 0 0 0 д 0 0 2 cos -^тг 0 0 0 0 0 0 д 0 2 cos -^тг 0 0 0 0 0 0 0 Д 2 cos far 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 ' 1 0 о 0 0 о 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 1 о 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 ' 0 о 1 0 0 0 1 о 0 0 1 0 0 1 0 0 0 0 0 о 0 0 0 0 0 о 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 -1 0 0 0 0 0 1 0 0 0 1 0 X 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 X 0 0 0 0 0 0 0 0 -1 0 0 0 1 0 0 0 0 1 0 0 0 0 1 1 0 0 1 -1 0 1 0 0 X 2cos^ 0 7Г 0 0 0 0 0 0 0 1 0 0 0 0 -1 0 0 1 2 cos 6 16 7Г _0 0 0 0 0 1 0 1_ • 1 1 0 0 0 0 0 0 X 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 -1 0 0 0 0 0 0 0 0 -1. X 1 0 0 0 0 0 -1 0 0 0 0 0 0 COS ^77 0 0 0 0 0 0 1 0 0 0 0 0 0 COS 0 0 0 0 0 fa 0 cos 0 б”- 0 0 0 0 0 1 0 0 0 0 0 0 X 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 1 0 o' 0 0 0 0 0 0 1 _ 0 0 0 0 0 0 0 1_ X 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 1 1 0 o’ 0 0 0 0 0 1 1 X 1 0 0 1 0 0 0 0 0 1 1 0 0 0 0 0 0 1 -1 0 0 0 0 0 1 0 0 -1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 X ' 1 0 0 0 0 0 0 1 0 1 0 0 0 0 1 0 0 0 1 0 0 1 0 0 0 c 0 c 0 c 1 1 - 0 c 0 c 0 c 0 0 1 0 1 0 -1 0 0 0 1 0 0 0 0 -1 0 1' 0 0 0 0 0 0 -1 Дополнительное достоинство описанного метода разложения на множители состоит в том, что он позволяет исключить шесть операций умножения в первой матрице путем их объединения с
Оптимизация DCT 195 квантованием или процедурой, обратной квантованию. Умно- жение матриц обладает свойством ассоциативности, а умноже- ние матриц на скалярную величину коммутативно. Поэтому, если матрица М разложена на множители так, как показано в Уравнении 9.31, матричные операции в вычислениях ГОСТ (Уравнение 10.34) могут быть упорядочены так, чтобы эти три операции выполнялись в первую очередь (Уравнение 10.35). Уравнение 10.34. xMrTM IDCT Т = ~MVMT fdct Уравнение 10.35. 1 0 0 0 0 0 0 0 0 0 72 0 0 ?/'V 0 0 0 0 4 ZW3. чп 0 0 0 0 0 2 cos yjir 0 2 COS ^77 ? X 0 0 0 0 0 0 72 2 COS ^77 0 0 I 0 0 0 0 0 0 x T 0 0 0 0 0 72 0 0 2 COS -^77 0 0 0 0 0 0 72 0 A 6 2 cos -jgTT о о 0 0 ins 0 A '(’/И'' 0 0 2 COS ^77 1 0 0 72 0 0 0 0 0 0 0 0 0 0 0 0 2 cos 7777 0 0 72 0 0 0 0 0 2 cos for X 0 0 0 0 0 0 72 2 cos -~тг 0 0 I 0 0 0 0 0 0 0 0 0 0 0 72 ~ 5 2 COS -jg-TT 0 0 0 0 0 0 0 0 72 0 2 COS 4^77 о о 0 0 0 0 0 72 2 COS 7777
196 Форматы и алгоритмы сжатия изображений в действии Действие данного выражения сводится к умножению каждо- го элемента в матрице V на постоянную величину Sy , где Уравнение 10.36. SiJ J о F(0) = l F(n) =----—-----, /г = 1, 2, 3,4,5,6,7 ~ n 2 COS----71 16 При декодировании JPEG-файлов преобразованию IDCT не- посредственно предшествует процесс, обратный квантова- нию, во время которого каждый элемент матрицы Т умножа- ется на постоянную величину. Если объединить процедуру вычисления ГОСТ и процедуру, обратную квантованию, вы- полняемую путем умножения каждого значения квантования на величину Sy , тогда соответствующие операции в уравне- нии 10.35 могут быть исключены. При вычислении преобра- зования FDCT операции в уравнении 10.33 выполняются на последнем шаге, перед квантованием. Если каждый элемент в таблице квантования, используемый для кодирования, делит- ся на Sy , то эти операции также моглт быть исключены из прямого преобразования DCT. Таким образом, остается 29 операций сложения и 5 операций умножения на каждую единицу данных. Заключение В этой главе показано, как с помощью разложения матриц на множители можно значительно уменьшить число операций, выполняемых для реализации преобразований DCT и ГОСТ. Производительность работы программы является следствием эффективного проектирования в целом, отнюдь не только ре- зультатом усилий по созданию программного кода. Прежде чем загромождать исходный текст кода, пытаясь повысить эффективность работы программы, проведите необходимые измерения производительности, чтобы удостовериться в том, что достигаемый выигрыш в скорости оправдывает усложне- ние программного кода.
Оптимизация DCT 197 Примеры программного кода, использованного в этой главе, являются новой реализацией классов JpegEncoderDataUnit, JpegDecoderDataUnit, JpegEncoderQuantizationTable и JpegDecoderQuantizationTable, первоначально представленных в главе 7. Новые классы объединяют вычисления DCT и IDCT с квантованием, используя процедуру, описанную в этой главе. Эти новые классы структурированы так, что они могут заме- нить предыдущие версии в классах JpegDecoder (глава 8) и JpegEncoder (глава 9) путем внесения незначительных изме- нений. Класс JpegDecoder не требует модификации для ис- пользования новых классов. В классе JpegEncoder требуется добавить в функцию-член BuildScaledTables вызов класса таб- лицы квантования до выполнения преобразования DCT.
ГЛАВА 11. Прогрессивные изображения JPEG В этой главе рассматриваются вопросы кодирования и деко- дирования прогрессивных изображений JPEG, которые, хотя и используются достаточно редко, постепенно обретают ши- рокую популярность. Одной из движущих сил, способст- вующих распространению прогрессивных изображений JPEG, является Всемирная паутина (World Wide Web) - иде- альная среда для распространения прогрессивных изображе- ний JPEG. Использование прогрессивных изображений на Web-страницах позволяет посетителям Web-сайтов вначале ознакомиться с содержанием Web-странички до того, как полностью завершится загрузка изображений. Другой скры- той движущей силой распространения прогрессивных изо- бражений JPEG служит расширение доступных программных средств и библиотек (особо отметим библиотеку UG), под- держивающих работу с этими изображениями. Разбиение компонентов в прогрессивном JPEG Последовательный файл JPEG может содержать единствен- ный скан (scan), или данные могут быть организованы в виде множества сканов, каждый из которых содержит один или несколько компонентов. В последовательном изображении JPEG каждый компонент полностью кодируется внутри од- ного скана. В прогрессивном изображении JPEG кодирован- ные компоненты занимают несколько сканов. Каждый ком- понент содержится, как минимум, в двух сканах, и может со- держаться максимум в 896 сканах1. Компоненты разделяются и распределяются между скана- ми двумя различными способами. Первый способ известен под названием спектральное выделение (spectral selection). Спектральное выделение обозначает деление компонента на диапазоны (band) коэффициентов DCT. Каждый диапа- зон представляет собой непрерывный ряд коэффициентов DCT, расположенных в зигзагообразном порядке. Помимо того, что диапазон должен включать непрерывный ряд ко- эффициентов, единственное ограничение, накладываемое на коэффициенты диапазона, требует, чтобы все коэффи- 1 На практике число сканов никогда не приближается к верхней границе.
200 Форматы и алгоритмы сжатия изображений в действии Рис. 11.1. Пример единицы данных, разделенной на диапазоны спектрального выделения циенты DC были в одном диапазоне. Компонент должен быть разделен, как минимум, на два скана: один, содержа- щий коэффициенты DC, и другой, содержащий коэффици- енты АС. В предельном варианте, компонент может быть разделен на 64 диапазона с одним коэффициентом в каж- дом диапазоне. 'п: Первый скан компонента должен содержать коэффициенты DC. Диапазоны, содержащие коэффициенты АС, могут ко- дироваться в любом порядке. Прогрессивные сканы, содер- жащие коэффициенты DC, могут быть перемежающимися (interleaved), в то время как сканы, содержащие коэффици- енты АС, должны быть построчными. На Рис. 11.1 пред- ставлен пример единицы данных, разделенной на четыре диапазона. Другой способ разделения компонентов в прогрессивном скане называется последовательным приближением (succes- sive approximation), которое используется вместе со спек- тральным выделением для разбиения отдельных диапазонов (band) на множество сканов. В отличие от спектрального вы- деления, использование метода последовательного прибли- жения в прогрессивных сканах совершенно необязательно. При его использовании точность первоначального диапазона
Прогрессивные изображения JPEG 201 уменьшается на несколько разрядов (битов). Последующие сканы для диапазона каждый раз увеличивают точность на один разряд. Функция преобразования, используемая при последователь- ном приближении, называется в стандарте JPEG точечным преобразованием (point transform). Для коэффициентов DC точечное преобразование является просто правым сдвигом на число битов, указываемое с помощью величины последова- тельного приближения. Для коэффициентов АС точечное преобразование описывается следующей формулой Входное _ значение Результат = —-—-------------------- ' ^Последовательное _ приближение На первый взгляд может показаться, что точечные преобра- зования АС и DC одинаковы, но в данном случае это не так. В Таблице 11.1 представлены точечные преобразования АС и DC с величиной последовательного приближения, равной 1. Заметьте, что значения точечных преобразований АС и DC могут отличаться для отрицательных значений, и для точечного преобразования АС справедливо равенство: F(X) = —F(—X). Таблииа 11.1. Значения DC и АС с величиной послелова тельного Входное значение DC АС 5 2 2 приближения 4 2 2 равной 1 3 1 1 2 1 1 1 0 0 0 0 0 -1 -1 0 -2 -1 -1 -3 -2 -1 -4 -2 -2 -5 -3 -2
202 Форматы и алгоритмы сжатия изображений в действии Рис. 11.2. Пример деления скана с помошью методов спектрального выделения и последова тельного приближения На Рис. 11.2 представлен пример компонента, разделенно- го на 12 сканов с использованием комбинации методов спектрального выделения и последовательного приближе- ния. Разделение с помощью спектрального выделения сов- падает с делением, представленным на Рис. 11.1. Первый скан в этом примере содержит коэффициент DC с величи- ной последовательного приближения равной 3. Остальные три диапазона спектрального выделения могут выводиться в любом порядке. Однако внутри каждого диапазона ска- ны, которые уточняют коэффициенты с помощью последо- вательного приближения, должны располагаться в строгом порядке. Обработка прогрессивных файлов JPEG Полная обработка прогрессивных файлов JPEG может быть реализована способом, широко применяемым для обработки последовательных файлов JPEG. Основное отличие состоит в обработке сканов. На Рис. 11.3 проиллюстрировано различие между обработкой последовательных и прогрессивных фай- лов JPEG. Достаточно очевидно, что отображение прогрессивных фай- лов JPEG «на лету» требует значительно большей обработки, чем отображение последовательных файлов или даже ото- бражение прогрессивных файлов, когда они полностью деко- дированы. По этой причине отображение прогрессивных файлов JPEG «на лету» оправдано, только если данные при- нимаются через сеть, скорость передачи которой мала по сравнению со скоростью работы процессора.
Прогрессивные изображения JPEG 203 Рис. 11.3. Обработка послеловательных и прогрессивных файлов JPEG Последовательный процесс While MORESCANS Do Begin ReadScanData End PerformIDCT ColorConvert Displayimage Прогрессивный процесс While MORESCANS Do Begin ReadScanData PerformIDCT ColorConvert Displayimage End Как показано на Рис. 11.3, прогрессивные изображения JPEG обновляются после каждого сканирования, но это не носит обязательного характера. Декодер может быть реализован так, что он будет обновлять и отображать изображение толь- ко после того, как определит, что получено достаточно новых данных для обновления. Используемый при отображении изображения «на лету» процесс обновления совпадает с про- цессом обновления последовательных файлов. Если прогрес- сивное изображение не отображается «на лету», полный про- цесс декодирования, в основном, совпадает с процессом де- кодирования последовательных файлов и мало отличается по объему выполняемой обработки. Обработка прогрессивных сканов Первый шаг декодирования прогрессивного скана состоит в определении типа скана. Всего существует четыре типа про- грессивных сканов, каждый из которых обрабатывается от- личным от других способом. DC АС Первый скан для диапазона 1. Первый скан DC 3. Первый скан АС Обновляющий скан для диапазона 2. Обновляющий 4. Обновляющий скан DC скан АС Вся информация, необходимая для определения типа скана, хранится в маркере SOS2, где поля начала и конца спектраль- ного выделения определяют коэффициенты, попадающие в ’ См. Главу 5.
204 Форматы и алгоритмы сжатия изображений в действии диапазон. Если оба этих значения равны нулю, скан принад- лежит типу DC. Если оба значения ненулевые, то скан при- надлежит типу АС. Величина последовательного приближения хранится в двух 4- битовых полях, упакованных в 1 байт. Если 4 старших би- та равны нулю, то рассматриваемый скан будет первым ска- ном диапазона. В противном случае, когда это поле ненуле- вое, рассматриваемый скан будет обновляющим. Если оба этих битовых поля равны нулю, то последовательное при- ближение для диапазона не используется. Обработка первого скана для диапазона выполняется одинаково, независимо от того, используется последовательное приближе- ние или нет. Проверка достоверности данных полей, которые должны вы- полняться декодером, включает в себя следующее. ✓ Если начало спектрального выделения равно нулю, конец спектрального выделения должен быть равен нулю. ✓ Если конец спектрального выделения равен нулю, начало спектрального выделения должно быть равно нулю. ✓ Начало спектрального выделения не должно быть больше конца спектрального выделения. ..... 4 ✓ Если начало спектрального выделения не равно нулю, изо- бражение может содержать только один компонент. ✓ Значение конца спектрального выделения не может быть больше 63. ✓ Младшие и старшие битовые поля последовательного при- ближения не могут быть больше 13. ✓ Старшие биты последовательного приближения должны быть или равными нулю, или быть больше, чем млашие биты.
Прогрессивные изображения JPEG 205 Минимальные кодированные блоки (MCUs) в прогрессивных сканах Данные в прогрессивных сканах организованы в виде MCU точно так же, как и в последовательных сканах. Прогрессив- ные сканы DC могут быть перемежающимися (interleaved) или построчными. Сканы АС всегда построчные, поэтому в них на каждый MCU приходится одна единица данных. Для прогрессивных сканов, содержащих коэффициенты АС, чис- ло и позиция единиц данных такие же, как и для построчных последовательных сканов. Прогрессивные сканы могут включать маркеры перезапуска. Интервал перезапуска определяет число модулей MCU меж- ду маркерами перезапуска, в точности так же, как и в после- довательных сканах. Для сканов АС серии конца диапазона (end-of-band runs) не могут пересекать маркеры перезапуска. Серии конца диапазона (end-of-band run) будут подробнее описаны чуть ниже. Использование таблиц Хаффмана в прогрессивных сканах Маркер SOS определяет числовой идентификатор таблиц Хаффмана (Huffman), используемых каждым компонентом в скане. Стандарт JPEG требует, чтобы все таблицы Хаффмана, необходимые для обработки скана, определялись до маркера SOS. Проверка наличия таблиц Хаффмана, используемых сканом, которую должен выполнять декодер при обработке прогрессивных сканов, отличается от проверки, выполняемой для последовательных сканов. Для каждого компонента в последовательном скане требует- ся две таблицы Хаффмана (DC и АС). В прогрессивном JPEG скан использует или таблицу DC, или таблицу АС, но не обе вместе. В действительности, обновляющий прогрессивный скан DC вообще не использует таблицы Хаффмана. В файле JPEG вполне вероятно появление прогрессивного скана DC до определения таблиц Хаффмана АС, что совершенно недо- пустимо в последовательном скане JPEG.
206 Форматы и алгоритмы сжатия изображений в действии Декодирование единицы данных Алгоритм 11.1. Декодирование коэффиииентов DC прогрессив- ного JPEG-файла Первый скан DC Процесс декодирования первого скана для получения коэф- фициентов DC почти совпадает с процессом декодирования, который применяется для извлечения коэффициентов DC в последовательном скане (см. главу 8). Единственное отличие состоит в том, что декодированное значение коэффициента DC (сдвинутое влево на величину последовательного при- ближения) перед сохранением подвергается точечному пре- образованию. Алгоритм И.] иллюстрирует декодирование единицы данных. GLOBAL SUCCESSIVEAPPROXIMATION GLOBAL LAST_DC_VALUE Procedure FirstDCDataunit (COEFFICIENTS [0..63]) Begin BITCOUNT = DecodeUsingDCHuffmanTable () BITS = ReadLiteralBits (BITCOUNT) DCDIFFERENCE = Extent (BITS, BITCOUNT) DCVALUE = DCDIFFERENCE + LAST_DC_VALUE LAST_DC_VALUE = DCVALUE COEFFICIENTS [II] = DCVALUE LeftShift SUCCES- SIVEAPPROXIMATION End Алгоритм 11.2. Уточняющие коэффиииенты DC , £ • Обновляющие сканы DC Обновляющие сканы DC (refining DC scans) относятся к чис- лу наипростейших сканов JPEG с точки зрения их обработки. Сжатые данные скана содержат исключительно необрабо- танные биты данных, по одному биту на единицу данных. Алгоритм 11.2 показывает все вычисления, необходимые для обработки единицы данных в скане такого типа. GLOBAL SUCCESSIVEAPPROXIMATION Procedure Ref ineDCDataUnit (COEFFICIENTS [0. . 63]) Begin BIT = ReadLiteralBits (1) DCCOEFFICIENTS [0] = DCCOEFFICIENTS [0] Or (BIT LeftShift SUCCES- SIVEAPPROXIMATION) End
Прогрессивные изображения JPEG 207 Первые сканы АС Простота декодирования коэффициентов DC более чем ком- пенсируется сложностью декодирования коэффициентов АС. Кодирование первого скана диапазона коэффициентов АС подобно кодированию, применяемому в последовательном методе с некоторыми добавлениями. В прогрессивном JPEG добавляется концепция серии конца диапазона (end-of-band [ЕОВ]). Это серия единиц данных, где коэффициенты АС в пределах диапазона равны нулю. В последовательном JPEG каждая единица данных кодиру- ется независимо от остальных. Из-за серий конца диапазона (ЕОВ-серий) единицы данных в сканах АС не являются независимыми. В последовательных изображениях JPEG значение 0016 кода Хаффмана используется для установки в ноль оставшихся коэффициентов в единице данных. Это эквивалентно ЕОВ- серии длиной 1. В таблице 11.2 перечислены коды конца диапазона (ЕОВ) и связанные с ними возможные размеры ЕОВ-серий. Таблииа 11.2. Колы АС и соответствующая длина промежутков ЕОВ Значение кода Длина ЕОВ-серии 0016 1 10,6 2-3 20,6 4-7 30,6 8-15 40,6 16-31 50,6 32-63 60,6 64-127 70,6 128-255 80,6 256-511 90,6 512-1023 АО, 6 1024-2047 во, 6 2048-4095 со, 6 4096-8191 D0,6 8192-16383 Е0,6 16384-32767
208 Форматы и алгоритмы сжатия изображений в действии Необработанные биты, следующие за байтом, кодированным по методу Хаффмана, используются для определения ЕОВ- серий в точности так же, как они используются с литераль- ными значениями. Четыре старших бита указывают число дополнительных битов, используемых как часть кода ЕОВ. Поскольку длина ЕОВ-серий всегда положительна, функция Extend() не используется. Вместо этого выполняется преобра- зование необработанных битов в длину ЕОВ-серии с помо- щью формулы: EOBRUN=(1 Leftshift HIGHBITS) -t- ReadRawBits (HIGHBITS) Если в потоке сжатых данных встречается код ЕОВ, когда диапазон обработан лишь частично, текущий диапазон ста- новится первой единицей данных в ЕОВ-серии, и оставшиеся коэффициенты устанавливаются в нуль. При обработке ЕОВ- серии не забывайте учитывать в расчетах текущий диапазон коэффициентов. Алгоритм 11.3 описывает процедуру декодирования первого скана для диапазона коэффициентов АС. Метод обработки сканов в прогрессивном JPEG отличается от метода обработ- ки в последовательном JPEG следующими особенностями: ✓ Обновляются только коэффициенты внутри диапазона спек- трального выделения; ✓ Значения коэффициентов сдвигаются влево на величину по- следовательного приближения; ✓ Обрабатываются ЕОВ-серии. Обновляющие сканы АС Обновляющие сканы АС представляют собой сущий кошмар для специалистов, решающих задачи декодирования прогрес- сивного JPEG. Проблема реализации состоит в том, что эти сканы содержат данные для обновления всех предыдущих ненулевых коэффициентов, пропущенных по причине появ- ления нулевой серии или ЕОВ-серии. В обновляющем АС скане 4 младших бита значений, кодиро- ванных по методу Хаффмана могут быть равны 1 или 0. Должно быть, это оправданно, поскольку обновляющий скан только добавляет 1 бит на коэффициент. Если для обновле- ния коэффициента требуется более 1 бита, он должен быть закодирован в предыдущих сканах.
Прогрессивные изображения JPEG 209 Обработка обновляющих сканов АС почти совпадает с обра- боткой первых сканов. Всякий раз, когда для значения, коди- рованного по методу Хаффмана, величина 4 младших битов равна 1, коэффициент становится ненулевым в первый раз. За этим значением во входном потоке данных сразу следует один необработанный знаковый бит. Новое значение коэф- фициента вычисляется так: If SignBit = 1 Then Coefficientvalue = 1 Leftshift ScanSuccessiveAp- proximation Else If SignBit = 0 Then Coefficientvalue = -1 Leftshift ScanSuccessiveAp- proximation По производимому действию приведенный программный код, в сущности, совпадает с функцией Extend. Основной отличительной чертой обновляющего скана явля- ется обработка нулевых серий и ЕОВ-серий. В нулевых сери- ях у обновляющего скана подсчитываются только коэффици- енты с нулевым значением. Представленная ниже последова- тельность коэффициентов пропускалась бы серией из 4 (не 6) нулей: 004020 Каждый раз, когда из-за нулевой серии или ЕОВ-серии про- пускается ненулевой коэффициент, этот коэффициент обнов- ляется с помощью l-ro необработанного бита, включенного во входной поток данных. Предположим, что в предыдущем примере значение ’ кода Хаффмана было 4116- За этим кодом следовали бы три необ- работанных бита: первым располагался бы знаковый бит для ненулевого коэффициента, создаваемого с ненулевым значе- нием; следующий бит обновил бы коэффициент со значени- ем 4, и последний обновил бы коэффициент со значением 2. Алгоритм 11.4 служит иллюстрацией процедуры обновления предыдущего ненулевого коэффициента. После того как будет пропущено корректное число ненуле- вых коэффициентов, следующему коэффициенту присваива- ется значение, найденное в начале процедуры. Обратите внимание, что данные для коэффициента не хранятся в стро- го определенном порядке. Данные для последнего коэффици- ента располагаются в начале входного потока данных.
210 Форматы и алгоритмы сжатия изображений в действии Global EOBRUN Global SSS // Spectral Selection Start Global SSE // Spectral Selection End Global SUCCESSIVEAPPROXIMATION Global EOBRUN Procedure ACFirstDataUnit (COEFFICIENTS [0..63]) Begin For II = SSS To SSE Do COEFFICIENTS [II] = 0 If EOBRUN > 0 Then Begin EOBRUN = EOBRUN - 1 Return End II = SSS While II <= SSE Do Begin VALUE = DecodeUsingACTable LOBITS = VALUE And 0F16 HIBITS = (VALUE And F016) Rightshift 4 If LOBITS <> 0 Then Begin EXTRABITS = ReadRawBits (LOBITS) II = II + HIGHBITS COEFFICIENTS [II] = Extend (EXTRABITS, LOBITS) Leftshift SUCCESSIVEAPPROXI- MATION II = II + 1 End Else Begin If HIGHBITS = F16 Then II = II + 16 // Run of 16 Zeros Else If HIGHBITS = 0 Then II = SSE + 1 Else //We subtract one to account for ending the current block. EOBRUN = (1 Leftshift HIGHBITS) + ReadRawBits (HIGHBITS) - 1 Return End End End Алгоритм 11.3. Деколирование коэффициентов AC в прогрес- сивном JPEG
Прогрессивные изображения JPEG 211 Алгоритм 11.4. Обновление значений коэффициентов АС Procedure RefineAC (COEFFICIENT) Begin If COEFFICIENT > 0 Then Begin If ReadRawBits (1) <> 0 Then Begin COEFFICIENT = COEFFICIENT +(1 LeftShift SUCCESSIVEAPPROXIMATION) End End Else if COEFFICIENT < 0 Then Begin If ReadRawBits (1) <> 0 Then Begin COEFFICIENT = COEFFICIENT + (-1 LeftShift SUCCESSIVEAPPROXIMATION) End End Если 4 младшие бита в байте, кодированном по методу Хаффмана, равны нулю, код не создает никаких новых нену- левых коэффициентов. Однако по-прежнему выполняется процесс обновления существующих ненулевых коэффициен- тов. Когда значение байта, кодированного по методу Хафф- мана, равно F016, следующие 16 нулевых коэффициентов пропускаются, но все перемежающиеся ненулевые коэффи- циенты обновляются с помощью предыдущей процедуры. Как и в начальных сканах, значения кода 0016, 1016,...Е016 за- ставляют декодер пропускать данные до конца определенно- го числа диапазонов. Четыре старших бита указывают число считываемых дополнительных битов для чтения, и счетчик конца диапазона (ЕОВ) вычисляется так же, как и прежде. Все ненулевые коэффициенты, пропущенные в результате пропуска ЕОВ-серии, обновляются с помощью необработан- ных битов. Важно помнить, что при пропуске нулевых коэффициентов декодер должен заканчивать процесс пропуска в конце диа- пазона или на нулевом коэффициенте. Предположим, диапазон содержит 20 коэффициентов со зна- чениями 00000800080800000088 т
212 Форматы и алгоритмы сжатия изображений в действии в начале скана. Если первый декодированный байт для этого диапазона был равен 81 !6, это заставило бы декодер пропус- тить 8 нулевых значений. После пропуска 5 коэффициентов декодер считал бы 1 необработанный бит для обновления первого значения равного 8. Обновленный 00000800080800000088 t Декодер пропустил бы следующие 3 нулевых коэффициен- та (из общего числа 8) и остановился бы в указанной ниже точке. 0 0 0 .0 0 8 0 0 0 8 0 8 0 0 0 0 0 0 8 8 Т Поскольку этот коэффициент уже ненулевой, все, что можно сделать - это обновить его. Декодер должен перемещаться к следующему нулевому коэффициенту, обновляя пропущен- ные ненулевые коэффициенты. Обновленный Новый коэффициент 00000800084800000088 t Алгоритм 11.5 служит иллюстрацией процедуры обновления коэффициентов АС в прогрессивном скане. Алгоритм 11.5. Обновление коэффициентов АС в прогрес- сивном скане Global SSS // Начало спектрального выделения Global SSE // Конец спектрального выделения Global SUCCESSIVEAPPROXIMATION Global EOBRUN Procedure ACRefineDataUnit (COEFFICIENTS [0..63]) Begin II = SSS While II <= SSE Do Begin If EOBRUN > 0 Then Begin While II <= SSE Do Begin
Прогрессивные изображения JPEG 213 If COEFFICIENT [II] о 0 Then RefineAC (COEFFICIENT (II) II = II + 1 End EOBRUN = EOBRUN - 1 Return End VALUE = DecodeUsingACTable LOBITS = VALUE AND 0F16 HIBITS = (VALUE AND F016) Rightshift 4 If LOBITS = 1 Then Begin EXTRABIT = ReadRawBits (1) While HIGHBITS > 0 OR COEFFICIENTS [II] <> 0 Do Begin - If COEFFICIENTS [II] <> 0 Then RefineAC (COEFFICIENTS [II]) Else HIGHBITS = HIGHBITS - 1 II = II + 1 End If EXTRABIT <> 0 COEFFICIENTS [II] = 1 Leftshift SUCCESSIVEAPPROXIMATION Else COEFFICIENTS [II] = -1 LeftShift SUCCESSIVEAPPROXIMATION II = II + 1 End Else If LOBITS = 0 Then Begin If HIGHBITS = F16 Then // Run of 16 Zeros Begin While HIGHBITS >= 0 Do Begin If COEFFICIENTS [II] <> 0 Then RefineAC (COEFFICENTS [II]) Else HIGHBITS = HIGHBITS - 1 End End Else If HIGHBITS = 0 Then EOBRUN = 1 Else EOBRUN = (1 LeftShift HIGHBITS) + ReadRawBits (HIGHBITS) End End End Алгоритм 11.5. Прололжение
214 Форматы и алгоритмы сжатия изображений в действии Подготовка к созданию прогрессивных файлов JPEG Наибольшую трудность при создании кодера прогрессивных файлов JPEG представляет определение содержимого каждо- го скана. Для каждого скана кодер должен определять: ✓ Включаемые компоненты (несколько компонентов могут со- держаться только в диапазонах коэффициентов DC); ✓ Спектральную область; ✓ Последовательное приближение. Указание всех параметров для каждого скана было бы для пользователя делом утомительным и подверженным ошиб- кам. Возможным решением этой проблемы могло бы стать предварительное определение набора последовательностей сканов, из которых пользователь осуществлял бы свой вы- бор. Метод, который, с нашей точки зрения, эффективен, состоит в определении для прогрессивного JPEG стандарт- ной последовательности сканов и предоставлении пользова- телю возможности вносить желаемые изменения. Для каж- дого скана пользователь может назначать компоненты, ука- зывать последнее значение в спектральной области и на- чальную величину последовательного приближения. В на- чале процесса кодирования для определения начальной спектральной области последующих сканов используется спектральная область предыдущих сканов. Если пользова- тель определил для компонента сканы с последними значе- ниями в спектральной области, установленными равными: О 5 20 63, то кодер автоматически назначит диапазоны 0-0 1-5 6-20 21-63 в качестве спектральных диапазонов скана. Кодер обрабатывает сканы в порядке, определяемом пользо- вателем. Если спектральное выделение определено для како- го-либо скана, декодер повторяет список сканов и уменьшает спектральное выделение на 1. Далее декодер выводит все сканы, содержащие спектральные диапазоны, которые все еще требуют обновления. Этот процесс характеризуется средней сложностью. Он предоставляет пользователю много возможностей для вывода прогрессивных сканов, но не по-
Прогрессивные изображения JPEG 215 зволяет осуществлять полный контроль над содержимым ка- ждого скана и порядком их расположения. Кодер не должен чрезмерно усердствовать при разбиении данных изображения на сканы. Каждый скан в прогрессив- ном изображении должен содержать значимую часть дан- ных. Поскольку последний коэффициент АС почти всегда равен нулю, создание сканов со спектральной областью от 63 до 63 или даже от 61 до 63 не очень полезно. Чем дальше от начала зигзагообразной структуры, тем большее число коэффициентов следует включать в скан. Следует руково- дствоваться общим правилом: чем больше значения кванто- вания, тем больше число коэффициентов, приходящихся на диапазон. Последовательное приближение еще больше подвержено не- правильному употреблению. Используя спектральное выде- ление, диапазон может быть разделен на 14 диапазонов, в ко- торые последние 13 сканов вносят по 1 биту в каждый коэф- фициент диапазона. При 8-битовых дискретизованных дан- ных для декодирования коэффициентов DC требуется не бо- лее 11 битов (при 12-битовой дискретизации данных это чис- ло равно 15). Использование величины последовательного приближения 13 для кодирования 8-битовых данных лишено смысла, поскольку многие сканы не будут добавлять в изо- бражение какую-либо информацию. Поскольку разрядность коэффициентов АС, как правило, на- много меньше, чем разрядность коэффициентов DC, исполь- зование последовательного приближения для разделения ко- эффициентов АС на большее число сканов еще более нецеле- сообразно. Приемлемые значения последовательного при- ближения определяются разрядностью значений квантования и тем, насколько далеко расположен диапазон в-зигзагооб- разной структуре. Если кодер дает пользователю возможность определять со- держимое сканов, он должен выполнять ряд проверок, гаран- тирующих наличие в выходном файле корректного изобра- жения JPEG. Кроме проверок, характерных для последова- тельного JPEG, кодер прогрессивного JPEG должен удосто- вериться в том, что: ✓ Сканы содержат весь спектральный диапазон для каждого компонента.
216 Форматы и алгоритмы сжатия изображений в действии ✓ Спектральные диапазоны компонента не перекрываются. ✓ Спектральные диапазоны, содержащие коэффициент DC, не содержат каких-либо коэффициентов АС. ✓ Величина последовательного приближения находится в диапазоне 0-13. Кодирование прогрессивных сканов Кодирование прогрессивных изображений JPEG весьма схо- же с кодированием последовательного JPEG-изображения с использованием множества сканов. Как и в случае прогрес- сивного декодирования, основное отличие состоит в кодиро- вании единиц данных. Как сообщалось ранее в данной главе, в прогрессивном файле JPEG встречаются четыре различных типа сканов. JPEG-кодер, описанный в главе 9, использовал функции lnterleavedPass() и NoninterleavedPass() для управления соз- данием сканов. Эти функции выполняли деление изображе- ний на MCU и обрабатывали маркеры перезапуска. Функ- ции были реализованы так, что само кодирование единиц данных выполнялось с использованием указателей на функ- ции-члены. Такая реализация может показаться странной для последовательных изображений, но та же самая функ- ция используется для управления прогрессивными сканами ,DC после ее интегрирования в программный код прогрес- сивного JPEG, тем самым позволяя управлять, в общей сложности, тремя типами сканов с помощью одной и той же программы. Кодирование Хаффмана Прогрессивные изображения могут содержать до 4 таблиц Хаффмана DC и до 4 таблиц Хаффмана АС, определяемых в любой момент времени. Исходный программный код про- грессивного JPEG, приведенный в конце этой главы, исполь- зует максимум две таблицы каждого типа, в точности как программный код базового последовательного JPEG. Как и прежде, кодирование каждого скана осуществляется за два прохода: первый проход используется для сбора статистики по частотам кодов Хаффмана, а во втором проходе выполня- ется кодирование и вывод данных. Для каждого прохода ис-
Прогрессивные изображения JPEG 217 пользуется один и тот же управляющий код, с указателями на функции, которые определяют, какая из двух операций вы- полняется для данного прохода. Декодирование единицы данных Первые сканы DC За исключением точечного преобразования, применяемого к значению коэффициента, кодирование коэффициентов DC в первом скане диапазона идентично кодированию коэффици- ентов DC в последовательном скане. Коэффициенты DC ко- дируются как разность между текущим коэффициентом DC и значением последнего закодированного коэффициента DC для того же самого компонента. Разность коэффициентов DC кодируется в виде значения разрядности кода Хаффмана, за которым следует несколько литеральных битов. Для простоты, приведенный ниже пример показывает только одну переменную последнего значения коэффициента DC. Реализация действующей программы требует наличия для каждого компонента отдельной переменной. В точности так- же, как и для последовательного JPEG, значение последнего коэффициента DC для каждого компонента должно устанав- ливаться в нуль в начале скана и везде, где обрабатывается маркер перезапуска. Алгоритм 11.6 иллюстрирует процесс кодирования единицы данных в первом скане DC. Алгоритм 11.6. Колирование коэффициентов DC в первых сканах Global SUCCESSIVEAPPROXIMATION Global LAST_DC_VALUE Function CountBits (VALUE) Begin COUNT = 0 While VALUE <> 0 Do Begin COUNT = COUNT + 1 VALUE = VALUE RightShift 1 End End Procedure EncodeDCFirst (COEFFICIENTS [0..63]) Begin // Точечное преобразование (Point Transform)
218 Форматы и алгоритмы сжатия изображений в действии Алгоритм 11.6. Продолжение VALUE = COEFFICIENTS [0] Rightshift SUCCESSIVEAP- PROXIMATION DIFFERENCE = VALUE - LAST_DC_VALUE LAST_DC_VALUE = DIFFERENCE If DIFFERENCE >= 0 Then Begin BITCOUNT = CountBitS (DIFFERENCE) HuffmanEncode (BITCOUNT) OuputLiteralBitS (BITCOUNT, DIFFERENCE) End Else Begin BITCOUNT = CountBitS (-DIFFERENCE) HuffmanEncodeDC (BITCOUNT) OuputLiteralBitS (BITCOUNT, DIFFERENCE Xor FFFFFFFF16) End End Обновляющие сканы DC Как видно из алгоритма 11.7, кодирование обновляющих ко- эффициентов DC для единицы данных выполняется триви- альным образом. Скан содержит единственный бит для об- новления коэффициента DC. Выполнять кодирование Хафф- мана не требуется. Алгоритм 11.7. Кодирование коэффициентов DC в обновляющих сканах Global SUCCESSIVEAPPROXIMATION Procedure EncodeDCRefine (COEFFICIENTS [0..63]) Begin VALUE = (COEFFICIENTS [0] Rightshift SUCCESSIVEAP- PROXIMATION) And 1 OutputLiteralBits (1, VALUE) End Первые сканы AC Коэффициенты AC кодируются с использованием последова- тельности байтов, кодированных по методу Хаффмана, за ко- торыми следует строка литеральных битов. Байт, кодирован- ный по методу Хаффмана, делится на два 4-битовых поля. Если 4 младших бита ненулевые, код представляет ненулевой литеральный коэффициент. Младшие биты определяют раз- рядность кода и указывают число литеральных битов, кото- рые следуют за кодом. Четыре старших бита определяют число нулевых коэффициентов, которые пропускаются перед записью ненулевого коэффициента.
Прогрессивные изображения JPEG 219 Байтовый код FO 16 означает, что следующие 16 значений ко- эффициентов равны нулю. Любое другое значение с 4 млад- шими битами, установленными в ноль, определяет разряд- ность длины серии диапазонов, в которых все коэффициенты равны нулю (см. Таблицу 11.2). Четыре старших бита опре- деляют число необработанных битов, записанных в выход- ной поток для указания точной длины ЕОВ-серии. Кодировщик обрабатывает единицу данных, начиная с пер- вого коэффициента в диапазоне и двигаясь к последнему ко- эффициенту, кодирует коэффициенты в зигзагообразном по- рядке. При кодировании коэффициентов АС обрабатываются только ненулевые коэффициенты. Кодер должен вести об- служивание счетчика числа последовательных нулевых ко- эффициентов внутри единицы данных и счетчика блоков, в которых все коэффициенты равны нулю. Алгоритм 11.8 служит иллюстрацией процесса кодирования единицы данных в первом прогрессивном скане АС. Проце- дура EncodeACRefine вызывает процедуру PrintEOBRun для вывода ожидающей обработки ЕОВ-серии непосредственно перед кодированием литерального коэффициента. В про- граммном коде примера не показано, что процедура PrintEOBRun должна вызываться всякий раз, когда в выход- ной поток выводится маркер перезапуска. Процедура PrintEOBRun также должна вызываться в конце кодирования единицы данных, чтобы обеспечить вывод в выходной поток данных всех ЕОВ-серий. Алгоритм 11.8. Кодирование коэффициентов AC в первых сканах АС Global SUCCESSIVEAPPROXIMATION Global SSS Global SSE Global EOBRUN Procedure PrintEOBRun Begin If EOBRUN = 0 Then Return BITCOUNT = CountBits (EOBRUN Rightshift 1) HuffmanEncodeAC (BITCOUNT Leftshift 4) OutputLiteralBits (BITCOUNT, EOBRUN) End Procedure EncodeACFirst (COEFFICIENTS [0..63]) Begin ZERORUN = 0 // Число последовательных нулевых коэф- фициентов
220 Форматы и алгоритмы сжатия изображений в действии For II = SSS То SSE) Begin // Точечное преобразование (Point Transform) VALUE = COEFFICIENTS [II] / (1 LeftShift SUCCESSIVEAPPROXIMATION) If Value = 0 Then ZERORUN = ZERORUN + 1 Else Begin // Встречено литеральное значение, поэтому любая ЕОВ-серия, // начавшаяся с предыдущего блока, завершена, так же, // как и любая нулевая серия внутри этого блока. PrintEOBRun // Наибольшая длина нулевой серии, которая может быть // выведена с литералом, равна 15. Если длина серии больше 15, // следует вывести код для 16 нулей до записи литерала. While ZERORUN >= 16 Do Begin HuffmanEncodeAC (F016) ZERORUN = ZERORUN - 16 End If VALUE > 0 Then Begin BITCOUNT = CountBits (VALUE) HuffmanEncodeAC ((ZERORUN LeftShift 4) Or BITCOUNT) OutputLiteralBitS (BITCOUNT, VALUE) End Else Begin BITCOUNT = CountBits (-VALUE) HuffmanEncodeAC ((ZERORUN LeftShift 4) Or BITCOUNT) OutputLiteralBitS (BITCOUNT, VALUE Xor FFFFFFFF16) End ZERORUN = 0 End End // Если диапазон закончился в нулевой серии, тогда преобразуем их // в ЕОВ-серию If ZERORUN о 0 Then Begin EOBRUN = EOBRUN + 1 // Убедитесь, что максимальная длина ЕОВ-серии не превышена If EOBRUN = 7FFF16 Then PrintEOBRun End End Алгоритм 11.8. Продолжение
Прогрессивные изображения JPEG 221 Обновляющие сканы АС Кодирование обновляющих сканов АС является одним из самых сложных процессов в кодировании JPEG. Процедура кодирования обновляющих сканов АС отвечает базовой структуре алгоритма, используемого для кодирования пер- вого скана в диапазоне. Важная особенность обновляющих сканов состоит в том, что последовательности битов, опре- деляющие кодированные по методу Хаффмана значе- ния/литералы, используются только для кодирования коэф- фициентов, которые впервые устанавливаются ненулевыми в текущем скане. Коэффициенты, которые были установле- ны ненулевыми в предыдущем скане, не включаются в ну- левые серии. Вместо этого любой код, вызывающий про- пуск нулевых значений, сопровождается обновляющим би- том для каждого ненулевого значения, встречающегося сре- ди нулей. Алгоритм 11.9 иллюстрирует процесс кодирования обнов- ляющих сканов АС. Логика работы процедуры RefineBand в основном отвечает логике работы обновляющих сканов. Процедура выводит обновляющий бит для каждого пропу- щенного ненулевого кода. Коды, применяемые для кодирования сканов, идентичны ко- дам, используемым для кодирования первого скана АС в диапазоне. Единственное отличие в кодированных данных состоит в том, что пары битов, кодированных по методу Хаффмана значений/литералов, сопровождаются последова- тельностями битов, которые обновляют значение каждого пропущенного коэффициента. Если нулевая серия или ЕОВ- серия вызывают пропуск коэффициентов от М до N, процеду- ра RefineBand(M, N) выводит обновляющие биты. Процедура RefineEOBRun для обновляющих сканов немного отличается от процедуры, применяемой для первых сканов, поскольку она должна обновлять все пропущенные ненуле- вые коэффициенты. Пропуск коэффициентов из-за ЕОВ- серий требует дополнительных глобальных данных. В при- мере используются переменные RUNSTARTDATAUNIT и RUNSTARTCOEFFICIENT для маркировки единицы данных и коэффициента в том месте, где началась ЕОВ-серия. (ЕОВ- серия может начинаться в середине единицы данных).
222 Форматы и алгоритмы сжатия изображений в действии Кодирование единиц данных для обновляющих сканов АС представляет собой более сложную задачу. Поскольку длина нулевой серии является счетчиком нулевых коэффициентов, а не определяет число коэффициентов, пропускаемых в нуле- вой серии, программный код для обработки нулевых серий длиной свыше 16 также несколько более сложен. Global DATAUNITS [0..*][0..63] Global CURRENTDATAUNIT // Индекс текущей единицы данных в DATAUNITS Global EOBRUN Global RUNSTARTDATAUNIT Global RUNSTARTCOEFFICIENT Global SSS // Начало спектрального выделения Global SSE // Конец спектрального выделения Global SUCCESSIVEAPPROXIMATION Procedure RefineBand (COEFFICIENTS [0..63], START, END) Begin For II = START TO END Begin VALUE = COEFFICIENTS [II] / (1 LeftShift SUCCESSIVEAPPROXIMATION) If VALUE <> 0 Then Begin If VALUE < 0 Then VALUE = - VALUE OutputLiteralBits (1, VALUE And 1) End End End Procedure PrintEOBRun Begin If EOBRUN = 0 Then Return BITCOUNT = CountBitS (EOBRUN Rightshift 1) HuffmanEncodeAC (BITCOUNT Leftshift 4) OutputLiteralBits (BITCOUNT, EOBRUN) For II = 1 To EOBRUN DO Begin RefineBand (DATAUNITS [RUNSTARTDATAUNIT + II - 1], RUNSTARTCOEFFICIENT, SSE) RUNSTARTCOEFFICIENT = SSS End EOBRUN = 0 End Алгоритм 11.9. Кодирование обновляющих сканов AC
Прогрессивные изображения JPEG 223 Procedure EncodeACRefine (COEFFICIENTS [0..63]) Begin ZERORUN = 0 For II = SSS To SSE DO Begin VALUE = COEFFICIENTS [II] / (1 LeftShift SUCCESSIVEAPPROXIMATION) If VALUE = 0 Then Begin If ZERORUN = 0 Then ZEROSTART = II ZERORUN = ZERORUN + 1 End Else If Value = 1 Or Value = -1 Then Begin PrintEOBRun While ZERORUN >= 16 Do Begin ZEROLIMIT = ZEROSTART ZEROCOUNT = 0 While ZEROCOUNT < 16 Do Begin OLDVALUE = COEFFICIENTS [ZEROLIMIT] / (1 LeftShift SUCCESSIVEAPPROXIMATION) If OLDVALUE = 0 Then ZEROCOUNT = ZEROCOUNT + 1 ZEROLIMIT = ZEROLIMIT + 1 End HuffmanEncodeAC (F016) RefineBand (COEFFICIENTS, ZEROSTART, ZEROLIMIT - 1) ZEROSTART = ZEROLIMIT ZERORUN = ZERORUN - 16 End If VALUE > 0 Then Begin BITCOUNT = CountBitS (VALUE) HuffrnanEncodeAC ((ZERORUN LEFTSHIFT 4) Or BITCOUNT) OutputLiteralBitS (BITCOUNT, VALUE) End Else Begin BITCOUNT = CountBitS (-VALUE) HuffrnanEncodeAC ((ZERORUN LEFTSHIFT 4) Or BITCOUNT) OutputLiteralBitS (BITCOUNT, VALUE Xor FFFFFFFF16) End RefineBand (COEFFICIENTS, ZEROSTART, II - 1) ZERORUN = 0 End End Алгоритм 11.9. Продолжение
224 Форматы и алгоритмы сжатия изображений в действии Алгоритм 11.9. Продолжение If ZERORUN о 0 Then Begin If EOBRUN = 0 Then Begin RUNSTARTDATAUNIT = CURRENTDATAUNIT RUNSTARTCOEFFICIENT = ZEROSTART End EOBRUN = EOBRUN + 1 If EOBRUN = 7FFF16 Then PrintEOBRun End End Заключение Данная глава, посвященная прогрессивному режиму JPEG, завершает описание формата JPEG. В этой и предыдущих главах рассмотрены все характеристики JPEG, которые отно- сятся к числу наиболее широко используемых. Материал данных глав содержит описание всех режимов JPEG, которые могут вам встретиться при работе с JPEG-файлами, разме- щенными в Интернете. Исходный программный код для данной главы не является завершенной программой, а скорее представляет дополни- тельный код, необходимый для расширения сферы действия программ из глав 8 и 9 за счет включения прогрессивного режима кодирования и декодирования.
ГЛАВА 12. GIF Формат: GIF Разработчик: CompuServe Определение: Формат Графического Обмена (Graphics Interchange Format), спецификация версии 89а В этой главе описываются формат GIF (Graphics Interchange Format - формат графического обмена) компании Compu- Serve, и метод сжатия LZW, используемый для сжатия дан- ных изображения в формате GIF. До недавнего времени формат GIF компании CompuServe был самым распростра- ненным форматом, используемым для хранения изображе- ний. В 1987 компания CompuServe опубликовала первую спецификацию формата обмена графическими данными под названием GIF87a. Данная спецификация распространялась бесплатно, и практически все программы обработки изо- бражений обеспечивали поддержку формата GIF. Позже компания CompuServe выпустила расширенную, совмести- мую снизу вверх версию стандарта, известную под названи- ем GIF89a. Однако большинство GIF-изображений используют только возможности стандарта GIF87a. Основные характеристики GIF включают: ✓ Поддержку до 256 цветов, для описания которых применя- ется от 1 до 8 битов на пиксел. ✓ Хранение в одном файле множества изображений. Для фотографических изображений на смену формату GIF пришел формат JPEG, благодаря лучшему сжатию и большей глубине цвета. Формат GIF продолжает использоваться для других приложений, но его распространению сильно мешают юридические препятствия.
226 Форматы и алгоритмы сжатия изображений в действии Порядок расположения байтов Формат GIF хранит многобайтовые целые числа с младшим байтом на первом месте (прямой порядок байтов). Строки битов считываются в направлении от самого младшего бита к самому старшему биту. В битовых строках, которые пере- секают границы байта, биты второго байта старше битов первого байта. Файловая структура Заголовок Дискриптор глобального экрана Глобальная таблица цветов ^Изображение 1 ^Изображение 2 ^Изображение л Завершитель ' Рис. 12.1. Структура файла GIF Файл в формате GIF состоит из фиксированной области в на- чале файла, за которой располагается переменное число бло- ков, и заканчивается файл завершителем изображения (image trailer). В формате GIF87a переменная область содержит ис- ключительно описания изображения. В формате GIF89a пе- ременная область может включать или описания изображе- ния, или блоки расширений (extension block). Общая структу- ра файла в формате GIF представлена на Рис. 12.1. Заголовок gif В начале файла GIF должен располагаться заголовок GIF. За- головок позволяет программе идентифицировать формат GIF и определить версию формата. В Таблице 12.1 представлена структура заголовка GIF. Программы, которые не используют возможности, включенные в стандарт GIF89a, все еще про- должают создавать заголовок GIF87a для обеспечения со- вместимости файлов изображений со старыми декодерами. Логический дескриптор экрана Дескриптор глобального экрана (global screen) определяет ло- гическую область экрана, в которой воспроизводятся отдель- ные изображения из файла GIF. Дескриптор указывает разме- ры области, а также цвет фона (выбранный из глобальной таблицы цветов). Дескрипторы отдельных изображений оп- ределяют, в каком месте логического экрана должно распола- гаться изображение. Структура дескриптора экрана включает 7 байтов и приводится в Таблице 12.2.
GIF 227 Таблииа 12.1. Структура Имя ПОЛЯ Размер Описание 3 байта заголовка GIF Сигнатура Значение поля должно равняться ASCII-строке «GIF» Версия 3 байта Значение поля должно равняться ASCII-строке «87а» или «89Ь» Таблииа 12.2. Формат лескриптора уогического экрана Имя поля Размер Описание Ширина логического экрана 2 байта Высота логического экрана 2 байта Битовые поля 1 байт Размер обшей таблицы цветов Биты 0-2 Число записей в глобальной таблице цветов равно 2(N+1) Флаг сортировки таблицы цветов Бит 3 Устанавливается, когда цвета в глобальной таблице цветов сортируются в порядке важно- сти Число битов на пиксел Биты 4-6 Число битов на пиксел минус 1 Флаг глобальной таблицы цветов Бит 7 Устанавливается, когда используется глобальная таблица цветов Цвет фона 1 байт Указатель цвета в глобальной таблице цветов Пропорция размеров пиксела 1 байт Если это значение ненулевое, ширина и высота пиксела не совпадают. Выражение (N+15)/64 равняется ширине пиксела, деленного на высоту пиксела На Рис. 12.2 представлена связь между логическим экраном и отдельными изображениями в файле GIF.
228 Форматы и алгоритмы сжатия изображений в действии Рис. 12.2. Связь между логическим экраном и изображениями Глобальная таблица цветов Отдельные изображения в файле могут использовать или гло- бальную таблицу цветов, или определять собственную таблицу цветов. Совместное использование изображениями в файле глобальной таблицы цветов уменьшает размер файла и упрощает его использование в системах, которые могут вос- производить ограниченное количество цветов. Кроме того, глобальная таблица цветов определяет цвет фона для логиче- ского экрана. Если в дескрипторе экрана установлен бит глобальной таб- лицы цветов, то глобальная таблица цветов следует сразу за дескриптором экрана. Глобальная таблица цветов представ- ляет собой массив структур, формат которых представлен в Таблице 12.3. Число записей в массиве определяется по зна- чению поля Global Color Table Size (Размер глобальной табли- цы цветов), в дескрипторе экрана.
GIF 229 Таблица 12.3. Формат записей таблицы цветов Имя ПОЛЯ Размер Описание Красное 1 байт Значение красной цветовой компоненты Зеленое 1 байт Значение зеленой цветовой компоненты Синее 1 байт Значение синей цветовой компоненты Типы блоков После глобальной таблицы цветов располагается переменная часть GIF-файла. Файл содержит последовательность блоков, которые идентифицируются 1-байтовым кодом в начале бло- ка. В Таблице 12.4 перечисляются типы блоков и связанные с ними коды блоков. Таблица 12.4. Коды блоков Код Тип 2116 Расширение 2С16 Блок изображения ЗВ16 Завершитель файла GIF (ЗаголовокЛ I изображения J Локальная блина нветов Минимильный размер кода данных 1 данных 2 данных 3 ’ Блок данных п Признак KOHuaJ Рис. 12.3. Структура определения изображения Завершитель файла Блок завершителя (terminator) отмечает конец GIF-файла. Данный блок длиной в 1 байт состоит исключительно из кода блока. Блок изображения Блок изображения определяет изображение в GIF-файле. Изображение начинается с заголовка, который определяет размер и размещение изображения. Формат структуры заго- ловка представлен в Таблице 12.5. Если в заголовке изобра- жения установлен флаг Local Color Table (Локальная таблица цветов), изображение вместо глобальной таблицы цветов использует локальную таблицу цветов. Точно так же, как и глобальная таблица цветов, локальная таблица цветов пред- ставляет собой массив записей, указывающих цвет (Таблица 12.3). Число элементов в массиве определяется значением поля Local Color Table Size (Размер локальной таблицы цве- тов) в заголовке. На Рис. 12.3 показана общая структура определения изобра- жения в GIF-файле.
230 Форматы и алгоритмы сжатия изображений в действии Таблица 12.5. Структура заголовка изображения Имя ПОЛЯ Размер Описание Left Position (Левая позиция) 2 байта Смешение изображения влево внутри логического экрана Right Position (Правая позиция) 2 байта Смешение изображения вверх внутри логического экрана Image Width (Ширина изображения) 2 байта Image Height (Высота изображения) 2 байта Bit Field (Битовое поле) 1 байт Local Color Table Size (Размер локальной таблицы цветов) Биты 0-2 Число цветовых компонентов в локальной таблице цветов равно (N+1)2 Резервировано Биты 3-4 Не используется Sort Flag (Флаг сортировки) Бит 5 Если флаг установлен/ цвета в локальной таблице цветов сор- тируются в порядке их важно- сти Interlace Flag (Флаг чередования) Бит 6 Если флаг установлен, данные изображения выводятся в ре- жиме чередования Local Color Table Flag (Флаг локальной таб- лицы цветов) Бит 7 Если флаг установлен, изобра- жение использует локальную таблицу цветов Блоки данных После байта, определяющего размер кода, сразу же начина- ется непрерывная последовательность блоков данных, кото- рые содержат сжатые данные изображения. Блок данных со- стоит из 1-байтового поля счетчика, за которым следуют от 1 до 255 байтов данных. Цепочка блоков данных изображения всегда заканчивается блоком данных с нулевыми байтами данных - другими сло- вами, единственным байтом с нулевым значением. Мы обсу- дим формат сжатого блока чуть позже в этой главе.
GIF 231 Л Начало 4 I расширения (21) ( Код 4 1 расширения Заголовок расширения ^Блок данных 1 ^Блок данных 2~ ^Блок данных 3 данных п Блоки расширения Блоки расширения были добавлены в формат GIF в специфи- кации GIF89a. Структура блока расширения представлена на Рис. 12.4. Первый байт в блоке расширения содержит код 2116. Этот байт сопровождается вторым байтом, который со- держит код, определяющий тип расширения. Коды типов расширений перечисляются в Таблице 12.6. Формат заголовка расширения зависит от типа расширения. Первый байт в заголовке содержит размер заголовка без уче- та байта размера. Заголовок сопровождается набором блоков данных. Каждый блок состоит из байта счетчика, сопровож- даемого 1-255 байтами данных. Набор блоков данных завер- шается нулевым байтом (блок данных с нулевыми байтами данных). Структура блоков расширения такова, что программа может пропускать их, без анализа структуры каждого отдельного типа расширения. Алгоритм 12.1 иллюстрирует процедуру пропуска блоков расширения. Рис. 12.4. Формат блока расширения Таблииа 12.6. Коды ТИПОВ Код Тип 1 Расширение простого текста графических расширений F9 Расширение управления графикой FE Расширение комментария FF Расширение программы Алгоритм 12.1. Пропуск блоков расширений в GIF-файле DATA = ReadByte () // Тип расширения (Extention Туре) DATA = ReadByte () // Счетчик (Count) While DATA о О Begin For II = 1 To DATA ReadByte () End Расширение простого текста Блок расширения простого текста (plain text extension) ис- пользуется для прорисовки на логическом экране сетки тек- ста с фиксированными промежутками. Это расширение со- стоит из заголовка, сопровождаемого последовательностью
232 Форматы и алгоритмы сжатия изображений в действии блоков данных, содержащих текст для прорисовки. Блоки данных после заголовка содержат отображаемый текст. Фор- мат заголовка расширения простого текста представлен в Таблице 12.7. Таблниа 12.7. Формат Имя поля Размер Описание Block size (Размер блока) 1 байт расширения простого текста Значение 12 Text Grid Left (Левая точка текстовой сетки) 2 байта Позиция текста на логическом экране Text Grid Right (Правая точка текстовой сетки) 2 байта Позиция текста на логическом экране Text Grid Right (Ширина текстовой сетки) 2 байта Размер блока текста в пикселах Text Grid Height (Высота текстовой сетки) 2 байта Размер блока текста в пикселах Character Cell Width (Ширина текстовой ячейки) 1 байт Ширина в пикселах каждого символа Character Cell Width (Высота текстовой ячейки) 1 байт Высота в пикселах каждого символа Text Foreground Color 1 байт Указатель цвета текста (Пвет текста) • «и в глобальной таблице цветов Text Background Color (Ивет фона текста) 1 байт Указатель цвета фона в глобальной таблице цветов Расширение управления графикой Расширение управления графикой (graphic control text) опре- деляет, как должно быть нарисовано следующее изображение в файле GIF. Расширения управления графикой обычно ис- пользуются для определения порядка прорисовки отдельных кадров (frames) в анимации GIF. Для каждого изображения может быть только одно расшире- ние управления графикой. Этот блок расширения GIF не со- держит каких-либо данных, так что за заголовком сразу сле- дует завершающий байт данных с нулевым значением. Со- держимое заголовка расширения управления графикой пред- ставлено в Таблице 12.8.
GIF 233 Таблииа 12.8. Заголовок расширения управления графикой Имя поля Размер Описание Block Size (Размер блока) 1 байт Должно быть равно 4 Bit Fields (Битовые поля) 1 байт Transparent Color Flag (Флаг прозрачного цвета) Бит 0 Устанавливается, если исполь- зуется указатель прозрачного цвета User Input Flag (Флаг пользователь- ских входных данных) Бит 1 При установке флага программа должна ожидать перед отобра- жением следующего изображения ввода данных пользователем. Disposal Method (Метод освобождения памяти) Биты 2-4 Указывает, что должен делать декодер после прорисовки изо- бражения. 0 - Отсутствие действий 1 - Оставить изображение на месте 2 - Восстановить цвет фона 3 - Восстановить то, что было в данном месте перед прорисовкой изображения Зарезервированы Биты 5-7 Delay Time (Время задержки) 2 байта Промежуток времени в едини- цах 1/1000 секунды, которое декодер должен ждать перед продолжением обработки пото- ка данных Transparent Color Index (Указатель прозрачного цвета) 1 байт Если установлен флаг прозрач- ного цвета, пикселы с указанным цветом не отображаются. Расширение комментария Расширение комментария (comment extension) позволяет ко- деру сохранять в пределах файла GIF информацию любого рода. Программа не должна использовать расширение ком- ментария для хранения данных, управляющих обработкой потока GIF. В расширении комментария отсутствует заголо- вок и, даже нет байта счетчика. Блоки данных, содержащие текст комментария, следуют сразу за кодом типа расширения.
234 Форматы и алгоритмы сжатия изображений в действии Расширение программы Кодер может использовать блок расширения программы (ap- plication extension), чтобы сохранить в GIF-потоке данные, характерные для конкретной программы. Назначение расши- рения программы подобно расширению комментария за ис- ключением того, что это расширение может использоваться для хранения данных, необходимых для процесса декодиро- вания. Специфическая для программы информация хранится внутри блоков данных, следующих за заголовком. Формат за- головка программы представлен в Таблице 12.9. Таблица 12.9. Заголовок расширения программы Имя поля Размер Описание Block size (Размер блока) 1 байт 11 Application ID (Идентификатор программы) 8 байтов ASCII-Строка, идентифицирующая программу, создавшую блок Authentication Code (Код аутентификации) 3 байта Эти три байта программа может использовать для определения подлинности блока. Чередование В общем случае изображения GIF хранятся в порядке сверху вниз и слева направо. Однако если в заголовке изображения установлен флажок режима чередования, строки пиксельных данных не передаются в строгом порядке сверху вниз. Вме- сто этого, изображение формируется за четыре прохода. Пер- вый проход содержит пиксельные данные для каждой вось- мой строки, начиная с самой верхней строки (нулевой стро- ки). В остальные проходы заполняются строки, пропущенные в предыдущих проходах. В Таблице 12.10 приводятся номера строк, включаемых в каждый проход. Таблица 12.10. Порядок чередования Проход Начальная строка Интервал 1 0 (верхняя строка) 8 строк 2 4 8 3 2 4 4 1 2
GIF 235 Процедура чередования решает ту же задачу, что и в про- грессивном JPEG. Когда изображение передается по сети, чередование позволяет пользователю получить представле- ние о передаваемой информации до того, как будут загру- жены все данные изображения. Программы, которые ото- бражают «на лету» изображения GIF с режимом чередова- ния, обычно заполняют отсутствующие строки изображения копиями строк, уже полученных за предыдущие проходы. В первом проходе программа копирует каждую строку во- семь раз, во втором проходе - четыре раза, и в третьем про- ходе - один раз. Это приводит к эффекту постепенного «проявления» изображения, что внешне выглядит более привлекательно, чем отображение отдельных, визуально разъединенных, строк на экране. Формат сжатых данных Пиксельные данные изображения GIF сжимаются с помощью метода, называемого LZW. Сжатие LZW также известно в ка- честве схемы сжатия на основе словаря (dictionary-based compression). Этим названием подчеркивается, что метод сжатия LZW поддерживает ведение списка, или словаря, по- следовательностей значений, встречающихся в несжатых данных. В процессе сжатия при определении этих последова- тельностей в несжатых данных они заменяются кодом, кото- рый ссылается на такую же последовательность в словаре. Чем больше объем словаря с последовательностями значе- ний, тем чаще они будут встречаться в несжатых данных, и тем большей будет степень сжатия. Специфика сжатия на основе словаря состоит в способе пе- редачи словаря в сжатые данные. Наиболее широко распро- страненные схемы сжатия на основе словаря базируются на методах передачи словаря, описанных Абрахамом Лемпелем (Abraham Lempel) и Яковом Зивом (Jacob Ziv) (в 1977 и 1978 годах), и известны, соответственно, как LZ77 и LZ78. В методе LZ77 для применения словаря используется под- вижное окно в несжатых данных1. В методе LZ78 словарь формируется в динамическом режиме из несжатых данных. 1 Метод LZW рассматривается более детально в главах, описывающих формат PNG.
236 Форматы и алгоритмы сжатия изображений в действии Сжатие GIF Метод LZW, представляющий одну из разновидностей метода LZ78, был описан в статье Тэрри Велша (Terry Welsh) из компа- нии Sperry (ныне Unisys) в 1984. Компания CompuServe вскоре применила этот метод для сжатия изображений в формате GIF. В методе LZW сжатый поток данных состоит полностью из ко- дов, идентифицирующих строки в словаре. Словарь вначале создается так, чтобы содержать в виде заранее определенной строки любое возможное значение данных. Например, при ко- дировании 8-битовых данных, словарь первоначально содержит 256 однобайтовых строк со значениями от 0 до 255. Программа сжатия читает символы из входного потока дан- ных и добавляет их в конец текущей строки до тех пор, пока в словаре будет находиться строка, соответствующая теку- щей строке. Когда текущей строке не будет найдено соответ- ствие в словаре, программа выводит код самой длинной строки, для которой найдено соответствие, и добавляет в словарь строку, для которой не было найдено соответствия (это будет строка с найденным соответствием плюс один символ). Далее программа формирует новую строку, в начале которой располагается символ, создавший ситуацию несоот- ветствия. Каждый раз при записи кода в выходной поток в словарь добавляется новая запись. Алгоритм 12.2 служит иллюстрацией процедуры создания словаря в методе LZW. Здесь мы предполагаем, что исполь- зуются 8-битовые данные, и что функция Output записывает в выходной поток 9-битовые коды. Global String DICTIONARY [0..511] Global NEXTCODE = 256 Procedure Initialize Begin For I = 0 To NEXTCODE - 1 Do DICTIONARY [I] = CHARACTER (I) End Function SearchDictionary (String SEARCH) Begin For I = 0 To NEXTCODE - 1 Do Begin If DICTIONARY [I] = SEARCH Then Return I End Return -1 End Алгоритм 12.2. Упрошенное сжатие LZW
GIF 237 Алгоритм 12.2. Продолжение Procedure Compress (String DATA) Begin - . / Initialize LASTSTRING = NULL For I = 1 To Length (DATA) Do Begin Currentstring = LASTSTRING + DATA [I] CODE = SearchDictionary (CURRENTSTRING) If CODE < 0 Then Begin I/ Теперь получена строка, для которой нет // соответствия в словаре. Выводим // код самой длинной подстроки, для которой // есть соответствие. CODE = SearchDictionary (LASTSTRING) Output (CODE) // Добавляем в словарь строку, для которой // не найдено соответствие. DICTIONARY [NEXTCODE] = CURRENTSTRING NEXTCODE = NEXTCODE + 1 // Начинаем новую строку с символа, // заканчивавшего строку, для которой // не было найдено соответствие LASTSTRING = DATA [I] End Else Begin // Для текущей строки есть соответствие в словаре. // Продолжаем добавлять к строке символы // до возникновения несоответствия. LASTSTRING = CURRENTSTRING End End // Выводим все, что осталось Output (SearchDictionary (LASTSTRING))' End Рис. 12.5 иллюстрирует процесс LZW-сжатия на примере строки. Первый столбец показывает вид исходной строки на каждой стадии процесса сжатия; второй столбец показывает значения, записываемые в выходной поток на каждой стадии; третий столбец показывает вновь создаваемый код. Входная строка из примера на Рис. 12.5, включает 27 симво- лов. Поскольку каждый символ определяется -8 битами, то для всей строки потребуется 216 битов. Для представления этой же строки в методе LZW используется 20 литеральных значений (literal values) и словарных кодов. Для кодирования каждого значения LZW требуется 9 битов, а вся строка опре- деляется 180 битами, что на 17% меньше по сравнению с не- сжатой строкой. Для кодирования удвоенной строки (строка
238 Форматы и алгоритмы сжатия изображений в действии повторяется дважды) потребуется только 33 кода, (31%-ое уменьшение), а для кодирования утроенной строки необхо- димо 42 кода (41%-ое уменьшение). Таким образом, чем больше повторов во входном потоке данных, тем большая степень сжатия, обеспечиваемая методом LZW. Рис. 12.5. Пример LZW-сжатия A MAN A PLAN A CANAL PANAMA Входные данные Выходные данные Новый код A MAN A PLAN A CANAL PANAMA A MAN A PLAN A CANAL PANAMA <SPACE> 256='A<SPACE>' MAN A PLAN A CANAL PANAMA M 257='<SPACE>M' AN A PLAN A CANAL PANAMA A 258='MA N A PLAN A CANAL PANAMA N 259=AN' A PLAN A CANAL PANAMA <SPACE> 260='N<SPACE>' A PLAN A CANAL PANAMA 256 261 ='A PLAN A CANAL PANAMA P 262='A<SPACE>P' LAN A CANAL PANAMA L 263='PL' AN A CANAL PANAMA 259 264='LA' A CANAL PANAMA 261 265='AN<SPACE>' CANAL PANAMA <SPACE> 266='<SPACE>A<SPACE>' CANAL PANAMA C 267='<SPACE>C' ANAL PANAMA 259 268='CA' AL PANAMA A 269='ANA' L PANAMA L 270=AL' PANAMA <SPACE> 271='L<SPACE>' PANAMA P 272='<SPACE>P' ANAMA 269 273='PA' . MA 258 274='ANAM' Развертывание GIF Распаковщик LZW считывает коды из потока сжатых данных по отдельности и поддерживает работу со словарем тем же самым способом, что и упаковщик. Каждый код просто заме- няется значением из словаря. Единственная тонкость в распаковке состоит в возможности по- явления в потоке сжатых данных кодов, которые не были опре- делены в словаре. На Рис. 12.6 представлен пример сжатия, ил- люстрирующий возникновение такой ситуации. Обратите вни- мание, что код 259 выводится одновременно с определением кода. Декодер, обрабатывающий такую последовательность данных, прочитал бы значение 259 до определения кода 259.
GIF 239 Рис. 12.6. ABYABABAX Пример Входные Выходные Новый LZW-сжатия, когда код данные данные КОД используется ABYABABAX А до того, как он BYABABAX В 256=‘АВ' определен в YABABAX Y 257='BY' словаре АВАВАХ 256 258='YA' АВАХ 259 259='АВА' X X 260='АВАХ' Такая ситуация может возникать только в случае, когда новая строка словаря состоит из строки, представленной последним обработанным кодом, и последнего символа, содержащегося в коде, определенным в словаре последним. Как видно из Рис. 12.6, последний код, выведенный до 259, равен 256 и ему соответствует значение 'АВ'. Последним символом пре- дыдущего кода (258) в словаре является 'А', так что строкой словаря для кода 259 будет 'АВ' + 'А'= 'АВА'. Алгоритм 12.3 иллюстрирует процесс развертывания LZW-кода. Алгоритм 12.3. Упрошенное развертывание LZW-кола Procedure Expand Begin LASTCODE = Inputcode () Output (LASTCODE) While NOT EndOfStream DO Begin CODE = Inputcode () If CODE < NEXTCODE Then Begin Output (Dictionary [CODE]) Dictionary [NEXTCODE] = Dictionary [LASTCODE] + Dictionary [NEXTCODE -1][1] NEXTCODE = NEXTCODE + 1 LASTCODE = CODE End Else Begin // Особый случай использования кода // до его определения Dictionary [NEXTCODE] = Dictionary [LASTCODE] + Dictionary [LASTCODE][1] NEXTCODE = NEXTCODE + 1 Output (DICTIONARY [CODE]) LASTCODE = CODE End End End
240 Форматы и алгоритмы сжатия изображений в действии Размеры кода До сих пор подразумевалось, что мы используем 9 битов, что- бы представить в потоке сжатых данных коды словаря и лите- ральные значения. Однако если размер входного потока пре- вышает 256 байтов, то для представления каждого значения необходимо будет использовать 10 битов. Входные потоки больших размеров могут потребовать еще больших размеров кода. Поскольку использование слишком большого размера кода приводит к слабому сжатию, возникает проблема выбора размера кода, оптимального для большинства ситуаций. Решение этой проблемы в методе сжатия LZW состоит в использовании переменного размера кода. В начале процесса сжатия каждое значение сохраняется с помощью минимально возможного числа битов (почти всегда это число равно 9). Ко- гда количество кодов становится слишком большим, чтобы их можно было представить с помощью текущего размера кода, размер кода увеличивается на 1 бит. Если начальный размер кода равен 9, то коды выводятся с использованием 9 битов, пока не будет создан код 512. Тогда размер кода автоматиче- ски увеличивается до 10 битов. Аналогично, после достижения кода 1024, размер кода будет увеличен до И битов. Макси- мальный размер кода, разрешенный в формате GIF, равен 12. Когда значения кода достигают 212-1, кодеры и декодеры GIF прекращают добавлять в словарь новые значения. Кодер GIF может выводить специальный код очистки (clear code), предписывающий декодеру выполнить установку сло- варя в его первоначальное состояние. Кодер может выводить . код очистки всякий раз, когда определяет, что при использо- вании нового словаря сжатие может быть улучшено. Очевид- ная ситуация, где это могло бы быть желательным - дости- жение максимально допустимого размера кода. Повторение друг за другом кодов очистки стандартом не запрещается, но расточительно. Значение кода очистки не фиксировано, а скорее зависит от минимального размера кода, который следует за заголовком изображения. Минимальный размер кода задает количество битов, используемых для кодирования пиксельных данных. Обычно это значение равно 8 битам на пиксел, но пиксель- ные данные изображений, не использующих 256 цветов, мо- гут быть сжаты с помощью меньшего числа битов.
GIF 241 В Таблице 12.11 показано соотношение между минимальным размером кода и кодами, используемыми в изображениях GIF. Код конца (end code) применяется для указания конца сжатого потока данных. Таблииа 12.11. Использование колов GIF Диапазон кодированных значений Применение 0_2Л^ини*<альный размер кола _ -j Литеральные коды ^Минимальный размер кола Код очистки ^Минимальный размер кола -j Код конца ^Минимальный размер кола 2 — 2 — 1 Коды строк Структура словаря 256 = АВ 257 = ВА 258 = АВС 259 = СА 260=ABD АВС I I I В А А 256 257 259 С D 258 260 Рис. 12.7. Прелставление LZW-словаря в виле лерева В наших примерах сжатия и развертывания файлов GIF для определения словаря использовался массив строк. Обычно же словарь представляется с помощью древовидной структуры. На Рис. 12.7 показано, как строки, сгенерированные при сжа- тии строки ‘ABABCABD', могут быть представлены в виде дре- вовидной структуры. Код может транслироваться в строку путем перемещения от узла дерева, соответствующего коду, к корню дерева. При преобразовании кода в строку путем прохода дерева от его листа до корня строка генерируется в обратном порядке. На Рис. 12.7 проход по дереву, начийая с кода 260, дает в ре- зультате строку "DBA". Для упорядочивания строки применя- ется стек. При проходе дерева, каждый раз, когда достигается узел дерева, соответствующий символ помещается в стек. При достижении корня дерева символы выталкиваются из стека в правильном порядке. Дерево может быть представлено в виде массива структур. Так как максимальная длина кода равна 12 битам, макси- мальное число узлов дерева равно 2 . Размер стека также ра- вен 2 символов. Алгоритм 12.4 иллюстрирует реализацию развертывания LZW-кода с использованием словаря в виде древовидной структуры и кодов переменной длины.
242 Форматы и алгоритмы сжатия изображений в действии Global Structure DICTIONARYTREE Array [0..212-!] Begin Byte CHARACTER Integer PARENT End Global STACK Array [1.. 212] Of Byte Global STACKPOINTER Global MINIMUMCODESIZE = 8 Global CODESIZE Global ENDCODE Global CLEARCODE Global NEXTCODE Global FIRSTCHARACTER Procedure initializeDictionary Begin For II = 0 To 2CodeSize-l Do Begin DICTIONARYTREE [II].CHARACTER = II DICTIONARYTREE [II].PARENT = 0 End STACKPOINTER = 0 CODESIZE = MINIMUMCODESIZE CLEARCODE = 2MINIMUMC0DESIZE ENDCODE = CLEARCODE + 1 NEXTCODE = ENDCODE + 1 End Procedure Outputcode (CODE) Begin // Помещение символов словарных записей // в стек в обратном порядке Do Begin STACK [STACKPOINTER] = DICTIONARYTREE [CODE].CHARACTER STACKPOINTER = STACKPOINTER + 1 CODE = DICTIONARYTREE [CODE].PARENT End While DICTIONARYTREE [CODE].PARENT <> 0 // Древовидная структура усложняет поиск // первого символа в последнем обработанном коде. // Мы помним об этом. FIRSTCHARACTER = STACK [STACKPOINTER] // Выталкиавние значения из стека в обратном порядке. While STACKPOINTER > 0 Do Begin Алгоритм 12.4. Развертывание LZW
GIF 243 Output (STACK [STACKPOINTER]) STACKPOINTER = STACKPOINTER - 1 End End Procedure Expand (OUTPUT : String) Begin InitializeDictionary () CODE = ReadBits (CODESIZE) While CODE = ClearCode Do CODE = ReadBits (CODESIZE) OutputCode (CODE) While TRUE Do Begin LASTCODE = CODE If NEXTCODE >= 2codesize And CODESIZE < 12 Then CODESIZE = CODESIZE + 1 CODE = ReadBits (CODESIZE) If CODE = ENDCODE Then Return Else If CODE = CLEARCODE Then Begin InitializeDictionary () CODE = ReadBits (CODESIZE) While CODE = CLEARCODE Do CODE = ReadBits (CODESIZE) If CODE = ENDCODE Then Return OutputCode (CODE) End Else If CODE < NEXTCODE Then Begin OutputCode (CODE) DICTIONARYTREE [NEXTCODE].PARENT = LASTCODE DICTIONARYTREE [NEXTCODE].CHARACTER = FIRSTCHARACTER NEXTCODE = NEXTCODE + 1 End Else Begin // Особый случай неопределенного кода DICTIONARYTREE [NEXTCODE].PARENT = LASTCODE DICTIONARYTREE [NEXTCODE].CHARACTER = FIRSTCHARACTER NEXTCODE = NEXTCODE + 1 OutputCode (CODE) End End End Алгоритм 12.4. Продолжение
244 Форматы и алгоритмы сжатия изображений в действии esxssassssBBte Анимация в GIF В отличие от всех других форматов, обсуждаемых в этой книге, формат GIF позволяет сохранять в одном файле мно- жество изображений. В Web-браузерах это свойство GIF- формата используется для сохранения простых мультиплика- ций. Официальные стандарты не описывают порядок ото- бражения GIF-файла, содержащего множество изображений. Многие программы просмотра изображений ограничиваются воспроизведением только первого изображения в файле GIF. Тем не менее, отображение GIF-анимации основными Web- браузерами отличается определенной согласованностью. На Рис. 12.8 представлена последовательность из трех кад- ров, составляющих простую анимацию. Для хранения этих изображений в виде анимации GIF, три изображения кодиру- ются друг за другом в отдельные блоки изображений. Обыч- но Web-браузеры отображают каждое изображение последо- вательно, с максимально возможной скоростью. Чтобы управлять интервалом времени между воспроизведением от- дельных кадров, можно использовать расширение управле- ния графикой (см. Таблицу 12.8). Расширение управления графикой воздействует только на изображение, находящееся непосредственно за расширением, так что, возможно, в ани- мационной последовательности потребуется определять по одному расширению для каждого изображения. Рис. 12.8. Пример GIF-анимаиии Большинство программ проигрывают анимацию всего один раз. Чтобы создать анимацию, проигрываемую в цикле, в файл следует включить специальное расширение програм- мы (см. Таблицу 12.9), формат которого представлен в Таб- лице 12.12. Хотя идентификатор программы определен как "NETSCAPE", он всего лишь указывает на программу- создатель блока. Другие Web-браузеры также распознают данный формат блока.
GIF 245 Поле Repeat Count (Счетчик повторений) в расширении про- граммы задает число проигрываний анимации. Нулевое зна- чение определяет бесконечное число проигрываний анима- ции. Поскольку воспроизведение изображений может суще- ственно загрузить процессор домашнего компьютера, осо- бенно, если не определена задержка между кадрами, то, в большинстве случаев, идею бесконечного проигрывания анимации нельзя назвать хорошей. Таблица 12.12. Формат расширения программы с циклом Имя ПОЛЯ Размер Описание Block Size (Размер блока) 1 байт 11 Application ID (Идентификатор программы) 8 байтов "NETSCAPE" Authentication code (Код аутентификации) 3 байта "2.0" Block Size (Размер блока) 1 байт 3 Extension Туре (Тип расширения) 1 байт 1 Repeat Count (Счетчик повторов) 2 байта Число повторных запусков мультипликации Terminator (Завершитель файла) 1 байт 0 Дескриптор логического экрана (Logical screen descriptor) (см. Таблицу 12.2) определяет размеры анимации. Каждое изображение вовсе не обязано обновлять весь логический эк- ран. Поля размеров и положения изображения, входящие в за- головок изображения (см. Таблицу 12.5), позволяют опреде- лять в пределах логического экрана область для обновления изображения. Отсутствие обновления экрана в каждом изо- бражении может значительно уменьшить размер файла GIF. Рис. 12.9. Анимация, частично обновляющая логический экран
246 Форматы и алгоритмы сжатия изображений в действии На Рис. 12.9 показано, как в рассмотренной выше анима- ции можно установить обновление только части логиче- ского экрана. Юридические проблемы В своей статье, опубликованной в 1984 году в журнале "IEEE Computer", Вэлш (Welsh) не упомянул, что им подана в 1983 году заявка на патент на описанный в статье метод. Впослед- ствии, в 1985 г., был получен патент (4,558,302), и им стала распоряжаться компания Sperry (теперь Unisys). По некото- рым причинам (в то время патенты на программное обеспе- чение были новинкой, и связанные с ними юридические во- просы не были отработаны) компания CompuServe при вы- пуске спецификации на формат GIF не проверила патентную чистоту метод LZW. Со временем использование формата GIF росло, а вопросы, касающиеся патента носили теоретический характер, пока в 1994 компания Unisys не потребовала от пользователей GIF лицензионных выплат за пользование LZW. Это сделало не- возможным использование GIF в бесплатно распространяе- мых программах. Решение проблемы с патентом для формата GIF не сводится только к получению лицензии от компании Unisys. Сущест- вует множество других патентов, относящихся к методу LZ, права на которые могут быть нарушены при реализации дан- ного метода сжатия. В 1989 году Виктору Миллеру (Victor Miller) и Марку Вегману (Mark Wegman) из компании IBM был выдан широко известный патент (4,814,726), связанный с форматом GIF. Их патент описывает метод, который почти идентичен методу LZW. В результате такой ситуации с патен- тами, любой, кто захочет использовать формат GIF в какой- либо программе, нуждается в совете адвоката. Фундаментальная проблема состоит в том, что метод LZW сам по себе не является оригинальной разработкой, а пред- ставляет частный случай более ранней работы. При наличии базы данных, переполненной патентами, производными от LZ, невозможно определить, права на какие патенты могут быть нарушены при новой реализации формата GIF. Этих патентов не просто много, хуже того, они еще и напи- саны на юридическом жаргоне, что делает их трудными для
GIF 247 понимания. В связи с юридическим хаосом вокруг GIF, луч- шее решение для разработчиков состоит в использовании других форматов. В отличие от формата JPEG, ситуация с па- тентами на GIF вряд ли будет разрешена удовлетворительно. IIIHIiL. II lll.l.I.lll . II I I I Несжатый GIF Патентами защищен метод сжатия LZW, а не формат GIF, по- этому вполне возможно создавать файлы GIF, которые не ис- пользуют сжатия LZW. Самый простой способ реализации кодера GIF, не использующего LZW, состоит в кодировании каждого байта данных с помощью 9 битов, и выводе кода очистки после каждых 254 кодов. Хотя это приводит к отри- цательному сжатию, соответствующий декодер GIF сможет правильно интерпретировать данные. Уже реализованы другие методы сжатия, совместимые с форматом GIF. В принципе, можно вести счет серий одина- ковых значений пикселов или серий из разных значений пик- селов и сжимать их в формате GIF. Неизвестной остается лишь патентная чистота этих методов. Заключение Формат GIF был первым форматом изображения, получив- шим всеобщее признание. К сожалению, юридические про- блемы положили конец развитию GIF. В отличие от других основных графических форматов, ныне работы по развитию GIF не ведутся. Все это, вместе со свойственными формату GIF ограничениями, отсутствующими в других форматах, по сути, сделало формат GIF устаревшим. Нельсон (Nelson) (1992) издал превосходное введение в ме- тоды сжатия LZ и их основные реализации. Алгоритмы LZ77, LZ78, и LZW первоначально были описаны Зивом (1977, 1978) и Вэлшем (1984). Мы можем рассказать вам, как GIF работает. К сожалению, мы не можем продемонстрировать работу с форматом GIF. Из-за проблем с патентами, на прилагаемом к книге компакт- диске нет никакого исходного кода GIF. Простое описание GIF в книге уже требует вовлечения адвокатов в процесс под- готовки издания. Шекспир был прав.
ГЛАВА 13. PNG Формат: PNG (Portable Network Graphics - Переносимая сетевая графика) Разработчик: Группа Разработки PNG Определение: Спецификация PNG V1.0 (RFC 2083) Формат данных ZLIB V3.3 (RFC 1950) Формат сжатых данных DEFLATE Спецификация V1.3 (RFC 1951) Формат PNG - самый новый графический формат из всех описанных в этой книге. Именно сейчас он начинает завое- вывать широкое признание сообщества Интернет, а его под- держка включается во все, сколько-нибудь значимые, про- граммы просмотра изображений. Формат PNG использует процесс сжатия без потерь и под- держивает следующие возможности. ✓ До 48 битов на пиксел для цветных изображений. ✓ 1-, 2-, 4-, 8-, и 16-битовая точность дискретизации (sample precision). ✓ Альфа-канал для полного управления прозрачностью. ✓ Совершенное цветовое соответствие. Из-за юридических проблем, блокирующих использование GIF, именно формат PNG ныне следует использовать вместо GIF в тех приложениях, где формат JPEG - неподходящая альтернатива. В ситуациях, где требуется обеспечить сжатие без потерь изображений с 24-битовой глубиной цвета, на- пример, при многократном повторном редактировании изо- бражений, формат PNG подходит намного лучше в качестве промежуточного формата, чем формат JPEG. В этой главе описывается структура PNG-файлов и формат отдельных частей, определяемых в стандарте PNG. В двух последующих главах рассматриваются формат сжатых дан- ных и вопросы чтения и записи PNG-файлов.
250 Форматы и алгоритмы сжатия изображений в действии История Когда компания Unisys начала требовать от пользователей GIF плату за лицензии, использование GIF во многих ситуа- циях стало невозможным, особенно для свободно (бесплатно) распространяемого программного обеспечения. Предприня- тые компанией Unisys действия привели к тому, что формат JPEG стал быстро заменять GIF в программах обработки фо- тографических изображений. Однако формат JPEG не сжи- мает некоторые типы изображений так хорошо, как GIF, и поэтому JPEG не смог заменить GIF во всех областях его применения. По прошествии нескольких дней после заявления, сделанного компанией Unisys о том, что они будут требовать лицензии на использование формата GIF, Томас Боутелл (Thomas Boutell) организовывал команду, которая теперь называется Группой Разработки PNG (PNG Development Group). Нача- лось быстрое развитие стандарта PNG, было выпущено и представлено общественности несколько черновых проектов. Финальная версия стандарта вышла 1 октября 1996, всего лишь через полтора года после начала проекта. Порядок размещения байтов Формат PNG хранит многобайтовые целые числа со старшим байтом на первом месте (обратный порядок байтов). Битовые строки считываются в направлении от младших битов к старшим. Когда битовая строка пересекает границу байта, старшие биты находятся во втором байте. Коды Хаффмана внутри сжатых данных сохраняются в виде битового кода, записанного в обратном порядке. Старшие би- ты кода Хаффмана сохраняются в младших значащих битах байтов данных. Формат файла Файлы PNG организованы в виде последовательности блоков, называемых в стандарте PNG порциями (chunk). Существует три источника определения типов порций. Некоторые типы порций определяются в стандарте PNG; это наиболее важные
PNG 251 порции, которые должен обрабатывать декодер. Группа Разра- ботки PNG также ведет список зарегистрированных открытых (public) типов порций. При создании кем-либо нового типа порции, который может быть полезен для широкой публики, разработчик может представить свой новый тип для рассмот- рения и последующего возможного добавления в список типов порций PNG. Наконец, есть приватные (private) порции, опре- деляемые конкретными программами. Структура порций соответствует формату, представленному в Таблице 13.1. Этот формат позволяет декодеру пропускать порции, которые он не умеет обрабатывать, и порции, кото- рые по мнению разработчиков не существенны для данной реализации PNG-формата. Способность игнорировать неиз- вестные или несущественные порции является очень важным свойством, так как декодеры должны уметь обрабатывать файлы, содержащие приватные порции, созданные другими программами, а также новые порции открытого типа. Таблииа 13.1. Формат пориии PNG Поле Размер Описание Length (Длина) 4 байта Количество байтов в поле Data (Данные) 0-2 147 483 647 (23,-1) байтов1 тУРе (Тип) 4 байта Имя порции Data (Данные) Длина байтов Данные порции. Формат зависит от типа порции CRC (Контроль циклическим избыточным кодом) 4 байта Контрольные значения CRC-32, вычисляемые по данным порции Именование порций Порциям PNG присваиваются уникальные имена, которые состоят из четырех символов ASCII. Первый, второй и чет- вертый символы в имени типа порции могут быть или про- писными, или строчными. Регистры (верхний или нижний) этих символов подчиняются описываемому ниже соглаше- нию, которое позволяет декодеру определять информацию о порции по одному только имени. 1 Ограничения на размер, накладываемые спецификацией стандарта PNG учитывают возможности языков программирования, которые не умеют обрабатывать целые числа без знака.
252 Форматы и алгоритмы сжатия изображений в действии Третий символ в имени порции должен быть заглавным. Если программа встречает имя порции, содержащее значения, от- личные от символов ASCII, то такое имя считается ошибоч- ным (не достоверным). На Рис. 13.1 показаны некоторые примеры имен порций и приводится описание их значений. Рис. 13.1. Примеры имен порций PNG Открытые Резервные Критичные^ ! Безопасные для копирования IHDR Критичные, открытые, небезопасные для копирования g АМА Некритичные, открытые, небезопасные для копирования pHYs Некритичные, открытые, безопасные для копирования арРх Некритичные, приватные, безопасные для копирования А1РХ Недостоверные АрРх Критичные, приватные, безопасные для копирования арРХ Некритичные, приватные, небезопасные для копирования аааХ Недостоверные Критические пориии Если первый символ в имени порции находится в верхнем регистре (бит 5 пуст), порция считается критический. Чтобы декодировать изображение, декодер должен обработать кри- тическую порцию (critical chunk) абсолютно во всех случаях. Если декодер встречает критическую порцию, которую не может распознать, он должен выводить сообщение об ошиб- ке. Стандарт PNG определяет только четыре критические порции: IHDR, PLTE, IDAT и IEND. Открытые и приватные пориии Второй символ в имени порции открытого типа должен быть заглавным. Открытые типы порций включают все типы, оп- ределенные стандартом PNG, а также дополнительные типы порций, зарегистрированные Группой Разработки PNG. Программы могут создавать собственные приватные типы порций для хранения данных, характерных для конкретной программы. Второй символ в имени порций приватного типа должен быть строчным, чтобы обеспечить отличие от порций открытого типа. Хотя стандарт PNG не запрещает создание программами критиче- ских порций приватного типа, использование таких порций, скорее всего, сделает изображение нечитаемым для других программ.
PNG 253 Безопасные для копирования порции Последний символ в имени типа порции должен быть строч- ным, если эта порция безопасна для копирования, и пропис- ным, если это не так. Программа не должна копировать не распознаваемые ею порции, если четвертый символ в имени типа порции не является заглавным. Предположим, вы разрабатываете программу-редактор изо- бражений PNG, которая автоматически помещает рамку и ло- готип в создаваемое изображение, а затем сохраняет изобра- жение в новом файле. Если программа встречает не извест- ную ей порцию, может быть два варианта дальнейших дейст- вий: передача этой порции в выходной файл без каких-либо изменений или отбрасывание порции. Если программа-редактор PNG встречает приватную порцию, созданнлто программой архивирования, которая сохранила внутри изображения данные индексирования (например, те- му изображения, дату создания, имя фотографа), то програм- ма-редактор не будет знать, как интерпретировать информа- цию такого рода. Тем не менее, копирование этой приватной порции в выходной файл привело бы к совершенно досто- верным результатам. Такая приватная порция, возможно, бу- дет образовывать порцию, безопасную для копирования. С другой стороны, предположим, что программе-редактору PNG встретилась приватная порция, которая содержит ин- формацию по использованию в изображении цветов. После добавления границы, информация в порции больше не будет корректной. Такая приватная порция будет небезопасной для копирования. Контроль циклическим избыточным кодом Каждая PNG-порция содержит 32-битовое значение цикличе- ского избыточного кода (Cyclic Redundancy Check [CRC] - контроль циклическим избыточным кодом), которое вычис- ляется, исходя из кода типа порции и данных порции. CRC - это математическая функция, обычно используемая в сетевом программном обеспечении для проверки корректности дан- ных в полученном сетевом пакете. Перед посылкой пакета передатчик вычисляет для данных функцию CRC, и затем добавляет в передаваемый пакет вычисленное значение CRC. Приемник вычисляет функцию CRC для полученных данных и сравнивает результат со значением CRC из пакета. Если два
254 Форматы и алгоритмы сжатия изображений в действии этих значения CRC не совпадают, приемник пакета может послать передатчику квитирование (неподтверждение прие- ма) для запроса повторной пересылки пакета. Формат PNG-файла определяет расчет функции CRC для ка- ждой порции, чтобы декодеры могли проверять достовер- ность данных в порции после создания файла PNG. Декодер должен вычислять значение CRC для каждой порции в файле PNG и проверять, чтобы вычисленное значение CRC соответ- ствовало значению CRC, хранящемуся в порции. Порция, где эти два значения CRC не совпадают, должна считаться не- достоверной. Функция CRC основана на операции полиномиального деле- ния входных данных по модулю 2, где каждый бит во вход- ном потоке обрабатывается как коэффициент в огромном по- линоме. Значение функции CRC равно остатку от деления. Выбор полинома определяет те типы ошибок в битовом коде, которые могут быть обнаружены функцией CRC. Широко распространено применение 16-битовых и 32-битовых функ- ций CRC. 32-битовый циклический избыточный код (CRC) позволяет обнаруживать большее число ошибок в пакетах больших размеров. Формат PNG использует 32-битовую вер- сию функции CRC, которая известна как CRC-32. В формате PNG применяется следующий полином: Л х2<+ х23+ х22 + х16+ х >2+ ХИ+ х10+ х8+ х^ % t который, в сущности, равен 1 0000 0100 1100 0001 0001 1101 1011 01112 Программные реализации функции CRC всегда используют для вычисления значения функции табличный поиск. По ме- ре обработки каждого байта во входном потоке с помощью справочной таблицы обновляется величина, известная как ре- гистр CRC. В функции CRC, используемой в формате PNG, регистр CRC инициализируется установкой всех битов в 1. После того, как завершится обработка последнего байта, ко- нечное значение CRC будет равно поразрядному дополнению до 1 значения регистра CRC. Используемая в формате PNG процедура вычисления значе- ния CRC для реализации с помощью справочной таблицы вы- глядит как подпрограмма, приводимая ниже.
PNG 255 unsigned long CrcRegister ; void CrcByte (unsigned char data) { unsigned int index = (CrcRegister A data) & OxFF ; CrcRegister = CrcTable [index] A ((CrcRegister >> 8) & OxOOFFFFFF) ; return ; } unsigned long Crc (unsigned char buffer [], unsigned int length) { CrcRegister = OxFFFFFFFFL ; for (unsigned int ii = 0 ; ii < length ; ++ ii) CrcByte (buffer [ii]) ; return -CrcRegister ; } Прежде, чем выполнять какие-либо вычисления CRC, необ- ходимо инициализировать справочную таблицу, содержащую предварительно рассчитанные значения для всех возможных целых значений байтов. Инициализация справочной таблицы может выполняться с помощью приводимой ниже функции: unsigned long CrcTable [256] ; void MakeCrcTable () for (unsigned int ii = 0 ; ii < 256 ; ++ ii) { CrcTable [ii] = ii ; for (unsigned int jj = 0 ; jj < 8 ; ++ jj) { if ((CrcTable [ii] & 0x1) == 0) CrcTable [ii] >>= 1 ; else CrcTable [ii] = 0xEDB88320L A (CrcTable [ii] » 1); } } return ; } Математика, лежащая в основе метода CRC, выходит за рамки этой книги. Тем не менее, чтобы дать вам некоторое представле- ние о том, как выполняется вычисление CRC, сравним константу EDB88320,6 = 1110 1101 1011 1000 1000 0011 0010 00002, используемую для генерирования справочной таблицы CRC, со значением, которое, как мы говорили, эквивалентно CRC. Если взять это значение, изменить порядок битов на обратный и затем добавить в начало единичный бит, то получим значение полино- ма CRC-32 1 0000 0100 1100 0001 0001 1101 1011 01112.
256 Форматы и алгоритмы сжатия изображений в действии Обработка порции Большинство декодеров PNG будет, вероятнее всего, реали- зовываться с применением общей функции чтения данных порции в память. Эта общая процедура выполняла бы сле- дующие шаги: 1. Чтение размера данных порции. 2. Чтение и сохранение типа порции. 3. Если размер данных порции превосходит объем буфера, выделяется память под буфер большего размера. 4. Чтение данных порции. 5. Вычисление значения CRC для данных порции. 6. Чтение из файла значения CRC порции. 7. Сравнение расчетного значения CRC со значением CRC, считанным из файла. Если значения CRC не совпадают, порция недостоверна. После последнего шага декодер может вызвать функцию об- работки порции конкретного типа. Структура файла На Рис. 13.2 показана общая структура PNG-файла. PNG- файл должен начинаться с сигнатуры PNG, за которой следу- ет порция IHDR, и завершается файл порцией IEND. Располо- жение других порций в пределах файла отличается некоторой гибкостью. Ограничения на порядок расположения порций рассматриваются при обсуждении форматов порций. Сигнатура PNG состоит из 8 байтов, значения которых долж- ны быть равны 137, 80, 78, 71, 13, 10, 26, и 10. Они соответст- вуют значениям ASCII-кода 137, Р, N, G, <RETURN>, <LINEFEED>, <CTRL/Z> и <RETURN>. В использовании этих значений в сигнатуре присутствует некая скрытая логика. Кроме очевидной причины включения в файл строки "PNG" для идентификации формата файла, применение большинст- ва других значений достаточно хитроумно.
PNG 257 ^Сигнатура PNG Порция IHDR Порция PLTE ^Порция I DAT 1 Порция I DAT 2 Порция IDAT 3 Порция IDAT n Порция IEND Рис. 13.2. Структура PNG-файла В операционной системе Unix символ <LINEFEED> использует- ся для разделения записей в текстовом файле. В системе MS DOS записи разделяются парой символов <RETURNxLINEFEED>. Многие программы передачи файлов могут работать или в двоичном, или в текстовом режиме. В двоичном режиме эти программы делают побайтовую копию файла, а в текстовом режиме они заменяют символы <LINEFEED> парами символов <RETURN><L1NEFEED>, когда вы- полняется перенос файлов из системы Unix в DOS, и заменяют пары символов <RETURNxLINEFEED> символами <L1NEFEED>, когда файлы перемещаются из DOS в Unix. Если PNG-файл пе- редается одной из таких программ в текстовом режиме, пары символов <RETURNxLINEFEED> или символ <LINEFEED> будут нарушены, в результате декодеру не надо будет считывать файл дальше сигнатуры, чтобы узнать, что файл запорчен. Первый байт в сигнатуре является неотображаемым ASCII- кодом, уменьшая тем самым вероятность того, что декодер перепутает текстовый файл с PNG-файлом. Если вы случайно введете PNG-файл в командную строку DOS, символ <CTRUZ> в заголовке остановит печать содержимого файла, расположенного за сигнатурой. Представление цветов в PNG Формат PNG поддерживает пять различных цветовых моде- лей, или методов представления цвета пикселов внутри изо- бражения. Метод представления цвета определяется в файле в порции IHDR. За исключением формата BMP, все остальные форматы файлов, описанные в книге, используют только один метод представления цвета. Трехкомпонентный RGB Как и формат BMP, формат PNG может представлять цвета в виде трех RGB-компонент. Каждый пиксел представляется тремя 8-битовыми или 16-битовыми значениями цветовых компонентов. Компоненты хранятся в порядке: красный, зе- леный и синий (противоположном порядку компонентов в
258 Форматы и алгоритмы сжатия изображений в действии формате BMP). Трехкомпонентный RGB может применяться только в случаях, когда глубина цвета равна 8 или 16 битам. (Цветовая Палитра Кроме того, PNG-изображения могут использовать в качестве цветовой модели цветовую палитру так же, как это делается в форматах BMP и GIF. Размер палитры зависит от точности дискретизации (sample precision). Файлы изображений, ис- пользующих цветовую палитру, должны содержать порцию PLTE, определяющую палитру. Цветовые палитры могут ис- пользоваться только в случаях, когда глубина цвета равна 1, 2, 4 или 8 битам. Полутоновая шкала В полутоновой цветовой модели изображение описывается с помощью одного компонента, который задает относитель- ную интенсивность свечения пиксела. Полутоновая цвето- вая модель может использоваться для всех значений глуби- ны цвета PNG. В большинстве систем для отображения по- лутоновых изображений декодер должен создавать палитру, используя процедуру, подобную той, что представлена в Алгоритме 13.1. Алгоритм 13.1. Создание полутоновой палитры MAXPIXELVALUE = 2DIS₽IAYBI'rDEFTH-l For II = 0 То MAXPIXEVALUE Do Begin PALETTE [II].RED = II PALETTE [II].GREEN = II PALETTE [II].BLUE = II End RGB с Альфа-каналом PNG-изображения поддерживают использование Альфа- канала для управления прозрачностью изображения. Альфа- канал позволяет объединять изображение с его фоном. Каж- дое значение пиксела содержит дополнительное Альфа- значение (Alpha value), размер которого в битах равен глуби- не цвета изображения. Цветовая модель RGB с Альфа- каналом может использоваться только при глубине цвета равной 8 и 16 битам.
PNG 259 Нулевое значение Альфа-канала означает, что пиксел полно- стью прозрачен, и в этом случае фон полностью виден через изображение. Значение Альфа-канала равному ^убипа^та^оброжепш, _ j соответсТвуеТ ПОЛНОСТЬЮ НвПрОЗраЧ- ному пикселу; это означает, что фон полностью закрыт изо- бражением. Когда значение Альфа-канала равно промежу- точной величине, цвет пиксела сливается с фоном посредст- вом процедуры, показанной в Алгоритме 13.2. Алгоритм 13.2. Слияние Альфа-канала MAXPIXELVALUE = (1 LeftShift BITDEPTH) - 1 OUTPUT.RED = (ALPHA * IMAGEVALUE.RED + (MAXPIXELVALUE - ALPHA) * BACK- GROUND. RED) / MAXPIXELVALUE OUTPUT.GREEN = (ALPHA * IMAGEVALUE.GREEN + (MAXPIXELVALUE - ALPHA) * BACK- GROUND .GREEN) / MAXPIXELVALUE OUTPUT.BLUE = (ALPHA * IMAGEVALUE.BLUE + (MAXPIXELVALUE - ALPHA) * BACK- GROUND. BLUE) / MAXPIXELVALUE Полутоновая шкала с Альфа-каналом Альфа-канал также может использоваться для полутоновых изображений, только в этом случае глубина оттенка ограни- чивается 8 или 16 битами. Цвет каждого пиксела изображе- ния, использующего полутоновую цветовую модель, пред- ставляется с помощью двух значений, содержащих одинако- вое число битов, причем значение Альфа-канала следует за значением интенсивности серого цвета. Процедура слияния изображения с фоном для данной цветовой модели такая же, как и для цветовой модели RGB с Альфа-каналом, за исклю- чением того, что в полутоновой модели с Альфа-каналом присутствует только один компонент. Аппаратно-независимый цвет Все цветовые пространства, рассмотренные до сих пор, были относительными цветовыми пространствами (relative color spaces), в которых значения цветовых компонентов изменя- ются от 0 до 2;V-1, где N - число битов, используемых для представления компонента. Нуль представляет минимальное значение компонента для устройства, a 2N~l - максимальное значение. Предположим, что вы работаете в компании Coca- Cola (Кока-кола), и вам требуются этикетки для бутылок, на- печатанные с одинаковым ярко-красным цветом фона, ис-
260 Форматы и алгоритмы сжатия изображений в действии пользуемым на всех бутылочных наклейках компании Coca- Cola. Если вы сообщите печатнику, что этикетку следует на- печатать цветом (230,0,0) в цветовом пространстве RGB и с точностью дискретизации 8 битов, то цвет напечатанных в конечном итоге этикеток будет зависеть от печатного обору- дования. В действительности, для решения таких задач необ- ходим метод указания абсолютного цвета. Начиная с 1931 года, как раз этим целям служит в фотогра- фии, печати и кино стандарт CIE 1931 (Committee Internationale de L’Eclairage - Международная комиссия по освещению). Этот стандарт использует три цветовых компо- нента, которые обычно обозначаются XYZ. Компонент Y представляет собой яркость (luminance), как и в цветовом пространстве YCbCr; компоненты X и Z представляют ин- формацию о цвете. Они подобны компонентам СЬ и Сг, но реализованы другим способом. Если программе известны значения XYZ для красного, сине- го, зеленого и белого цветов устройства, на котором изобра- жение было первоначально создано, можно преобразовать RGB-значения изображения в значения XYZ, задающие абсо- лютный цвет. Если эти цветовые значения известны также и для экранного изображения, их можно преобразовать в соот- ветствующие RGB-значения для устройства отображения так, что изображение будет воспроизводиться с использованием первоначальных цветов. В этом методе предполагается, что устройство отображения может показывать все XYZ-цвета изображений - на практике данное предположение не всегда справедливо. Продавцы мониторов персональных компьютеров редко вклю- чают значения XYZ в документацию на оборудование. Обычно такая информация предоставляется продавцами при прямой просьбе покупателя. Чтобы еще более запутать ситуацию, изготовители монито- ров указывают цвета, используя цветовое пространство, свя- занное с цветовым пространством XYZ и известное под на- званием xyY. Цветовое пространство xyY является проекцией пространства XYZ на два измерения. Соотношение, связы- вающее пространства xyY и XYZ описывается следующим уравнением:
PNG 261 Уравнение 13.1. Преобразование цветовых пространств xyZ/XYZ X Х~ X +Y + Z Y У~X+Y+Z Y = Y У z_rx(l-x->) У Проецирование цветового пространства XYZ на два измере- ния позволяет представить все возможные цвета на плоском листе бумаги, хотя и с потерей составляющей освещенности (luminance) или яркости (brightness). Рис. 13.3 служит иллюстрацией цветового пространства xyY. Черный треугольник в центре представляет границы CMYK, цветовой охват или диапазон цветов, которые могут отобра- жаться типичным компьютерным монитором. Этот треуголь- ный диапазон - лишь небольшое подмножество видимых цветов. Цветовой охват может изменяться в значительной степени в зависимости от конкретного устройства. Например, диапазон цветов, воспроизводимых типичным настольным цветным принтером, несколько отличается от цветового ох- вата компьютерного монитора. Одна из причин, почему цвета в файлах изображений, как правило, не кодируются с помощью цветового пространства XYZ, заключается в том, что это требует гораздо большей точности данных. Применение цветовой модели RGB позво- ляет ограничиться точностью данных, достаточной для пред- ставления всех цветов, которые может выводить устройство отображения. Поскольку цветовое пространство XYZ охваты- вает все возможные видимые цвета, а не небольшое подмно- жество цветов, воспроизводимых устройством, для кодиро- вания всех цветов цветовой модели XYZ требуется большее число информационных битов. Решение, применяемое в формате PNG, включает использование цветовой модели RGB для кодирования цветовых значений, и создание пор- ций, которые позволяют декодеру определять цвета, реально присутствовавшие в исходном изображении.
262 Форматы и алгоритмы сжатия изображений в действии Когда я связался с производителем моих мониторов, они предоставили мне следующую информацию: Рис. 13.3. Цветовое пространство xyY Монитор 1 х у Красный .612 .353 Зеленый .293 .595 Синий .149 .068 Белая точка: 9300К Монитор 2 X у Красный .625 .340 Зеленый .280 .595 Синий .155 .070 Белая точка: 9300К Устройства отображения обычно изготавливаются так, что- бы белая точка попадала или находилась вблизи набора то- чек данных, образующих так называемую кривую абсолют- но черного тела (black body curve). 9300 К является стан- дартным значением белой точки на компьютерном монито-
PNG 263 ре, у которого значение ху равно (0.285, 0.293). Подразуме- вается, что значение Y равно 1.0. Тогда белая точка для обо- их мониторов описывается в цветовом пространстве XYZ координатами: X = 0,973 У= 1 Z = 1,440 Преобразование из пространства RGB в XYZ описывается произведением матриц в следующем виде: Уравнение 13.2. Преобразование цветового пространства RGB в XYZ X CrXr Cgxg Cbxb R Y CRyR СсУс СвУв G Z Ся(1 -xr-Yr) CG(1 ~xg ~Tg) Q(1 ~XB~ ув) В где CR, Cg и Св - это константы, а цветовые значения RGB промасштабированы, чтобы попадать в диапазон 0-1.0. Сле- дующий шаг состоит в поиске значения этих трех констант. Если подставить значения ху для первого монитора в Урав- нение 13.2, получим: Уравнение 13.3. X' Y Cr X Cr x 0.612 0.353 CG x 0.293 CB Cb x 0.149' x 0.068 R G Cg X 0.595 z 0.035 cG X 0.212 Cb x 0.783 В Мы уже вычислили XYZ-координаты белой точки и знаем, что RGB значение белой точки равно (1.0, 1.0, 1.0). Если под- ставить это значение в предыдущее уравнение, получим: Уравнение 13.4. 0.973 \Cr X 0.612 cG X 0.293 CB x 0.149' T 1.000 = Cr X 0.353 cG X 0.595 Cb x 0.068 1 1.440 Cr X 0.035 cG X 0.212 Cb x 0.783 1 которое может быть разложено на множители: Уравнение 13.5. 0.973 1.000 1.440 0.612 0.293 0.1491 ГО? 0.353 0.595 0.068 CG 0.035 0.212 0.783 Св
264 Форматы и алгоритмы сжатия изображений в действии Это - набор трех линейных уравнений с тремя неизвестными переменными. Теперь можно решить уравнение относитель- но Cr, Cg и Св, получив в результате (0,698, 1,094, 1,512). Та- ким образом, преобразование из цветового пространства RGB в цветовое пространство XYZ для данного монитора прини- мает вид: Уравнение 13.6. X' 0.427 0.321 0.225’ R У = 0.246 0.651 0.103 G Z 0.024 0.232 1.184 В Чтобы выполнить обратное преобразование из XYZ в RGB, следует инвертировать матрицу преобразования. Проще все- го это можно сделать с помощью метода Гауссова исключе- ния (Gaussian elimination). Исключение строк (row reduction) и инверсия матриц не входят в круг вопросов, рассматривае- мых в данной книге, но вы найдете объяснение этих методов в любой книге по линейной алгебре, например, Антона (Anton) (1981). Ниже представлена обратная функция для первого монитора. Уравнение 13.7. R ' 3.170 -1.389 -0.4831 X G = -1.227 2.123 0.049 У В 0.175 -0.387 0.845 Z Гамма Цветовые модели, используемые для представления изобра- жений, основываются на предположении, что между значе- нием цветового компонента и цветом, видимым на экране, существует линейная связь. В действительности применяе- мые устройства отображения не реагируют линейно на по- ступающий входной сигнал. Гамма (Gamma) приближенно описывает нелинейные характеристики этих устройств. С ма- тематической точки зрения, Гамма - степенная функция: Г(х) = х” где 0<х< 1 <р > 0
PNG 265 Настройка Гаммы изображения может выполняться как со- вместно с преобразованием в цветовое пространство XYZ, так и отдельно. Регулировка Гаммы оказывает большее воздей- ствие на вид изображения на компьютерном мониторе, чем преобразование в цветовое пространство XYZ и обратно. Эффект воздействия Гаммы на изображение состоит в при- дании компоненту более темного или более светлого оттенка. Значения Гаммы больше 1 делают изображение более тем- ным, а меньше 1 - более светлым. Обратите внимание, что область определения и диапазон значений Гаммы совпадают. Если входное значение функции находится в диапазоне от О до 1, то выходное значение также будет принадлежать этому же диапазону. Значение Гаммы для системы отображения равно значению объединенной Гаммы компонентов. Уравнение 13.8. Объединение Гамм Г1(Г2(...1Мг))) = .г1 2 = ^1ХИх...хед = %] Другими словами, значение Гаммы для системы отображения равно произведению значений Гамм всех ее компонентов. Порция дАМА позволяет кодеру сохранять значение Гаммы системы, с помощью которой создавалось изображение. Раз- работчики декодеров PNG сталкиваются с двумя проблемами: ✓ Какие значения Гаммы должны использоваться для просмот- ра изображения? ✓ Чему равна Гамма системы, используемой для отображения изображения? Фактически, программа не может определить, каким должно быть значение Гаммы для просмотра изображения. В хорошо освещенной комнате значение Гаммы, вероятно, должно быть равно приблизительно 1,0. В темной комнате значение Гаммы должно быть больше, приблизительно 1,5 или около этого. Проблема здесь состоит в том, что, если в программное обес- печение декодера не поступает сигнал от светового датчика, то нет никакой возможности определить нужное значение Гам- мы. Лучшее решение - предоставить пользователю возмож- ность самому вводить значение Гаммы или использовать для просмотра изображений значение Гаммы равное 1,0. Для по- >; лучения наилучших результатов многие программы отображе-
266 Форматы и алгоритмы сжатия изображений в действии ния изображений позволяют пользователю корректировать Гамму после того, как изображение выведено на экран. Некоторые профессиональные системы отображения предос- тавляют возможность запроса значения Гаммы системы или, даже, настройки Гаммы с помощью программ. При разработ- ке программного обеспечения для персональных компьюте- ров следует предполагать, что Гамма для всех компонентов компьютера, кроме монитора, равна 1. Если точное значение Гаммы неизвестно2, стандарт PNG рекомендует использовать для мониторов значение Гаммы равное 2,5. Большинство продавцов мониторов обладают данной информацией, хотя она и отсутствует в напечатанной документации. Как сооб- щил производитель моих мониторов, для них значение Гам- мы равно 1,8. Если у вас непрофессиональная система отображения, про- грамма просмотра PNG-файлов не сможет изменять Гамму. Если в PNG-файле присутствует порция дАМА, содержащая значение Гаммы для изображения, то это значение Гаммы будет фиксированным. Так как полная Гамма системы ото- бражения равна Уравнение 13.9. Желаемая_Гамма_просмотра = Программная_Гамма х Гамма-.монитора х Гамма_из_файла то программа может настраивать ее значение, регулируя зна- чения пикселов. Тогда коррекция Гаммы, которую должна использовать программа, равна Уравнение 13.10. _ „ Желаемая гамма просмотра Программная_Гам.ма = ~ Гамма_монитора х Гамма_из_файла Программы должны применять коррекцию Гаммы только к цветовым компонентам. Для Альфа-канала Гамма-коррекция не применяется. Чередование Так же, как и GIF, формат PNG поддерживает режим чередо- вания при отображении изображений. Метод чередования, 2 Ожидается, что в следующей версии стандарта PNG будет рекомендовано значение 2,2 для обес- печения совместимости со стандартом sRGB.
PNG 267 используемый в текущем стандарте PNG, называется Adam 73. В будущем возможно появление других методов чередо- вания, но сейчас стандартом поддерживается только этот ме- тод. В методе Adam 7 чередуются пикселы изображения, а не его строки. Изображение делится на блоки по 8x8 пикселов и обновляется за семь проходов. Применяемая в методе Adam 7 структура чередования пикселов, представлена на Рис. 13.4. Рис. 13.4. 1 6 4 6 2 6 4 6 Шаблон 7 7 7 7 7 7 7 7 чередования 5 6 5 6 5 6 5 6 Adam 7 7 7 7 7 7 7 7 7 3 6 4 6 3 6 4 6 7 7 7 7 7 7 7 7 5 6 5 6 5 6 5 6 7 7 7 7 7 7 7 7 Рис. 13.5. Отображение рисунка в режиме черелования Adam 7 3 В честь создателя метода чередования Адама Кастелло (Adam М. Castello).
268 Форматы и алгоритмы сжатия изображений в действии Метод Adam 7 значительно более труден для реализации, чем построчное чередование в формате GIF. К счастью, шаблон чередования содержит постоянные интервалы, что может быть использовано декодером. На Рис. 13.5 показано, как де- кодер отображал бы «на лету» блок пикселов 8x8, используя шаблон чередования Adam 7. Этот рисунок позволяет яснее представить порядок чередования в методе Adam 7. Критические пориии Стандарт PNG определяет четыре критические порции (IHDR, PLTE, IDAT, и IEND). Большинство PNG-файлов не должно содержать никаких других порций кроме указанных выше. Порции IHDR, IDAT, и IEND должны присутствовать в каж- дом PNG-файле. Ранее уже перечислялись общие операции, которые должен выполнить декодер при обработке порции. IHDR Любой PNG-файл содержит одну порцию IHDR, которая должна следовать сразу за сигнатурой PNG. Блок IHDR опре- деляет размеры изображения, глубину цвета, и цветовую мо- дель. Структура блока данных внутри порции IHDR пред- ставлена в Таблице 13.2. Длина данных порции IHDR равна 13 байтам. Любая другая длина порции должна рассматри- ваться декодерами как недостоверная. Декодер должен проверять, чтобы глубина цвета соответст- вовала цветовой модели. Как уже упоминалось ранее, не вся- кая комбинация глубины цвета и цветовой модели является допустимой. Цветовая модель RGB и цветовые модели с Альфа-каналом работают только при глубине цвета равной 8 и 16 битам. Когда глубина цвета равна 16 битам, модель цве- товой палитры не действует. Поля Compression method (Метод сжатия) и Filter method (Ме- тод фильтрации) предназначены для будущих расширений стандарта PNG. В настоящее время поддерживается единст- венный метод сжатия - Deflate (Понижение порядка) с 32К- байтовым или меньшим подвижным окном, и определен только один метод фильтрации. Декодер должен проверять, чтобы значения этих полей были нулевыми.
PNG 269 Для обработки порции IHDR декодер должен: ✓ Удостовериться в том, что до обработки IHDR никакие дру- гие порции не были обработаны; ✓ Проверить соблюдение следующих требований: - Длина данных порции должна быть равна 13; - Поля Compression method (Метод сжатия) и Filter method (Метод фильтрации) должны быть нулевыми; - Признак метода чередования должен быть равен 0 или 1; - Признак цветовой модели должен быть равен 0,2,3,4 или 6; - Точность дискретизации (sample precision) должна рав- няться 1, 2, 4, 8 или 16 битам; - Должны быть согласованы друг с другом точность дис- кретизации и тип цветовой модели; - Должна быть выделена память для буфера изображения и цветовой палитры. Таблица 13.2. Формат данных порции IHDR Имя поля Размер поля Описание Width (Ширина) 4 байта Ширина изображения в пикселах Height (Высота) 4 байта Высота изображения в пикселах Bit depth (Битовая глубина) 1 байт Точность дискретизации (1,2, 4, 8 или 1 6) Color type (Тип цветовой модели) 1 байт Метод интерпретации данных изображения О - Полутоновое изображение 2 - Трехкомпонентный RGB 3 - Нветовая палитра 4 - Полутоновая модель с альфа- каналом 6 - RGB с альфа-каналом Compression method (Метод сжатия) 1 байт Должно быть нулевым Filter method (Метод фильтрации) 1 байт Должно быть нулевым Interlace method (Метод чередования) 1 байт 0 - Отсутствует чередование пикселов изображения 1 - Чередование Adam 7
270 Форматы и алгоритмы сжатия изображений в действии PLTE Порция PLTE определяет для изображения цветовую палит- ру. В изображении может быть только одна порция PLTE, и она должна располагаться перед первой порцией IDAT. Ко- гда для изображения используется модель цветовой палитры, файл должен содержать порцию PLTE. Данные в порции PLTE представляют собой массив элементов палитры, струк- тура которых показана в Таблице 13.3. Число элементов па- литры равно числу байтов данных в порции PLTE, деленному на 3, причем количество элементов палитры ограничивается значением 21 луби"а~увета. Число элементов палитры может быть меньше максимума, определяемого глубиной цвета. Значения цветов в порции PLTE находятся в диапазоне 0-255, незави- симо от глубины цвета изображения или цветовой модели. Таблииа 13.3. Формат структуры Имя ПОЛЯ Размер Описание Red (Красный) 1 байт Величина интенсивности красной компоненты (0-255) элементов палитры Green (Зеленый) 1 байт Величина интенсивности зеленой компоненты (0-255) Blue (Синий) 1 байт Величина интенсивности синей компоненты (0-255) При использовании цветовой модели RGB или RGB с Альфа- каналом присутствие в файле порции PLTE носит необяза- тельный характер. Кодер может включать в файл модель цве- товой палитры для изображений с вышеперечисленными цветовыми моделями, чтобы обеспечить использование ре- комендуемой палитры, если требуется выполнить квантова- ние цветности изображения до 256 цветов. В такой ситуации присутствие в файле порции не нарушает положений стан- дарта, даже когда глубина цвета равна 16 битам. Однако раз- рядность значений цветовых компонентов равна 8 битам, не- зависимо от глубины цвета. Файлы полутоновых изображе- ний не могут содержать порцию PLTE. Для обработки порции PLTE декодер должен: ✓ Удостовериться в том, что никакая другая порция PLTE еще не обрабатывалась; ✓ Проверить, чтобы цветовая модель изображения не была ни полутоновой, ни полутоновой с Альфа-каналом;
PNG 271 ✓ Проверить достоверность данных порции: - Число байтов данных в PLTE кратно 3; - Число элементов палитры не превышает 2Глуби"а-чвста-г - Число элементов палитры не превышает 256; ✓ Сохранить RGB-значения палитры порции, используемые для декодирования порции. IDAT Порции IDAT содержат сжатые данные изображения. Все порции IDAT внутри PNG-файла должны следовать одна за другой, не перемежаясь с порциями других типов. Блоки IDAT могут находиться в любом месте после блока IHDR и до блока IEND. Если PNG-файл содержит блок PLTE, блоки IDAT должны располагаться после блока PLTE. Размер данных в блоке IDAT может изменяться в диапазоне от 0 до 231 - 1. Обычно число байтов данных внутри блока IDAT должно на- ходиться в пределах от 4 до 16 Кб. Естественно, последний блок в цепи IDAT-блоков может со- держать гораздо меньше байтов. PNG-файлы, в которых от- сутствуют блоки IDAT, считаются недостоверными. Структу- ра сжатых данных внутри блоков IDAT рассматривается в Главе 13. В отличие от всех других типов порций, большинство деко- деров, вероятно, будут обрабатывать все блоки IDAT как еди- ную группу, а не по отдельности. Это упрощает задачу раз- вертывания сжатых данных и помогает удостовериться в том, что все блоки IDAT располагаются в файле непрерывной це- почкой. При встрече с первым блоком в цепочке блоков IDAT декодер должен: ✓ Удостовериться в том, что до этого не встречались другие цепочки блоков IDAT; ✓ Проверить, чтобы была обработана порция PLTE, если в ка- честве цветовой модели используется цветовая палитра; ✓ Развернуть сжатые данные изображения. IEND Порция IEND отмечает конец PNG-файла, поэтому очевидно, что она должна быть последней порцией в PNG-файле.
Форматы и алгоритмы сжатия изображений в действии 272 Для обработки порции IEND декодер должен: ✓ Удостовериться в том, что обработан хотя бы один блок IDAT; ✓ Удостовериться в том, что длина данных порции равна нулю; ✓ Завершить процесс декодирования. Некритичные пориии Стандарт PNG определяет несколько некритичных или вспо- могательных порций. Это порции, присутствие которых в PNG-файле не является обязательным. Кодер не должен соз- давать ни одну из этих порций, а декодер PNG может просто игнорировать их. Однако, если вы разрабатываете декодер PNG, было бы желательно реализовать обработку как можно большего числа стандартных порций. Также и кодер, чтобы обеспечить максимально возможную переносимость изобра- жения, должен вместо приватных порций программ создавать стандартные, некритичные, порции везде, где это возможно. Многие из некритичных порций, фактически, необходимы только соответствующим специализированным программам или используются для промежуточного хранения данных. Все, что необходимо для файлов, передаваемых через Интер- нет или внедряемых на Web-страницы - это одна, или, воз- можно, две порции tEXt, плюс порция дАМА. bKGD Порция bKGD определяет для изображения возможный цвет фона. Если изображение отображается в окне, размеры кото- рого больше, чем размеры изображения, декодер может ис- пользовать этот цвет фона для заливки областей вне изобра- жения. Если изображение содержит Альфа-канал, декодер может выполнять слияние фонового цвета с изображением. Порция bKGD должна располагаться в изображении перед порциями IDAT. Если изображение содержит порцию PLTE, то она должна предшествовать порции bKGD. Формат данных внутри порции bKGD зависит от цветовой модели изображения. ✓ иветовая палитра. Данные порции состоят из одного байта, который является указателем цвета в цветовой палитре.
PNG 273 ✓ Полутоновая или полутоновая с Альфа-каналом. Данные пор- ции состоят из одного 2-байтового целого числа, которое оп- ределяет интенсивность фона. ✓ RGB или RGB с Альфа-каналом. Данные порции состоят из трех 2-байтовых целых чисел, которые определяют значения для красной, зеленой и синей компонент фона. cHRM Кодер может создавать порцию cHRM для хранения аппарат- но-независимой спецификации (1931 CIE) цветов, применяе- мых для просмотра изображения на исходном дисплее (с по- мощью которого создавалось изображение). Эти данные мо- гут использоваться для преобразования RGB-значений пик- селов в абсолютные цвета посредством метода, описанного ранее в этой главе. Формат порции cHRM представлен в Таб- лице 13.4. Таблииа 13.4. Имя поля Размер Описание Формат пориии cHRM X белой точки 4 байта Значение для белой точки х 100 000 Y белой точки 4 байта Значение для белой точки х 100 000 X красной точки 4 байта Значение для красной точки х 100 000 Y красной точки 4 байта Значение для красной точки х 100 000 X зеленой точки 4 байта Значение для зеленой точки х 100 000 Y зеленой точки 4 байта Значение для зеленой точки х 100 000 X синей точки 4 байта Значение для синей точки х 100 000 Y синей точки 4 байта Значение для синей точки х 100 000 gAMA Если кодеру PNG известно правильное значение Гаммы, ис- пользовавшееся для просмотра исходного изображения, ко- дер может сохранить эту информацию в порции дАМА, чтобы декодер мог повторно воспроизводить изображение так, как оно выглядело на дисплее, с помощью которого создавалось изображение. Данные порции дАМА содержат 4-байтовое це- лое число, равное произведению значения Гаммы на 100 000. Таким образом, значение Гаммы, равное 2,1, хранилось бы в порции дАМА как 210 000. Порция дАМА должна распола-
274 Форматы и алгоритмы сжатия изображений в действии гаться в файле до любой из порций PLTE и IDAT. Формат порции gAMA представлен в Таблице 13.5. Таблииа 13.5. Формат данных пориии gAMA Имя поля Размер Описание Gamma value (Значение Гамма) 4 байта Значение Гамма из файла х 100 000 hIST Кодер может помещать порцию hIST в любой PNG-файл, ко- торый содержит порцию PLTE для обеспечения декодеров приблизительными частотами использования каждого цвета палитры. Порция hIST помогает декодеру в выборе исполь- зуемых цветов, когда отсутствует возможность отображения всех цветов палитры. Если изображение содержит порцию hIST, она должна следовать за порцией PLTE и предшество- вать порциям IDAT. Данные порции hIST представляют собой массив 2-байтовых целых чисел без знака. Число элементов массива в порции hIST должно совпадать с числом цветовых элементов в пор- ции PLTE. Каждый элемент в массиве hIST приблизительно равен относительной частоте использования соответствую- щего цвета из порции PLTE. Если кодеру известны абсолютные частоты использования цветов из палитры, то он может промасштабировать значения так, чтобы они представлялись с помощью 16 битов. Однако нулевое значение частоты должно применяться только тогда, когда цвет не используется вообще. Для RGB-изображения значения частот всегда будут приблизительными, и ни одно из значений не должно быть нулевым. pHYs Порция pHYs используется для хранения абсолютного или от- носительного размера пикселов устройства, использовавшего- ся для просмотра изображения при его создании. Если PNG- файл не содержит порцию pHYs, декодер должен будет дейст- вовать, исходя из предположения, что форма пикселов квад- ратная, а физический размер пикселов устройства, на котором первоначально отображалось изображение, неизвестен. Пор- ция pHYs должна предшествовать в файле порциям IDAT. Формат данных порции pHYs представлен в Таблице 13.6.
PNG 275 Таблица 13.6. Формат данных пориии pHYs Имя ПОЛЯ Размер Описание Pixels Per Unit X (Число пикселов на единицу X) 4 байта Pixels Per Unit Y (Число пикселов на единицу Y) 4 байта Unit Specifier (Указатель единиц измерения) 1 байт 0 - значения X и Y определяют пропорцию размеров 1 - единицы измерения равны метрам. Если значение поля Unit Specifier (Указатель единиц измере- ния) равно О, X, и Y, размеры пиксела в порции pHYs опреде- ляют относительные размеры пикселов на исходном дисплее. Декодер может использовать эту информацию для масшта- бирования изображения на выходном дисплее. Если значение поля Unit Specifier (Указатель единиц измере- ния) равно 1, X, и Y размеры задают для исходного дисплея число пикселов на одном метре. Декодер может использовать эту информацию для вывода изображения с теми же самыми размерами, что и на исходном дисплее. sBIT Кодер может использовать порцию sBIT для хранения коли- чества значащих битов в исходных дискретизованных дан- ных. Если глубина цвета исходных данных, например, 12 би- тов, не поддерживается форматом PNG, декодер может ис- пользовать информацию из порции sBIT для воспроизведения исходных дискретизованных данных. Формат данных порции sBIT зависит от цветовой модели изображения. ✓ Полутоновая. Данные порции состоят из 1 байта, значение которого равно числу значащих битов. ✓ RGB и Цветовая палитра. Данные порции состоят из 3 байтов, значения которых равны числу значащих битов для красной, зеленой и синей компонент.
276 Форматы и алгоритмы сжатия изображений в действии ✓ Полутоновая с Альфа-каналом. Данные порции состоят из 2 байтов, значения которых равны числу значащих битов по- лутоновых данных и значению Альфа-канала. ✓ RGB с Альфа-каналом. Данные порции состоят из 4 байтов, значения которых равны числу значащих битов, соответст- венно, для красной, зеленой и синей компонент и значению Альфа-канала исходного изображения. Все данные порции sBIT должны быть больше нуля и не больше глубины цвета. Для преобразования дискретизованного значения из PNG- файла в значение с исходной глубиной цвета декодер может воспользоваться процедурой, подобной приводимой ниже: unsigned int sourcemax = 1 << sBITvalue ; unsigned int filemax = 1 << BitDepth ; sourcevalue = (filevalue * sourcemax + filemax - 1) / filemax ; В кодере применяется почти такая же процедура: unsigned int sourcemax = 1 << SourceBitDepth ; unsigned int filemax = 1 << FileDepth ; filevalue = (sourcevalue * filemax + sourcemax - 1) / sourcemax ; tEXt Кодер может использовать порцию tEXt для хранения тексто- вой информации, не влияющей на декодирование изображе- ния. Порция tEXt располагается в любом месте между пор- циями IHDR и IEND (но не между порциями IDAT), причем в PNG-файле может быть произвольное число порций tEXt. Данные порции содержат ключевое слово (keyword) и значе- ние ключевого слова. Формат данных порции tEXt представ- лен в Таблице 13.7. Длина поля Keyword (ключевое слово! определяется местоположением признака конца NULL (0). Эта длина не может быть нулевой. Длина поля Text (Текст) равна длине данных порции минус длина полей Keyword (ключевое слово) и Terminator (Признак конца). Эта длина может рав- няться нулю. Концы строк внутри текста должны представ- ляться одиночным символом <LINEFEED>.
PNG 277 Таблица 13.7. Формат порции tEXt Имя ПОЛЯ Размер Описание Keyword (Ключевое слово) Переменный, 1-79 байтов Строка ASCII-символов Terminator (Признак кониа) 1 байт Нулевой признак кониа ключевого слова Text (Текст) Переменный Строка ASCII-символов Стандарт PNG определяет ключевые слова, приводимые в Таблице 13.8. Кодер может использовать данные ключевые слова или создавать новые; однако для обеспечения макси- мальной переносимости изображения декодер должен ис- пользовать предопределенные ключевые слова везде, где это возможно. Ключевые слова чувствительны к регистру. Таблииа 13.8. Предопределенные ключевые слова для порции tEXt Ключевое слово Описание Author (Автор) Имя создателя изображения Comment (Комментарий) Общий комментарий; переделан из комментария GIF Copyright (Авторские права) Сведения об авторских правах Creation Time (Время создания) Время создания исходного изображения Description (Описание) Развернутое описание изображения Disclaimer (Отказ от прав) Юридический отказ от прав Software (Программное обеспечение) Программа, создавшая изображение Source (Источник) Устройство, использовавшееся для создания изображения Title (Заголовок) Краткое описание изображение или заголовок Warning (Предупреждение) Предупреждение о содержимом
278 Форматы и алгоритмы сжатия изображений в действии tIME Порция tIME используется для хранения времени последней модификации изображения. В порции tEXt хранится время создания изображения. Формат данных порции tIME показан в Таблице 13.9. Вместо местного следует пользоваться зулус- ским (Zulu) временем или по Гринвичу (Greenwich). Про- граммы, не меняющие данных изображения, не должны соз- давать новые порции tIME. Порция tIME может располагаться в любом месте после порции IHDR и до порции IEND, но не между порциями IDAT. Таблица 13.9. Формат пориии tIME Имя ПОЛЯ Размер Описание Year (Год) 2 байта Григорианский год (2020, но не 20) Month (Месяц) 1 байт 1-12 Day (День) 1 байт 1-31 Hour (Час) 1 байт 1-23 Minute (Минута) 1 байт 0-59 Second (Секунда) 1 байт 0-60 tRNS Порция tRNS используется для реализации прозрачности без применения Альфа-канала. При использовании этого меха- низма, значения Альфа-канала связываются с цветами, а не с пикселами. Порция tRNS должна располагаться после порции PLTE, при ее наличии, и перед порциями IDAT. Формат дан- ных порции tRNS зависит от цветовой модели изображения, хранящегося в файле. ✓ иветовая палитра. Данные порции состоят из массива байтов, которые определяют значения Альфа-канала, связанные с цветовыми элементами в порции PLTE. Каждому пикселу с цветовым указателем N соответствует N-ый элемент порции tRNS, который определяет значения Альфа-канала для пик- села. Число элементов в порции tRNS должно быть не боль-
PNG 279 ше числа цветовых элементов в порции PLTE. Для элементов палитры, которым в порции tRNS нет соответствующего элемента, значение Альфа-канала равно 255. ✓ Полутоновая. Данные порции состоят из 2-байтового целого числа, которое определяет прозрачный цвет. Все пикселы с этим цветовым значением полностью прозрачны; пикселы с любым другим цветовым значением полностью непрозрач- ны. ✓ RGB. Данные порции состоят из трех 2-байтовых целых чи- сел, которые определяют цветовые RGB-значения. Все пик- селы этого цвета полностью прозрачны; пикселы любого другого цвета полностью непрозрачны. Порция tRNS не должна использоваться, когда в цветовую модель входит Альфа-канал. zTXt Порция ZTXt выполняет ту же самую функцию, что и порция tEXt, за исключением того, что в порции ZTXt текстовые дан- ные сжимаются с использованием метода Deflate (этот же са- мый метод применяется для сжатия данных изображения). Точно так же, как и в случае порции tEXt, в файле может быть произвольное число порций zTXt, и они могут нахо- диться в любом месте файла после порции IHDR и перед пор- цией IEND, но не между порциями IDAT изображения. Фор- мат zTXt порции представлен в Таблице 13.10. Таблица 13.10. Формат порции zTXt Имя ПОЛЯ Размер Описание Keyword (Ключевое слово) 1-79 байтов Несжатая текстовая строка Separator (Разделитель) 1 байт Нулевой признак конца ключевых слов. Compression method (Метод сжатия) 1 байт Значение поля должно быть равно 0 Compressed text (Сжатый текст) Переменный Текст, сжатый с использова- нием метода Deflate
280 Форматы и алгоритмы сжатия изображений в действии Заключение Эта глава содержит введение в формат PNG и описание структуры файлов PNG и порций, входящих в состав файлов. Формат PNG включает поддержку аппаратно-независимых цветов, обеспечиваемую с помощью регулировки Гаммы и цветовой модели XYZ. Формат PNG превосходит GIF во всех отношениях кроме одного: поддержки анимации. В отличие от GIF, PNG-файлы могут содержать только одно изображе- ние. Как уже упоминалось, в настоящее время разрабатыва- ется новый стандарт с поддержкой множества изображений, называемый MNG, который устранит последний барьер на пути к широкому использованию PNG вместо GIF. На прилагаемый к книге компакт-диск записан стандарт PNG, описывающий форматы файлов и блоков PNG. Фолей (Foley) со своими соавторами (1996) приводит дополнитель- ную информацию по коррекции Гаммы, Альфа-каналу и цве- товому пространству XYZ. Блинн (Blinn) (1998), а также Пор- тер (Porter) и Дафф (Duff) (1984) предоставляют полезную информацию по Альфа-каналу и его использованию. Кэм- пбелл (Campbell) (1987), а также Рамабадран (Ramabadran) и Гайтонд (Gaitonde) (1988) дают введение в вычисления CRC. В этой главе содержится пример исходного кода программы PNGDUMP, которая выводит на экран имя порции, длин\ данных порции и значение CRC для каждой порции PNG- файла. Структура этой программы очень похожа на функ- циональную структуру декодера PNG. Для критичных пор- ций, определяемых стандартом PNG, программа PNGDUMP выполняет соответствующие проверки достоверности пор- ций. Основной компонент, добавление которого сделало бы программу к PNGDUMP действующим декодером - это под- программа развертывания данных изображения, хранящихся в блоках IDAT. (Вопросы развертывания сжатых данных рас- сматриваются в следующей главе.) Для запуска программы PNGDUMP введите > PNGDUMP somefile.png в командную строку. Пример выходных данных программы PNGDUMP показан на Рис. 13.6.
PNG 281 Рис. 13.6. { IHDR Пример выходных Data Length: 13 ланных программы Data CRC: 9cc69707 PNCDUMP File CRC: 9cc69707 Image Size: 383 x 262 Bit Depth: 8 Color Type: Palette Index Compression Method: defl ate/infl ate - 32k Sliding Window Filter Method: adaptive Interlace Method: none } { PLTE Data Length: 768 Data CRC: 9fe76824 File CRC: 9fe76824 Palette Color Count: 100 } { IDAT Data Length: 2000 Data CRC: 710a2c5b File CRC: 710a2c5b } { IDAT Data Length: 2000 Data CRC: d857c86a File CRC: d857c86a } { IDAT Data Length: 2000 Data CRC: 119cab52 File CRC: 119cab52 } { IDAT Data Length: 2000 Data CRC: Iab5b934 File CRC: Iab5b934 } { IDAT Data Length: 2000 Data CRC: 610914db File CRC: 610914db } { IDAT Data Length: 5b7 Data CRC: cee96fbe File CRC: cee96fbe } { IEND Data Length: 0 Data CRC: ae426082 File CRC: ae426082 }
ГЛАВА 14. Развертывание сжатых данных PNG-изображения В предыдущей главе, посвященной декодированию PNG- файлов, осталась нерассмотренной тема декодирования сжа- тых данных изображения в блоках IDAT. В этой главе описы- ваются оставшиеся незатронутыми вопросы декодирования PNG-файла. Основное внимание уделяется методу сжатия Deflate, который в формате PNG используется для упаковки пиксельных данных в порциях IDAT. Развертывание сжатых данных изображения Первый шаг в обработке сжатых данных изображения состо- ит в их развертывании. В процессе развертывания данные в порциях IDAT файла изображения обрабатываются как не- прерывный поток байтов, который передается программе- распаковщику для выполнения процедур Deflate/Inflate раз- вертывания. Сегментация потока сжатых данных на порции IDAT не влияет на процесс развертывания. Если бы все сжа- тые данные хранились в одной порции IDAT, или если бы каждый сжатый байт помещался в отдельную порцию IDAT, или если бы для хранения сжатых данных использовалась другая сегментация, промежуточная между этими двумя крайними вариантами, в любом случае последовательность сжатых байтов данных была бы одной и той же. ZLIB, Deflate и PNG До того, как компания Unisys стала требовать лицензии на использование метода LZW в программном обеспечении, об- ласть применения LZW не ограничивалась форматом GIF. Сжатие LZW также реализовывалось во многих типах про- грамм сжатия, включая программу compress из операцион- ной системы Unix. Когда метод LZW стало нельзя использо- вать в свободно распространяемом программном обеспече- нии, возникла неотложная потребность в бесплатном методе сжатия, пригодном для замены метода LZW. Решение про- блемы было найдено в виде универсальной библиотеки сжа- тия, известной как ZLIB.
284 Форматы и алгоритмы сжатия изображений в действии Библиотека ZLIB использует основанный на алгоритме LZ77 метод сжатия, называемый Deflate, происхождение которого связано с программами ZIP и PKZIP. Исходный код сжатия в программе ZIP был слишком сильно ориентирован на про- грамму общего назначения, поэтому Жан-Луп Гейли (Jean- Loupe Gailly) и Марк Адлер (Mark Adler) разработали биб- лиотеку ZLIB, позволяющую реализовывать метод сжатия Deflate в самых разных программах. Библиотека ZLIB исполь- зуется не только в формате PNG, но и в программе архивиро- вания GZIP. В настоящее время Deflate является единствен- ным методом сжатия, поддерживаемым библиотекой ZLIB, но форматом ZLIB предусматривается возможность добавления других методов сжатия. В данной главе мы собираемся рассмотреть библиотеку ZLIB и метод Deflate только в приложении к формату PNG. При использовании в PNG-файлах не все установки, действующие в ZLIB/Deflate, являются допустимыми. Примеры исходного программного кода в этой и следующей главах содержат реа- лизации PNG-подмножества метода сжатия Deflate. Сжатие LZ77 Метод сжатия LZ77 использует подвижное окно для ведения словаря обрабатываемого текста. Поток сжатых данных представляет собой последовательность кодов в виде лите- ральных значений или команд для распаковщика по копиро- ванию текста из подвижного окна в выходной поток. Распаковщик LZ77 считывает коды из потока сжатых данных последовательно. Коды, представляющие литеральные зна- чения, копируются непосредственно в выходной поток. Коды команд заменяются в выходном потоке текстом, копируемым из окна LZ. В обоих случаях подвижное окно LZ перемещает- ся так, что последний символ, скопированный в выходной поток, включается в окно. Большое преимущество сжатия с помощью словаря над кодированием Хаффмана состоит в том, что сжатие с помощью словаря может выполняться «на лету», без необходимости предварительной обработки всего потока, что делает метод сжатия с помощью словаря удоб- ным для таких приложений, как сжатие потоков данных в компьютерной сети.
Развертывание сжатых данных PNG-изображения 285 Рис. 14.1. Пример распаковки по метолу LZ77 На Рис. 14.1 представлен упрощенный пример развертывания данных по методу LZ77 с помощью 16-байтового подвижного окна. Данные состоят из 7-битового ASCII-текста, и еще 1 бит используется для различения литеральных значений от ко- манд, поэтому каждый код в сжатом потоке может быть за- кодирован с помощью 8 битов. В этом примере команды ко- пирования представлены записями <Offset:Length>, где Offset (смещение) - число байтов от начала окна LZ77, a Length (длина) - число копируемых байтов. >МА В описываемом примере первые шесть кодов являются лите- ральными значениями, которые копируются в выходной по- ток. Седьмой код копирует в выходной поток два символа, начиная с десятой позиции в окне LZ ("А"). По мере чтения новых кодов окно заполняется, и текст теряется для процес- сов сжатия. Обратите внимание, что конечная запись "МА" в тексте могла быть сжата в код, если бы строка не сдвигалась из окна.
286 Форматы и алгоритмы сжатия изображений в действии Сжатие Deflate Данные в формате Deflate хранятся в блоках, которые разво- рачиваются или сжимаются с использованием разновидности метода LZ77. Сейчас мы сконцентрируем внимание на фор- мате сжатых блоков Deflate. В методе Deflate используется 32 килобайтовое (или меньшее число, являющееся степенью 2) подвижное окно, расположенное на самом последнем деко- дированном тексте. Во время процесса развертывания в этом окне находятся самые последние развернутые байты данных. Сжатый поток данных содержит коды, которые представляют собой или литеральные значения, или коды расстоя- ния/длины. Когда распаковщик встречает литеральное значе- ние, он копирует его в выходной поток и затем перемещает подвижное окно на одну позицию. Когда из сжатого потока считывается код расстояния/длины, распаковщик использует расстояние, чтобы определить начало последней развернутой строки для копирования данных в выходной поток. При копировании строки из подвижного окна необходимо обслуживать в подвижном окне два указателя, или индекса: один в исходном тексте, который копируется, а другой - в выходных данных. Так как размер подвижного окна является степенью 2, то проще реализовать окно в виде кольцевого буфера вместо физически перемещаемого буфера. Возврат указателей в начало 32К-байтного буфера осуществляется путем выполнения побитовой операции AND (логическое сложение) над указателем и значением 7FFi6 (215-1). Установ- ка индексов в 32-Кбайтном буфере достигается выполнением побитовой операции AND над указателем и значением 7FF]6 (215-1). Алгоритм 14.1 иллюстрирует реализацию операции копиро- вания. В алгоритме предполагается наличие функции OutputByte, которая обрабатывает каждый байт после его раз- вертывания. Аргументами функции CopyData являются число копируемых байтов и расстояние от текущей позиции вывода в окне. Метод Deflate использует в сжатом потоке коды в диапазоне 0-285. Коды 0-255, естественно, представляют в сжатом по- токе литеральные байты. Код 256 служит для маркировки конца сжатого блока, а коды 257-285 используются для за- пуска команды копирования из подвижного окна.
Развертывание сжатых данных PNG-изображения 287 Алгоритм 14.1. Копирование данных по метолу LZ77 Global OUTPUTPOSITION Constant WINDOWSIZE = 1 Leftshift 15 Constant WINDOWMASK = WINDOWSIZE - 1 II 7FF PROCEDURE CopyData (LENGTH, DISTANCE) Begin // Мы добавили размер окна, чтобы индекс // всегда был положительным. // Операция AND будет исключать все излишние расстоя- ния // из данного сложения // (We add the window size to ensure the index COPYPOSITION = (WINDOWSIZE + OUTPUTPOSITION - DIS- TANCE) COPYPOSITION = COPYPOSITION AND WINDOWMASK For II = 1 To LENGTH DO Begin WINDOW [OUTPUTPOSITION] = WINDOW [COPYPOSITION] OutputByte (WINDOW [OUTPUTPOSITION]) // Перемещение на следующую позицию вывода OUTPUTPOSITION = OUTPUTPOSITION + 1 OUTPUTPOSITION = OUTPUTPOSITION And WINDOWMASK // Перемещение к следующему копируемому байту COPYPOSITION = COPYPOSITION + 1 COPYPOSITION = COPYPOSITION And WINDOWMASK End End Формат команды копирования представлен на Рис. 14.2. Ко- ды 257-285 являются частью компонента длины в специфи- каторе команды копирования. Каждый код длины состоит из базового значения длины и нескольких дополнительных би- тов, связанных с этим значением. После чтения кода декодер считывает указанное число дополнительных битов. Чтобы получить полную длину копии, значение дополнительных битов складывается с базовым значением. Базовые значения и число дополнительных битов для каждой длины кода при- водятся в Таблице 14.1. Рис. 14.2. Формат команды копирования <Код длины>[Дополнительные биты длины] <Код расстояния>[Дополнительные биты расстояния] За дополнительными битами следует другой код расстояния, изменяющийся в диапазоне 0-29. Код расстояния определяет базовое значение расстояния от текущего местоположения в буфере и число дополнительных битов. В Таблице 14.2 для кодов расстояний приводятся число дополнительных битов и базовые значения.
288 Форматы и алгоритмы сжатия изображений в действии Таблица 14.1. Базовые значения коловллины Код длины Базовое значение Дополнительные биты Возможные значения длины 257 3 0 3 И число дополнительных битов 258 4 0 4 259 5 0 5 260 6 0 6 261 7 0 7 262 8 0 8 263 9 0 9 264 10 0 10 265 11 1 11-12 266 13 1 13-14 267 15 1 15-16 268 17 1 17-18 269 19 2 19-22 270 23 2 23-26 271 27 2 27-30 272 31 2 31-34 273 35 3 35-42 274 43 3 43-50 275 51 3 51-58 276 59 3 59-66 ТП 67 4 67-82 278 83 4 83-98 279 99 4 99-114 280 115 4 115-130 281 131 5 131-162 282 163 5 163-195 283 195 5 195-226 284 227 5 227-257 285 258 0 258
Развертывание сжатых данных PNG-изображения 289 Таблииа 14.2. Базовые значения Код расстояния Базовое значение Дополнительные биты Возможные значения длины И число дополни- 0 1 0 1 тельных битов 1 2 0 2 2 3 0 3 3 4 0 4 4 5 1 5-6 5 7 1 7-8 6 9 2 9-12 7 13 2 13-16 8 17 3 17-24 9 25 3 25-32 10 33 4 33-48 11 49 4 49-64 12 65 5 65-96 13 97 5 97-128 14 129 6 129-192 15 193 6 193-256 16 257 7 257-384 17 385 *7 385-512 18 513 8 513-768 19 769 8 769-1024 20 1025 9 1025-1536 21 1537 9 1537-2048 22 2049 10 2049-3072 23 3073 10 3073-4096 24 4097 11 4097-6144 25 6145 11 6145-8192 26 8193 12 8193-12288 27 12289 12 12289-16384 28 16385 13 16385-24575 29 24577 13 24577-32768
290 Форматы и алгоритмы сжатия изображений в действии Пример 1. Считывание кода длины «275». Из Таблицы 14.1 определяем, что базовое значение равно 51, а количество дополнительных битов равно 3. 2. Считывание 3 битов дает 1012(5). Значение длины равно 5+51 =56. 3. Считывание кода длины «14». Из Таблицы 14.2 определяем, что базовое значение равно 129, а количество дополнительных битов равно 6. 4. Считывание 6 битов дает 0011002( 12). Значение расстояния равно 12+129=141 Эта команда копирует 56 символов, расположенных за 129 пози- ций до текущей позиции в буфере. В нормальных условиях можно было бы ожидать, что диапа- зоны значений будут ограничиваться степенями 2. Однако в Таблице 14.1 и Таблице 14.2 присутствуют значения 0-285 и 0-29. Так, как же в таком случае кодируются длина и рас- стояние? Ответ - с помощью кодирования Хаффмана. В большинстве процедур развертывания сжатых данных используются две таблицы Хаффмана. Одна из таблиц применяется для деко- дирования длин и литеральных значений, а другая - для де- кодирования Значений расстояний. Кодирование Хаффмана в методе Deflate Метод кодирования Хаффмана, используемый в формате PNG со сжатием Deflate, почти идентичен методу, применяе- мому в формате JPEG (см. Главу 6). Фактически, для декоде- ра PNG, содержащегося на компакт-диске, следует сделать лишь небольшие модификации класса декодера Хаффмана JPEG. Ниже перечисляются различия между кодированием Хаффмана для форматов JPEG и PNG: ✓ В формате JPEG коды Хаффмана, содержащие все единицы, недопустимы. В формате PNG такие коды допускаются.
Развертывание сжатых данных PNG-изображения 291 ✓ В формате JPEG максимальная длина кода Хаффмана равна 16 битам. В формате PNG максимальная разрядность кодов длины и расстояния составляет 15 битов, в то время как таб- лицы кодируются с помощью, максимум, 4 битов. ✓ В формате PNG, если значениям X и Y соответствуют коды Хаффмана одинаковой длины и X больше, чем Y, то код Хаффмана для X больше, чем код Хаффмана для Y. В форма- те JPEG расположение кодов Хаффмана соответствует рас- положению значений в файле. ✓ В формате PNG коды Хаффмана хранятся с обратным поряд- ком битов. Код Хаффмана 11Оог (6) хранится в сжатых данных как 011 и (3). ✓ В формате PNG определения таблицы Хаффмана содержат длину кода Хаффмана для любого возможного значения. Не- используемым значениям присваивается длина кода равная нулю. В формате JPEG длина кода определяется только для тех значений, которые используются на самом деле. Как и в формате JPEG, входными данными для процесса ге- нерирования таблицы Хаффмана являются массив значений и массив длин кодов Хаффмана. В формате PNG значения сор- тируются по величине, а не по длине кода, и массив содержит нулевые коды длины. Нам необходимо добавить процедуру сортировки этих массивов по длине кода и во время генери- рования кода Хаффмана следует учитывать значения с нуле- выми кодами длины. Алгоритм 14.2 иллюстрирует процесс декодирования сжатого блока. Процедуры DecodellsingLengthTable и DecodellsingDistanceTable реализуют декодирование кодов Хаффмана и передачу декодированных значений в выходной поток, используя, соответственно, литералы/таблицу Хафф- мана для длин или таблицу Хаффмана для расстояний. В процессе декодирования также задействованы функция ReadLiteralBits(n), которая возвращает следующие п битов из входного потока, и функция CopyData, определяемая в Алго- ритме 14.1.
292 Форматы и алгоритмы сжатия изображений в действии Алгоритм 14.2. Проиесс декодирования по методу Deflate Procedure DecodeBlock Begin While True Do Begin CODE = DecodeUsingLengthTable () If CODE = 256 Then Return Else If CODE < 256 Then OutputByte (CODE) Else Begin EXTRA = LENGTHEXTRABITS [CODE] BASE = LENGTHBASES [CODE] LENGTH = BASE + ReadLiteralBitS (EXTRA) CODE = DecodeUsingDistanceTable () EXTRA = DISTANCEEXTRABITS [CODE] BASE = DISTANCEBASES [CODE] DISTANCE = BASE + ReadLiteralBitS (EXTRA) CopyData (LENGTH, DISTANCE) End End End Формат сжатых данных До сих пор мы рассматривали сжатие PNG, двигаясь от об- щего к частному. Теперь мы собираемся вернуться назад и рассмотреть формат сжатых данных ZLI В/Def late. Структура сжатых данных представлена в Таблице 14.3. Об- ратите внимание, что большинство полей не являются пол- ными байтами и при использовании в формате PNG для большинства полей определены обязательные значения. Поле Compression Level (Уровень сжатия) относится к информа- тивным полям. Оно дает представление о целесообразности повторного сжатия данных. Поле Check Bits (Контрольные биты) используется для проверки кратности значения заго- ловка числу 31. Двухбайтовый заголовок, значение которого не кратно 31, считается недостоверным. Контрольная сумма Adler-32 выполняет ту же самую функ- цию, что и CRC-32 для блоков PNG. Главное различие состо- ит в том, как они используются. При расчете значения CRC- 32 для PNG-блока входными данными являются байты, хра- нящиеся в файле. Значение контрольной суммы Adler-32 для сжатого потока рассчитывается на основе распакованных байтов. При распаковке каждого байта декодер должен об- новлять значение контрольной суммы Adler-32. После распа-
Развертывание сжатых данных PNG-изображения 293 ковки всех данных декодер должен сравнивать значение кон- трольной суммы Adler-32, вычисленное для развернутых дан- ных, со значением, хранящимся в поле контрольной суммы Adler. Если эти два значения не совпадают, декодер будет считать, что данные были повреждены. Таблииа 14.3. Формат сжатых ланных Имя ПОЛЯ Размер Описание Header (Заголовок) 2 байта Compression method (Метод сжатия) 4 бита Должно быть равно 8 Window Size (Размер окна) 4 бита Должно быть не более 7 Check Bits (Контрольные биты) 5 битов Делает значение первых двух байтов кратным 31 Preset Dictionary (Предустановленный словарь) 1 бит Должно быть нулевым Compression Level (Уровень сжатия) 2 бита 0 - Самое быстрое сжатие 1 - Быстрое сжатие 2 - Сжатие по умолчанию 3 - Максимальное сжатие Compressed Blocks (Сжатые блоки) Переменный Adler Checksum (Контрольная сумма Adler) 4 байта Контрольная сумма Adler-32, вычисленная для распако- ванных данных Представленный ниже программный код служит иллюстрацией вычислений контрольной суммы Adler-32. Функция UpdateAdler обновляет значение переменной AdlerRegister после распаковки каждого байта. Перед вычислением контрольной суммы ре- гистр Adler инициализируется путем установки в 1. Значение контрольной суммы Adler, хранящееся в файле, равно значению регистра Adler после обработки последнего байта. В отличие от CRC-32 никакой модификации значения не требуется. unsigned long AdlerRegister = 1 ; const unsigned long PRIME = 65521L ; void UpdateAdler(unsigned char value) ( unsigned long low = AdlerRegister & OxOOOOFFFFL ; unsigned long high = (AdlerRegister >> 16) & OxOOOOFFFFL ;
294 Форматы и алгоритмы сжатия изображений в действии low = (low + value) % PRIME ; high = (low + high) % PRIME ; AdlerRegister = (high << 16) | low ; Блоки сжатых данных Сжатые данные могут быть разделены на любое число бло- ков. Кодер может сжимать все изображение в один блок, но в некоторых случаях использование множества блоков позво- ляет улучшить степень сжатия. Каждый блок начинается с 3- битового заголовка, формат которого представлен в Таблице 14.4. Заголовок определяет метод, используемый для сжатия блока и, если за данным блоком следуют другие блоки, то в заголовке сообщается об их наличии. Если в заголовке уста- новлен бит Final (Конечный), вслед за этим блоком размеща- ется значение контрольной суммы Adler-32. Блоки, сжатые методом Deflate, никак не связаны с блоками IDAT. Сжатый блок даже не обязательно должен начинаться на границе байта. Таблица 14.4. Формат заголовка сжатого блока Имя поля Размер Описание Final (Завершение) 1 бит 1 - Это последний сжатый блок 0 - После этого блока располагаются другие сжатые блоки тУРе (Тип) 2 бита 0 - Данные не сжаты 1 - Данные сжаты с помошью фиксированных кодов Хаффмана 2 - Данные сжаты с помошью динамических кодов Хаффмана 3 - Недостоверные данные Формат несжатых блоков Если значение поля Туре (Тип) в заголовке сжатого блока яв- ляется признаком несжатых данных, остальные данные в блоке выровнены по байтам. Любые неиспользуемые биты, расположенные после заголовка, отбрасываются. Формат не- сжатого блока данных представлен в Таблице 14.5. Распа- ковщик просто копирует несжатые байты в выходной поток.
Развертывание сжатых данных PNG-изображения 295 Таблица 14.5. Формат блока несжатых ланных Имя поля Размер Описание Length (Длина) 2 байта Число байтов данных в блоке NLength (N-Длина) 2 байта Поразрядное дополнение поля Length (Длина), используемое для контроля достоверности Block Data (Данные блока) Число бай- тов в поле длины Байты несжатых данных Динамические коды Хаффмана Динамические коды Хаффмана представляют собой наиболее оптимальный метод сжатия. Битовые поля, приведенные в Таблице 14.6, следуют непосредственно за заголовком сжато- го блока. Эти поля задают число значений, которые на самом деле содержатся в сжатых данных. Хотя для развертывания сжатых данных используются две таблицы Хаффмана, в Таб- лице 14.6, как видим, определяются три длины. Необходи- мость в дополнительном поле обусловлена тем, что длины кодов в таблицах Хаффмана длин/литералов и расстояний также кодируются по методу Хаффмана. За структурой, показанной в Таблице 14.6, следует последова- тельность 3-битовых полей общим числом до 19. Фактическое число битовых полей равно значению поля Length (Длина) плюс 4. Эти битовые поля содержат длины кодов Хаффмана для значений 0-18. Длины хранятся в следующем порядке: 16 17 18 0 8 7 9 6 10 5 11 4 12 3 13 2 14 1 15 Таблица 14.6. Поля Имя поля Длина Описание динамического Literals 5 битов Число кодов длины/литералов - кода Хаффмана (Литералы) 257 (257-286) Distances (Расстояния) 5 битов Число кодов расстояний - 1 (1-32) Lengths (Длины) 4 бита Число кодов длин кодов - 4 (4-19) Маловероятно, что для элементов в конце списка в файле бу- дет храниться соответствующее значение длины. Значениям, для которых отсутствует элемент списка, назначается нуле-
296 Форматы и алгоритмы сжатия изображений в действии вой код длины. На основе этих кодов длин распаковщик соз- дает таблицу Хаффмана, используемую для декодирования длин кодов в обеих таблицах Хаффмана для литералов/длин и расстояний. Коды Хаффмана со значением 0-18 используются для коди- рования таблиц Хаффмана для литералов/длин и расстояний. В Таблице 14.7 описывается назначение этих кодов. Кодам 16, 17, и 18 соответствует несколько связанных с ними до- полнительных битов. Когда декодер встречает один из этих кодов, за кодом следует указанное число литеральных битов. Таблииа 14.7. Кодирование длин Код Описание Базовое значение Дополнительные биты 0-15 Литеральное значение Отсутствует 0 16 Повторить 3-6 раз предыдущий код 3 2 17 Повторить 3-10 раз длину 0 3 3 18 Повторить 11-138 раз длину 0 11 7 Пример Декодер считывает из входного потока значение «17» кода Хаффмана. Следуя Алгоритму 14.7 декодер считывает 3 дополнительных бита 1012 (5). Это значение добавляется к базовому значению, в результате получаем 8 (= 3 + 5). Эта команда устанавливает следующие 8 длин кодов равными 0. Затем во входном потоке следуют длины кодов таблицы Хаффмана для литералов/длин. Число длин кодов равно зна- чению поля Literals (Литералы) из Таблицы 14.6 плюс 257. Распаковщик считывает значения (0-18) кодов Хаффмана для команд и обрабатывает эти коды согласно Таблице 14.7, пока не будет считано указанное число длин кодов. Далее сразу же следуют длины кодов таблицы Хаффмана для расстояний. Число кодов расстояний равно значению поля Distances (Расстояния) в Таблице 14.6 плюс 1. Коды длины в таблице расстояний кодируются тем же самым способом, что и в таблице литералов/длин.
298 Форматы и алгоритмы сжатия изображений в действии Фиксированные коды Хаффмана При использовании фиксированных кодов Хаффмана сжатые данные в блоке следуют сразу за заголовком блока. Сжатые данные могут быть как выровненными, так и не выровнен- ными по байтам. В блоках этого типа вместо кодов, генери- руемых по частотам их использования, применяется предо- пределенный набор кодов Хаффмана. Блок с фиксированными кодами Хаффмана развертывается так же, как и блок с динамическими кодами Хаффмана. Единственное различие в обработке состоит в том, что длины из таблиц Хаффмана не хранятся во входном потоке. Таблица Хаффмана для кодов длин/литералов генерируется с исполь- зованием длин кодов, представленных в Таблице 14.8. Таб- лица Хаффмана для кодов расстояний использует длину 5 для всех возможных значений (0-29). Таблица 14.8. Длины колов Значение Длина колов 0-143 8 Хаффмана лля литералов/ллин 144-255 9 при использовании фиксированных 256-279 7 колов Хаффмана 280-287 8 Запись развернутых данных в изображение В предыдущих разделах этой главы описывался метод преоб- разования потока сжатых байтов, содержащихся в последова- тельности блоков IDAT, в поток развернутых (несжатых) бай- тов данных. Прежде, чем записать распакованные данные в изображение, над ними необходимо выполнить операции че- редования, фильтрации и преобразования цветов. Чередование При отображении с чередованием пикселов изображение разделяется на области, выводимые на экран за семь прохо- дов. Для получения структуры чередования, подобной той, что показана в Таблице 14.9, можно воспользоваться регу- лярностью шаблона чередования Adam 7. Используя эту структуру, внутри блока размером 8x8 задается местополо- жение первого пиксела, а также интервалы по строкам и
Развертывание сжатых данных PNG-изображения 299 Алгоритм 14.4. Проиесс чередования с использованием таблииы столбцам до следующих пикселов, обновляемых в каждом проходе. При переходе между соседними блоками 8x8 все интервалы по строкам и столбцам остаются постоянными. Следующий пример иллюстрирует возможное применение информации из Таблицы 14.9 для определения последова- тельности пикселов, обрабатываемых в каждом проходе по изображению, отображаемому в режиме чередования. Procedure ProcessPass Begin ROW = FirstRow While ROW < IMAGEHEIGHT Do Begin COL = FirstColumn While COL < IMAGEWIDTH Do Begin ProcessDataForPixel (ROW, COL) COL = COL + Columnlnterval End ROW = ROW + Rowinterval End End Таблица 14.9. Интервалы между обновляемыми пикселами Проход 1 -я строка 1 -й столбец Интервал по строкам Интервал по столбцам 1 1 1 8 8 в методе Adam 7 2 1 5 8 8 3 5 1 8 4 4 1 3 4 4 5 3 1 4 2 6 1 2 2 2 7 2 1 2 1 Используя данные Таблицы 14.9, число пикселов на строку в заданном проходе чередования изображения рассчитывается как: ,г Ширина_изображения + Интервал_по_столбцам - 1 Число _ пикселов _ на _ строку ------------------------------------------- Интервал _по_ столбцам Если чередование областей изображения отсутствует, число пикселов на строку равно просто ширине изображения и ис- пользуется всего один проход. Число битов, требуемых для
300 Форматы и алгоритмы сжатия изображений в действии представления пикселов в каждой цветовой модели, пред- ставлено в Таблице 14.10. Тогда, число битов, необходимых для представления каждой строки, будет равно: Число_битов_на_строку = Число_битов_на_пиксел х Число_пикселов_на_строку Наконец, число байтов на строку равно: ,, , м Число_битов_на_строку + 7 Число _ байтов _на_ строку =---------------------- Таблица 14.10. Число битов на пиксел в цветовых моделях формата PNC Цветовая модель Число битов на пиксел RGB 3 X Глубина цвета RGB с Альфа-каналом 4 X Глубина цвета Полутоновая Глубина цвета Полутоновая с Альфа-каналом 2 X Глубина цвета Цветовая палитра Глубина цвета Фильтрация Фильтр - это функция, которая преобразовывает данные строки пикселов в формат, позволяющий достичь более вы- сокой степени сжатия. Пиксельным данным в каждой строке предшествует отдельный байт, который определяет метод фильтрации, примененный к данной строке. В Таблице 14.11 перечислены все возможные значения для байта фильтра, и соответствующие этим значениям типы фильтров. Значения вне диапазона 0-4 являются недостоверными. Нулевое значе- ние типа фильтра означает, что строка не подвергалась фильтрации, поэтому данные строки содержат фактические значения пикселов. Таблица 14.11. Коды фильтров строк Код Тип фильтра 0 Не фильтруется 1 Субфильтр (Sub filter) 2 Суперфильтр (Up filter) 3 Усредняющий фильтр 4 Фильтр Пифа (Paeth)
Развертывание сжатых данных PNG-изображения 301 Поскольку в текущей главе описывается декодирование PNG- изображений, в этом разделе рассматривается процесс, обрат- ный процессу фильтрации. Сам метод фильтрации описывается в следующей главе. Некоторые фильтры вычисляются на основе дефильтрован- ных (подвергшихся процессу, обратному фильтрации) дан- ных, сгенерированных для предыдущей строки. Для хранения пиксельных данных целой строки декодер PNG вынужден обслуживать два буфера достаточно большого размера. Один буфер содержит данные текущей строки, а в другом буфере находятся данные предыдущей строки. Процесс фильтрации включает вычисления на основе значе- ний смежных пикселов. Фильтрация выполняется побайтно, а не попиксельно, причем для аналогичных байтов разных пикселов осуществляется взаимосвязанная фильтрация. На- пример, если обрабатывается изображение, использующее цветовую модель RGB с глубиной цвета в 16 битов, старший байт для красного компонента одного пиксела всегда исполь- зуется вместе со старшим байтом красного компонента дру- гого пиксела. Если глубина цвета меньше 8 битов, фильтра- ция выполняется на смежных байтах. В Таблице 14.12 приве- дены интервалы между соответствующими байтами для воз- можных комбинаций глубины цвета и цветовой модели. Таблица 14.12. Интервал между соответствуюшими байтами, используемый при фильтрации Цветовая модель Глубина цвета Интервал Полутоновая Е 2, 3, 4, 8 1 Полутоновая 16 2 Полутоновая с Альфа-каналом 8 2 Полутоновая с Альфа-каналом 16 4 Цветовая палитра 1,2, 3, 4, 8 1 RGB 8 3 RGB 16 6 RGB с Альфа-каналом 8 4 RGB с Альфа-каналом 16 8 В последующих разделах описываются для разных типов фильтра процедуры, обратные процессу фильтрации. В этих описаниях буфер buffer[previous] содержит дефильтрованные байты предыдущей строки, а буфер buffer[current] содержит
302 Форматы и алгоритмы сжатия изображений в действии фильтрованные байты текущей строки. Значение переменной interval определяется из Таблицы 14.12. Если X - первый байт в строке, значение буфера buffer[N][X-1 ] равно нулю. Аналогично, если текущая строка является первой строкой прохода по изображению, подразумевается, что все значения буфера buffer[previous] равны нулю. Все фильтры реализуются на основе целочисленной арифме- тики, а байты данных обрабатываются с учетом их знака (Ал- горитмы 14.5-14.8). Если результат процесса, обратного фильтрации, больше 255, то используется только младший значащий байт. Алгоритм 14.5. Функиия, обратная субфильтраиии Function ReverseSub (X) Begin Return buffer [current][X] + buffer [current][X- Interval] End Алгоритм 14.6. Функиия, обратная суперфильтраиии Function ReverseUp (X) Begin Return buffer [current][X] + buffer [previous][X] End Алгоритм 14.7. Функиия, обратная усрелняюшему фильтру Function ReverseAverage (X) Begin Return buffer [current][X] + (buffer [current][X-Interval] + buffer [previous][X]) / 2 End Алгоритм 14.8. Функиия, обратная фильтру Пифа (Paeth) Function PaethPreductor (Left, Above, UpperLeft) Begin pa = abs (above - upperleft) pb = abs (left - upperleft) pc = abs (left - upperleft + above - upperleft) If pa <= pb AND pa <= pc Then Return Left Else if pb <= pc Return Above Else Return UpperLeft End Fuction ReversePaeth (X) Begin
Развертывание сжатых данных PNG-изображения 303 Алгоритм 14.8. Продолжение Return buffer [current][X] + PaethPredlctor ( buffer [current][X-Interval], buffer [previous][X], buffer [previous][X-Interval]) End Цветовая коррекция Во многих случаях после завершения процесса, обратного процессу фильтрации, данные готовы для отображения. Ко- гда программа обладает необходимой информацией, декодер может выполнить цветовую коррекцию пиксельных данных. Если файл PNG содержит порцию cHRM, декодер может пре- образовать пиксельные данные в формат CIE 1931 для полу- чения точных цветов, отображавшихся на исходном дисплее, а затем откорректировать данные для отображения на суще- ствующем целевом дисплее. Если файл содержит порцию gAMA, данные могут быть откорректированы для выходного дисплея с помощью регулировки Гаммы. Переход от 16 к 8 битам Большинство существующих компьютерных систем поддер- живают глубину цвета, не превышающую 8 битов. Если только вы не создаете декодер для специализированной сис- темы, которая поддерживает большие значения глубины цве- та, перед вами встает задача преобразования 16-битовых дан- ных в 8-битовые. Технически правильный метод преобразо- вания значений пикселов с одной глубиной цвета в значения пикселов с другой глубиной цвета таков: Уравнение 14.1. Преобразование глубины ивета 2 Новая _ глубина _ цвета _ Новое значение = Прежнее значение х — ~ г — ^Прежняя-глубина-Цвета _ । Простейший метод перехода от 16-битовых к 8-битовым дан- ным состоит в отбрасывании младшего байта в каждом 16- битовом значении цвета после выполнения цветовой коррек- ции (если цветовая коррекция применима). Получаемые ре- зультаты фактически не отличаются от значений, вычислен- ных согласно Уравнению 14.1. Любой из двух указанных методов преобразования может быть причиной появления на изображении больших областей сплошного цвета, которые могут придавать изображению, особенно фотографиям, странный вид. В некоторых случаях
304 Форматы и алгоритмы сжатия изображений в действии в процессе цветового преобразования может быть желатель- ным применение эффекта размывания (dithering) для улуч- шения вида изображения. Прозрачность Если в качестве цветовой модели используются RGB с Аль- фа-каналом или полутоновая с Альфа-каналом, или если PNG-файл содержит порцию tRNS, то, при необходимости, может применяться эффект прозрачности. Если у изображе- ния есть фон, и декодеру доступны цветовые данные фона, изображение в PNG-файле может быть объединено с пиксе- лами фона посредством метода, описанного в предыдущей главе. Другая возможность состоит в объединении изображе- ния со сплошным фоном, который определяется программой или указывается в порции bKGD. Заключение В этой главе описаны остававшиеся нерассмотренными ас- пекты формата PNG, которые необходимо знать для реализа- ции декодеров PNG. Помимо объяснения метода сжатия Deflate, рассмотрены формат пиксельных данных, включая процесс фильтрации. Формат сжатых данных PNG описан в руководствах Дейча (Deutsch) и Гейли (Gailley) (1996а), а также Дейча (Deutsch) (1996b). Оба эти документа находятся на прилагаемом ком- пакт-диске. Книга Блинна (Blinn) (1998) содержит описание метода цветового сглаживания (dithering), пригодного для преобразования 16-битового изображения в 8-битовое. Пример программного кода для этой главы, содержащийся на прилагаемом компакт-диске, представляет собой закончен- ный класс декодера PNG, именуемый PngDecoder. Для чтения PNG-файла и его преобразования в объект Bitmapimage этот класс использует тот же самый метод, что и все другие деко- деры, описанные в данной книге. , На компакт-диске также записана в качестве примера про- грамма декодирования PNG-формата, преобразующая PNG- файл в файл формата Windows BMP. Эта программа запускается с помощью следующей команды: DECODER input.png output.bmp
ГЛАВА 15. Создание PNG-файлов Это - последняя глава, посвященная формату PNG. В ней описывается процесс создания файлов формата PNG, кото- рый, по сути, обратен процессу чтения PNG-файлов, описан- ному в предыдущей главе. Обзор Базовый процесс создания PNG-файлов довольно прост и включает следующие шаги: 1. Запись сигнатуры PNG. 2. Запись порции IHDR формата PNG. 3. Создание порции PLTE для изображений, использующих цветовую палитру. 4. Сжатие данных изображения в последовательность блоков IDAT. 5. Запись порции IEND. Кодер может быть разработан так, что он будет, при необхо- димости, добавлять дополнительные (необязательные) пор- ции PNG. Дополнительные порции могут быть или предо- пределенными открытыми порциями, или приватными пор- циями, предназначенными для отдельных программ. Однако в большинстве случаев для создания файла PNG достаточно выполнить перечисленные выше шаги. За исключением создания блоков IDAT, все указанные шаги тривиальны. Практически вся данная глава посвящена рас- смотрению вопросов хранения данных в цепочке порций IDAT. За информацией по другим порциям обращайтесь к Главе 13. Метод сжатия Deflate В предыдущей главе описан формат данных, сжатых методом Deflate и хранящихся в виде цепочки блоков IDAT. Хотя оче- видно, что упаковщик работает с теми же самыми структура- ми данных, что и распаковщик, процедура сжатия - это не просто процесс, обратный развертыванию сжатых данных.
306 Форматы и алгоритмы сжатия изображений в действии Спецификация метода Deflate определяет общую схему вы- полнения процесса сжатия. Спецификация рекомендует при- держиваться указываемой схемы, поскольку любой процесс сжатия LZ окружен «минным полем», защищающих его па- тентов. Реализация сжатия Deflate так же, как и процесс развертыва- ния сжатых данных, требует ведения окна, содержащего по- следние из обработанных развернутых байтов данных. Объем памяти, выделяемый под окно, задается степенью 2 и может быть равен 32 Кб или меньшему значению. Процесс сжатия нуждается в дополнительном упреждающем окне, распола- гаемом в пока еще не сжатых данных. В буфере упреждаю- щего окна, от его начала, ищется самая длинная подстрока, для которой есть полное соответствие в подвижном окне LZ77. Так как максимальная длина совпадающих строк, до- пустимая в методе Deflate, равна 258 байтам, размер упреж- дающего окна должен быть, по крайней мере, такой же вели- чины, чтобы вмещать самые длинные из возможных строк. Округление размера упреждающего окна до следующей сте- пени числа 2 (512) упрощает размещение строк в окне. Алгоритм 15.1 служит иллюстрацией общего процесса сжа- тия данных изображения в формате PNG. В грубом прибли- жении процедура сжатия по выполняемым действиям обрат- на функции DecodeBlock, рассмотренной в предыдущей гла- ве. Значения длин и расстояний преобразуются в коды и ли- теральные биты с помощью программного кода, также пред- ставленного в предыдущей главе. В Алгоритме 15.1 опущены два существенных момента. Во- первых, в PNG-файле таблицы Хаффмана предшествуют данным изображения, поэтому кодер вначале должен сгене- рировать таблицы. Во-вторых, отсутствует процедура, ис- пользуемая кодером для нахождения совпадающих строк в окнах LZ77. Поиск совпадающих строк в окне LZ77 Поиск наилучшего соответствия, выполняемый с начала бу- фера упреждающего окна - наиболее трудоемкая и длитель- ная часть процесса сжатия PNG-файлов. Простой последова- тельный перебор потребовал бы 32 К операций для каждой сжимаемой строки, что в итоге могло бы составить миллиар- ды операций поиска, выполняемых при сжатии файла изо- бражения. Вместо прямолинейного решения в спецификации
Создание PNG-файлов 307 Deflate рекомендован подход, состоящий в использовании хэш-таблицы, в которой значения хэш-функции рассчитыва- ются с помощью 3-байтовых последовательностей. Хэш-таблица (hash table) - это структура, применяемая для хранения объектов, обращение к которым осуществляется с помощью ключа, когда число возможных значений ключа значительно превышает число элементов таблицы в любой заданный момент времени. С хэш-таблицами обычно рабо- тают с помощью строковых ключей. Многие реализации компиляторов используют хэш-таблицы для хранения пере- менных, определяемых модулями. Типичный исходный мо- дуль для компилятора может включать несколько сотен имен переменных из миллиардов и миллиардов возможных вари- антов. Во время сжатия PNG-файла используются 32768 эле- ментов, принимающих, максимум, 16 миллионов возможных значений. Алгоритм 15.1. Процедура сжатия Deflate While MOREIMAGEDATA Do Begin FindLongestMatchInLZ77Window (LENGTH, DISTANCE) If LENGTH < 3 Then Begin ConvertLengthToCode (LENGTH, CODE, EXTRABITS, BITCOUNT) HuffmanEncodeLength (CODE) OutputLiteralBits (EXTRABITS, BITCOUNT) ConvertDistanceToCode (DISTANCE, CODE, EXTRABITS, BITCOUNT) HuffmanEncodeDistance (CODE) OutputLiteralBits (EXTRABITS, BITCOUNT) CopyFromLookaheadBuffer (LENGTH) End Else Begin HuffmanEncodeLength (FirstLookahead ()) CopyFromLookaheadBuffer (1) End End Ссылка на элементы в хэш-таблице осуществляется с помо- щью хэш-значений. На Рисунке 15.1 показана структура хэш- таблицы. Хэш-значение генерируется по ключу с помощью хэш-функции. Входным аргументом хэш-функции является ключ, а возвращается хэш-функцией целочисленное значение внутри некоторого фиксированного диапазона. Хэш-значение используется в качестве индекса массива, содержащего спи- сок объектов с одинаковым хэш-значением. Хорошая хэш-
308 Форматы и алгоритмы сжатия изображений в действии функция должна распределять возможные значения ключей равномерно по диапазону индексных значений. Поскольку мы работаем с пиксельными значениями, вероят- ность появления которых одинакова, можно использовать простую хэш-функцию, которая возвращает значения в диа- пазоне 0 ... 23,v - 1. const int mask = (1<<N) - 1 ; unsigned int Hash (unsigned char vl, unsigned char v2, unsigned char v3) < return (vl & mask) | ((v2 & mask) << N) | ((v3 & mask) << (2 * N)) ; } Большая проблема, возникающая при применении хэш- таблиц, особенно в случае сжатия PNG, состоит в обработке элементов с одинаковыми хэш-значениями. Эта проблема из- вестна под названием хэш-коллизии (hash-collision). Нам предстоит работать с разными 3-байтовыми последователь- ностями, которым соответствуют одинаковые хэш-значения, если только мы не создадим хэш-таблицу с 16 миллионами элементов, что может быть осуществимо через несколько лет. Кроме того, мы рассчитываем, что при наличии в окне LZ77 идентичных 3-байтовых последовательностей, можно будет заменять строки кодами длины/расстояния. Идентичным по- следовательностям будут соответствовать идентичные значе- ния хэш-функции. Вообразите изображение со сплошным фоном. Абсолютно не исключено, что всем элементам, со- держащимся в окне LZ77, будут соответствовать одинаковые значения хэш-функции. Чтобы разрешить хэш-коллизии, свяжем в цепочку элементы с идентичными значениями хэш-функции. Для хранения 3- байтовых последовательностей можно определить хэш- таблицу следующим образом: Structure HashEntry Begin INDEX : Unsigned Integer NEXT : Pointer To HashEntry End Global HashTable [0..(l Leftshift (3 * N) - 1] Of Pointer To HashEntry
Создание PNG-файлов 309 Рис. 15.1. Структура хэш-таблииы Хэш-таблина Буфер Хэш-функция возвращает указатель на первый элемент в хэш- таблице. Местоположение других элементов с тем же самым хэш-значением устанавливается путем перемещения указателя на следующий элемент. Алгоритм 15.2 демонстрирует базо- вую процедуру поиска наилучшего соответствия в окне LZ77. Процедура сжатия может использовать дополнительные кри- терии для определения наилучшего соответствия. Например, может учитываться как расстояние, так и длина кода. При возрастании значения расстояния также увеличивается и чис- ло дополнительных битов, требуемых для его кодирования. Если значение расстояния для 3-байтового соответствия на-
310 Форматы и алгоритмы сжатия изображений в действии столько большое, что требует для своего кодирования 13 до- полнительных битов, вполне возможно, что упаковщик смо- жет закодировать строку с помощью меньшего числа битов, воспользовавшись 3 литеральными значениями, а не кодами длины и расстояния. Подумайте, что случится, если описанная только что процеду- ра используется для изображения, содержащего относительно небольшое число цветов. Цепочки хэш-значений могут стать достаточно длинными, что сделало бы поиск по всей цепочке весьма медленным. Оптимальное решение этой проблемы со- стоит в ограничении числа элементов в цепочке хэш-значений, среди которых процедура сжатия будет искать лучшее соот- ветствие. Этот предел может быть выбран так, чтобы получить оптимальное соотношение степени и времени сжатия данных. Ограничение числа элементов в каждой цепочке хэш- значений, по которым производится поиск, не оказывает су- щественного отрицательного влияния на степень сжатия. Од- нако такое ограничение может обеспечить значительное со- кращение времени сжатия. Предел, устанавливаемый на число элементов, по которым ведется поиск, может быть сделан ре- . гулируемым параметром так, чтобы пользователь мог сам оп- тимизировать соотношение время/степень сжатия. Алгоритм 15.2. Поиск совпадающих элементов в хэш-таблиие Procedure BestMatch (BESTLENGTH, BESTOFFSET) Begin BESTLENGTH = 0 BESTOFFSET = 0 HASHVALUE = Hash (LOOKAHEAD [0], LOOKAHEAD [1], LOOKAHEAD [2]) HASHENTRY = HashTable [Hashvalue] If HASHENTRY = NULL Then Return // Возможные соответствия отсутствуют While HASHENTRY <> NULL Do Begin II = 0 While LZWINDOW [HASHENTRY.INDEX + II] = LOOKAHEAD [I] Do II = II + 1 If II > BESTLENGTH Then Begin BESTLENGTH = II BESTOFFSET = HASHENTRY.INDEX End HASHENTRY = HASHENTRY.NEXT End End
Создание PNG-файлов 311 Каждый раз, когда перемещается символ из буфера упреж- дающего окна в окно LZ77, необходимо создать элемент хэш- таблицы, который ссылается на позицию символа, добавлен- ного в буфер. Значение хэш-функции для нового хэш- элемента должно рассчитываться с использованием значений в буфере упреждающего окна, так как для хэш-функции тре- буются значения следующих двух символов, которые еще не добавлены в окно LZ77. Кодер PNG должен поддерживать фиксированный пул элементов хэш-таблины вместо того, чтобы непрерывно выделять и осво- бождать элементы. Поскольку в окне LZ77 находится 215 симво- лов, то это число определяет также и размер пула хэш-элементов. Если упаковщик добавляет хэш-элемент в непустую цепочку хэширования, этот элемент должен появляться в начале це- почки, а не в конце. Такой способ добавления приводит тому, что поиск соответствия в окне LZ77 будет вначале выпол- няться для последней обработанной строки. Строки с мень- шими значениями расстояния могут быть закодированы с помощью меньшего числа битов. Генерирование таблиц Хаффмана Кодер PNG может использовать фиксированные коды Хафф- мана, представленные в Таблице 14.9, или генерировать коды Хаффмана, основанные на частотах использования. Проще реализовать фиксированные коды Хаффмана, но, очевидно, что за простоту приходится расплачиваться невысокой сте- пенью сжатия. На самом деле нет никаких реальных причин использовать фиксированные коды Хаффмана, если только вы не работаете с программой, для которой критичным пара- метром является скорость сжатия. В Главе 6 рассматривалось кодирование Хаффмана примени- тельно к формату JPEG. Тот же самый метод с некоторыми модификациями будет работать в кодерах Хаффмана. Разли- чия между методами генерирования таблиц Хаффмана в форматах JPEG и PNG перечислены в предыдущей главе. При использовании кодирования Хаффмана в формате JPEG, генерирование таблицы Хаффмана выполнялось за два, почти идентичных, прохода по данным изображения. В первом
312 Форматы и алгоритмы сжатия изображений в действии проходе собиралась информация о частоте использования значений. После генерирования таблиц Хаффмана по часто- там использования значений, во втором проходе повторялись шаги первого прохода за исключением того, что данные под- вергались кодированию Хаффмана. Для кодирования PNG-изображения может применяться та- кая же схема, но ей присущи несколько существенных недос- татков. При наличии двух почти идентичных проходов ос- новная проблема - это время, затрачиваемое на сжатие дан- ных изображения. Метод поиска в окне LZ77 совпадающих строк требует значительно больших объемов вычислений, чем кодирование энтропии в JPEG. Выполнение процесса сжатия PNG дважды заметно увеличивает время сжатия. Оптимальным решением данной проблемы является хране- ние в буфере литералов/кодов длины и расстояния. Простой метод реализации такого буфера заключался бы в использо- вании массива 2-байтовых целых чисел. Код дли- ны/расстояния мог бы храниться в буфере в виде 2 байтов то- гда, как литеральное значение можно было бы хранить с по- мощью 1 байта. В первом проходе по данным собирается ста- тистика использования значений кодов, и полученный ре- зультат записывается в буфер. После генерирования таблиц Хаффмана во втором проходе просто выполняется кодирова- ние значений, сохраненных в буфере. Алгоритм 15.3 иллюст- рирует возможную реализацию первого прохода. Насколько большим должен быть буфер для кодирования всего изображения? Ответ таков: в буфере не обязательно должно храниться все изображение полностью. Метод Deflate позволяет хранить сжатые данные во множестве сжатых блоков. Упаковщик может выделить память под бу- фер в самом начале сжатия изображения. После заполнения буфера упаковщик заканчивает первый проход. Завершив кодирование данных во втором проходе, кодер начинает но- вый блок Deflate и возобновляет первый проход с места, где он был остановлен. Другими словами, вместо двух проходов по всему изображению выполняется множество чередую- щихся проходов. Естественно, размер буфера влияет на размер результирую- щего файла изображения. Чем меньше размер буфера, тем больше число сжатых блоков, которые вносят избыточные данные от дополнительных таблиц Хаффмана в сжатый по- ток. Однако чрезмерное увеличение буфера может фактиче-
Создание PNG-файлов 313 Алгоритм 15.3. Сбор статистики по использованию колов Хаффмана ски увеличить размер сжатого изображения. Когда в единст- венный сжатый блок записывается слишком большой объем данных изображения, определяется так много кодов Хафф- мана, что избыточный размер файла, обусловленный длин- ными кодами Хаффмана, начинает превышать избыточный размер, связанный с дополнительными таблицами Хаффмана. Оптимальный размер буфера варьируется от изображения к изображению. Упаковщик мог бы предполагать, когда следу- ет создавать новый блок, основываясь на частотах использо- вания кодов Хаффмана. Это, вместе с большим буфером, обеспечивало бы наилучшее сжатие. После того как для таблиц длин/литералов и расстояний сге- нерированы коды Хаффмана, эти таблицы должны записы- ваться в выходной поток сжатых данных. Procedure GatherData Begin While MOREIMAGEDATA And COUNT + 1 < BUFFERSIZE Do If LENGTH > 3 Then Begin IncrementLengthFrequency (ConvertLengthToCode (LENGTH)) IncrementDis t anceFrequency (ConvertDi s tanceToCode (DISTANCE)) BUFFER [COUNT] = LENGTH + 256 COUNT = COUNT + 1 BUFFER [COUNT] = DISTANCE COUNT = COUNT + 1 End Else Begin BUFFER [COUNT] = CopyFromLookaheadBuffer (1) COUNT = COUNT + 1 End End Сохраненные таблицы Хаффмана кодируются по методу Хаффмана с помощью кодов, представленных в предыдущей главе. Самый простой метод генерирования кодов Хаффмана для кодирования длин кодов состоит в применении функции, которая в качестве аргументов использует указатели на функции, подобно функциям, использовавшимся для форма- та JPEG. Эта функция при каждой записи кодов длины в вы- ходной файл вызывается дважды. Первый раз функция вызы- вается вместе с функцией сбора статистики Хаффмана, а вто- рой раз - вместе с функцией, которая выводит в файл значе- ния длины, кодированные по методу Хаффмана.
314 Форматы и алгоритмы сжатия изображений в действии Алгоритм 15.4 иллюстрирует метод сжатия блоков Deflate с использованием буфера. Алгоритм 15.4. Сжатие по метолу Defalte Procedure OutputDataBlock Begin II = 0 While II < COUNT Do Begin If BUFFER [II] > 255 Then Begin ConvertLength (BUFFER [II], CODE, EXTRABITS, BITCOUNT) HuffmanEncodeUsingLengthTable (CODE) OutputLiteralBitS (EXTRABITS, BITCOUNT) II = II + 1 ConvertDiStance (BUFFER [COUNT], CODE, EXTRA- BITS, BITCOUNT) HuffmanEncodeUsingDlstanceTable (CODE) OutputLiteralBitS (EXTRABITS, BITCOUNT) II = I + 1 End Else Begin HuffmanEncodeUsingLengthTable (BUFFER [COUNT]) II = II + 1 End End Hu f fmanEncodeUs ingLengthTable (ENDCODE) End Procedure Compressimage Begin While NOREIMAGEDATA Do Begin GatherData GenerateHuffmanTables WrlteDeflateBlockHeader OutputDataBlock End End Одна из особенностей сжатия PNG состоит в том, что коды Хаффмана в сжатых данных хранятся с обратным порядком битов. В процессе декодирования кодов Хаффмана вначале считывается старший значащий бит кода, а затем добавляют- ся младшие значащие биты. Однако в сжатых данных PNG биты читаются в порядке от самого младшего к самому старшему значащему биту. Если бы коды Хаффмана храни- лись в нормальном порядке, распаковщик считывал бы пер- выми младшие значащие биты, что могло бы нарушить весь процесс декодирования Хаффмана. Представленный ниже
Создание PNG-файлов 315 пример иллюстрирует изменение порядка битов в коде Хаффмана на обратный. unsigned short ReverseHuffmanCode (unsigned short in- put) { unsigned short value = 0 ; for (unsigned int ii = 0 ; ii < 16 ; ++ ii) { if ((input & (1 << (15 - ii))) != 0) value |= (1 << ii) ; } return value ; } Фильтрация Каждой строке данных в файле PNG предшествует байт, ко- торый определяет метод фильтрации, примененный к данным строки перед сжатием. Возможные значения этого байта и соответствующие методы фильтрации приводились в преды- дущей главе. Функции фильтрации подобны функциям, об- ратным тем, что были представлены ранее. Sub Filter filteredvalue = image [row][X] - image [row][X-Interval] Up Filter filteredvalue = image [row][X] - image [row-1][X] Average Filter Filteredvalue = image [row][X] - (image [row][X-Interval] + image [row-1][X]) / 2 Paeth Filter filteredvalue = buffer [row][X] - PaethPredictor (image [row][X-Interval], image [row-1] [X], image [row-1][X-Interval]), где функции PaethPredictor и Interval совпадают с такими же функциями, определенными в предыдущей главе.
316 Форматы и алгоритмы сжатия изображений в действии Зачем используется фильтрация? Цель применения фильтров к строкам данных состоит в пре- образовании данных изображения в более сжимаемый вид. Предположим, что есть изображение, содержащее градиент- ный фон, в котором цвет каждого пиксела изменяется на фиксированную величину при переходе от одного пиксела к другому, соседнему пикселу. Такого типа фон знаком поль- зователям системы Windows, поскольку он встречается в диа- логах программ инсталляции. Для градиентного фона с пере- ходом от синего цвета к черному цветовые данные типичной строки выглядели бы следующим образом: 001002003004005006007008... Хотя эти данные отличает весьма регулярная структура, в них нет повторяющихся строк размером 3 байта или боль- ше, что уменьшает сжимаемость данных методом Deflate. Ес- ли бы эта же самая строка данных была пропущена через суб- фильтр (Sub Filter), определенный чуть выше, данные приоб- рели бы вид строки 001001001001001001001001 ..., которая гораздо лучше сжимается в PNG-файле. Оказывает- ся, что, в общем случае, фильтрация представляет наилучший способ повышения сжимаемости файла изображения. При- менение фильтров может, как правило, уменьшить размер изображения примерно на 30-40%. С другой стороны, фильтрация может увеличить размер PNG- файла. Для изображений, использующих цветовую палитру, не следует применять фильтрацию. Эффект фильтрации ос- нован на схожести цветовых значений соседних пикселов, а индексы, указывающие на цвета палитры, никак не связаны с реальным цветовым значением. Так как фильтрация опериру- ет с байтами, а не битами данных, использование фильтров для изображений с глубиной цвета меньше 8 битов не обес- печивает такого же результата, как для изображений с боль- шими значениями глубины цвета. Следовательно, фильтра- ция будет эффективна для изображений с малым значением глубины цвета только в крайне редких случаях.
Создание PNG-файлов 317 Какой фильтр следует использовать? Фильтры применяются к изображению в построчном поряд- ке, и могут меняться от строки к строке. В связи с этим воз- никает вопрос - какой фильтр будет наилучшим для каждой конкретной строки? Ответ нам неизвестен. Здесь находится поле для экспериментов и новых открытий. Спецификация PNG предлагает применять для каждой строки все фильтры. Каждое фильтрованное значение рассматрива- ется как байт со знаком (со значениями -128.. 127), а все по- лученные значения далее суммируются. Из всех фильтров выбирается тот, который обеспечивает получение наимень- шей суммы. Другая возможность состоит в поиске фильтра, после применения которого получаются самые длинные по- вторяющиеся строки значений. Простейшим методом автоматического выбора фильтра ко- дером является отказ от фильтрации для изображений с цве- товой палитрой или для изображений с глубиной цвета, меньшей 8 битов. Для других типов изображений первая строка должна фильтроваться с помощью субфильтра (Sub Filter), а для остальных строк следует применять фильтр Пифа (Paeth). В большинстве случаев такой метод обеспе- чивает получение результатов, мало чем уступающих тем, которые достигаются с помощью любого из упомянутых выше методов. Заключение В этой главе описан метод создания PNG-файлов, который, по сути, обратен методу чтения PNG-файлов. Как и для фай- лов JPEG, разработчик программы сжатия должен сам выби- рать параметры процесса сжатия, такие как размер порции IDAT, размер блока Deflate, глубина поиска в цепочках хэши- рования, используемый фильтр. Методы выбора наилучшего фильтра все еще находятся в стадии исследований. В бли- жайшем будущем формат PNG должен получить еще боль- шее распространение. Для этой главы на прилагаемом компакт-диске содержится программный код класса кодирования PNG, PngEncoder, ис- пользующего класс кодирования Хаффмана, который почти идентичен эквивалентному классу для формата JPEG, пред- ставленному в Главе 6. Единственное существенное различие
318 Форматы и алгоритмы сжатия изображений в действии касается функции BuildTable. В PNG-версии этой функции нет специального значения, обеспечивающего отсутствие ко- да Хаффмана, состоящего из одних единиц. Также функция проверяет, чтобы порядок расположения кодов Хаффмана соответствовал порядку расположения значений. Функция SetUseFilters, принадлежащая классу кодера, опре- деляет использование фильтров в процессе сжатия. Функция SetCompressionLevel управляет максимальной глубиной по- иска в цепочках хэширования, а функция SetBlocksize управ- ляет размером буфера сжатия. На диске также записан пример кодера, который преобразует файлы Windows BMP в PNG-файлы. Запуск программы вы- полняется вводом следующей командной строки: ENCODER [-f-F-M] input.bmp output.png - f Использовать фильтры - F Использовать самое быстрое сжатие - И Использовать максимальное сжатие Этим мы завершаем наше обсуждение формата PNG, а вместе с ним и всю книгу. Надеемся, что теперь вы знаете, как чи- тать и записывать изображения, используя наиболее распро- страненные форматы.
Глоссарий AC Coefficient (Коэффициент AC) - В JPEG так называют все коэффициенты DCT за исключением одного коэффициента самого младшего порядка. Эти коэффициенты определяют полином, состоящий из косинусных функций, причем вместе с порядковым номером коэффициента растет и частота соот- ветствующей косинусной функции. Additive Color Model (Аддитивная цветовая модель) - Цветовая модель, в которой значения компонентов добавляют цвет к черному цвету. Большие значения компонентов создают цве- та более близкие к белому цвету. Alpha Channel (Альфа-канал) - Значение пиксела (в дополне- ние к цветовым компонентам), которое представляет про- зрачность пиксела. Baseline JPEG (Базовый JPEG) - Разновидность режима по- следовательного JPEG, в котором число таблиц ограничено, а точность дискретизации должна составлять 8 битов. Big-Endian (Обратный порядок) - Представление целых чисел с помощью отдельных байтов, упорядоченных от старшего байта к младшему байту. См. Little-Endian. Bitmap Format (Растровый формат) - Формат изображений, в котором данные состоят из множества значений, описы- вающих цвет дискретных точек или пикселов. Coefficient (Коэффициент) См. DCT Coefficient. Chrominance (Цветность) - Компонент в цветовой модели, ко- торый представляет цвет пиксела, в противоположность его яркости. В цветовой модели YCbCr компонентами цветности являются СЬ и Сг. Chunk (Порция) - Основная единица деления PNG-файла. Color Model (Цветовая модель) - Метод определения цвета. Большинство цветовых моделей представляют цвета, исполь- зуя три измерения или компонента. Примерами цветовых мо- делей служат RGB, YCbCr и CMYK. Color Quantization (Квантование цвета) - Процесс уменьшения числа цветов в изображении. Обычно квантование использу- ется для вывода изображения на устройстве с ограниченными возможностями по отображению цветов, или при сохранении изображения в таком формате файлов, который не поддержи- вает все цвета, присутствующие в исходном изображении.
320 Форматы и алгоритмы сжатия изображений в действии Colorspace (Цветовое пространство) - Множество всех цве- тов, которые могут быть представлены с помощью конкрет- ной цветовой модели. Component (Компонент) - Одно из множества значений, ис- пользуемых для представления пиксела в конкретной цвето- вой модели. Большинство цветовых моделей представляют цвет с помощью значений трех компонентов. CRC (Cyclical Redundancy Check - Проверка циклическим из- быточным кодом) - Метод обнаружения искаженных дан- ных, основанный на математике полиномов. Data Unit (Единица данных) - В формате JPEG так называют 8x8 блок дискретизованных значений для одного компонента. DC Coefficient (Коэффициент DC) - Коэффициент DCT низ- шего порядка. Представляет постоянное значение. DCT (Discrete Cosine Transform - Дискретное косинусное пре- образование) - Математический метод, с помощью которого множество значений преобразуется в эквивалентное пред- ставление в виде суммы косинусных функций. Deflate (Понижение порядка) - Процесс сжатия, используе- мый в формате PNG. Представляет разновидность процесса LZ77, который включает кодирование Хаффмана (Huffman). Down-Sampling (Субдискретизация) - Процесс уменьшения разрешения компонента в изображении. Frame (Кадр) - В JPEG так называют группу из одного или нескольких сканов. Для распространенных режимов JPEG кадр совпадает со всем изображением. Gamut (Цветовой охват) - Диапазон цветов, которые могут отображаться конкретным устройством вывода. Gamma (Гамма) - Модель, обычно используемая для коррек- тировки цветов в изображении, основанная на свойствах сис- темы и среды просмотра. Hierarchical JPEG (Иерархический JPEG) - Редко используе- мый режим JPEG, в котором изображение разделяется на не- сколько кадров, которые улучшают качество изображения. Huffman Coding (Кодирование Хаффмана) - Метод сжатия, который для представления данных использует коды пере- менной длины.
Глоссарий 321 Inflate (Наполнение) - Процесс восстановления изображения в формате PNG. Этот процесс является обратным процессу Deflate (Понижение порядка). Interleaved Scan (Чересстрочный скан) - В JPEG так называют скан, который состоит из нескольких компонентов. Interlaced Image (Чересстрочное изображение) - Изображение, которое отображается не последовательно, а путем вывода строк или пикселов шаблона за несколько проходов по изо- бражению. JFIF (JPEG File Interchange Format - Формат обмена файлами JPEG) - Формат, используемый в файлах JPEG. JPEG-LS - Новая технология сжатия без потерь, используемая в формате JPEG. Little-Endian (Прямой порядок) - Формат представления це- лых чисел, в котором отдельные байты располагаются в по- рядке от младшего байта к старшему байту. Logical Screen (Логический экран) - В формате GIF так назы- вают логическую область дисплея для изображений, храня- щихся в файле. Отдельные изображения указывают свои раз- меры и местоположения на логическом экране. Lossy Compression (Сжатие с потерями) - Метод сжатия, ко- торый создает близкое приближение к исходным данным. Для увеличения сжатия методы сжатия с потерями отбрасы- вают информацию, которая полагается малозначащей для восприятия. Lossless Compression (Сжатие без потерь) - Способ сжатия, который позволяет восстанавливать точную копию исходно- го изображения. Lossless JPEG (JPEG без потерь) - Редко используемый ре- жим JPEG, который реализует сжатие без потерь. В настоя- щее время режим JPEG без потерь считается устаревшим. Luminance (Яркость) - Цветовой компонент, который пред- ставляет яркость. LZ - Семейство алгоритмов сжатия, названное по имени сво- их создателей Абрахама Лемпеля (Abraham Lempel) и Якова Зива (Jacob Ziv). LZW (Lempel-Ziv-Welch) - Разновидность метода LZ, исполь- зуемая в формате GIF.
322 Форматы и алгоритмы сжатия изображений в действии MCU (Minimum Coded Unit - Минимальный кодированный блок) - В JPEG так называют количество единиц данных, ко- торое кодируется как группа. Median Cut Algorithm (Алгоритм деления по медиане) - Алго- ритм Хекберта (Heckbert) для квантования цвета. Network Order (Сетевой порядок) - Идентично выражению «обратный порядок». Наименование указывает на тот факт, что в соответствии с протоколом Интернета (IP) целые числа передаются начиная со старшего байта. Noninterleaved Scan (Построчный скан) - В JPEG так называ- ют скан, который содержит только один компонент. Pixel (Пиксел) - Дискретное местоположение на устройстве отображения или отдельная точка внутри изображения рас- трового формата. Point Transform (Точечное преобразование) - Процесс, исполь- зуемый для уменьшения точности данных в прогрессивном JPEG, в котором используется последовательное приближе- ние. Для коэффициентов DC точечное преобразование заклю- чается в сдвиге на разряд (bit shift). Для коэффициентов АС точечное преобразование состоит в целочисленном делении. Progressive JPEG (Прогрессивный JPEG) - Режим JPEG, в ко- тором изображение разделяется на множество сканов. На- чальные сканы являются грубым представлением изображе- ния. Последующие сканы улучшают качество изображения. Quantization (Квантование) В JPEG так называют процесс уменьшения числа коэффициентов DCT, используемых для представления единицы данных. См. также Color Quantization. Raster Format (Точечный формат) - Идентично выражению «растровый формат». RGB Colorspace (Цветовое пространство RGB) - Цветовое про- странство, в котором для получения черного цвета необходи- мо складывать компоненты, представляющие относительные доли красного (red), зеленого (green) и синего (blue) света. RLE (Run Length Encoding - Кодирование длины серий) - Ме- тод сжатия, в котором последовательные серии с одинаковы- ми значениями кодируются с использованием пар длина се- рии/значение.
Глоссарий 323 Sampling Frequency (Частота дискретизации) - В JPEG так на- зывают относительную частоту дискретизации компонента по отношению к остальным компонентам изображения. Sample Precision (Точность дискретизации) - Число битов, используемых для представления значения компонента. Scan (Скан) - В JPEG так называют множество сжатых дан- ных, которое представляет один проход по изображению для одного или нескольких компонентов. Sequential JPEG (Последовательный JPEG) - Режим JPEG, в котором изображение сохраняется в порядке сверху вниз, слева направо. Spectral Selection (Спектральное выделение) - В прогрессив- ном JPEG так называют процесс разделения компонентов на диапазон спектральных полос или коэффициентов DCT, ис- пользуемый во всех изображениях прогрессивного JPEG. По желанию, спектральное выделение может использоваться в сочетании с последовательным приближением. SPIFF (Still Picture Interchange File Format - Формат обмена статическими изображениями) - Официальный формат фай- лов JPEG. Разработан как замена JFIF. Subtractive Color Model (Субтрактивная цветовая модель) - Цветовая модель, в которой из белого цвета вычитается цвет компонента. Большим значениям компонентов соответству- ют цвета, более близкие к черному цвету. Successive Approximation (Последовательное приближение) - В прогрессивном JPEG так называют процесс разделения компонентов на множество сканов путем уменьшения точно- сти данных в начальном скане, и использования последова- тельных сканов для улучшения качества данных. Последова- тельное приближение не требуется в прогрессивном JPEG. Truecolor (Истинный цвет) - Любая система, в которой одно- временно можно отобразить 2м или более цветов. Название отражает тот факт, что данное число примерно соответствует предельному количеству цветов, которых может различить человеческий глаз. Up-Sampling (Сверхдискретизация) - Процесс увеличения разрешения цветового компонента.
324 ' Форматы и алгоритмы сжатия изображений в действии Vector Format (Векторный формат) - Графический формат, в котором изображение состоит из последовательных команд рисования. XYZ Colorspace (Цветовое пространство XYZ) - Трехкомпо- нентная цветовая модель, определенная международной ко- миссией по освещению (Commission Internationale de 1’Eclairage - CIE) в 1931 году. В отличие от относительных цветов, эта модель определяет абсолютные цвета. YCbCr Colorspace (Цветовое пространство YCbCr) - Цветовая модель, используемая в JPEG. В модели YCbCr используют- ся три компонента, которые представляют яркость (Y) и цветность (СЬ и Сг).
Библиография Anton, Howard, Elementary Linear Algebra, John Wiley & Sons, New York, NY, 1981. Blinn, Jim, Jim Blinn’s Corner: Dirty Pixels, Morgan Kaufmann, San Francisco, CA, 1998. Boutell, Thomas et al., “PNG Specification,” Version 1.0, PNG Development Group, October 1996. Brown, C. Wayne and Shepherd, Barry J., Graphics File For- mats, Manning, Greenwich, CT, 1995. Burden, Richard L., Faires, J. Douglas, Reynolds, Albert C., Nu- merical Analysis, Prindle, Weber & Schmidt, Boston, MA, 1981. Campbell, Joe, C Programmer’s Guide to Serial Communica- tions, Howard W. Sams & Company, Carmel, IN, 1987. Deutsch, L. Peter and Gailly, Jean-Loup, “ZLIB Compressed Data Format Specification,” Version 3.3, RFC 1950, 1996. Deutsch, L. Peter, “DEFLATE Compressed Data Format Specifi- cation,” Version 1.3, RFC 1951, 1996. Foley, James D., van Dam, Andries, Feiner, Steven K., and Hughes John F., Computer Graphics Principles and Practice, Addison-Wesley, Reading, MA, 1996. CompuServe, Inc, “Graphics Interchange Format (GIF) Specifica- tion,” CompuServe, Columbus, OH, 1987. CompuServe, Inc, “Graphics Interchange Format (GIF) Specifica- tion,” Version 89a, CompuServe, Columbus, OH, 1989. Graham, Ian S., The HTML Source Book, John Wiley & Sons, New York, NY, 1997. Hamilton, Eric, “JPEG File Interchange Format,” Version 1.02, C-Cube Microsystems, September 1, 1992. Heckbert, Paul, “Color Image Quantization for Frame Buffer Dis- play,” ACM Computer Graphics Journal, Volume 16, Num- ber 3, July 1982. Huffman, D. A., “A Method for the Construction of Minimum Redundancy Codes,” Proceedings of the IRE, Volume 40, Number 9, pages 1098-1101.
326 Форматы и алгоритмы сжатия изображений в действии JPEG (199'4), Digital Compression and Coding of Continuous- tone Still Images, Part I: Requirements and Guidelines. ISE/IEC IS 10918-1, American National Standards Institute, New York, NY, 1994. Lindley, Craig A., Photographic Imaging Techniques in C++, John Wiley & Sons, New York, NY, 1995. Microsoft Corporation, Win32 Programmer’s Reference Volume 5: Messages, Structures, and Macros, Microsoft Press, Redmond, WA, 1993. Murray, James D. and vanRyper, William, Encyclopedia of Graphics File Formats, O’Reilly & Associates, Sebastopol, CA, 1994. Nelson, Mark, The Data Compression Book, M&T Books, San Mateo, CA, 1992. Nye, Adrian, Xlib Programming Manual, O’Reilly & Associates, Sebastopol, CA, 1988. Pennebaker, William B. and Mitchell, Joan L., JPEG Still Image Data Compression Standard, Van Nostrand Reinhold, New York, NY, 1993. Porter, Thomas and Duff, Tom, “Compositing Digital Images,” Computer Graphics, Volume 18, Number 3, July 1984. Ramabadran, Tenkasi V. and Gaitonde, Sunil S., “A Tutorial on CRC Computations,” IEEE Micro, August 1988, pages 62-75. Rao, K. R. and Yip, P., Discrete Cosine Transform, Academic Press, New York, NY, 1990. Rimmer, Steve, Windows Bitmapped Graphics, Windcrest Books, Blue Ridge Summit, PA, 1993. Scheifler, Robert W. and Gettys, James, X Window System, Digi- tal Press, Bedford, MA, 1990. Stroustrup, Bjarne, The C++ Programming Language, Third Edi- tion, Addison-Wesley, Reading, MA, 1997. Swan, Tom, Inside Windows File Formats, SAMS, Indianapolis, IN, 1993. Welsh, Terry, “A Technique for High-Performance Data Com- pression,” IEEE Computer, Volume 17, Number 6, June 1984, pages 8-19.
Библиография 327 Ziv, J. and Lempel, A., “A Universal Algorithm for Sequential Data Compression,” IEEE Transactions on Information Theory, Volume 23, Number 3, May 1977, pages 337-343. Ziv, J. and Lempel, A., “Compression of Individual Sequences via Variable-Rate Coding,” IEEE Transactions on Information Theory, Volume 24, Number 5, September 1978, pages 530-536. Интернет сайты JPEG www.jpeg.org www.ijg.org PNG www.cdrom.com/pub/png/ www.cdrom.com/pub/infozip/zlib/ www.cdrom.com/pub/mng GIF www.geocities.co.jp/SiliconValley/3453/gif_info/index_en.html members. aol.com/royalef General www.wotsit.org www.dcs.ed.ac.uk/~mxr/gfx/
Содержание Предисловие.......................................6 Выражение благодарности...........................9 ГЛАВА 1. Введение.........................................11 Представление изображений.........................И Векторная и растровая графика....................13 Цветовые модели..................................16 Полутоновая шкала................................18 Цветовая модель YCbCr............................18 Цветовая модель CMYK.............................20 Сравнение истинного цвета и палитры..............22 Сжатие изображений...............................24 Сопоставление сжатия без потерь со сжатием с потерями данных.....................27 Порядок расположения байтов и битов..............28 Квантование цвета................................31 Общий формат изображений.........................35 Определение типа данных..........................36 Общий класс изображений..........................36 Заключение.......................................39 ГЛАВА 2. Windows BMP.........................................41 Порядок данных...................................41 Структура файлов.................................42 Заголовок изображения............................43 Цветовая палитра.................................45 Данные пикселов..................................46 Сжатие...........................................48 Метод сжатия RLE8................................48 Метод сжатия RLE4................................49 Заключение.......................................50 ГЛАВА 3. ХВМ.................................................53 Формат файлов....................................53 Порядок расположения байтов......................54 Пример изображения...............................55
330 Форматы и алгоритмы сжатия изображений в действии Синтаксис файла..................................55 Чтение и запись ХВМ-файлов.......................56 Заключение.......................................56 ГЛАВА 4. Введение в JPEG.....................................57 Режимы сжатия JPEG...............................58 Последовательный режим...........................58 Прогрессивный режим..............................59 Иерархический режим..............................61 Режим сжатия без потерь..........................62 Какая часть JPEG рассматривается в данной книге?.62 Что такое файлы JPEG?............................64 Формат файлов SPIFF..............................64 Порядок расположения байтов......................65 Частота дискретизации............................65 Функционирование JPEG............................69 Чересстрочные и построчные сканы.................70 Заключение.......................................72 ГЛАВА 5. Формат файлов JPEG..................................73 Маркеры..........................................73 Сжатые данные....................................76 Типы маркеров....................................76 Маркеры АРРп.....................................77 Маркеры СОМ......................................77 Маркеры DHT......................................78 Маркеры DRI......................................79 Маркеры DQT......................................80 Маркеры EOI......................................81 Маркеры RSTn.....................................81 Маркеры SOI......................................81 Маркеры SOFn.....................................82 Маркеры SOS......................................83 Формат JFIF......................................85 Заключение.......................................88
Содержание 331 ГЛАВА 6. Кодирование Хаффмана в JPEG.......................91 Частота использования.............................91 Пример кодирования Хаффмана.......................93 Кодирование Хаффмана с использованием длин кодов.97 Кодирование Хаффмана в JPEG......................103 Ограничение длин кодов...........................104 Декодирование кодов Хаффмана.....................106 Заключение.......................................108 ГЛАВА 7. Дискретное косинусное преобразование.............109 Преобразование DCT в одном измерении.............110 Преобразование DCT в двух измерениях.............118 Основные операции с матрицами....................119 Использование прямого двумерного преобразования DCT...............................122 Квантование......................................722 Размещение в зигзагообразном порядке.............124 Заключение.......................................125 ГЛАВА 8. Декодирование изображений JPEG, сжатых в последовательном режиме.............................127 Размеры MCU......................................127 Декодирование единиц данных......................130 Декодирование коэффициентов DC...................130 Декодирование коэффициентов АС...................132 Пример декодирования.............................134 Обработка коэффициентов DCT......................137 Сверхдискретизация...............................137 Обработка маркеров перезапуска ..................138 Обзор декодирования в JPEG.......................139 Заключение.......................................140 Класс компонентов................................140 Класс декодера...................................141 Использование класса декодера....................143 Программа декодирования..........................143
332 Форматы и алгоритмы сжатия изображений в действии ГЛАВА 9. Создание последовательных файлов JPEG..............145 Параметры сжатия...............................145 Таблицы Хаффмана...............................146 Таблицы квантования............................147 Сканы..........................................148 Частоты дискретизации..........................149 Маркеры перезапуска............................151 Цвет или серая шкала...........................152 Структура выходных файлов......................153 Процесс кодирования............................154 Проверка достоверности.........................154 Вывод блоков...................................154 Субдискретизация...............................154 Чередование....................................157 Кодирование единиц данных......................158 Генерирование таблиц Хаффмана..................161 Заключение.....................................164 Класс компонентов..............................164 Класс кодеров..................................165 ГЛАВА 10. Оптимизация DCT....................................167 Разложение на множители матрицы DCT............167 Арифметика масштабированных целых чисел........185 Объединение квантования и преобразования DCT...186 Заключение.....................................196 ГЛАВА 11. Прогрессивные изображения JPEG.....................199 Разбиение компонентов в прогрессивном JPEG.....199 Обработка прогрессивных файлов JPEG............202 Обработка прогрессивных сканов.................203 Минимальные кодированные блоки (MCUs) в прогрессивных сканах.........................205 Использование таблиц Хаффмана в прогрессивных сканах.........................205 Декодирование единицы данных...................206 Первый скан DC.................................206 Обновляющие сканы DC...........................206
Содержание 333 Первые сканы АС..................................207 Обновляющие сканы АС.............................208 Подготовка к созданию прогрессивных файлов JPEG..214 Кодирование прогрессивных сканов.................216 Кодирование Хаффмана.............................216 Декодирование единицы данных.....................217 Первые сканы DC..................................217 Обновляющие сканы DC.............................218 Первые сканы АС..................................218 Обновляющие сканы АС.............................221 Заключение.......................................224 ГЛАВА 12. GIF..................................................225 Порядок расположения байтов......................226 Файловая структура...............................226 Заголовок GIF....................................226 Логический дескриптор экрана.....................226 Глобальная таблица цветов........................228 Типы блоков......................................229 Завершитель файла................................229 Блок изображения.................................229 Блоки данных.....................................230 Блоки расширения.................................231 Расширение простого текста.......................231 Расширение управления графикой...................232 Расширение комментария...........................233 Расширение программы.............................234 Чередование......................................234 Формат сжатых данных.............................235 Сжатие GIF.......................................236 Развертывание GIF................................238 Размеры кода.....................................240 Структура словаря................................241 Анимация в GIF...................................244 Юридические проблемы.............................246 Несжатый GIF.....................................247 Заключение.......................................247
334 Форматы и алгоритмы сжатия изображений в действии ГЛАВА 13. PNG..................................................249 История..........................................250 Порядок размещения байтов........................250 Формат файла.....................................250 Именование порций................................251 Контроль циклическим избыточным кодом............253 Обработка порции.................................256 Структура файла..................................256 Представление цветов в PNG.......................257 Трехкомпонентный RGB.............................257 Цветовая Палитра.................................258 Полутоновая шкала................................258 RGB с Альфа-каналом..............................258 Полутоновая шкала с Альфа-каналом................259 Аппаратно-независимый цвет.......................259 Гамма............................................264 Чередование......................................266 Критические порции...............................268 1HDR...................................:.........268 PLTE.............................................270 IDAT.............................................271 IEND.............................................271 Некритичные порции...............................272 bKGD.............................................272 cHRM.............................................273 gAMA.............................................273 hIST.............................................274 pHYs.............................................274 sBIT.............................................275 tEXt.............................................276 tIME.............................................278 tRNS.............................................278 zTXt.............................................279 Заключение.......................................280
Содержание 335 ГЛАВА 14. Развертывание сжатых данных PNG-изображения...............................................283 Развертывание сжатых данных изображения..........283 ZLIB, Deflate и PNG..............................283 Сжатие LZ77......................................284 Сжатие Deflate...................................286 Кодирование Хаффмана в методе Deflate............290 Формат сжатых данных.............................292 Блоки сжатых данных..............................294 Формат несжатых блоков...........................294 Динамические коды Хаффмана.......................295 Фиксированные коды Хаффмана......................298 Запись развернутых данных в изображение..........298 Чередование......................................298 Фильтрация.......................................300 Цветовая коррекция...............................303 Переход от 16 к 8 битам..........................303 Прозрачность.....................................304 Заключение.......................................304 ГЛАВА 15. Создание PNG-файдов..................................305 Обзор............................................305 Метод сжатия Deflate.............................305 Поиск совпадающих строк в окне LZ77..............306 Генерирование таблиц Хаффмана....................311 Фильтрация.......................................315 Зачем используется фильтрация?...................316 Какой фильтр следует использовать?...............317 Заключение.......................................317 Глоссарий........................................319 Библиография.....................................325
приложение. Содержание компакт-диска № Папка Что внутри 1 3rdParty\IJG Библиотека для работы с файлами формата JPEG. Исходные тексты прилагаются. Сайт разработчиков: www.ijg.org 2 3rdParty\lmageMagick Бесплатный пакет для обработки изображений, включает исходные тексты. Страница разработчика: www.wizards.dupont.com/cristy/ImageMagick.html 3 3rdParty\PNG Исходные тексты программ для работы с файлами формата PNG Образцы изображений в формате PNG 4 3rdParty\XV Программа просмотра изображений и ее исходные тексты Страница разработчика: www.trilon.com/xv 5 Examples Исходные тексты всех примеров из книги. Компилируются с помощью Borland C++Builder и Visual C++ 6 Images Примеры изображений 7 LibraryXBC LIBIMAGE.LIB библиотека для Borland C++ 8 LibraryXBCBVIEWER Программа просмотра изображений для Borland C++Builder 9 LibraryMNCLUDE Заголовочные файлы 10 Library\JPEGDUMP Программа JPEGDUMP 11 Library\JPEG JPEG сжатие и распаковка 12 Library\MSVC LIBIMAGE.LIB библиотека для MSVC++ 13 LibraryXPNG PNG сжатие и распаковка 14 LibraryXPNGDUMP Программа PNGDUMP SOURCE - Исходные тексты VIEWER - Программа просмотра изображений в формате BMP 15 Libra ry\SOURCE Исходные тексты VIEWER - Программа просмотра изображений в формате BMP 16 LibraryWIEWER Программа просмотра изображений в формате BMP 17 Specs Спецификации форматов файлов для хранения изображений
ПРАКТИКА ПРОГРАММИРОВАНИЯ ИСХОДНЫЕ ТЕКСТЫ ПРИЛАГАЮТСЯ Дж. Миано ФОРМАТЫ И АЛГОРИТМЫ СЖАТИЯ ИЗОБРАЖЕНИЙ В ДЕЙСТВИИ CD-ROM СОДЕРЖИТ ВСЕ НЕОБХОДИМЫЕ ПРОГРАММЫ И ИСХОДНЫЕ КОДЫ ► Addison Wesley1