

                      PCX-Bilder in Pascal
                      --------------------

Nachdem Ihr sicherlich die Theorieabhandlung der PCX-Bilder gele-
sen habt, geht es nun gleich weiter mit der Umsetzung in die
Praxis mit Pascal.

Das folgende Programm liest ein 320x200x256-PCX-Bild ein und
bringt es auf den Bildschirm. Eine hhere Auflsung ist zwar auch
machbar, doch ein wenig komplizierter, wenn man kein passenden
BGI-Aufsatz hat. In der nchsten Ausgabe von STOD drfte wohl
(wenn ich gengend Zeit finde) auch ein wenig zu dem Thema ste-
hen.

Nun aber zum Programm. Obwohl es eigentlich nicht ntig ist,
berprfe ich trotzdem am Anfang des Programms, ob es sich ber-
haupt um ein PCX-Bild handelt (erstes Byte mu '0A' sein). Den
Rest des Headers bergehe ich einfach mal. Dann werden 30000
Byte aus der Datei gelesen. Die tatschliche Anzahl der gelesenen
Bytes werden von der Prozedur 'BlockRead' in 'GeleseneBytes' zu-
rckgeliefert. Der Rest des Programms, das meiner Meinung nach
gengend dokumentiert ist, lt sich nach dem Schema beschreiben,
das auch schon im allgemein abgefaten Text steht: Sollte die
Zhlvariable 'Index' einen Werte ungleich 0 beinhalten, so wird
das nchste Byte sooft in den Videospeicher geschrieben, wie es
Index vorschreibt. Andernfalls wird das nchste Byte daraufhin
berprft, ob es ein Zhlbyte ist (Byte AND $C0 = $C0). Ist das
der Fall, wird das Byte in Index gespeichert, und es geht wieder
von vorne los. Sollte es nicht so sein, reprsentiert das jetzige
Byte einen einzelnen Pixel und wird in den Videospeicher bertra-
gen. Danach geht's ebenfalls von vorne los.
Zum Schlu der Prozedur wird dann noch die Palette gesetzt, die
sich am Ende der Datei befindet.

Die Prozedur:

PROCEDURE PCX(PCXFile:STRING);
VAR PCX                        : FILE;
    Daten                      : ^BYTE;
    DatenMem                   : POINTER;
    Pal,ScreenPos,Pos,Index,
    Wiederholung,GeleseneBytes : WORD;
BEGIN
  ASSIGN(PCX,PCXFile);
  {$I-}
   RESET(PCX,1);
   IF IOResult <> 0 THEN Exit;
  {$I+}
  GetMem(Daten,30000);                        {Bytes reservieren}
  DatenMem := Daten;                      {Anfangsadresse merken}
  BlockRead(PCX,Daten^,128,GeleseneBytes);         {Header lesen}
  IF Daten^ <> $0A THEN BEGIN            {PCX-Kennung vorhanden?}
   Close(PCX);                         {Nein: Prozedur verlassen}
   Exit;
  END;
  Index := 0; ScreenPos := 0;
  REPEAT
   BlockRead(PCX,Daten^,30000,GeleseneBytes);       {Bytes lesen}
   Pos := 0;
   WHILE (Pos < GeleseneBytes) AND (ScreenPos <= 64000) DO BEGIN
            {Solange Daten noch brig sind, und nicht schon alle
                                              Pixel gesetzt sind}
    IF Index > 0 THEN BEGIN                  {Wiederholungsbyte?}
     FOR Wiederholung := 1 TO Index DO BEGIN               {Ja: }
      MEM[$A000:ScreenPos] := Daten^; {Schreibe Farbe sooft, wie
                                                   {Index besagt}
      Inc(ScreenPos);
     END;
     Index := 0;                           {Nein: Index auf null}
    END ELSE IF (Daten^ AND $C0) = $C0 THEN
     Index := Daten^ AND $3F         {Wenn Byte = Zhlbyte, dann
                                                   Index := Byte}
    ELSE BEGIN                          {Sonst: }
     MEM[$A000:ScreenPos] := Daten^;   {Schreibe Byte in Video-
                                         speicher - Einzelfarbe}
     Inc(ScreenPos);
    END;
    Inc(Pos); Inc(Daten);
   END;
   Daten := DatenMem;          {Ursprngliche Adresse herstellen}
  UNTIL GeleseneBytes = 0;
  Seek(PCX,FileSize(PCX)-769);    {Auf 769. Byte vor Ende setzen}
  BlockRead(PCX,Daten^,769);                     {769 Byte lesen}
  IF Daten^ = $0C THEN BEGIN                {Paletten-Erkennung?}
    Inc(Daten);               {Auf Anfang der Farbtabelle setzen}
    FOR Pal := 1 TO 768 DO BEGIN
     Daten^ := Daten^ SHR 2;    {Paletteneintrge durch 4 teilen}
     Inc(Daten);
    END;
    Dec(Daten,768);                    {Wieder auf Anfang setzen}
    ASM
     MOV BX,0
     MOV CX,256
     MOV AX,1012h
     LES DX,Daten
     INT 10h                                  {Palette eintragen}
   END;
  END;
  Daten := DatenMem;     {Daten wieder auf ursprngliche Adresse
                                                          setzen}
  FreeMem(Daten,30000);               {Speicher wieder freigeben}
  Close (PCX);
END;



Tja, soviel zu dieser Prozedur. Das Listing mu (natrlich!)
nicht abgeschrieben werden, sondern befindet sich in dem Ver-
zeichnis 'SOURCES' im STOD-Pfad. Eine Demo-Prog wird da eventuell
auch noch zu finden sein - schaut Euch mal ein wenig um.

Und wie immer: Sollten noch irgendwelche Fragen oder Verbes-
serungsvorschlge vorhanden sein ---> her damit!


                                                 Kemil