Referat von Oliver Pola
Quelle: R. Steinbrecher: "Bildverarbeitung in der Praxis", Oldenbourg, Seite 273ffDas PCX-Format wurde entwickelt von der Firma Zsoft-Corporation, USA.
Es existieren die Versionen 0, 2, 3, 4 und 5. Version 0 war nur für
zwei oder vier Farben geeignet, Version 2 unterstützte 16 Farben.
Die aktuelle Version 5 verarbeitet auch 256 Farben aus 16,7 Millionen oder
Echtfarben (24 Bit).
Die maximale Größe der Bilder im PCX-Format beträgt
65536 x 65536 Pixel. Es wird nur das RGB-Modell unterstützt und die
Lauflängen-Kodierung angewendet.
Lauflängen-Kodierung (RLC):
Bei der Lauflängen-Kodierung werden aufeinander folgende gleiche
Farbwerte in der Form kodiert, daß nur einmal der Farbwert und die
Anzahl der Wiederholungen gespeichert wird.
Kennzeichen für die Lauflängen-Kodierung ist das setzen der
beiden höchsten Bits. Die unteren 6 Bit geben dann die Anzahl (max.
63) der Wiederholungen, das folgende Byte den Farbwert an. Die Kodierung
erfolgt für maximal eine Zeile.
Das bewirkt das Problem, daß Farbwerte >191 immer Lauflängen-kodiert
werden, auch wenn der Farbwert nur einmal auftritt.
Byte Anzahl Bezeichner Wert / Bedeutung
0 1
Hersteller
10 = Zsoft
1 1
Versionsnr.
0, 2, 3, 4 oder 5
2 1
Kodierung
1 = RLC
3 1
Bits pro Pixel
1, 2, 4 oder 8
4 8
Bildgröße
X_Min, Y_Min, X_Max, Y_Max jeweils 2 Byte
12 2
horiz. Aufl.
in dpi
14 2
vert. Aufl.
in dpi
16 48
Header-Palette
LUT für 16 oder weniger Farben
64 1
reserviert
0
65 1
Farbebenen
1-4
66 2
Bytes / Zeile / Farbebene zur Ermittlung des benötigten
Speichers
68 2
Interpretation
1 = Farbe oder s/w, 2 = Grauwerte
70 2
horiz. Bildschirmgröße
72 2
vert. Bildschirmgröße
74 54
Leer
bis Byte 128
Angaben mit 2 Byte sind Integer-Werte.
Darauf folgen die Bildinformationen mit Bezug auf die Farbpalette oder
zuerst Rot-Ebene dann Grün-Ebene dann Blau-Ebene.
Anschließend folgt, wenn benötigt, die 256-Farben-Palette
mit 256 Farbtripeln (R,G,B), eingeleitet von einer dezimalen 12.
Die folgenden Algorithmen gehen davon aus, daß Version 5 mit Grauwerten,
also 256 Farben, verwendet wird.
1 unsigned char *bild;
/* Adresse des Bildspeichers (Array) */
2 unsigned int bildzeilen;
/* Anzahl der Zeilen/Spalten des Bildes */
3 unsigned int bildspalten;
4
5 Save_PCX()
6 {
7 int Z_Index,
S_Index;
/* PCX-Größenangaben */
8 unsigned
char PCXHeader[128];
9 unsigned
char LUT[768]; /*
Farbpalette */
10 unsigned char
Pixel;
11 unsigned char
Anzahl;
12 int PCX_fd;
/* File-Descriptor */
13 int i, j, z,
s;
14 long Index;
/* Adresse des Pixels im Bild */
15
16 ... Datei PCX_fd zum schreiben öffnen
...
17
18 /* PCX-Header
erzeugen */
19 S_Index = bildspalten-1;
20 Z_Index = bildzeilen-1;
21
22 PCXHeader[0]
= 10;
/* Zsoft */
23 PCXHeader[1]
= 5;
/* Version 5 */
24 PCXHeader[2]
= 1;
/* RLC */
25 PCXHeader[3]
= 8;
/* Bits pro Pixel und Ebene */
26 PCXHeader[4]
= 0;
/* Xmin Low-Byte */
27 PCXHeader[5]
= 0;
/* Xmin High-Byte */
28 PCXHeader[6]
= 0;
/* Ymin Low-Byte */
29 PCXHeader[7]
= 0;
/* Ymin High-Byte */
30 PCXHeader[8]
= S_Index-256*(S_Index/256); /* Xmax Low-Byte */
31 PCXHeader[9]
= S_Index/256;
/* Xmax High-Byte */
32 PCXHeader[10]
= Z_Index-256*(Z_Index/256); /* Ymax Low-Byte */
33 PCXHeader[11]
= Z_Index/256;
/* Ymax High-Byte */
34 PCXHeader[12]
= 0;
/* X-Auflösung in dpi */
35 PCXHeader[13]
= 0;
36 PCXHeader[14]
= 0;
/* Y-Auflösung in dpi */
37 PCXHeader[15]
= 0;
38
39 /* Farbtabelle
für 16 oder weniger Farben (nicht verwendet)*/
40 for(i=16; i<64;
i++) PCXHeader[i] = 0;
41
42 PCXHeader[64]
= 0;
/* reserviert */
43 PCXHeader[65]
= 1;
/* Anzahl der Ebenen */
44 PCXHeader[66]
= S_Index+1-256*((S_Index+1)/256); /* Bytes/Zeile
*/
45 PCXHeader[67]
= (S_Index+1)/256;
46 PCXHeader[68]
= 2;
/* Grauwerte */
47 PCXHeader[69]
= 0;
48 PCXHeader[70]
= 0;
/* Auflösung des Bildschirms */
49 PCXHeader[71]
= 0;
50 PCXHeader[72]
= 0;
51 PCXHeader[73]
= 0;
52
53 /* unbenutzte
Bytes auf 0 Setzen */
54 for(i=74; i<128;
i++) PCXHeader[i] = 0;
55
56 /* Farbtabelle
(Graukeil) */
57 for(i=0; i<256;
i++)
58
for(j=0; j<3; j++) LUT[i*3+j] = i;
59
60 write(PCX_fd,
PCXHeader, 128);
61
62 /* RLC berechnen
*/
63 for(z=0; z<=Z_Index;
z++)
64 {
65
Index = (long)z * (long)bildspalten;
66
s = 0;
67
while(s<=S_Index)
68
{
69
Pixel = bild[Index+s]; /* erstes Vorkommen
der Farbe */
70
s++;
71
Anzahl=1;
72
while((s<=S_Index) && (Pixel==bild[Index+s]) && (Anzahl<63))
73
{
74
Anzahl++;
75
s++;
76
}
77
/* Anzahl>1 oder Farbe>=192, dann RLC durchführen */
78
if((Anzahl>1) || (Pixel>=192))
79
{
80
Anzahl = 0xC0 + Anzahl; /* RLC-Kennung */
81
write(PCX_fd, Anzahl, 1);
82
write(PCX_fd, Pixel, 1);
83
}
84
else
85
{
86
write(PCX_fd, Pixel, 1); /* einmaliges Pixel mit Grauwert<192
*/
87
88
}
89
}
90 }
91 /* LUT Farbpalette
schreiben */
92 Pixel=12;
/* Kennzeichen f. Bild-Ende */
93 write(PCX_fd,
Pixel, 1);
94 write(PCX_fd,
LUT, 768); /* Farbpalette */
95 close(PCX_fd);
96 }
Algorithmus zum Laden
1 unsigned char *bild;
/* Adresse des Bildspeichers (Array) */
2 unsigned int bildzeilen;
3 unsigned int bildspalten;
4
5 Load_PCX()
6 {
7 unsigned
char PCXHeader[128];
8 unsigned
char Pixel;
9 unsigned
char Anzahl;
10 int PCX_fd;
/* File-Descriptor */
11 int i, j, z,
s;
12 long Index;
13
14 ... Datei PCX_fd zum lesen öffnen
...
15
16 /* PCX-Header
einlesen und auf Version 5 testen */
17 read(PCX_fd,
PCXHeader, 128);
18 if((PCXHeader[0]!=10)
|| (PCXHeader[1]!=5) ||
19
(PCXHeader[2]!=1) || (PCXHeader[3]!=8))
20 {
21
ShowError("Falsches Datenformat.");
22
return();
23 }
24
25 /* Bildmaße
berechnen */
26 bildspalten
= 256*(unsigned int)PCXHeader[9]+(unsigned int)PCXHeader[8]+1;
27 bildzeilen =
256*(unsigned int)PCXHeader[11]+(unsigned int)PCXHeader[10]+1;
28
29 /* RLC einlesen
*/
30 Index = 0;
31 z = 0;
32 while(z<bildzeilen)
33 {
34
s = 0;
35
j = 0;
36
while(s<bildspalten)
37
{
38
read(PCX_fd, Pixel, 1);
39
if(Pixel>192)
40
{
41
Anzahl = Pixel-192;
42
read(PCX_fd, Pixel, 1);
43
for(i=0; i<Anzahl; i++)
44
{
45
bild[Index++] = Pixel;
46
s++;
47
}
48
}
49
else
50
{
51
bild[Index++] = Pixel;
52
s++;
53
}
54
}
55
z++;
56 }
57 close(PCX_fd);
58
59 /* Einlesen
der Farbpalette entfällt, da Grauwerte vorausgesetzt */
60 }