Перетворення форматів графічних файлів

Перетворення форматів графічних файлів

Національний університет "Києво-Могилянська Академія"



Кафедра інформатики

Перетворення форматів
 графічних файлів



Курсова робота
студента ДКТ-4
Підгорного Свєтослава



Науковий керівник:
Бублик В. В.

Київ
1998








План



	Вступ	2

	Коли який формат використовувати	4

	Інтернет	4

	Друковані видання	5

	Електронні презентації	6

	Перетворення файлів	7

	Перетворення растрового в растровий	7

	Перетворення векторного у векторний	8

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

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

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

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

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

	Формат PCX	11

	Формат BMP	12

	Опис програми	14

	Висновки	20

	Література	21

	Додаток 1	22

Вступ

Комп‘ютерна графіка традиційно поділяється на два види: векторну та растрову. Векторне зображення складається з набору відрізків, багатокутників, кривих, що задані в деякій системі координат і описані математично. З векторними даними пов‘язана інформація про їхні атрибути (наприклад, колір, товщина, тощо). Векторне зображення легко масштабувати, повертати, нахиляти. Тому воно не залежить від пристрою відображення – чи то монітор з роздільною здатністю 72 dpi, чи принтер з роздільною здатністю 600 dpi. Файли векторного формату корисні для збереження лінійних елементів (наприклад, ліній та прямокутників), а також елементів, які можна розкласти на прості геометричні об‘єкти (наприклад, текст). Растрове зображення – це масив цифрових значень, що визначають колір окремих пікселів. Кількість бітів на піксель визначає кількість кольорів, що можуть задаватися для цього пікселя. Файли цього типу добре підходять для збереження реальних зображень, наприклад фотографій та відеозображень. Існує ще третій тип – метафайли, – це файли, де міститься як векторна частина зображення, так і растрова.

Але зображення майже ніколи не записується у файл просто так. Як правило, воно кодується за деяким алгоритмом, крім того спочатку додається блок службової інформації (наприклад: ідентифікатор формату, версія формату, роздільна здатність по горизонталі, вертикалі, кількість бітів на колір, тип кодування, кількість площин, палітра, кількість пікселів на дюйм, тощо). Найчастіше графічні дані кодуються з метою зменшення об‘єму файла, але можлива й інша мета (наприклад, щоб: файли не могли продивитися сторонні люди, визначити чи не спотворені дані (наприклад, за методом CRC), тощо). Кодування бувають таких типів: упаковування пікселів, RLE, LZW, Huffmen або CCITT, DCT або JPEG, JBID, ART, Fractal, або будь-якого, який ви самі можете придумати.

За іншою класифікацією графічні файли поділяються на власні (що належать деякій графічній програмі), та обміну (що створені для обміну між декількома програмами). Майже кожна графічна програма має свій власний формат, а для обміну даними з іншими програмами використовує формати обміну.

Коли який формат використовувати

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

Інтернет

В Інтернеті найпоширенішими форматами є GIF та JPEG. Головним принципом, за яким створювалися ці формати, є мінімізація розміру файлу для передачі у мережі з низькою пропускною здатністю. GIF підтримує палітрові дані з максимальною кількістю кольорів 256 (без прозорості), анімацію, хоча остання модифікація (GIF89a) може мати у кожному кадрі свою палітру і при використанні прозорих областeй можна досягти більшої кількості кольорів. У випадку коли у вихідному форматі було до 256 кольорів, перетворення на GIF відбудеться без втрат, а якщо ні, то потрібно виконати тонування (dithering), або визначити кольори, що найчастіше використовуються, і подібні кольори перетворити в один, щоб загальна кількість кольорів не перевищувала 256. JPEG є у деякому плані альтернитивою GIF, тому що підтримує 24 біти на колір, але аналогічно до GIF, зони з схожими кольорами перетворюються на один колір при чому навіть при низькому ступені стиснення втрати неминучі. Останнім часом був створений формат PNG, що на відміну від GIF підтримує повну гаму кольорів (до 48 біт), і використовує алгоритм запаковки схожий на LZW. Але він поки що не настільки поширений, як два попередніх.

Серед векторних форматів для Інтернет слід назвати Flash та VRML. VRML – це формат тривимірних сцен, для перегляду яких потрібен додатковий модуль – VRML plug-in (наприклад, Cosmo Player). Цей формат підтримує декілька базових геометричних фігур, різні типи осівтлення, матеріалів, текстур, шрифтів. Flash – це унікальний метафайловий формат, що підтримує анімацію, морфінг, градієнтну прозорість, шари, звук, реакцію на події від мишки чи клавіатури, тощо. Для його перегляду потрібен інший plug-in – Shockwave Flash, а для створення існує лише єдиний редактор – Macromedia Flash, який є досить простим векторним редактором з підтримкою лінії часу (timeline), але можливостей якого досить для написання складних сторінок.

Друковані видання

Без сумніву, при роботі з конкретною програмою результат роботи варто зберігати у її рідному форматі, що підтримує, як правило, усі можливості та нюанси цієї програми. Але для обміну фійлів (наприклад з видавництвом) варто використати формати TIFF для растрових даних, та EPS для векторних, чи метафайлових. При цому не будуть виникати проблеми з підтримкою цих форматів у іншій версії чи на іншій платформі. Формат TIFF має два варіанти: для PC та для Mac. Починаючи з версії 5.0 (1988) він підтримує запаковку LZW, а з 6.0 (1992) – JPEG. Насьогодні це один з найуніверсальніших форматів, що підтримує кольори від 1 до 24 бітів, стиснення за методами RLE, LZW, CCITT 3, CCITT 4, JPEG, без стиснення, декілька зображень у одному файлі, альфа-канали. Формат EPS є також дуже універсальним – він підтримує запис даних у текстовому та двійковому форматі, зображення у монохромному, напівтоновому та кольоровому режимі, DCS, роздільну здатність від 75 до 3000 dpi, мініатюри (preview) та шляхи обрізки (clipping path).

Електронні презентації

У електронних презентаціях немає якого-небудь стандартного формату графічних файлів, кожен виробник підтримує формати які він вважає за потрібне. Багато з виробників створюють свої формати. Більшість програми створення електронних презентацій (наприклад, Microsoft PowerPoint, Lotus Smart Suite, Corel Presentation, Astound) підтримують декілька (до 20) різних графічних форматів. 

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

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

Перетворювати можна двома типами програм: програмами створення та програмами перетворення форматів. У програмі створення (наприклад, Adobe Photoshop) можна відкрити файл у його власному форматі та зберегти в іншому. Якщо одне перетворення потрібно зробити для багатьох файлів, можна використати Batch-перетворення або скористатися спеціальними програмами перетворення (наприклад, Image Alchemy від Handmade Software, Inc.). Універсальна програма перетворення може не так добре розуміти власний формат, як програма створення, але вміє перетворювати набагато більше форматів.

Перетворення растрового в растровий

Перетворення растрового в растровий формати як правило дає найкращі результати з усіх видів перетворення. Усі растрові формати складаються з пікселів, і перетворюються просто піксел за пікселом. Відмінність може бути тільки у заголовках файлів, способах зберігання піксельних даних (наприклад, сторінками) та способах їхнього кодування (наприклад, RLE, LZW, тощо). Можливо доведеться розділити дані на площини, або перевести в іншу модель кольору (наприклад, з RGB у CMYK, HSB, або L*a*b). При перетворенні файлів з одного формату (вихідного) в інший (результуючий) може виникнути ситуація, коли у результуючому форматі може не вистачити кольорів для передачі усіх відтінків початкового зображення. Прикладом такої проблеми може бути перетворення з формату TIFF, що містить 32 біти на піксель, у формат GIF, що не може містити більше ніж 8 бітів на піксель. У таких випадках використовують операції обробки зображень, такі як квантування чи суміш кольорів. Звичайно, що частину інформації при цьому буде втрачено.  Тому користувачу доведеться вирішити, що краще – втратити інформацію, чи, можливо, перетворити в інший формат. Може виникнути інша ситуація, коли в результуючому форматі не вистачить полів у заголовку, або навпаки, будуть поля, яких не було у вихідному форматі. У першому випадку деякі дані просто втратяться, а у другому, програмі перетворення прийдеться визначати дані для додаткових полів самостійно.

Перетворення векторного у векторний

Таке перетворення не є надто складним, але можливе виникнення двох проблем. Перша, пов‘язана з відмінностями у кількості та типі об‘єктів або їх параметрів. Наприклад, деякі формати підтримують тільки прості елементи зображення, типу кола, або прямокутників. Потужні формати можуть підтримувати набагато більше додаткових складних елементів (наприклад градієнти, сплайни, шрифти, криві Безьє). Друга проблема виникає через те, що різною може бути система виміру, її точність, тощо.

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

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

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

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

  BMPheader[10] := 54;

Початок даних – 14 байтів заголовку №1 + 40 байтів заголовку №2.

  BMPheader[14] := 40; {header size}

Розмір заголовку 2 та одночасно ідентифікатор версії – три.

  BMPheader[18] := PCXheader[8]+1;
  BMPheader[19] := PCXheader[9];
  BMPheader[22] := PCXheader[10]+1;
  BMPheader[23] := PCXheader[11];

Записується ширина та висота зображення.

  BMPheader[26] := 1; {planes}

Кількість площин.

  BMPheader[28] := 24; {bpp}

Бітів на піксель.

  blockwrite(BMPF, BMPheader, 54);

Створенй заголовок записується на диск.

  result:=1;
  size:=0;
  curx:=0;
  while result=1 do begin

Ініціалізуються рахівники, та змінна виходу з циклу, при закінченні даних файла.

    blockread(PCXF, b, 1, result);

Читається один байт, причому, якщо зчитування неможливе (кінець файлу), result прийме значення нуль, і виконається умова виходу з циклу.

    if (b and $C0) = $C0 then begin
      b:=b and $3F;
      blockread(PCXF, val, 1, result);
    end else begin
      val:=b;
      b:=1;
    end;

Стандартний алгоритм розпаковки RLE-закодованих даних формату PCX. Тут обробляється зчитаний байт та якщо потрібно зчитується наступний, і на виході маємо b – кількість повторів, val – значення, яке потрібно повторити.

    gotoxy(1, wherey); write(size); clreol; inc(size);

Для індикаціі того, що програма щось робить, а не зависла, на екран виводиться кількість вже перетворених пікселів, яка (кількість) після цього інкрементується.

    for i:=1 to b do begin
      buf[curx]:=val;
      inc(curx);
    end;

Відбувається запис у буфер значення b val разів.

    if (curx=BPL*3) then begin
      for i:=0 to BPL-1 do begin
        blockwrite(BMPF, buf[i+2*BPL], 1);
        blockwrite(BMPF, buf[i+BPL], 1);
        blockwrite(BMPF, buf[i+000], 1);
      end;
      curx:=0;
    end;

Коли ми зчитали увесь рядок у буфер, час його записати. Але через те, що RGB дані у PCX форматі розбиті на площини, запис йде з трьох точок буферу, що поступово зміщуються. Зауважте обернений формат запису триплетів у форматі BMP, спочатку йде B, потім G, а потім R. У кінці ми переводимо вказівник знову на початок буферу.

  end;
  writeln;
  close(PCXF);
  close(BMPF);

Закінчили читати файл й записувати тимчасовий. 

Починаємо перевертання тимчасового файлу у нормальний формат BMP.

  assign(PCXF, 'dollar.tmp');
  reset(PCXF, 1);
  assign(BMPF, 'dollar.bmp');
  rewrite(BMPF, 1);

Спочатку, як завжди, відкриємо файли. Врахуйте, що тимчасовий файл відкривається змінною, що раніше відповідала PCX файлу. Так зроблено для мінімізації кількості змінних.

  blockread(PCXF, BMPheader, 54);
  blockwrite(BMPF, BMPheader, 54);

Зчитаємо й запишемо заголовок без змін. Будемо зчитувати файл по рядкам з кінця, а записуватимемо з початку. 

  for i:=1 to HGT do begin

Як не дивно, зчитувати рядки потрібно стільки раз, скільки у нас рядків.

    pos1 := filesize(PCXF)-(BPL*3*i);

Визначається позиція кожного рядку у файлі: від кінця файлу віднімаємо i рядків довжиною BPL*3 (*3 тому, що RGB).

    gotoxy(1, wherey); write(pos1); clreol;

Просто виводимо цю позицію на екран.

    seek(PCXF, pos1);
    blockread(PCXF, buf, BPL*3);
    blockwrite(BMPF, buf, BPL*3);
  end;

Переходимо до визначеной позиції, зчитуємо і записуємо рядок зображення.

  close(PCXF);
  close(BMPF);
  writeln;
end.

У кінці бажано позакривати все, що відкривали. Можна було б також витерти тимчасовий файл.

Висновки

Завданням даної роботи було дослідження основних принципів перетворення форматів графічних файлів. У роботі наведено різні класифікації графічних форматів. Розглянуто можливі галузі застосування цих форматів, як то: Internet, друковані видання, електроні презентації. Також наведено детальний опис усіх можливих варіантів перетворення одного формату в інший, зазначено типові проблеми, які при цьому виникають. Крім того створено програму перетворення для двох конкретних растрових форматів. Під час роботи над програмою ретельно досліджено будову форматів PCX та BMP, описано алгоритм їхнього перетворення, пояснено реалізацію алгоритму на мові Pascal. 

Література

		Д. Мюррей, У. Райпер "Энциклопедия форматов графических файлов", BHV, Киев, 1997.

		Р. Водески "Графика для Web", Диалектика, Киев, 1998.

		ftp://ftp.mv.com/pub/ddj/1994/1194.09/bmp.zip

		ftp://x2ftp.oulu.fi/pub/msdos/programming/formats

		ftp://telva.ccu.uniovi.es/pub/graphics/file.formats

		Журнал "ЧИП", 9/97, стр. 58, "Графические форматы BMP, GIF, JPEG, PNG и FLASHPIX"



Додаток 1

Повний текст програми перетворення.

Uses
  crt;
var
  PCXF, BMPF: file;
  PCXheader: array [0..127] of byte;
  BMPheader: array [0..53] of byte;
  i, result, curx, HGT: integer;
  buf: array [0..1959] of byte;
  b, val: byte;
  size, pos1, BPL: longint;
begin
  assign(PCXF, 'dollar.pcx');
  reset(PCXF, 1);
  assign(BMPF, 'dollar.tmp');
  rewrite(BMPF, 1);

  blockread(PCXF, PCXheader, 128);
  for i:=0 to 53 do begin
    BMPheader[i]:=0;
  end;

  writeln('W: ', PCXheader[9]*256+PCXheader[8]+1);
  HGT := PCXheader[11]*256+PCXheader[10]+1;
  writeln('H: ', HGT);
  BPL := PCXheader[67]*256+PCXheader[66];

  BMPheader[0] := $42; {header word}
  BMPheader[1] := $4D;
  BMPheader[10] := 54;
  BMPheader[14] := 40; {header size}
  BMPheader[18] := PCXheader[8]+1;
  BMPheader[19] := PCXheader[9];
  BMPheader[22] := PCXheader[10]+1;
  BMPheader[23] := PCXheader[11];
  BMPheader[26] := 1; {planes}
  BMPheader[28] := 24; {bpp}
  blockwrite(BMPF, BMPheader, 54);
  result:=1;
  size:=0;
  curx:=0;
  while result=1 do begin
    blockread(PCXF, b, 1, result);
    if (b and $C0) = $C0 then begin
      b:=b and $3F;
      blockread(PCXF, val, 1, result);
    end else begin
      val:=b;
      b:=1;
    end;
    gotoxy(1, wherey); write(size); clreol; inc(size);
    for i:=1 to b do begin
      buf[curx]:=val;
      inc(curx);
    end;
    if (curx=BPL*3) then begin
      for i:=0 to BPL-1 do begin
        blockwrite(BMPF, buf[i+2*BPL], 1);
        blockwrite(BMPF, buf[i+BPL], 1);
        blockwrite(BMPF, buf[i+000], 1);
      end;
      curx:=0;
    end;
  end;
  writeln;
  close(PCXF);
  close(BMPF);

  assign(PCXF, 'dollar.tmp');
  reset(PCXF, 1);
  assign(BMPF, 'dollar.bmp');
  rewrite(BMPF, 1);
  blockread(PCXF, BMPheader, 54);
  blockwrite(BMPF, BMPheader, 54);
  for i:=1 to HGT do begin
    pos1 := filesize(PCXF)-(BPL*3*i);
    gotoxy(1, wherey); write(pos1); clreol;
    seek(PCXF, pos1);
    blockread(PCXF, buf, BPL*3);
    blockwrite(BMPF, buf, BPL*3);
  end;
  close(PCXF);
  close(BMPF);
  writeln;
end.









1