← ST-Computer 10 / 1988

ST-Ecke: WEITERBILDUNG - DEGAS komprimiert- und IFF-Format

Grundlagen

Nachdem wir uns in der letzten Ausgabe mit dem allgemeinen Aufbau eines Bildes und den einfachen (ungepackten) Bildformaten auseinandergesetzt haben, wollen wir weiter dieses Thema erforschen und die Geheimnisse der Packformate ergrĂŒnden. ZunĂ€chst betrachten wir allgemein, wie es ĂŒberhaupt möglich ist, Daten auf ein Minimum zu reduzieren, ohne daß tatsĂ€chlich Information verloren geht. Im weiteren Verlauf werden wir uns mit dem ersten Bildformat beschĂ€ftigen, das die Daten gepackt also komprimiert abspeichert- dem IFF-Format. Das Interessante des IFF-Formats ist, daß es nicht nur fĂŒr Bilddaten, sondern auch fĂŒr diverse andere Daten wie zum Beispiel Text verwendet werden kann.

ZunĂ€chst möchte ich mich dafĂŒr entschuldigen, daß in der letzten Ausgabe ein paar Zeilen im C-Listing gefehlt haben. Wahrscheinlich hat man beim Setzen das Wort Packen zu wörtlich genommen. Wir liefern die Zeilen in Listing 3 hiermit nach.

Weniger ist mehr

ZunĂ€chst wird sich der brave BĂŒrger (oder auch Programmierer ) fragen, wie es ĂŒberhaupt möglich sein kann, in weniger Daten genau die gleiche Information unterzubringen wie im Originaldatensatz - geht dabei nicht unausweichlich Information verloren ? Um so verblĂŒffender ist es, wenn relativ einfach gehaltenene Bilder sich nicht nur auf die HĂ€lfte, sondern vielleicht von 32000 Bytes auf knapp 1000 Bytes ohne jeglichen Informationsverlust verkĂŒrzen lassen. Zauberei? Wirklich nicht! Schauen wir uns dieses Wunder an einem alltĂ€glichen Beispiel an: Stellen Sie sich vor, Sie wĂŒrden ins Theater gehen, eine lange Schlange Menschen am Eingang sehen und wollten einem Bekannten nach selbigen Theaterbesuch ĂŒber diese Menschenkette erzĂ€hlen. Sicherlich kĂ€men Sie nicht auf die Idee, die Menschenkette auf folgende Art zu beschreiben: Vorne stand ein Mann, dann kam noch ein Mann und noch ein Mann, dann folgte eine Frau mit Kind und noch eine Frau mit Kind und so weiter. Vielmehr faßt man auch im normalen Sprachgebrauch mehrere gleiche Dinge durch AufzĂ€hlung zusammen. Sie werden mir recht geben, daß die Beschreibung “ Ich sah 3 MĂ€nner und 2 Frauen mit Kind in einer Schlange” eleganter klingt. Obwohl die Beschreibung kĂŒrzer ist, ist der Informationsgehalt der gleiche! Was spricht nun dagegen, Ă€hnliches auch auf die Beschreibung von Bilddaten anzuwenden? (Auch wenn es wahrscheinlich keinen Ihrer Bekannten interessieren wird, wie Ihre Bilder aussehen.)

Packen wir’s an

Normalerweise stehen in einer (nicht komprimierten) Datei hintereinander alle Bytes so, wie sie nachher auch im Bildschirmspeicher zu finden sind. Dies ist selbst dann der Fall, wenn hundertmal das gleiche Byte vorhanden ist. Viel schöner wĂ€re es doch, wenn folgende Beschreibung möglich wĂ€re: “Zuerst kommen 25 unzusammenhĂ€ngende Bytes, dann hundertmal das Byte X, dann zehnmal das Byte Y, dann wieder zwölf Bytes ohne Zusammenhang...”. Sie bemerken, daß wir keine Information beim Abspeichem der Daten verlieren, wenn wir spĂ€ter beim Laden die Datei wieder ‘dechiffrieren’. Die Kunst des Komprimierens ist es nun, ein Verfahren zu entwickeln, das möglichst viele wiederkehrende Muster erkennt und verschlĂŒsseln kann. Dabei ist die einfachste Art, den Bildspeicher in den aufeinanderfolgenden Bytes nach Bytefolgen abzusuchen. Bei Bildern, in denen aber hĂ€ufig senkrechte Linien Vorkommen, hilft das nicht. Man muß ein solches Bild senkrecht, nicht waagrecht durchsuchen. Auf diese Weise kann man sich die tollsten Suchalgorithmen ĂŒberlegen, um ein Bild zu packen.

Bei digitalisierten Bildern sollte dieser Algorithmus besonders ausgefuchst sein, weil hier kaum gleiche aufeinanderfolgende Bytes zu finden sind. Hier geht man meistens noch eine Ebene tiefer, indem man sogar Bitmuster zu finden versucht. Langsam wird auch deutlich, warum das Packen von (speziell digitalisierten ) Bildern teilweise so lange dauert, daß man “eine kleine Kaffeepause” entlegen kann - das Suchen von (Bit-)Mustem dauert relativ lange. Bereitet man ein solches Bild spĂ€ter wieder auf, kennt man aufgrund der Kodierung das Muster und kann die Daten im Bruchteil einer Sekunde wieder zurĂŒckgewinnen.

Die Qual der Wahl

Nun gibt es inzwischen auf dem ATARI ST eine Vielzahl von Zeichen- und Malprogrammen (gerade erreichte die Redaktion das 100undxte), und fast jedes Programm hat seine eigene Speicherroutine, will sagen sein eigenes Speicherformat. Unsere kleine Reihe soll dazu beitragen, daß Sie wenigstens die bekanntesten Formate, die Sie mit Ihrem gekauften Programm erstellen, auch in Ihren eigenen Programmen verwenden können. Bitte haben Sie VerstĂ€ndnis, daß wir nur den Auspacker des entsprechenden Datenformats und die Information ĂŒber das Format veröffentlichen. Das hat zwei GrĂŒnde: Erstens ist die eigentliche Komprimierroutine meist viel komplizierter als die Entkomprimierung, und zweitens steckt im Packer viel mehr Softwaregrips, was auf deutsch heißt, daß kaum ein Programmierer bereit ist, die Zustimmung zur Veröffentlichung des Packers zu geben.

DEGAS ELITE und das IFF-Format

Beim IFF-Format handelt es sich um ein Format, daß ursprĂŒnglich von der Firma Electronic Arts entwickelt und auf dem AMIGA (ATARI-Liebhaber werden mir die ErwĂ€hnung dieses Namens verzeihen) in Deluxe Paint zum ersten Mal eingesetzt wurde. SpĂ€ter wurde es auf dem ST in Tom Hudsons DEGAS ELITE in abgewandelter Form verwendet und ist auch auf vielen anderen Rechner verbreitet. Der Vorteil dieses Packformates ist, daß es so allgemein gehalten ist, daß man damit nicht nur Bilder, sondern beliebige andere Daten gepackt speichern kann - allerdings werden wir nur das Packformat fĂŒr Bilder erklĂ€ren.

Klumpen

Betrachtet man das IFF-Format, erkennt man, daß es aus einer Reihe von Blöcken besteht, die in IFF-Sprache unter dem aussagekrĂ€ftigen Namen CHUNK bekannt sind - fĂŒr alle, die dem AngelsĂ€chsischen nicht so zugetan sind: CHUNK bedeutet soviel wie großer Brocken oder Klumpen. Wie schon zu vermuten ist, gibt es Chunks unterschiedlicher Art.

Förmlich

ZunĂ€chst beginnt eine IFF-Datei mit einem sogenannten FORM-Chunk, der die Art der Datei angibt, denn, oben erwĂ€hnte ich es schon, man kann nicht nur Bild - sondern auch Text- oder Musikdaten mit IFF verschlĂŒsseln. Dieser FORM-Chunk hat die sagenhafte LĂ€nge von nur 8 Bytes, in denen die KĂŒrzel 8SVX (8-Bit-Sample-Voice), SMUS (Simple Music Score), FTXT (formatierter Text) oder -was uns am meisten interessiert - ILBM (Interleaved Bit Map ) stehen können. Jedem Name des Chunks folgt die LĂ€nge desselben, wobei die ID, also der Namen selbst, nicht miteinbezogen wird. Ein Wort noch zu dem KĂŒrzel ILBM: Wie Sie wahrscheinlich aus unserer letzten Folge noch wissen, wird ein Bild aus mehreren Planes aufgebaut, die auch noch wortweise (ATARI) oder zeilenweise (IFF-Format) ineinander verschachtelt sind, was man Interleaved-Bit-Planes (oder Map) nennt. Erkennt unser Entpacker am Form-Chunk, der ein ILBM enthĂ€lt, daß es sich um eine Grafik-Datei handelt, “weiß” er, daß auf einen FORM-Chunk ein BMHD-CHUNK folgt.

FORM-Chunk BMHD-Chunk CMAP-Chunk CRNG-Chunk BODY-Chunk
GesamtlÀnge - 8 Byte (L)
IFF-Art-Grafik (4B)
Chunk-LĂ€nge(L)
Breite (W)
Höhe (W)
X-Position (W)
Y-Position (W)
Bitplane-Anzahl (B)
Maskierung (B)
Komprimierung(B)
Null (B)
Transparenzfarbe (W)
X-Aspekt (B)
Y-Aspekt (B)
Seitenbreite (W)
Seitenhöhe (W)
Chunk-LĂ€nge (L)
Farbe 0 Rot (B)
Farbe 0 GrĂŒn (B)
Farbe 0 Blau (B)
Farbe 1 Rot (B)
Farbe 1 GrĂŒn (B)
Farbe 1 Blau (B)
Farbe 2 Rot (B)
Farbe 2 GrĂŒn (B)
Farbe 2 Blau (B)
Farbe 3 Rot (B)
Farbe 3 GrĂŒn (B)
Farbe 3 Blau (B)
Chunk-LĂ€nge (L)
Null (W)
Geschwindigkeit (W)
aktiviert (W)
untere Farbe (B)
obere Farbe (B)
Chunk-LĂ€nge (L)
Bilddaten (B)

Tabelle 1: Die unterschiedlichen Grafik-Chunks (B=Byte, W=Wort, L=Langwort)

Der Kopf der ganzen Sache

An AbkĂŒrzungen wurde nicht gespart: BMHD bedeutet Bit-Map-Header. Er enthĂ€lt allgemeine Informationen eines Bildes. Schaut man sich diesen Chunk an (Tabelle 1), erkennt man einige interessante Eigenschaften: ZunĂ€chst bietet die Angabe der Koordinaten sowie der Breite und Höhe die Möglichkeit, Teile oder sogar ÜbergrĂ¶ĂŸen von Bildern abzuspeichern, die spĂ€ter entsprechend verarbeitet werden. Weiter ist im BMHD-Chunk die Anzahl der Planes enthalten, bei der darauf hingewiesen werden soll, daß der AMIGA bis zu fĂŒnf, der ST aber nur vier Planes enthĂ€lt, so daß unwillkĂŒrlich bei der Darstellung Information verloren geht.

Maskenball

Ein weiterer Eintrag gibt die Art der Maskierung an. Dabei wird zwischen 0 (keiner Maskierung), 1 (in Bilddaten vorhandene Maske), 2 (Transparenz) und 3 (Lassotechnik) unterschieden. Eine Maske ist eine Bilddatenmenge, durch die man kennzeichnen kann, an welcher Stelle ein eventuell vorhandener Hintergrund durchscheinen (ein gelöschtes Bit) oder vom neuen Bild verdeckt (ein gesetztes Bit) sein soll. Bei transparenter Maskierung wird an der Stelle im Bild, wo sich eine (an anderer Stelle) definierte Transparenzfarbe befindet, der Hintergrund des schon vorhandenen Bildes durchgeblendet. Die Verarbeitung der Lassotechnik ist relativ aufwendig zu programmieren. Die Vorgehensweise: Die Daten der Lassomaske kennzeichnen eine sich irgendwann wieder schließende, im Bild befindliche Kurve. Der Bildbereich im Innern dieser FlĂ€che wird als transparent verarbeitet. Weiterhin sind im BMHD die Transparenzfarbe sowie das Flag vorhanden, das angibt, ob die Datei komprimiert (1) oder ungepackt (0) vorliegt. Zwei weitere EintrĂ€ge kennzeichnen das VerhĂ€ltnis zwischen Breite und Höhe eines Bildes. Vorhanden ist auch eine Information, wie groß der Arbeitsbildschirm ist, wobei diese Werte auch kleiner sein können als das eigentliche Bild - uns ist allerdings bisher kein Programm bekannt, daß dies unterstĂŒtzt. Die genaue Reihenfolge und den Speicherplatzbedarf entnehmen Sie bitte Tabelle 1.

# CHUNK Bemerkung

FORM: : kennzeichnet die IFF-Datei in ihrer Art und LĂ€nge, ILBM entspricht Grafikart

BMHD: : enthÀlt allgemeine Informationen der Grafik wie zum Beispiel Auflösung, Anzahl der Planes, Komprimierung etc.

CMAP: : enthĂ€lt die Werte fĂŒr die Farbpalette. Es können bis zu 8 Bits pro RGB-Wert Vorkommen, wobei der ATARI ST 3 Bits und der AMIGA 4 Bits unterstĂŒtzt.

CRNG: enthĂ€lt Daten ĂŒber Farbrotation und Shading, der CRNG ist meist vierfach vorhanden.

BODY: : eigentlicher Grafikdatenteil
Bilder sind zeilenweise und planeweise abgespeichert, meist innerhalb der Zeile komprimiert

Tabelle 2: Der Aufbau einer IFF-Grafik-Datei

DEGAS komprimiert:

Screenformat:

nach IFF-Format komprimierte Bilddaten,
ab Byte 35 .. xxx,

32 Bytes Farbpalette nicht nach IFF-Standard Bytes 3 .. 34,

32 Bytes Farbanimationsdaten, hinter den komprimierten Bilddaten

Auflösung:

LOW ( * PCI ), MED ( *.PC2 ), HIGH ( *.PC3 ),

DateilÀnge:

variabel, abhÀngig vom Bildinhalt, da Packformat

Kennung:

  1. Byte = 80, !!!
  2. Byte = Auflösung (0=LOW, 1=MED, 2=HIGH ).

Bemerkung:

IFF-Standard nur bei der Komprimierung eingehalten, die Definitionschunks des IFF sind nicht vorhanden.

AMIGA-IFF:

Screenformat:

nach IFF - Standard aufgebautes Datenfile,
Bilddaten durch ‘BMHD’- und ‘BODY’-chunk gekennzeichnet,

Farbpalette durch ‘BMHD’- und ‘CMAP’-chunk gekennzeichnet.

Farbanimationsdaten nach IFF-Format evtl, enthalten

Auflösung: frei wÀhlbar, im BMHD eingetragen

DateilÀnge: variabel, abhÀngig vom Bildinhalt

Kennung: FORM-Chunk am Dateianfang.

Dateinamen nicht festgelegt, Vorschlag (*.IFF)

Tabelle 3: Zusammenstellung der Bildformate

Noch mehr Information...

bietet der CMAP-Chunk, der die Farbpalette beschreibt. FĂŒr jede Farbe stehen drei Bytes zur VerfĂŒgung, die jeweils die Rot-, GrĂŒn- und Blauwerte der Farbe angeben. Wichtig hierbei ist folgendes: Der ATARI ST besitzt vier und der AMIGA bis zu fĂŒnf Planes. Möchte man Bilder ausnutzen, die fĂŒnf Planes enthalten, muß man aufwendige Farbumrechnungen durchfĂŒhren, um eine Farbpalette zu erstellen, die mit 16 Farben fast so gute Ergebnisse wie mit 32 liefert. Ein weiteres Problem ergibt sich dadurch, daß die RGB-Werte beim AMIGA 32 Stufen annehmen können, wĂ€hrend der ATARI nur 8 Stufen besitzt. Man hat die Werte des AMIGAs durch 2 zu teilen, andernfalls findet man eine völlig falsche Farbgebung vor!

Es geht rund

Bevor wir endlich zu den eigentlichen Grafikdaten kommen, fehlt noch eine zusĂ€tzliche Information, die sich mit Farbrotationen beschĂ€ftigt. Als Farbrotation bezeichnet man das Weitergeben einer Farbinformation von einem Register in das andere. Einige unter Ihnen werden vielleicht die Animation von ATARI kennen, in der ein Adler ĂŒber den Bildschirm fliegt, unter dem die Brandung bewegt zu sehen ist. Die Bewegung der Brandung ist nur durch Rotieren der einzelnen Farben erzeugt! Der Chunk, der uns Auskunft ĂŒber die Farbrolleigenschaften des Bildes gibt, hat den unaussprechlichen Namen CRNG, was ausfĂŒhrlich Color Range (Farbbereich) heißt. Außer der Möglichkeit die Farbrotation ein- und auszuschalten, kann man hier die Geschwindigkeit und die Anfangs- und Endfarbe angeben, zwischen denen die Inhalte gerollt werden sollen. Bei einer Geschwindigkeit von 2 hoch 14 also 16384, werden sechzig Rotationen pro Sekunde durchgefĂŒhrt. Daraus folgt, daß eine Rotation pro Sekunde einem Vert von 273 und ein Wert von 1 einer Rotation in etwa viereinhalb Minuten spricht.

Endlich eingepackt

Nach soviel Vorinformation folgen, lange erwartet, die Grafikdaten. Wie nicht anders zu vermuten, hat auch dieser Block einen Namen - BODY. Der BODY (Körper) enthĂ€lt die Daten eines Bildes in gepackter oder ungepackter Form, je nachdem, ob der Kompressionseintrag gesetzt ist oder nicht. Nun sind wir schon daran gewöhnt, daß die einzelnes Planes beim ATARI nicht hintereinander abgelegt, sondern ineinander als Worte verschachtelt sind. Bei IFF sind die Planes auch nicht vollstĂ€ndig hintereinander, sondern immer bildzeilen weise hintereinander gespeichert (gefolgt von einer eventuell vorhanden Maskenzeile). Dadurch hat man die Möglichkeit, Teile eines Bildes zu laden, ohne wie wild durch die Datei springen zu mĂŒssen. Innerhalb dieser Zeilen geschieht nun die Komprimierung, die (leider) nicht besonders effektiv ist. Der Packer sucht in einer Zeile nach n gleichen aufeinanderfolgende Bytes. Am Anfang eines Kodierungsteils steht immer ein sogenanntes Befehlsbyte. Liegt der Wert n zwischen 0 und 127, werden die nĂ€chsten n+1 Bytes unverĂ€ndert (praktisch ungepackt) ĂŒbernommen. Ist es ein Wert zwischen -1 und -128, wird das folgende Byte -n+1mal wiederholt in den Speicher geschrieben die Zahl Null wĂ€re sinnlos, da das zweifache Wiederholen zwei Bytes kosten wĂŒrde... Da das oberste Bit einschaltet, ob das folgende Byte, aufgrund des sich aus den unteren sieben Bits ergebenden Wertes, wiederholt werden soll, fĂŒhrt der Wert 128 (“Wiederhole nullmal !”) zu keinem Ergebnis.

Unterschiede zu DEGAS ELITE compressed

Wie oben schon angedeutet, unterscheiden sich IFF-Format und Pack-Format von DEGAS-ELITE, haben aber auch etwas gemeinsam, daher werden beide Formate in einer Folge der BILDUNG abgehandelt. Leider stimmen sie nur in der Art der Komprimierung ĂŒberein, so daß alle Header fehlen und auch die Farbpalette nicht im IFF-Format abgespeichert ist. Werden wir speziell: Das erste Byte enthĂ€lt eine Null, die wir auch besser so lassen, da sie wie viele, auch im IFF-Format vorhandene, Nullen Platzhalter fĂŒr spĂ€tere Erweiterungen darstellt. Im zweiten Byte findet man die Auflösung kodiert, wobei 0 niedrige, 1 mittlere und 2 hohe Auflösung bedeutet. Die folgenden 32 Bytes enthalten die Farbpalette, wie schon angesprochen, nicht als IFF-Format, sondern als ganz normale Palette des ST. Hinter der Farbpalette folgen die nach IFF komprimierten Daten, deren Anzahl der Zeilen sich aus der Auflösung ergibt. Wie wir es schon von der normalen DEGAS-Datei kennen, folgen am Ende noch 32 Bytes Farbanimationsdaten.

ResĂŒmee

Wir haben nun die ersten beiden Pack-Formate kennengelernt und dabei festgestellt, daß das IFF-Format hervorragend dazu geeignet ist, Daten unter Rechnern auszutauschen, zumal es auch noch andere Chunks fĂŒr andere Datenarten gibt, allerdings ist der Komprimieralgorithmus relativ mĂ€ĂŸig. Es wird immer nur eine Zeile untersucht und außerdem das Bild nur byteweise und waagrecht ĂŒberprĂŒft, was bei vielen Bildern zu kaum einem Erfolg fĂŒhrt. Leider hat sich DEGAS-ELITE, obwohl es die gleiche Komprimierung wie IFF benutzt, nicht an den IFF-Standard gehalten, obgleich das Programm die Möglichkeit bietet, IFF-Bilderzu laden.

Ausblick

In der nĂ€chsten Bildung werden wir uns mit einem weiteren Format beschĂ€ftigen: dem GEM-VDI- oder auch Image-Format. Viele unserer Leser haben danach gefragt, so daß wir auch dieses Pack-Format in unsere Bildungsreihe hineinnehmen. Packen wir’s also das nĂ€chste Mal an...

SH

Bild 1: Anfang einer IFF-Bilddatei
Bild 2: Schema des Anfangs einer IFF-Bilddatei
* modul AUSPACK.S * * Assemblermodul zum Auspacken von * verschiedenen gepackten Bildformaten. * * * Originalauszug aus dem Grafikpaket IMAGIC * von APPLICATION SYSTEMS /// HEIDELBERG. * * Version 1.0 * * verfasst am 8-8-1988 von Jörg DrĂŒcker * Copyright (c) 1988 by IMAGIC GRAFIK. * * * DEGAS ELITE BILDER * * auspacken * * * xdef DEC_ELIT DEC_ELIT: bsr GET_PAR * Parameter holen cmpi.b #$80,(a0) * header byte "80' testen bne ERR_DONE cmp.b 1(a0),d0 * Bildauflösung testen bne ERR_DONE lea 34(a0),a0 * Farbinformation ĂŒberspringen * * * Register fĂŒr eine Vollbild * * IFF-Dekomprimierung einrichten * * * INIT_LOW: suba.l a2,a2 * compressed lines move.w #200,d6 * 200 scanlines moveq #6,d5 * plane byte offset (ATARI scheme) moveq #4,d4 * plane count moveq #40,d3 * line byte count per plane moveq #40,d7 tst.w d0 * Niedere Auflösung? beq.s ELIT_DECOMP * Ja... INIT_MED: moveq #2,d5 * plane byte offset (ATARI scheme) moveq #2,d4 * plane count moveq #80, d3 * line byte count per plane moveq #80,d7 subq.w #1,d0 * Mittlere Auflösung? beq.s ELIT_DECOMP * Ja... INIT_HIGH: moveq #0,d5 * plane byte offset (ATARI scheme) moveq #1,d4 * plane count add.w d6,d6 * 400 scanlines ELIT_DECOMP: bsr ERASE_PIC bsr IFF_DECOMP * IFF-format decompression bra ALL_DONE * * * AMIGA IFF BILDER * * auspacken * * * xdef DEC_IFF DEC_IFF: bsr GET_PAR * Parameter holen bsr ERASE_PIC * Bild löschen * * * Register fĂŒr eine Standard * * IFF-Dekomprimierung einrichten * * * * * * **EinschrĂ€nkungen:** * * Anzahl Farbplanes nur 1/2/4 * * * * Keine Maskentechniken * * zugelassen * * * * NOTE: data Starts direct with 'BMHD' (Bitmap-Header) chunk ... cmpi.1 #'BMHD',(a0) * Bitmap-Header chunk found? bne ERR_DONE * no, abort movem.w 8(a0),d1-d2 * picture width & height in pixel move.w d2,d6 * number of scanlines addq.w #7, d1 lsr.w #3,d1 * plane bytes per line (pix+7) div 8 moveq #0,d3 move.b 16(a0),d3 * number of planes * NOTE: only 1/2/4 planes can be handled. move.w d3,d2 * d2 nur zum Testen (1/2/4) subq.w #1,d2 beq.s PLANES_OK subq.w #1,d2 beq.s PLANES_OK subq.w #2,d2 bne ERR_DONE * otherwise abort PLANES_OK: move.b 17(a0),d2 * masking technique, 0 = mskNone, * 1 = mskHasMask, 2 = mskHasTranspcolor, * 3 = mskLasso cmp.b #1, d2 beq ERR_DONE * cannot handle mask in data. suba.1 a2,a2 * "compressed" tst.b 18(a0) * compression flag, 1=compressed bne.s COMPRESSED move.w d1,a2 * number of bytes per line (uncomp) COMPRESSED: move.w d3,d4 * number of planes move.w d1,d3 * number of plane bytes per line subq.w #1,d0 * res = low? bmi.s RES_LOW beq.s RES_MED cmpi.w #1,d4 * Anzahl planes testen bne ERR_DONE moveq #0,d5 * plane byte offset HIGH = 0 moveq #80, d7 * screen bytes per line cmpi.w #400,d6 * max. 400 scanlines ble.s GET_BODY move.w #400, d6 bra.s GET_BODY RES MED: cmpi.w #2,d4 * Anzahl planes testen bne ERR_DONE moveq #2,d5 * plane byte offset MED = 2 moveq #80,d7 cmpi.w #200,d6 * max. 200 scanlines ble.s GET_BODY move.w #200,d6 bra.s GET_BODY RES_LOW: cmpi.w #4,d4 * Anzahl planes testen bne ERR_DONE moveq #6,d5 * plane byte offset LOW = 6 moveq #40,d7 cmpi.w #200, d6 * max. 200 scanlines ble.s GET_BODY move.w #200,d6 GET_BODY: move.1 4(a0),d0 * chunk length addq.1 #1,d0 bclr #0,d0 * even length lea 8(a0,d0.1),a0 * skip chunk cmpi.1 #'BODY',(a0) * body chunk found? bne.s GET_BODY addq.l #8,a0 * Start of body chunk bsr IFF_DECOMP * IFF-format decompression bra ALL_DONE * * * AMIGA IFF BILDER * * Farbpalette umrechnen * * * xdef COL_IFF COL_IFF: movea.l 4(sp),a1 * COLOR data pointer movea.l 8(sp),a0 * IFF DATA - Start of BMHD chunk * * * Standard IFF Farbdaten holen * * * * **EinschrĂ€nkungen:** * * ---------------- * * Anzahl Farbregister == 16 * * * * NOTE: data Starts direct with 'BMHD' (Bitmap-Header) chunk ... moveq #0,d0 cmpi.l #'BMHD',(a0) * Bitmap-Header chunk found? bne.s RETURN_COL * no, abort GET_COLR: move.1 4(a0),d0 * chunk length addq.l #1,d0 bclr #0,d0 * even length lea 8 (a0, d0.1),a0 * skip chunk cmpi.l #'CMAP',(a0) * CMAP chunk found? bne.s GET_COLR addq.l #8,a0 * Start of color chunk moveq #15, d6 * 16 color registers moveq #4,d4 * #4 MAKE_COLR: moveq #0,d0 * color register moveq #2,d1 * 3 values MAKE_1: lsl.w d4,d0 * next nibble move.b (a0)+,d0 * IFF RGB value ( upper nibble ) lsr.b #1,d0 * convert IFF RGB range 0..15 * to ATARI RGB range 0..7 dbra d1, MAKE_1 lsr.w d4,d0 * position d0 to: "0rgb" move.w d0,(a1)+ * save color value dbra d6,MAKE_COLR moveq #1,d0 * return "OK" RETURN_COL: movea.1 (sp)+,a0 addq.l #8,sp * cleanup stack jmp (a0) * rts * * * GEM VDI BILDER * * auspacken * * * xdef DEC_VDI DEC_VDI: bsr GET_PAR * Parameter holen bsr ERASE_PIC * erase picture * vorlĂ€ufig nicht verfĂŒgbar, wird spĂ€ter erweitert: bra ERR_DONE * Fehlermeldung * * * IMAGIC BILDER * * auspacken * * * xdef DEC_IMAG DEC_IMAG: bsr GET_PAR * Parameter holen bsr ERASE_PIC * erase picture * vorlĂ€ufig nicht verfĂŒgbar, wird spĂ€ter erweitert: bra ERR_DONE * Fehlermeldung * * * Fehlerausgang * * Booleanwert FALSE zurĂŒckgeben * * * ERR_DONE: moveq #0,d0 * "error" bra.s RETURN * * * Normalausgang * * Booleanwert TRUE zurĂŒckgeben * * * ALL_DONE: moveq #1,d0 * "no error" RETURN: movem.l (sp)+,d7/a6 * restore d7 / a6 movea.1 (sp)+,a0 lea 12(sp),sp * cleanup stack jmp (a0) * rts * * * Hilfsfunktion * * Parameter vom Stack holen * * Register korrekt setzen * * * GET_PAR: lea 8(sp),a4 * Zeiger auf Parameter move.w (a4)+,d0 * RESOLUTION move.w (a4)+,d6 * PICLEN movea.1 (a4)+,a1 * PICTURE movea.1 (a4)+,a0 * COMPRESSED DATA move.1 (sp)+,a5 * Return Adresse movem.l d7/a6,-(sp) * Register retten jmp (a5) * * * Hilfsfunktion * * Bildinhalt löschen * * * * a1 = picture * d6 = picturelen (32000 or more, but always a multiple of 64 bytes !) ERASE_PIC: movem.l d0-d7/al-a2,- (sp) moveq #0,d0 moveq #0,d1 moveq #0,d2 moveq #0,d3 moveq #0,d4 moveq #0,d5 moveq #0,d7 move.l d0,a2 * "0" ins a2 adda.w d6,a1 * upper border lsr.w #6,d6 * picturelen div 64 subq.w #1,d6 * ZĂ€hler -1 clrpic: movem.l d0-d5/d7/a2,-(a1) * 32 bytes movem.l d0-d5/d7/a2,-(a1) * 32 bytes dbra d6,clrpic movem.l (sp)+,d0-d7/a1-a2 rts *=========================================* * * * Routinen zur Dekomprimierung * * * *=========================================* * * * Standard IFF Dekomprimierung * * a0 = compr. source * a1 = pic destination * a2 = uncompressed linelength in bytes /0 = compressed lines * * d3 = max destination line byte count per plane * d4 = number of planes * d5 = byte offset from plane-to-plane (ATARI scheme) * d6 = total number of destination lines (ysize) * d7 = number of destination plane bytes per line (80/80/40) IFF_DECOMP: move.1 d4,a4 subq.l #1,a4 * plane count -1 move.1 d3,a3 * line byte count bclr #0,d3 * only even byte counts move.w d3,d0 neg.w d0 muls d4,d0 * -(byte count) x (plane count)+2 addq.1 #2,d0 movea.1 d0,a5 * next plane offset move.w d7,d2 * destination bytes per line mulu d4,d7 * source bytes per line (even) sub.l d5,d7 subq.l #2,d7 * (bytes_per_line) - (byte offset)-2 movea.1 d7,a6 * next line offset subq.w #1,d6 * "dbra" ylines counter move.w a4,d4 * "dbra" planes counter clr.w d3 * plane byte counter moveq #0,d7 * destination offset (Start = 0) MAIN_LOOP: cmp.w a3,d3 * one plane written? bpl.s NEXT_PLANE move.w a2,d0 * packed data? bne.s COPY_LOOP * take line-length as byte count * for uncompressed data moveq #0,d0 move.b (a0)+,d0 * compression byte bmi.s MULTIPLE * negative: multiple byte count * positive: single bytes following COPY_LOOP: addq.w #1,d3 cmp.w d3, d2 * check line clipping bmi.s COPY_CLIP move.b (a0),0(a1,d7.w) * copy <d0> bytes COPY_CLIP: addq.1 #1,a0 * position in destination screen according to the * ATARIs special colorplane encoding scheme: addq.w #1,d7 btst #0,d7 * second byte written? bne.s COPY_1 add.w d5,d7 * add plane byte offset COPY_1: dbra d0,COPY_LOOP bra.s MAIN_LOOP * all singles written MULTIPLE: neg.b d0 * multiple counter bmi.s MAIN_LOOP * Byte was $80: "no Operation byte" move.b (a0)+,d1 * multiple byte MULT_LOOP: addq.w #1, d3 cmp.w d3, d2 bmi.s MULT_CLIP move.b d1,0(a1,d7.w) * write <d0> multiple bytes MULT_CLIP: * position in destination screen according to the * ATARIs special colorplane encoding scheme: addq.w # 1, d7 btst #0,d7 * second byte written? bne.s MULT_1 add.w d5,d7 * add plane byte offset MULT_1: dbra d0,MULT_LOOP bra.s MAIN_LOOP * all multiples written NEXT_PLANE: clr.w d3 * clear line byte counter bclr #0,d7 * re-position from even position add.w a5,d7 * re-position on next plane dbra d4,MAIN_LOOP * plane counter move.w a4,d4 * re-load counter add.w a6,d7 * position on next line dbra d6,MAIN_LOOP END_IFF: rts * all lines done, end *=====================================* end

Listing 1: Benötigte Assemblerroutinen

{ Erweiterung zu BILDEINLESEN aus ST-Computer 8/9 88 ST-Ecke } { Diese Zeilen sind allein nicht lauffĂ€hig ! ! } program BILDEINLESEN ( input, output ) ; { Demonstrationsprogramm zum Einlesen von verschiedenen Bildformaten. -> Erweiterung zu BILDEINLESEN aus ST-Computer 8/9 88 ST-Ecke Version 1.0 verfasst am 7-6-1988 von Jörg DrĂŒcker erweitert am 8-8-1988 neue Bildformate. Copyright (c) 1988 by IMAGIC GRAFIK. } {...} PICTURE_TYPES = ( P_DEGAS, { Degas unkomprimiert } P_DOODLE, { Doodle / Screenformat } P_NEO, { Neochrome Format } P_ART, { ART Director } P_DEGCOM, { Degas komprimiert } P_IFF, { AMIGA IFF } P_GEMVDI, { GEM VDI Format } P_IMAGIC, { IMAGIC komprimiert } P_UNDEF ); { unbekanntes Format } {...} { globale Variablen } AUFLOESUNG : integer; { Systemfunktionen: } function getrez : integer; { Aktuell eingestellte Bildschirmauf lösung holen } xbios ( 4 ); {...} { Assemblerroutinen zur EntschlĂŒsselung der gepackten Bildformate: } function DEC_ELIT ( COMP, PICTURE : DATA_POINTER; PICSIZE, RESOLUTION : integer ): boolean; externa1; function DEC_IFF ( COMP, PICTURE : DATA_POINTER; PICSIZE, RESOLUTION : integer ): boolean; external; function DEC_VDI ( COMP, PICTURE : DATA_POINTER; PICSIZE, RESOLUTION : integer ): boolean; external; function DEC_IMAG ( COMP, PICTURE : DATA_POINTER; PICSIZE, RESOLUTION : integer ): boolean; external; { Assemblerroutinen zur EntschlĂŒsselung der der Farbpalette: } function COL_IFF ( IFF_DATA, COLOR_DATA : DATA_POINTER): boolean; external; { folgende Routine wird insgesamt ausgetauscht } procedure HOLE_BILDDATEN ( READBUF, DEST : DATA_POINTER; PIC_TYPE : PICTURE_TYPES; RESOLUTION : integer ); { Hole Bildinhalt, je nach Bildformat } var OK : boolean; begin OK := true; { O.K. fĂŒr alle nicht komprimierten Formate ) case PIC_TYPE of {...} P_DEGCOM : OK := DEC_ELIT ( READBUF, DEST, PICTURELEN, RESOLUTION ); P_IFF : OK := DEC_IFF ( ADDR_OFFSET ( READBUF, 12 ) { FORM chunk ĂŒberspringen } DEST, PICTURELEN, RESOLUTION ); P_GEMVDI : OK := DEC_VDI ( READBUF, DEST, PICTURELEN, RESOLUTION ) ; P_IMAGIC : OK := DEC_IMAG ( READBUF, DEST, PICTURELEN, RESOLUTION ) end; { case } if not OK then begin writeln ( chr ( 27 ), 'E', chr ( 7 ) ) ; { Bildschirm löschen, Warnton } writeln ( 'Fehler beim EntschlĂŒsseln des Bildformats !' ) ; writeln; writeln ( 'Weiter mit <RETURN>' ) end end; { HOLE_BILDDATEN } procedure HOLE_FARBEN ( READBUF : DATA_POINTER; FARBEN : COLOUR_PTR; PIC_TYPE : PICTURE_TYPES ); { Hole Farbpalette, je nach Bildformat } {...} OK : boolean; begin {...} OK := true; { O.K. fĂŒr alle nicht komprimierten Formate } {...} case PIC_TYPE of P_DEGAS, P_DEGCOM : TRANSFER ( ADDR_OFFSET (READBUF,2 ), COL.DATA, 32 ) ; {...} P_DOODLE, P_GEMVDI : SYSPALET ( COL.CPTR ); { aktuelle Palette holen } P_IFF : OK := COL_IFF ( ADDR_OFFSET ( READBUF, 12 ) , { FORM chunk ĂŒberspringen } COL.DATA ); P_IMAGIC : TRANSFER ( ADDR_OFFSET ( READBUF,6 ), COL.DATA, 32 ) end; { case } if not OK then { im Falle eines Fehlers: Systempalette einstellen ! } SYSPALET ( COL.CPTR ) ; end; { HOLE_FARBEN } { Hauptprogramm: } begin AUFLOESUNG := getrez; { Bildschirmauflösung ? } loop {...} repeat writeln; writeln ('Bildtyp eingeben:' ); writeln (' A = DEGAS Normal' ); writeln (' B = DOODLE' ); writeln (' C = NEO Chrome' ); writeln (' D = ART Director' ); writeln (' E = DEGAS komprimiert' ); writeln (' F = AMIGA IFF' ); writeln (' G = GEM VDI' ); writeln ( ' H = IMAGIC komprimiert' ) ; write ( '> ' ); readln ( BILDTYP ) ; case BILDTYP of 'A','a' : PIC_TYPE :=P_DEGAS; 'B','b' : PIC_TYPE :=P_DOODLE; 'C','c' : PIC_TYPE :=P_NEO; 'D','d' : PIC_TYPE :=P_ART; 'E','e' : PIC_TYPE :=P_DEGCOM; 'F','f' : PIC_TYPE :=P_IFF; 'G','g' : PIC_TYPE :=P_GEMVDI; 'H','h' : PIC_TYPE :=P_IMAGIC; otherwise : PIC_TYPE := P_UNDEF {...} HOLE_BILDDATEN ( LESEBUFFER.DATA, BILDSCHIRM, PIC_TYPE, AUFLOESUNG ); end.

Listing 2: Erweiterungslisting in PASCAL

case P_DOODLE: syspalet(farben); /* aktuelle Palette holen */ break; case P_NEO: transfer(readbuf+4,farben,32L); break; case P_ART: transfer(readbuf+32000L,farben,32L); break; } }

Listing 3: Fehlende Zeilen aus Listing 3 der letzten ST-Ecke