Смекни!
smekni.com

Перетворення форматів графічних файлів (стр. 2 из 3)

Перетворення метафайлів у метафайли

Оскільки метафайли містять растрові та векторні дані, при їх перетворенні виникають такі ж проблеми які виникають при перетворенні растрового у растровий та векторного у векторний. (див. два попередніх пункти).

Перетворення векторного чи метафайлового у растровий

Таке перетворення називають раструванням. Суть полягає у тому, що вихідне зображення розбивається на рядки та стовпчики (з заданою щільністю у dpi), що утворюють пікселі, які залишається записати в результуючому (растровому) форматі. При цьому, може виникнути ефект сходинок на похилих лініях та дугах, який можна приховати за допомогою невеличкого розмиття (anti-aliasing).

Перетворення растрового та метафайлового у векторний

Перетворення растрового та метафайлового у векторний є дуже складною операцією. Не завжди можна досягти гарних результатів, тому що при такому перетворенні використовуються складні алгоритми обробки зображень, еврістичні методи пошуку та виділення в однорідних растрових даних ліній, прямокутників, градієнтів, тощо.Ще однією проблемою проблемою є точна передача кольорів. Растрові дані, як правило, повнокольорові (24 bit), а векторні підтримують лише декілька кольорів, що може призвести до втрати кольорів у результуючому забраженні.

Найпоширенішими програмами, що можуть робити подібне перетворення, є Adobe Streamline та Corel Trace.

Перетворення растрового та векторного у метафайл

Таке перетворення не мусить викликати багато проблем, тому що метафайли добре підтримують растрові та векторні дані. Але формат зберігання растрових чи векторних даних може бути різним, тому виникають такі ж проблеми як і при перетворенні растрового у растровий та векторного у векторний.

Приклад програми перетворення

Розглянемо перетворення двох растрових форматів на конкретному прикладі створення програми для перетворення графічного зображення з формату PCX на Microsoft BMP третьої версії. Уся обробка графічних файлів була написана на мові Паскаль з нуля, без використання бібліотек, які в великій кількості можна знайти в Інтернет. На вході програми – файл у форматі PCX, на виході – BMP. Основний принцип роботи програми такий: зчитується заголовок файлу PCX, на його основі створюється заголовок файлу BMP, зчитуються дані кожного пікселя і записуються у формат BMP. Через те, що у форматі BMP рядки даних йдуть знизу догори (у PCX та інших форматах – навпаки), то спочатку записується тимчасовий файл з перевернутим зображенням, а потім цей тимчасовий файл перевертається, щоб отримати нормальний файл BMP, який можна відкривати й використовувати в інших програмах. Оскільки при написанні програми єдиною метою було зрозуміти головний принцип перетворення, то створена програма не є універсальною. Тому вона працює тільки з попередньо заданими іменами файлів і перетворює файли лише з 24 бітами на піксель. Інтерфейс програми вибрано найпростішим для того, щоб концентрувати увагу на самому перетворенні, а не реалізації інтерфейсу. Також, не було приділено уваги анлізу помилок. Розглянемо формати файлів PCX та BMP докладніше, перш ніж перейти до аналізу самої програми.

Формат PCX

PCX – один з форматів, що часто використовується, через свою простоту. Спочатку він був розроблений фірмою 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".