ST-Ecke: BILDUNG

Bild 1: Die hohe Auflösung

Bisher wurde in allen möglichen Varianten besprochen, wie Bilder im \TARI ST-Speicher verwaltet werden. Inzwischen gibt es aber eine Unmenge von Grafik-Programmen wie DEGAS, IMAGIC, STAD, ARTDIRECTOR, DOODLE und viele mehr, so daß es, wie wir Anden, an der Zeit ist, die Speicherformate dieser Programme zu beschreiben. Was nutzt das schönste Bild, wenn man es nicht vernünftig weiterverarbeiten kann, da das Dateiformat fehlt. Unter den gängigen Formaten beAnden sich gepackte Formate, die wir auch nicht verschmähen wollen.

Aufgrund der Vielfalt der Dateiformate werden wir die Beschreibung auf mehrere ST-Ecken verteilen. In der heutigen Ausgabe wird noch einmal kurz auf die interne Grafikspeicherverwaltung des STs eingegangen, um dann die einfachsten Dateiformate zu besprechen. Als Abrundung des Ganzen folgt dann ein Programm, mit dem man diese Dateien einlesen kann.

Der ATARI ST besitzt in seiner momentanen Version drei verschiedene Grafikauflösungen mit unterschiedlicher Anzahl von Farben. Da für jede Auflösung die gleiche Anzahl Bytes verwendet wird, muß mit steigender Auflösung zwangsläufig die Verfügbarkeit verschiedener Farben sinken. Bei der höchsten Auflösung (HIGH-Resolution) besitzt der ST 540 x 400 Punkte bei zwei Farben. Diese zwei Zustände der Farben (Bildpunkt AN/AUS) können in einem Bit abgespeichert werden, daher ergibt sich ein Speicherbedarf von 32000 Bytes (600 * 400 / 8 = 32000). Bei der mittleren Auflösung MEDIUM-Resolution) werden 640 x 200 Punkte und damit vier Farben anhand zweier Bits kodiert, während die niedrige Auflösung 320 x 200 mit 16 Farben pro Punkt bietet, dafür aber vier Bits benötigt. Die hohe Auflösung ist in ihrer Speicherverwaltung relativ einfach zu verstehen, da ein Punkt in einem Bit kodiert ist und die Punkte hintereinander abgelegt sind. Das bedeutet, daß das Wort (zwei Bytes), das den ersten Punkt der zweiten Bildschirmzeile enthält, direkt hinter dem Wort steht, welches den letzten Punkt der ersten Zeile enthält. Die Berechnung der Adresse des Wortes, das unser Bildpunkt (Pixel) enthält, ist folgendermaßen durchzuführen:

long Adresse;
Adresse = 2* (y* Worte pro Zeile + x/16) * Anzahl der Planes

Der Rest der x/16-Division ergibt (indirekt) das Bit im Wort. Aber Achtung: Bit 15 ist Punkt 0 und Bit 0 ist Punkt 15. also ist die Bitnummer eines Pixels in einem Wort 15-x/16. Warum wir die Adresse auf Wortbasis errechnen, sehen wir gleich bei der MEDIUM- und LOW-Resolution.

Wir wissen, daß wir zur Darstellung von vier Farben zwei Bits benötigen, wobei es im ersten Moment naheliegt, diese für die Farbinformation benötigten Bits in einem Byte bzw. Wort hintereinander abzulegen. Dies wurde beim ST aber nicht getan. Hardwaremäßig ist es günstiger, die verschiedenen Bits eines Pixels in unterschiedlichen Bytes (oder Worten) an gleichen Bitpositionen unterzubringen. Prinzipiell kann man sich dies (ähnlich wie im Druckereigewerbe) als mehrere Folien vorstellen, die zusammen die Farbe ergeben (Bild 1 bis 3). Diese verschiedenen Ebenen nennt man Planes, so daß die High-Resolution ein Plane besitzt bzw. die Medium- zwei und die Low-Resolution vier davon.

In der Praxis gibt es nun zwei verschiedene Arten, die Planes im Speicher abzulegen. Die erste, für den Programmierer am einfachsten zu verstehende Methode ist, die einzelnen Planes wie völlig verschiedene Bildschirme zu behandeln, und daher einfach hintereinander abzulegen. Dieses Verfahren ist aber in der Hardwareumsetzung relativ umständlich. Einfach in Hardware umzusetzen, aber leider schwieriger zu verstehen, ist das INTERLEAVED PLANE FORMAT, bei dem die Planes gemischt sind. Wie sie von oben noch wissen, wird die Bitinformation in einem Wort untergebracht. Hat man nun mehrere Planes, so folgt hinter Wort 0 der Plane 0 nicht das Wort 1 der Plane 0, sondern das Wort 0 der Plane 1 und dann das Wort 0 der Plane 2 usw., bis das jeweils erste Wort der vorhandenen Planes erfaßt ist. DerNachteil ist, daß man ein wenig rechnen muß, wenn ein Punkt gesetzt werden soll. Am besten, Sie schauen sich noch einmal die Bilder 1 bis 3 und das Programmlisting 1 an, das an einem Beispiel zeigt, wie ein Punkt gesetzt wird. In ihm wird zunächst die Wortadresse berechnet und dann aufgrund des Teilerrestes x%16 (Modulo 16) das Bit an die richtige Position gerollt und ODER-verknüpft. Nur nebenbei: Die angegebene Methode des Bildschirmlöschens dient nur noch einmal zur Verdeutlichung, daß der Bildschirminhalt nichts anders als ein im Monitor sichtbar gemachter Speicher ist, den man auch löschen kann. Bitte löschen Sie Ihren Bildschirm nicht auf eine solche Methode -das ist sehr unsauber programmiert. Verwenden Sie zum Löschen des Bildschirms lieber eine VDI-Funktion.

Farben wie ein Regenbogen...

hat der ST zwar nicht ganz, aber man hat doch immerhin 512 Farben zur Verfügung. Wie aber funktioniert das, wo wir doch nur höchstens vier Bits als Farbinformation zur Verfügung gestellt bekommen? Ganz einfach: Im ST befindet sich eine Liste, in denen die 16 aus den 512 ausgesuchten Farben stehen, die sie für ihre LOW-Resolution benutzen möchten. Findet der ST nun als Bitinformation im Grafikspeicher die Zahl 4, so schaut er in seiner Farbtabelle nach und nimmt diese dort abgespeicherte Farbe zur Bilddarstellung am Monitor. Eine solche Tabelle, die man in Fachkreisen auch LOOK-UP-Table nennt, hat gewisse Vorteile. Man kann, allein durch Austauschen der Werte in der Tabelle, die gesamten Farben des Bildes ändern. Wie wäre es zum Beispiel, wenn sie aus einem dunkelroten Abendhimmel ein wunderschönes, strahlendes Blau auf dem Bildschirm zaubern würden, ohne auch nur ein Bit im Grafikspeicher ändern zu müssen? Es ist sogar möglich, Farbverläufe, also Bildteile mit auf- oder absteigender Farbintensität durch Austauschen der Farbregisterinhalte zum Bewegen zu bringen. Kennen Sie die schöne ATARI-Demo, wo ein Vogel über eine Bucht fliegt und sich die Brandung bewegt? Die Animation der Brandung ist nur durch Verändern der Farb-Tabelle erreicht worden.

Bild 2: Die mittlere Auflösung

Das Geheimnis der 512 Farben

Die Farbtabelle liegt ab Adresse $FF8240 und kann und sollte über die XBIOS-Routine Setpalette(Integerfeld) gesetzt werden. Schauen wir uns zunächst aber an, wie eine Farbe definiert ist. Wenn ich Ihnen nun sage, daß die Farbinformation in einem Wort abgespeichert ist, so werden Sie sofort einwenden, daß damit ja 65536 Farben kodiert werden können. Richtig, es werden von den 16 Bits aber nur neun - entspricht 512 Farben - benutzt. Das Farbwort sieht folgendermaßen aus (x bedeutet nicht benutzt).

Farbwort: xxxx xRRR xGGG xBBB

Drei Nibbles (Halbbytes) werden für die Farbinformation benutzt, das vorderste nicht. Wie Sie vielleicht schon wissen, wird ein Farbbildpunkt auf einem Monitor (oder einem Fernseher) aus drei Punkten, nämlich einem blauen, einem grünen und einem roten, unterschiedlicher Intensität gewonnen. Sind alle drei Punkte aus, so gewinnt man Schwarz, werden alle Punkte mit höchster Intensität zum Leuchten gebracht, so erhält man die Farbe Weiß. Dieses RGB-Verfahren wird beim ATARI auch in dem Farbwort verwendet. Sie werden erkennen, daß in jedem Nibble die Intensität einer der drei Komplementärfarben eingestellt wird, wobei der ST in seiner bisherigen Ausführung nur Intensitäten zwischen 0 und 8 auswerten kann. Vielleicht wird es eine spätere Version des ST geben, die dann 16 Intensitäten und damit 4096 Farben unterstützt. Ein kleiner Tip am Rande: Wenn Sie mal ein wenig mit den 512 Farben spielen möchten, so kann das jeder, der einen Farbmonitor (oder einen Fernseher) an seinen ST anschließt, denn mit dem Kontrollfeld ist es möglich, bequem die Farben des ST durch Slider (Schieber) einzustellen. Es sind drei Slider für rot, grün und blau vorhanden, wobei diese sich nur in acht Stufen bewegen lassen. (Warum bloß?)

**DOODLE**

Screenformat: 32000 Bytes Bilddaten, Bytes 1..32000, keine Farbpaletten

Auflösung: LOW/MEDIUM/HIGH (*.DOO)

Dateilänge: 32000 Bytes

DEGAS normal

Screenformat: 32000 Bytes Bilddaten, Bytes 35 .. 32034,
32 Bytes Farbpalette, Bytes 3 .. 34,
(32 Bytes Farbanimationsdaten, Bytes 32035 .. 32066)

Auflösung: LOW (.PI1), MED (.PI2), HIGH (*.PI3)

Dateilänge: 32034 oder 32066 Bytes

Kennung: 1. Byte = 00
2. Byte = Auflösung (0=LOW, 1=MED, 2=HIGH)

NEO chrome

Screenformat: 32000 Bytes Bilddaten, Bytes 129 .. 32128,
32 Bytes Farbpalette, Bytes 5 .. 36

Auflösung: nur LOW (*.NEO)

Dateilänge: 32128 Bytes

ART Director

Screenformat: 32000 Bytes Bilddaten, Bytes 1.. 32000,
32 Bytes Farbpalette, Bytes 32001.. 32032,
weitere 15 Farbpaletten für Farbanimationen
Bytes 32033.. 32512

Auflösung: nur LOW (*.ART)

Dateilänge: 32512 Bytes

**Die Bildformate in der Übersicht**

Die Magie des Verschwindenlassens

Wollen wir die Grafiken abspeichem, so müssen zwei Informationen vorhanden sein, um das Bild vollständig rekonstruieren zu können: erstens der Bildschimspeicherinhalt mit den unterschiedlichen Planes und zweitens die Farbpalette. Ist man sich sicher, daß nur die Original-ATARI-Farbpalette benutzt worden ist, kann man auf das Abspeichem derselben verzichten.

Das hat Format

Verschiedene Grafikformate von verschiedenen Grafik-Programmen gibt es in Hülle und Fülle, so daß wir dieses Mal mit den einfachsten Formaten anfangen.

Das älteste und damit erste Malprogramm, das es für den ST gab, nennt sich DOODLE und ermöglichte ausschließlich das Zeichnen eines Bildes in der Original ATARI-Farbpalette. Daher werden als Datei auch nur einfach die 32000 Bytes eines Bildschirms abgespeichert und mehr nicht. Doodle-Bilder gibt es in allen Auflösungen, man kann sie aber nicht irgendwie unterscheiden - hier hilft nur ausprobieren. Der Extender des Dateinamens wird üblicherweise ‘DOO’, manchmal auch ‘PIC’, heißen.

Nach einiger Zeit folgte das Zeichenprogramm NEOCHROM, das zu damaliger Zeit durch die vielen Farben, die gleichzeitig im Auswahlfenster dargestellt wurden, auffiel. Eine Neochrom-Datei besitzt den Extender ‘NEO’ und ist 32128 Bytes lang. In den Bytes 5 bis 36 ist die Farbpalette abgespeichert, während sich die Bilddaten ab Byte 129 befinden und wie gewohnt 32000 Bytes benötigen. Neochrom arbeitet nur in der niedrigen Auflösung und speichert daher auch nur Bilder dieser Auflösung ab.

Das erste umfangreiche, verkaufte Malprogramm nennt sich DEGAS, benannt nach einem nicht unbekannten Maler. Mit DEGAS lassen sich Bilder in allen drei Auflösungen zeichnen und daher auch laden und speichern. Die Auflösung des abgespeicherten Bildes läßt sich am zweiten Byte der Bilddatei erkennen (das erste Byte ist Null) - dabei bedeutet 0 LOW-, 1 MEDIUM- und 2 HIGH-Resolution. Die folgenden 32 Bytes stellen wie gewohnt unsere Farbpalette dar und anschließend kommen die 32000 Bytes unseres Bildschirmspeichers. Da eine DEGAS-Datei aber anstatt der 32034 Bytes auch 32066 Bytes haben kann, fragt sich der schlaue Leser, was in den letzten 32 Bytes ist. In DEGAS ist es möglich, die oben beschriebene Farbanimation durch Vertauschen der Registerinhalte anzuwenden. Diese Farbinformation steht in den genannten 32 zusätzlichen Bytes. Die Datei hat abhängig von der Auflösung unterschiedliche Extender. Bei niedriger Auflösung verwendet DEGAS den Extender ‘PI1’, bei mittlerer ‘PI2’ und bei hoher ‘PI3’.

Last not least schauen wir uns noch das Einfach-Format von ART-DIRECTOR an. Eine ART Director-Bilddatei besteht aus 32512 Bytes, wobei die Bilddaten in den ersten 32000 Bytes enthalten sind. Die folgenden 32 Bytes enthalten wieder die bekannten Daten unserer Look-Up-Table. Der folgende Platz wird wie in DEGAS für Farbanimation benutzt, wobei im Gegensatz zu DEGAS bei ART-Director weitere 15 Farbpaletten abgespeichert werden! Wie ART-Director-Besitzern hinreichend bekannt ist, arbeitet dieses Programm nur in niedriger Auflösung und seine Dateien besitzen den Extender ‘ART’.

Bild 3: Die niedrige Auflösung

Ein letztes Wort

Wie Sie sehen, sind die gängigsten Formate sehr einfach und damit auch ziemlich schnell in eigene Programme zu integrieren, zur einfacheren Handhabung haben wir die Daten noch einmal in einer Übersicht zusammengefaßt. Trotzdem haben wir noch ein Programm in PASCAL und C programmiert, damit die Vorgehens weise, ein Bild zu laden, klar wird. Bei der nächsten Wanderung durch die Epochen der Bildformate werden wir uns dann mit etwas aufwendigeren Methoden der Bildspeicherung beschäftigen, die es ermöglichen, die Datenmenge auf ein Minimum zu reduzieren (gepackte Bilddaten), oder ohne größere Probleme. Bilder unter Rechnern auszutauschen (Beispiel IFF-Format). Bis dahin wünsche ich noch frohes Laden, Speichern und natürlich Zeichnen von Bildern.

(SH / Jörg Drücker)

/***************************************************/
/*                                                 */
/* Zeichnen eines Punktes in beliebiger Auflösung  */
/*                                                 */
/***************************************************/

#include <osbind.h>
#include <gemdefs.h>

#include <vt52.h>

int vdi_handle;
int work_out[16] , work_in[16] ;

int intin[34],intout[16],ptsin[16], ptsout[16], contrl[10];

/******************************************/
/* Diese Programm wird durch Anfahren der */
/* linken oberen Ecke beendet             */
/******************************************/

main()
{
	int loop, x,y, wort; 
	unsigned int *wortadr; 
	int *basis; 
	long *speicher; 
	int status; 
	int planes;

	appl_init();	/* Applikation anmelden */

	open_vwork();	/* VDI initialisieren */

	planes = 1<< (2-Getrez());	/* Anzahl der Bits pro Pixel */

	basis = (int *) Logbase();
	speicher= (long*) basis;

	graf_mouse(M_OFF,0L);
	loop=8000;	/* 8000 Langwörter = 32000 Bytes */
	while(loop) /* Bildschirmspeicher löschen */
	{
		*speicher++ =0L;	/* Langwort löschen */
		loop—;
	}
	graf_mouse(M_ON,0L);

	do
	{
		vg_mouse(vdi_handle,&status,&x,&y);
			/* Mauskoordinate holen */ 
		if (status) /* Maustaste gedrückt */
		{
			graf_mouse(M_OFF,0L); /* Maus ausschalten */

			wort=(y*40+x/16)*planes;

			wortadr=(unsigned int *) (basis+wort); 
			*wortadr|= ((unsigned int )0x8000)>>(x%16);

			graf_mouse(M_ON,0L); /* Maus anschalten */
		}
	} while(x || y);	/* bis Koordinate 0,0 */

	v_clsvwk(vdi_handle);	/* VDI	abmelden */
	appl_exit();	/* Applikation abmelden */
}

open_vwork() /* Initialisieren der VDI-Workstation */
{
	int i;

	for (i=0; i<10; work_in[i++]=1); 
	work_in[10]=2;
	v_opnvwk(work_in, &vdi_handle, work_out);
}

Listing 1: So setzt man einen Punkt in beliebiger Auflösung

program BILDEINLESEN ( input, output ) ;

{ *-------------------*
Demonstrationsprogramm zum Einlesen 
von verschiedenen Bildformaten.
  ---------------------

  Version 1.0

  verfasst am 7-6-1988 von Jörg Drücker

  Copyright (c) 1988 by IMAGIC GRAFIK.

*-------------------* }

{$P-, keine Pointerchecks ! }

{ globale Konstanten:
--------- }

const PICTURELEN = 32000; { ST Bildschirmgrösse }

{ globale Datentypen:
--------- }

type DATA_POINTER = Abyte; {universeller Pointertyp}
	COLOUR_DATA = packed array [0 . . 15] of integer; 
	COLOUR_PTR = ^COLOUR_DATA;

	BYTE_ARRAY = packed array [ 1..maxint ] of byte;
	
	{ Maximal 32767 Bytes, für Bilddaten voll ausreichend }

{ bekannte Bildformate:
---------- }

PICTURE_TYPES = ( P_DEGAS, { Degas unkomprimiert } 
				P_DOODLE, { Doodle/Screenformat } 
				P_NEO,	{ Neochrome Format }
				P_ART,	{ ART Director }
				P_UNDEF ) ; { unbekanntes Format }


{ globale Variablen:
--------- }

var LESEBUFFER : record case boolean of
			false :	(	DATA :DATA_POINTER );
			true :	(	BLOC : ABYTE_ARRAY )
		end;

	BILDSCHIRM : DATA_POINTER;

	SYSTEMFARBE,
	BILDFARBE : COLOUR_PTR;

	EXTERNDATEI : packed file of BYTE_ARRAY; 
	DATEINAME : string [ 255 ] ;

	BILDTYP	: char;
	PIC_TYPE : PICTURE_TYPES;

{ Systemfunktionen:
--------- )

function physbase : DATA_POINTER;

{ Physikalische Bildschirmaddresse ermitteln }

xbios ( 2 );

procedure setpalette ( palette : COLOUR_PTR ) ;

{ Farbpalette setzen }

		xbios ( 6 );

{ Hilfsprozeduren in PASCAL:
------------- }

function ADDR_OFFSET ( D : DATA_POINTER;
			OFFSET : long_integer )
				: DATA_POINTER;

{ berechnet Offset zur gegebenen Addresse D hinzu. }

var X : record case boolean of
		false : ( DATA : DATA_P01NTER ); 
		true ( ADDR : long_integer )
		end;

begin
	X.DATA := D;	{	Pointer	kopieren	}
	X.ADDR := X.ADDR + OFFSET; { Offset addieren } 
	ADDR_OFFSET : = X.DATA	{	Ergebnis zuweisen }
end; { ADDR_OFFSET }

procedure TRANSFER (SOURCE, DESTINATION :DATA_POINTER;
			AMOUNT : integer );

{ Byteweises kopieren beliebiger Speicherbereiche }

var S, D : record case boolean of

		false :	( DATA : DATA_POINTER ) ;
		true :	( BLOC : ^BYTE_ARRAY )

		end;
	I : integer;

begin

	S.DATA := SOURCE;	{ Pointer zuordnen }
	D.DATA := DESTINATION;

	for I := 1 to AMOUNT do {Anzahl Bytes kopieren} 
		D.BLOC^ [ I ] := S.BLOC^ [ I ] 
end; { TRANSFER }

procedure SYSPALET ( C : COLOUR_PTR ) ;

{ Hole aktuelle Farb-Palette } 

var I : integer;

function setcolor (register, value: integer): integer; 
	xbios ( 7 ) ;

begin

	for I := 0 to 15 do

		C^ [ I ] := setcolor ( I, -1 )
				{ Farbe nur holen }

end; { SYSPALET }

procedure HOLE_BILDDATEN (READBUF, DEST : DATA_POINTER;
				PIC_TYPE: PICTURE_TYPES) ;

{ Hole Bildinhalt, je nach Bildformat }

begin

	case PIC_TYPE of

		P_DEGAS : TRANSFER (ADDR_OFFSET(READBUF,34), 
							DEST,
							PICTURELEN);

		P_DOODLE : TRANSFER (READBUF,
							DEST,
							PICTURELEN);

		P_NEO : TRANSFER(ADDR_OFFSET (READBUF,128), 
						DEST,
						PICTURELEN) ;

		P_ART : TRANSFER (READBUF,
						DEST,
						PICTURELEN)

	end { case } 

end; { HOLE_BILDDATEN }

procedure HOLE_FARBEN ( READBUF : DATA_POINTER;
				FARBEN : COLOUR_PTR;
				PIC_TYPE : PICTURE_TYPES ) ;

{ Hole Farbpalette, je nach Bildformat }

var COL : record case boolean of

			false :	(	DATA	:	DATA_POINTER );
			true : ( CPTR : COLOUR_PTR )
		  end;

begin

	COL.CPTR := FARBEN; { Pointer gleichsetzen }

	case PIC_TYPE of

		P_DEGAS : TRANSFER (ADDR_OFFSET(READBUF,2), 
				COL.DATA,
				32);

		P_DOODLE : SYSPALET (COL.CPTR);
				{ aktuelle Palette holen }

		P_NEO : TRANSFER (ADDR_OFFSET(READBUF,4), 
				COL.DATA,
				32) ;

		P_ART : TRANSFER (ADDR_OFFSET(READBUF, 
				PICTURELEN),
				COL.DATA,
				32)

	end { case } 

end; { HOLE_FARBEN }

{ Hauptprogramm:
------- }

begin

	io_check ( false ) ;	{	eigene	Fehlerbehandlung }

	new ( LESEBUFFER.BLOC );	{	Arbeits - Bereiche anlegen }

	new ( SYSTEMFARBE ); 
	new ( BILDFARBE );

	BILDSCHIRM := physbase; { Addresse des phys. Bildschirms }
	SYSPALET ( SYSTEMFARBE ) ; { Ursprüngliche Farbpalette sichern }

	loop
		writeln ( chr ( 27 ), 'E' );	{ Bildschirm löschen }
		write ( 'Bitte Bildnamen eingeben: ' ); 
		readln ( DATEINAME );
	exit if length ( DATEINAME ) = 0;

		reset ( EXTERNDATEI, DATEINAME );

		if ( io_result = -33 ) or ( io_result = 9 ) 
			then begin

			writeln ( chr( 7 ) );	{	BEEP }
			writeln ( 'Datei ', DATEINAME,' existiert nicht !' );
			writeln;
			write ( 'drücke <RETURN> um fortzufahren . . .' );
			readln
		end
		else begin 
			repeat
				writeln;
				writeln ( 'Bildtyp eingeben:' ); 
				writeln ('	A	=	DEGAS Normal');
				writeln ('	B	=	DOODLE' );
				writeln ('	C	=	NEO Chrome' );
				writeln ('	D	=	ART Director');
				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;

					otherwise : PIC_TYPE := P_UNDEF
				end
			until PIC_TYPE <> P_UNDEF;

			LESEBUFFER.BLOC^ := EXTERNDATEI^;
			{ Daten zuordnen }

			{ Cursor ausschalten:
			--------- }

			write ( chr( 27 ), 'f' ) ;

			{ Bildinhalt beispielsweise zeigen: 
			------------------- }

			HOLE_FARBEN ( LESEBUFFER.DATA, BILDFARBE, PIC_TYPE ); 
			setpalette ( BILDFARBE ) ;

			HOLE_BILDDATEN ( LESEBUFFER.DATA,
					BILDSCHIRM, PIC_TYPE );

			readln; { warte auf Tastendruck }

			setpalette ( SYSTEMFARBE );

			{ Ursprüngl.Palette wiederherstellen }

			{ Cursor wieder einschalten: 
			--------------- }

			write ( chr( 27 ), 'e' )
		end
	end; { loop } 
	
	writeln;
	writeln ( 'Adieu' )

end.

Listing 2: Das Laden verschiedener Bildformate in PASCAL

/***************************************************/ 
/*                                                 */
/* Programm zum Einlesen diverser Bildformate      */
/*  wie DEGAS,DOODLE,ART Director und NeoChrome    */
/*                                                 */
/***************************************************/

#include <osbind.h>

#define PICTURELEN 32000L 
#define P_DEGAS 1 
#define P_DOODLE 2 
#define P_NEO 3 
#define P_ART 4

long bildschirm; /* Enthält Adresse des Bildschirms */ 
char *buffer; /* Adresse, an d.Daten geladen werden */ 
int systemfarbe[16], bildfarbe[16];

char pfad[64], fname[64];

main()
{
	int taste, i; 
	int fd, pic_type;

	appl_init ();

	buffer= (char*) Malloc(32550L);/* Speicher reserv. */ 
	if (buffer==(char*)-1)	/* Kein	Speicher	da */
	{
		appl_exit();
		return;	/* Programm beenden */
	}

	bildschirm = Physbase ();	/* Adresse d.Bildschirms */
	syspalet(systemfarbe);	/* Original-Palette holen */

	printf("\033E\n");	/* Bildschirm löschen */

	strcpy(pfad,"\*.*");	/* Anfangspfad */
	fname[0]=0;

	fsel_input(pfad,fname,&taste); /* Fileselektor */

	if (taste) /* OK gedrückt */
	{
	i=0;
	while (pfad[i]) i++; /* Bis ans Ende */
		/* und dann Wildcards wegwerfen */ 
		while (i && pfad[i]!=':' && pfad[i]!='\\') i—; 
		strcpy(&pfad[i+1],fname); /* u.Filename anhängen */

		fd = Fopen(pfad,0);	/* Datei öffnen */

		if (fd>0)	/* kein Fehler */
		{
			pic_type=form_alert (0,"[1][Bitte Bildtyp eingeben] [DEGAS|DOODLE|weiter]");

			if (pic_type==3) /* 'Weiter' angewählt */
				pic_type=2+form_alert(0,"[1][Bitte Bildtyp eingeben][NEOchrome|ART-Director]");
					/* Mal 32550 Bytes laden */
			Fread(fd,32550L,buffer);
				/* Palette aus Daten ziehen */ 
			hole_farben(buffer,bildfarbe,pic_type);

			Setpallete(bildfarbe); /* und setzen */ 
			hole_bilddaten(buffer,bildschirm,pic_type);
			gemdos(7);	/* Tastendruck */
			Setpallete(systemfarbe); /* Org.-Palette setzen */

			Mfree(buffer);	/* Speicher freigeben */
			Fclose(fd);	/* Datei schließen */
		}
		else
			form_alert(1,"[1][Beim Lesen ist|ein Fehler aufgetreten][ Abbruch ]");
	}
	appl_exit();	/* Tschüß */
	printf("Adieu\n");
}

/****************************************************/ 
/* Diese Routine kopiert einen Speicherbereich      */
/* von Source nach Destination mit amount Bytes     */
/****************************************************/

transfer(source, destination, amount) 
char *source, *destination; 
long amount;
{
	while (amount—)
		*destination++ = *source++;
}

/****************************************************/
/* Die Routine ermittelt die momentane Palette      */
/* und schreibt sie in c                            */
/****************************************************/

syspalet(c)
int *c;	/* zeigt auf Integerfeld von 16 Eintraegen */
{
	int i;
	for (i=0; i<16; i++)
		*c++ = Setcolor (i,-1) ;	/* Farbe nur holen */
}

/*****************************************************/ 
/* Routine holt aus den Daten die Bildaten je nach   */
/* Bildformat heraus                                 */
/*****************************************************/

hole_bilddaten( readbuf, dest, pic_type) 
char *readbuf, *dest; 
int pic_type;
{

	switch(pic_type)
	{
	case P_DEGAS: 
		transfer(readbuf+34,dest,PICTURELEN); 
		break;

	case P_ART; 
	case P_DOODLE: 
		transfer(readbuf,dest,PICTURELEN); 
		break;

	case P_NEO: 
		transfer(readbuf+128,dest,PICTURELEN); 
		break;
	}

}

/***************************************************/ 
/* Hier wird die Palette aus den Daten aussortiert */ 
/***************************************************/

hole_farben(readbuf, farben, pic_type) 
char *readbuf; 
int *farben; 
int pic_type;
{

switch(pic_type)
{
	case P_DEGAS: 
		transfer(readbuf+2,farben,32L); 
		break;

Listing 3: Das Laden verschiedener Bildformate in C



Aus: ST-Computer 08 / 1988, Seite 107

Links

Copyright-Bestimmungen: siehe Über diese Seite