PCX

Tento formát pochádza v dielne firmy PC Paintbrush a z tohto dôvodu sa niekedy označuje aj ako PC Paintbrush formát. Posledná verzia tohto formátu umožňuje ukladanie až 24-bitových obrázkov. Dáta môžu byť uložené s orientáciou na farebné plochy (roviny) alebo na body (aby v čase je vzniku vyhovoval hardvérovému návrhu obrazovky IMB EGA alebo IMB VGA).

Obrazové dáta sú kódované použitím varianty RLE algoritmu, ktorý je rýchly, ale na druhej strane nie veľmi účinný. Pri RLE kompresii je pomerne ťažko určiť priemernú alebo obvyklú kompresiu, pretože táto kompresia je vo veľkej miere závislá od kódovaných dát.

Organizácia súboru

Súbor PCX je organizovaný do troch hlavných častí: hlavička, obrazové dáta a farebná paleta. Farebná paleta obsahuje obvykle 256 farieb.

Hlavička

typedef sturct _PcxHeader {
	BYTE Identifier;	/* Indentifikátor PCX, vždy 0x0A */
	BYTE Version		/* Číslo verzie */
	BYTE Encoding;		/* Druh kódovania */
	BYTE BitsPerPixel;	/* Počet bitov na bod */
	WORD XStart;		/* Ľavá strana obrázku */
	WORD YStart;		/* Horná strana obrázku */
	WORD XEnd;		/* Pravá strana obrázku */
	WORD YEnd;		/* Spodná strana obrázku */
	WORD HorzRes;		/* Horizontálne rozlíšenie */
	WORD VertRes;		/* Vertikálne rozlíšenie */
	BYTE Patette[48];	/* 16 farebná EGA paleta */
	BYTE Reserved1;		/* Vyhradené */
	BYTE NumBitPlane;	/* Počet bitových rovín */
	WORD BytesPerLine;	/* Počet bajtov na skanovací riadok */
	WORD PaletteType;	/* Typ palety */
	WORD HorzScreenSize;	/* Horizontálna veľkosť obrazovky */
	WORD VertScreenSize;	/* Vertikálna veľkosť obrazovky */
	BYTE Reserved[54];	/* Rezervované */
} PCXHEAD;			
			
Identifier
je identifikačná hodnota definovaná k špecifikácii PCX. Jej hodnota je vždy 0x0A. Táto hodnota by sa mala stále kontrolovať. Niekedy sa stáva, že táto hodnota je 0x10. Vtedy by program mal skontrolovať, či zvyšné dáta v hlavičke sú aspoň trocha zmysluplné.
Version
obsahuje verziu programu Paintbrush ktorý vytvoril PCX súbor. Môže obsahovať nasledujúce hodnoty
  • 0 - Verzia 2.5 s pevnou EGA paletou
  • 2 - Verzia 2.8 s modifikovanou EGA paletou
  • 3 - Verzia 2.8 bez informácie o palete
  • 4 - PC PaintBrush for Windows
  • 5 - Verzia 3.0, všetky 24-bitové obrázky
Encoding
indikuje typ použitého kódovania. Je podporovaný iba jednoduchý prúdový RLE algoritmus, ktorý je v tomto poli určený hodnotou 1. Ak sa v tomto poli náhodou nachádza hodnota 0 značí to, že obrazové dáta sú nezakódované.
BitsPerPixel
je počet bitov na jeden obrazový bod. Možné hodnoty sú 1, 2, 4 a 8 pre 2-, 4-, 16- a 256-farebné obrázky.
XStart, YStart, XEnd, YEnd
ukladajú veľkosť obrázka v bodoch a tiež jeho relatívnu polohu vzhľadom na obrazovku. Teda ak sú hodnoty XStart a YStart nenulové, malo by byť vykresľovanie obrázka o tieto hodnoty posunuté. Hociktorý PCX obrázok môže obsahovať výplňové bajty na konci skanovacieho riadka alebo prídavné skanovacie riadky. Aby sa zabránilo zobrazeniu týchto dát, mali by byť zobrazované len hodnoty vo vnútri okna definovaného týmito hodnotami.
HorzRes, VertRes
označujú horizontálnu a vertikálnu veľkosť uloženého obrázka v bodoch alebo DPI (body na palec). Tieto hodnoty nie sú potrebné pri dekódovaní dát, takže ich môžeme kľudne ignorovať.
Palette
je 48-bajtové pole osembitových hodnôt, ktoré vytvárajú 16-farebnú paletu pre EGA adaptér.
NumBitPlane
je počet farebných rovín, ktoré obsahujú farebné dáta. Hodnota býva obvykle 1, 3, 4 je je asociovaná s hodnotou BitsPerPixel pre určenie vhodného režimu zobrazenia.
Tabuľka: Výpočet farbej hĺbky obrázku
Farebných rovín Bitov na bod a rovinu Max.počet farieb Videorežim
1 1 2 monochromatický
1 2 4 CGA
3 1 8 EGA
4 1 16 EGA a VGA
1 8 256 Extended VGA
3 8 16 777 216 Extended VGA a XGA
Táto hodnota sa používa aj pre určenie maximálneho počtu farieb, ktoré obrázok môže mať. MaxNumColors = (1L << (BitsPerPixel*NumBitPlane))
BytesPerLine
je veľkosť farebnej roviny v bajtoch v nezakódovanom skanovacom riadku. Keď túto hodnotu vynásobíme NumBitPlane získame celkovú veľkosť skanovacieho riadku v bajtoch. ScanLineLength = BytesPerLine * NumBitPlane
PaletteType
určuje informácie obsiahnuté v palete. Táto hodnota sa pri dekódovaní môže kľudne ignorovať.
  • 1 - dvojfarebná alebo monochromatická paleta
  • 2 - paleta v škále šedej
HorzScreenSize, VertScreenSize
reprezentujú rozlíšenie obrazovky, v ktorom bol obrázok vytvorený

Paleta

16-farebná EGA paleta

Prvé verzie PCX nepodporovali modifikovateľnú paletu. Neskôr sa objavili ďalšie dve verziu PCX formátu. Jedna s informáciou o palete (modifikovateľná paleta) a jedna bez paletovej informácie.

EGA paleta je 48-bajtové pole obsahujúce 16 RBG trojíc, s hodnotami v rozmedzí 0-255. Z tohto pola je podľa potreby vyplnených iba potrebné množstvo údajov, zvyšné sú nastavené na 00h. EGA má však iba 4 možné hodnoty pre každú z RGB farieb, takže každá z RBG hodnôt je posunutá o šesť bitov doprava.

EgaColorRed	=	EgaPalette[0] >> 6;
EgaColorGreen	=	EgaPalette[1] >> 6;
EgaColorBlue	=	EgaPalette[2] >> 6;
/* atď  */
			

4-farebná CGA paleta

EGA paleta môže byť použitá aj pre zobrazovanie CGA obrázkov. Tri farby slúžia ako farba popredia a jedna farba slúži ako farba pozadia. Najvýznamnejšie štyri bity prvého bajtu EGA palety určujú farbu pozadia v rozmedzí 0 - 15. Najvýznamnejšie tri bity štvrtého bajtu EGA palety obsahujú farbu popredia. Tri bity farby popredia korešpondujú s nastavením Color Burst, Enable a Palette Intensity (viac v štandarde CGA).

CgaBackGroundColor	=	EgaPalete[0] 4;
CgaColorBurstEnable	=	(EgaPalette[3]	& 0x80) >> 7;
CgaColorBurstEnable	=	(EgaPalette[3]	& 0x40) >> 6;
CgaColorBurstEnable	=	(EgaPalette[3]	& 0x20) >> 5;
			

256-farebná VGA paleta

VGA technológia vyberá 256 farieb z 262 144 možných. Keďže v hlavičke súboru nebolo dostatok miesta, bola informácia o VGA palete pridaná na koniec súboru. Keďže veľkosť obrazových dát nie je vždy rovnaká, nie je poloha palety určovaná vzhľadom na začiatok súboru ale jeho koniec. Aby sme zistili, či je VGA plate uložená v súbore, treba sa posunúť 769 bajtov od konca súboru. Ak sa tam nachádza hodnota C0h, obsahuje zvyšných 768 bajtov informáciu o VGA palete.

VGA paleta obsahuje 3x256 bajtov v rozmedzí 0-255. VGA zariadenia vedia pracovať iba s hodnotami 0-63 pre každú farebnú zložku, takže každá hodnota musí byť delená štvormi (posun o dva bity doprava).

Obrazové dáta

Na kódovanie obrazových dát za používa modifikovaný RLE algoritmus. Kódované dáta sa čítajú po jednom bajte. Ak sú dve najvýznamnejšie bity nastavené na 1, indukuje to začiatok dvojbajtového kódového paketu. Tento bajt vo svojich spodných šiestich bitoch obsahuje dĺžku. Táto je v rozmedzí od 1-63. Druhý bajt tohto paketu je číslo farby z palety, ktorá sa má daný počet krát zapísať na výstup.

Pokiaľ sú obe najvýznamnejšie bity nastavené na 0, je tento bajt považovaný za priamu hodnotu a paket má v tomto prípade dĺžku jedného bajtu.

Toto kódovanie nie je veľmi ideálne. Jednobajtová hodnota paketu môže obsahovať iba čísla v rozmedzí 0-63. Ak sa hodnota nachádza mimo tohto rozsahu, je nutné použiť dvojbajtovú variantu paketu. Toto môže mať za následok negatívnu kompresiu.

Dekódovanie PCX súboru

Aby sme boli schopní dekódovať PCX súbor, musíme si z hlavičky zistiť aspoň tieto informácie.

  • šírka obrázka v bodoch
  • výška obrázka v skanovacích riadkoch
  • počet výplňových bajtov na konci každého skanovacieho riadka
ImageWidth	=	XEnd - XStart + 1;
ImageHeight	=	YEnd - YStart + 1;
ScanLineLength	=	NumBitPlane * BytesPerLine;
			
Dĺžka výplne každého skanovacieho riadka bude hodnota LinePaddingSize.
LinePaddingSize	=	((BytesPerLine * NumBitPlane) * (8/BitsPerPixel)) - ((XEnd - XStart) + 1)
			
Pri dekódovaní predpokladajme, že máme bufer veľkosti skanovacieho riadku. Potom dekódovací algoritmus bude nasledovný:
  1. prečítaj bajt
  2. ak sú dva najvýznamnejšie bity rovné 1, je to počítadlo paketu. Spočítaj dĺžku tohto paketu
  3. prečítaj ďalší bajt
  4. zapíš tento bajt toľko krát, koľko udáva dĺžka paketu
  5. ak sú dva najvýznamnejšie bity rovné 0, je to hodnota bodu
  6. zapíš raz túto hodnotu
  7. opakuj predchádzajúce kroky až do naplnenia bufera