Автор: Капитан Немо
e-mail: capnemo@xakep.ru
Январь 2002 г.
Вступление
Вот пришло время и мне написать что-нибудь умное (как мне кажется:). При постановке (ужасных и жестоких:) опытов над PCX-ами использовался Borland Pascal 7.0. Однако, я не вижу особых трудностей, которые могли бы возникнуть при попытке все это перенести на С++.(Это может быть не только потому, что их действительно не будет :)) Разговор пойдет о чтении графического файла формата PCX. Все вопросы обсуждаются с теоретической точки зрения, т.е. никаких фрагментов программ я приводить не буду . Кому интересно, в конце документа есть ссылка на маленькую программу, которая читает монохромные и 256-цветовые PCX файлы. Для тех, кого заинтересовала статья - мыло в правом верхнем углу.
В доступных мне источниках говорится, что файл PCX был разработан фирмой ZSoft для PC Paintbrush под MS-DOS. Но кому это интересно?.. Формат по соглашению с фирмой M$ перешел в ее собственность вместе с программой и получил широкое распространение. Историческая справка окончена.
О формате
Файл Pcx может содержать одно изображение размером не более 65535х65535 пикселей. Количество цветов может быть 2,16,256,16777215. Тип изображения - растровое.
Файл PCX состоит из следующих частей:
Заголовок
Изображение
Палитра VGA
Подробно обо всем
Файл начинается заголовком:
TPCXHeader = record
ID: byte; {Идентификатор}
Vers: byte; {Версия файла}
Encode: byte; {Кодирования}
BitPerPix: byte; {Количество бит на пиксел}
Xstart: word; {Левая граница}
Ystart: word; {Верхняя граница}
Xend: word; {Правая граница}
Yend: word; {Нижняя граница}
HorRez: word; {Гор. разрешение}
VerRez: word; {Вер. разрешение}
EGAPal: array [1..48] of byte; {Палитра EGA}
Res1: byte; {-}
NumPl: byte; {Количество битовых плоскостей}
BytePerLine: word; {Байт на строку развертки}
PallType: word; {Тип палитры}
HorScSize: word; {Размер экрана по гор.}
VerScSize: word; {Размер экрана по вер.}
Res2: array[1..54] of byte; {-}
end;
ID - идентификатор файла PCX. Значение всегда 0Ah. Если
значение отлично от 0Ah, на этом можно заканчивать обработку изображения.
Vers - значение этого поля указывает на версию PCX.
Каждая версия подразумевает определенные требования для
программ чтения.
Значение | Версия формата |
0 | Версия 2.5 с фиксированной палитрой EGA |
2 | Версия 2.8 с модифицируемой палитрой EGA |
3 | Версия 2.8 без палитры |
4 | Версия PC Paintbrush для Windows |
5 | Версия 3.0 |
О том, как читать файл той или иной версии будет сказано
ниже.
Encode - указывает на схему кодирования. Согласно спецификации PCX, это поле может иметь два значения:
0 - данные не кодируются
1 - данные кодируются с использованием байт-ориентированной RLE-схемы. (Она описана далее)
Здесь следует отметить, что данные кодируются всегда, а значение этого поля большинством программ
игнорируется.
BitPerPix - количество бит, отводимых на пиксель в одной
цветовой плоскости. Значением поля может быть 1,2,4,8.
Важно помнить, что данные строки развертки дополняются
нулями до четного количества байт. Значение этого поля
можно использовать для отделения данных от заполнителя.
Xstart,YStart,XEnd,YEnd - Описывают размеры изображения
и его положение на экране. Большинство программ
игнорирует возможность размещения изображения в произвольной части экрана(и я их полностью поддерживаю :). Но
следует отметить важную особенность: изображение может иметь
фактический размер отличный от описанного этими полями.
Пример: Xstart=0,XEnd=100, а длинна строки 108 пикселей.
В изображение могут быть включены лишние строки.
В любом случае программа чтения файла должна отображать
только ту часть изображения, которая находится в прямоугольнике, описанном (Xstart,YStart) и
(XEnd,YEnd).
HorRez,VerRez - горизонтальное и вертикальное разрешение
изображения. Для декодирования изображения эти поля не
нужны и носят лишь информативный характер.
EGAPal - массив из 48 байт. Представляют собой палитру.
О ней разговор пойдет ниже.
Res1 - поле не используется начиная с Версии 2. Раньше
обозначало режим дисплея, на котором создавалось изображение. Если вы создаете файл, то следует установить
это поле в ноль. В противном случае некоторые программы
могут отказаться отображать изображение.
NumPl - задает количество цветовых плоскостей изображения. Возможные значения: 1,3,4. Комментарии по использованию этого значения даны после описания всех полей.
NumPl | BitPerPix | Максимальное число цветов | Видеорежим |
1 | 1 | 2 | Монохромный |
1 | 2 | 4 | CGA |
3 | 1 | 8 | EGA |
4 | 1 | 16 | EGA и VGA |
1 | 8 | 256 | Расширенный VGA |
3 | 8 | 16777216 | Расширенный VGA и XGA |
BytePerLine - размер незакодированной строки развертки одной цветовой плоскости в байтах. Умножая это значение на значение поля NumPl, получаем общую длину строки развертки в байтах.
PallType - тип палитры. 1-цветная или монохромная палитра, 2-градации серого цвета. Это поле игнорируется практически всеми программами, использующими PCX.
HorScSize,VerScSize - содержат информацию о разрешении
экрана, на котором было создано изображение. По-моему,
эти поля игнорируются большинством программ, но некоторые могут отказаться отображать изображение, если эти
поля не равны нулю.
Res2 - 54 байта должны содержать нули. Дополняют заголовок до 128 байт.
Схема кодирования файлов PCX.
Данные файла PCX сжимаются с
помощью простого байт-ориентированного
алгоритма группового кодирования. Вместо
описания этого алгоритма я просто приведу
алгоритм декодирования данных из которого (как
мне кажется:) станет понятен процесс сжатия.
После прочтения заголовка и вычисления
всех необходимых величин, как то размеры
изображения, количества цветов и установки
палитры, начинаем читать данные
изображения, которые идут сразу за
заголовком по одному байту. Алгоритм
выглядит так:
1.Читаем байт
2.Если два старших бита установлены в 1,т.е.
"байт">=0С0h(192),
преобразовать байт в счетчик группы по
формуле (("байт"-192)+1).
%:). Иначе, 4.
3.Прочитать следующий байт и записать этот
байт столько раз,
сколько указанно в счетчике.
4.Записать литерал один раз.
5.Если буфер не полон, 1.
Следует отметить, что формат PCX изначально был аппаратно-зависимым форматом(и остается таким :). Он был разработан, когда самыми популярными адаптерами были EGA-адаптеры. Собственно, они были самыми современными в то время. PCX файл версии 2.5 использовал фиксированную палитру EGA. Поддерживать чтение этого формата нет большой необходимости (разве что ваш дедушка еще не стер свою коллекцию "женских антропометрических данных":). Сомневаюсь, что ваша программа столкнется с изображением этой версии. Первое, что мы должны определить - это какую палитру мы должны использовать. Файл PCX может содержать (и в большинстве случаев содержит) две палитры. Первая - EGAPal в заголовке файла используется для отображения 2,4,8,16 цветовых изображений. Информация представляет собой набор триплетов (трех байтов, содержащих интенсивность красного, зеленого и синего цвета. RGB). Если используется не вся палитра - например, только 8 триплетов, то остальные должны содержать нули. Хотя это требование нарушается некоторыми программами. Каждый файл PCX содержит VGA палитру, которая расположена в конце файла. Найти палитру нетрудно - последние 256*3=768 байт и есть палитра :). Её отделяет от данных изображения байт с фиксированным значением $0C. Но, если вы намерены посмотреть, что там ваш дедушка хранил как зеницу ока :), может случиться и так, что палитры в файлах нет. Обычно, если используется палитра EGAPal, то в палитре VGA содержится ее копия, а остальные триплеты содержат нулевые значения. Изображения, использующие 24-битный цвет не используют палитру вообще, хотя обе палитры зачастую присутствуют в файле. И последнее замечание, касающееся палитр. Версия 2.8 без палитры предполагает использование родной палитры видеоадаптера. Читать в этом случае любую из палитр не имеет смысла. Второе, что мы должны определить - это формат строки развертки. Он зависит от полей BitPerPixel,NumPl. Сначала строку следует декодировать. Алгоритм декодирования рассмотрен ниже. Данные строки развертки могут храниться либо пиксельно-ориентировано, либо плоскостно-ориентировано. Монохромные изображения хранятся попиксельно. Каждый байт хранит информацию о 8 пикселях. 24-битовые изображения хранятся ввиде трех байтов, которые распределены на 3 цветовые плоскости. (Чтобы определить формат строки - см.Таблицу для видеорежимов.)
На этом и закончим. Пишите, читайте.
Программа тут
Написать мнение в гостевой книге.
:НАЗАД:
© 2001-2002 [F.E.G.]