один з форматів, що часто використовується, через свою простоту. Спочатку він був розроблений фірмою Zsoft для використання у програмі PC Paintbrush для MS-DOS. Дані зображення кодуються за допомогою одного з варіантів алгоритму RLE, який незважаючи на простоту та швидкісь, не є ефективним. Цей формат може містити зображення з 4, 8 та 24 бітами на піксель. Далі ми будемо розглядати особливості 24 бітового формату.
Перші 128 байтів файлу містять заголовок:
Typedef struct _PcxHeader {
BYTE Id; | Ідентикатор PCX (0Ah)
BYTE Version; | Версія
BYTE Format; | Кодування (1 - RLE)
BYTE BitsPixelPlane; | Кількість бітів на піксель
WORD Xmin; | Ліва мінімальна координата
WORD Ymin; | Верхня мінімальна координата
WORD Xmax; | Права максимальна координата
WORD Ymax; | Нижня максимальна координата
WORD Hdpi; | Горизонтальна роздільна здатність
WORD Vdpi; | Вертикальна роздільна здатність
BYTE EgaPalette[48]; | Палітра
BYTE Reserved; | Зарезервовано
BYTE NumberOfPlanes; | Кількість площин
WORD BytesLinePlane; | Кількість байтів на рядок
WORD PaletteInfo; | Тип палітри
WORD HScreenSize; | Розмір екрану по горизонталі
WORD VScreenSize; | Розмір екрану по вертикалі
BYTE Filler[54]; | Зарезервовано
} PCXHEADER;
Поле Id містить 0Ah, це означає, що даний файл направді є файлом формату PCX. Натепер підтримується лише один тип кодування – RLE, якому відповідає значення 1. Назви інших полів говорять самі за себе.
Дані у форматі PCX стискаються за допомогою простого алгоритму групового кодування, у якому група байтів, що повторюються, замінюється двома байтами: кількістю значень та самим значенням. Перший байт цієї двобайтової групи містить у двох старших бітах по одиниці, а у шести менших – кількість значень, які повторюються, що визначає максимальну довжину – 63 пікселя. Другий байт містить восьмибітове значення, що на виході повторюється стільки разів, скільки було задано у молодших шести бітах першого байту. Далі йде наступна пара кількість/значення. Якщо старші два біти першого байту нулі, то цей байт містить саме значення, а кількість повторень вважається 1. Отримані дані кодують колір послідовних пікселів, по три на піксель у форматі RGB. Але дані записуються не триплетами, а спочатку усі червоні компоненти для одного рядка растру, потім так само зелені, а потім сині. При цьому палітра не використовується.
Формат BMP
Формат BMP був створений компанією Microsoft спеціально для зберігання растрових даних у системі Windows. Дані заголовку та й його розмір змінювалися й доповнювалися з випуском нових версій цієї операційної системи. Ми будемо розглядати формат BMP версії три. Перший 14-байтовий заголовок однаковий для усіх версій:
Typedef struct
BITMAPFILEHEADER {
UINT16 type; | Тип файлу – 4D42h ("BM")
UINT32 size; | Розмір файлу в байтах
INT16 xHotspot; | Резерв
INT16 yHotspot; | Резерв
UINT32 offsetToBits; | Початок даних зображення
} BITMAPFILEHEADER;
У версії три далі йде 40-байтовий додатковий заголовок:
Typedef struct BITMAPHEADER {
UINT32 size; | Розмір цього заголовку у байтах
INT32 width; | Ширина зображення в пікселях
INT32 height; | Висота зображення в пікселях
UINT16 numBitPlanes; | Кількість площин
UINT16 numBitsPerPlane; | Кількість бітів на піксель
UINT32 compressionScheme; | Тип стиснення
UINT32 sizeOfImageData; | Розмір растру у байтах
UINT32 xResolution; | Горизонтальна роздільна здатність у пікселях на метр
UINT32 yResolution; | Вертикальна роздільна здатність у пікселях на метр
UINT32 numColorsUsed; | Кількість кольорів у зображенні
UINT32 numImportantColors; | Кількість важливих кольорів
}
Після заголовків йдуть дані 24-бітового зображення у форматі RGB, але на відміну від PCX, площини не використовуються і триплети кольорів йдуть один за одним.
Опис програми
Розглянемо програму перетворення растрового зображення з формату PCX у BMP рядок за рядком. Повний лістінг програми див. у додатку 1.
uses
crt;
Додатковий стандартний модуль crt використовується для позиціонування текстового курсора та очищення рядку.
Далі визначаються змінні:
var
PCXF, BMPF: file;
Нетипізовані файли для зчитування та запису інформації.
PCXheader: array [0..127] of byte;
Масив для зберігання заголовку PCX файлу.
BMPheader: array [0..53] of byte;
Масив для зберігання заголовку BMP файлу.
i, result, curx, HGT: integer;
Змінна циклу, результат зчитування та запису файлів і умова виходу з циклу, вказівник на поточний елемент у масиві buf, висота зображення у рядках (або пікселах).
buf: array [0..1959] of byte;
Масив для зберігання даних одного рядка. Максимальне значення індексу масиву вибрано довільно, але так, щоб можна було перетворити тестовий файл.
b, val: byte;
Дуплети даних формату PCX запакованого за алгоритмом RLE.
size, pos1, BPL: longint;
Рахівник кількості перетворених пікселів, кількості рядків, що були перевернуті з тимчасового файлу перевернутого BMP та кількість пікселів на рядок. BPL*3 – реальний об‘єм потрібного буфера для зберігання одного рядку.
Begin
assign(PCXF, 'dollar.pcx');
reset(PCXF, 1);
assign(BMPF, 'dollar.tmp');
rewrite(BMPF, 1);
Відкриваються два файли – для зчитування з PCX та запису у TMP.
blockread(PCXF, PCXheader, 128);
Зчитується заголовок PCX в масив PCXheader розміром 128 байт:
for i:=0 to 53 do begin
BMPheader[i]:=0;
end;
Майже всі дані новоствореного заголовку BMP міститимуть нулі.
writeln('Width: ', PCXheader[9]*256+PCXheader[8]+1);
HGT := PCXheader[11]*256+PCXheader[10]+1;
writeln('Height: ', HGT);
На екран виводяться ширина та висота зображення, взяті з заголовку PCX файлу, при чому висота нам ще знадобиться. Формула використовується для перетворення двох байтових значень у одне слово.
BPL := PCXheader[67]*256+PCXheader[66];
Визначається кількість байтів на рядок. Далі створюється заголовок формату BMP, поки що в пам‘яті.
BMPheader[0] := $42; {header word}
BMPheader[1] := $4D;
Заголовок всього формату BMP – "BM".
BMPheader[10] := 54;
Початок даних – 14 байтів заголовку №1 + 40 байтів заголовку №2.
BMPheader[14] := 40; {header size}
Розмір заголовку 2 та одночасно ідентифікатор версії – три.
BMPheader[18] := PCXheader[8]+1;