← ST-Computer 08 / 1988

Eigene Bilder in der Resource

Programmierpraxis

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)

  • Len(Aus$)-6 Bytes (Bilddaten)
  • 14 Bytes (Bitblk)
  • 2*24 Bytes (Objekte)
  • 4 Bytes (Objektbaumtabelle)

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
Bild 1: Bilder sagen mehr als tausend schöne Worte

Ingo BrĂŒmmer