Eigene Bilder in der Resource

Bilder verschönern eines Jeden Dialogbox. Doch was tun, wenn das Lieblings-RCS selbige stiefmütterlich behandelt? Ganz einfach: Die Bilder mit einem Malprogramm malen und eine Resource draus machen. RCS von Digital Research kann Bilder (Bitblk-Strukturen) nur hinzu laden und erwartet dabei einen C-Quellcode. Das RCS von Kuma besitzt zwar einen eigenen Icon-Editor, doch oft genug hat man das Bild schon und will es nicht noch einmal abmalen.

Außerdem soll es ja auch Leute geben, die mit der Lupe ihres Malprogramms besser zurechtkommen als mit einem Icon-Editor. So kam mir die Idee, ein Programm zu schreiben, daß einen beliebigen Bildschirmausschnitt in eine Bitblk-Struktur übersetzt. Besitzer des Kuma-RCS können so auch den Icon-Editor entlasten, denn ihr RCS ermöglicht es bequem, Bitblk-Strukturen in Icon-Strukturen zu wandeln. Sie können sich also fortan die Bilder für Ihre Resource mit Ihrem Lieblings- Malprogramm malen. Das GFA-Programm, das die Konvertierung vornimmt, finden Sie im nebenstehenden Listing.

Zur Vorgehens weise des Programms: Zunächst wählen Sie ein Bild aus, aus dem Sie den Ausschnitt haben wollen. Dieses muß im Screenformat (32kB) vorliegen. Dann können Sie mit einer ‘Gummibandbox’ den gewünschten Ausschnitt markieren. Dieser wird im String ‘ Aus$’ gespeichert und dann in die Bitblk-Struktur umgewandelt.

Diese wird in eine komplette Resource eingelagert, die mit jedem RCS zu laden ist. Zur Erzeugung der Bitblk-Struktur müssen allerdings zunächst Höhe und Breite des Ausschnitts bekannt sein. Jeder String, in dem per ‘GET’ ein Bildschirmteil gespeichert wurde, besitzt einen sechs Bytes langen Vorspann, in dem im ersten Wort die Breite und im zweiten die Höhe (jeweils in Pixeln) des Ausschnitts vermerkt sind. Das dritte Wort enthält Informationen über die Bildschirmauflösung, Farbebenen etc.

Jede neue Pixelzeile des Ausschnitts beginnt an einer Wortadresse. Das bedeutet, daß bei einem 15 Pixel breiten Ausschnitt also jeweils das letzte Bit der Wörter ‘verschenkt’ wird. Wäre dieser Ausschnitt wiederum 15 Pixel hoch, so ergäbe sich für die Länge des Strings in dem er gespeichert ist:

6+15*2 = 36 Bytes

Der String wäre wegen der Wortlänge jeder Zeile genauso lang, wenn der Ausschnitt nur ein Pixel breit wäre. Leider gibt es bei diesen Werten, die man aus dem Vorspann erfahren kann, einige Ungereimtheiten. Ein 16 Pixel breiter Ausschnitt nimmt nicht - wie vermutet -pro Zeile zwei Byte in Anspruch, sondern vier. Also wird bei jedem 16. Pixel bereits ein neues Wort begonnen. Ein Ausschnitt, für den im Vorspann eine Höhe von Null Pixeln vermerkt ist, ist aber in Wirklichkeit ein Pixel hoch. Daraus entstehen die zunächst unlogisch wirkenden Berechnungen im Programm. In der Bitblk-Struktur speichert (und erwartet, logo!) das AES folgende Informationen (siehe Tabelle) womit wir auf eine Länge von 14 Bytes kommen. Hinzu kommen die Bilddaten: pro angefangenem Wort 2 Bytes oder viel einfacher, Länge von ‘Aus$’-6.

Nun macht ja ein Bitblk noch keine Resource. Wir brauchen noch einen sog. Resource-Header, der wiederum 36 Bytes lang wird (Genaueres siehe Listing).

Dann fehlt noch die Objekt-Struktur (24 Bytes) und die Objektbaumtabelle (bei einem Baum 4 Bytes). Das wär’s eigentlich schon, doch kann das RCS von Digital Research mit der Resource, die jetzt entstünde, herzlich wenig anfangen. Das liegt daran, daß der Bitblk in dieser Resource eine Vaterfigur spielte, also das Wurzelobjekt seines Baumes darstellte.

Leider erlaubt eben dieses RCS nicht, ein solches Objekt auf das Klemmbrett zu kopieren, um es von dort aus weiter zu verarbeiten. Wir kommen also nicht umhin, dem Bild(chen) ein Vaterobjekt überzuordnen. Aber das soll ja kein Problem sein. Ich habe eine geringfügig größere Box gewählt, in der sich das Bild dann befinden wird. Allerdings erfordert das eine weitere Objektstruktur, mithin wird die Resource nochmal 24 Bytes länger. Die Länge ist wichtig für den Eintrag 'Rssize’ im Resource-Header (das ist der letzte). Haben Sie mitgezählt? Für die Länge ergibt sich:

36 Bytes (Header)

Es wird nun ein String dieser Länge vorbereitet und von seiner Adresse an werden die Daten per POKE, DPOKE und LPOKE gesetzt. Anschließend wird dieser String unter dem von Ihnen gewählten Dateinamen gespeichert.

Eine kleine Bemerkung vielleicht noch zu den letzten vier Werten der Objektstruktur. Hier sind X- und Y-Position (relativ zum Vaterobjekt) sowie Breite und Höhe der Objekte vermerkt. Während in einer Resource, die mit der AES-Funktion 110 (RSRC_LOAD) geladen wurde, diese Werte in Pixelkoordinaten vermerkt sind, werden sie in der Resource-Datei in Zeichenkoordinaten verlangt. Auf dem Monochrommonitor ist das ein Raster von 16 Pixeln Höhe und 8 Pixeln Breite. Der entsprechend geteilte Wert wird im Low-Byte der jeweiligen Koordinaten-Wörter gespeichert. Sollte die Koordinate nun nicht exakt auf diesem Raster liegen, also ein Rest bleiben, so wird dieser (nun in Pixeln) im High-Byte vermerkt. Beim Laden werden die Werte entsprechend der Bildschirmauflösung umgerechnet. Wenn Sie also das Programm in der mittleren Auflösung verwenden wollen, müssen Sie in der Zeile, in der die Koordinate durch 16 geteilt wird, diese 16 durch eine 8 ersetzen.

Ich hoffe, daß alle anderen Fragen durch das Listing selbst zu beantworten sind. Als dann wünsche ich Ihnen viel Spaß - beim Malen!

bi_pdata (Zeiger auf Bilddaten)	4	Bytes
bi_wb (Breite in Bytes)	2	Bytes
bi_hl	(Höhe in Pixeln)	2	Bytes
bi_x	(X-Position)	2	Bytes
bi_y	(y-Position)	2	Bytes
bi_color (Farbe des Bildes)	2	Bytes

Tabelle der Bild-Struktur

' *****************************************************************
' * PIC_BITB.BAS - aus (Bildschirm-) Bildern Bitblöcke erstellen  *
' * Copyright 1988 Ingo Brümmer, Lutherstraße 60, 3000 Hannover 1 *
' *****************************************************************
'
Repeat
    Print " Bitte eine Bilddatei wählen: "
    Fileselect Chr$(Gemdos(25)+65)+"\*.*","",Bild$
    '
    If Bild$=""             ! Bei Abbruch
        Edit	            ! Ende
    Endif
    Bload Bild$,Xbios(2)	! Bild laden
    Repeat
        Aus$=""
        Defmouse 5	        ! Maus -> Kreuz
        Sget Moni$	        ! Bildschirm merken
        Repeat
        Until Mousek=1	    ! Warten auf linke Taste
        X1%=Mousex	        ! Koordinaten merken
        Y1%=Mousey
        Do
            Mouse X2%,Y2%,T%    ! Maus merken
            Box X1%,Y1%,X2%,Y2% ! Gummibox zeichnen
            Vsync               ! Mit Vertical-Interrupt synchronisieren 
            Sput Moni$          ! altes Bild drauf
            Exit If T%=0        ! Raus, wenn Maus losgelassen
        Loop
        Get X1%,Y1%,X2%,Y2%,Aus$ ! Bildchen ausschneiden 
        Defmouse 0
        '
        Put X1%,Y1%,Aus$,12     ! Und invertiert drauflegen
        Pause 25
        Alert 0,"Bitblk draus machen?",1,"Ja|Nein",D%
        If D%=1
            Fileselect Chr$(Gemdos(25)+65)+"\*.*","", Rs$
        Endif
        If D%=1 And Rs$<>""	! Wenn Speichern und nicht Abbruch:
            '
            B%=Dpeek(Varptr(Aus$))      ! Breite in Pixeln
            B%=(B% Div 16+1)*16         ! auf Wortlänge bringen
            H%=Dpeek(Varptr(Aus$)+2)+1  ! Höhe in Pixeln
            '
            Imd$=Right$(Aus$,Len(Aus$)-6) ! Bilddaten
            '
            Rsc$=Space$(36+Len(Imd$)+14+2*24+4) ! Platz für RSC schaffen
            Adr%=Varptr(Rsc$)
            ' *************** rshdr basteln *************** 
            Dpoke Adr%+0,1               ! Vrsn, immer(?)=1
            Dpoke Adr%+2,36+Len(Imd$)+14 ! Offset Objekt-Struktur
            Dpoke Adr%+4,36+Len(Imd$)+14 ! Offset Tedinfo-Struktur
            Dpoke Adr%+6,36+Len(Imd$)+14 ! Offset Iconblk-Strukur
            Dpoke Adr%+8,36+Len(Imd$)    ! Offset Bitblk-Struktur
            Dpoke Adr%+10,36+Len(Imd$)   ! Offset freie Strings
            Dpoke Adr%+12,36             ! Offset gebundene Strings
            Dpoke Adr%+14,36             ! Offset Image-Daten
            Dpoke Adr%+l6,36+Len(Imd$)+14 ! Offset freie Images
            Dpoke Adr%+18,36+Len(Imd$)+14+2*24 ! Offset Baumtabelle 
            Dpoke Adr%+20,2              ! Anzahl der Objekte
            Dpoke Adr%+22,1              ! Anzahl der Bäume
            Dpoke Adr%+24,0              ! Anzahl der Tedinfos
            Dpoke Adr%+26,0              ! Anzahl der Iconblöcke
            Dpoke Adr%+28,1              ! Anzahl der Bitblöcke
            Dpoke Adr%+30,0              ! Anzahl der Strings
            Dpoke Adr%+32,0              ! Anzahl der Images
            Dpoke Adr%+34,Len(Rsc$)      ! Länge der Resource
            '
            ' **************** Bilddaten eintragen ********* 
            Bmove Varptr(Imd$),Adr%+36,Len(Imd$)
            '
            ' ************* Bit Image Block basteln ******** 
            Add Adr%,36+Len(Imd$)        ! Anfangsadresse d.Bitblk 
            Lpoke Adr%,36                ! Adresse der Bilddaten
            Dpoke Adr%+4,B% Div 8        ! Breite in Bytes
            Dpoke Adr%+6,H%              ! Höhe in Pixeln
            Dpoke Adr%+8,0               ! X-Position
            Dpoke Adr%+10,0              ! Y-Position
            Dpoke Adr%+12,1              ! Farbe
            Add Adr%,14                  ! Anfangsadresse der Objektstruktur
            '
            ' ********* Objektstruktur der Vater-Box ******* 
            Dpoke Adr%,-1                ! Nächstes Objekt, hier: keines
            Dpoke Adr%+2,1               ! Erstes Kind, hier: Nr.1
            Dpoke Adr%+4,1               ! Letztes Kind, hier: Nr.1
            Dpoke Adr% + 6,20            ! Objekttyp - G_box
            Dpoke Adr%+8,0               ! Objektflag
            Dpoke Adr%+10,16             ! Objektstatus - Outlined
            Lpoke Adr%+12,135424         ! Obj_spec - Langwort
            Dpoke Adr%+16,0              ! X-Position
            Dpoke Adr%+18,0              ! Y-Position
            Dpoke Adr%+20,B% Div 8+1     ! Breite in Spalten
            Poke Adr%+22,0               ! (Rest-)Höhe in Pixeln im Highbyte
            Poke Adr%+23,H% Div 16+1     ! Höhe in Zeilen im Lowbyte
            Add Adr%,24
            '
            ' ********* Objektstruktur des Bitblk ********** 
            Dpoke Adr%,0                 ! Nächstes Objekt, hier: Vater
            Dpoke Adr%+2,-1              ! Erstes Kind, hier: keines
            Dpoke Adr%+4,-1              ! Letztes Kind, hier: keines
            Dpoke Adr%+6,23              ! Objekttyp - Bitblk
            Dpoke Adr%+8,32              ! Objektflag - Lastob
            Dpoke Adr%+10,0              ! Objektstatus
            Lpoke Adr%+12,36+Len(Imd$)   ! Zeiger auf Bitblk - Langwort
            Dpoke Adr%+16,0              ! X-Position
            Dpoke Adr%+18,0              ! Y-Position
            Dpoke Adr%+20,B% Div 8       ! Breite in Spalten
            Poke Adr%+22,H% Mod 16       ! (Rest-)Höhe in Pixeln im Highbyte 
            Poke Adr%+23,H% Div 16       ! Höhe in Zeilen im Lowbyte
            '
            ' ************ Objektindex - Tabelle ************ 
            Lpoke Adr%+24,36+Len(Imd$)+14 ! Objektanfang des 0.Baumes
            Bsave Rs$,Varptr(Rsc$),Len(Rsc$) ! Speichern 
        Endif
        Put X1%,Y1%,Aus$ ! Invertierung weg
        Alert 0," Nochmal oder neues Bild? ",1,"Nochmal|Neu|Ende",D%
    Until D%>1 
Until D%=3

Mit diesem Listing können sie ihr Resource einbinden

Bild 1: Bilder sagen mehr als tausend schöne Worte

Ingo Brümmer
Aus: ST-Computer 08 / 1988, Seite 92

Links

Copyright-Bestimmungen: siehe Über diese Seite