Lasso-Funktion in Omikron.BASIC

Ich stand vor dem Problem, aus einem Bild einen unregelmässig geformten Ausschnitt herauszutrennen. Viele Malprogramme bieten zu diesem Zweck eine “Lasso” -Funktion an. Da ich weder ein solches Programm noch eine Grafik-Bibliothek mit dieser Funktion mein eigen nenne, entschied ich mich, die entsprechende Routine selbst zu erstellen.

Meine “Lasso"-Routine schneidet einen mit der Maus definierten Grafikblock aus und legt ihn zwecks Weiterverwendung in einem Puffer im BITBLT-Format ab. Im Demoprogramm kann der gewonnene Ausschnitt an anderer Stelle im Bildschirm einkopiert werden.

Nutzung des Unterprogramms

Die Lasso-Prozedur wird vom Hauptprogramm aus mit Lasso(UNDO,MODUS) aktiviert. UNDO=1 bewirkt, daß vor Ausführung der Prozedur ein zusätzlicher Speicher angelegt wird, in den das Originalbild gerettet wird. Dadurch bleibt das "Lasso" nach Programmbeendigung nicht auf dem Bildschirm liegen. UNDO kann als 0 definiert werden, wenn der Erhalt des Originalbildes nicht verlangt wird oder wenn Speichersparen vonnöten ist. Der Parameter MODUS gibt die Art der Verknüpfung des Lasso-Inhalts mit dem Hintergrund an. Er ist gleichbedeutend mit der BITBLT-Verknüpfungsart (0-15). Nach Aufruf wird zunächst mit Mausklick der Lasso-Startpunkt festgelegt. Der Zeiger zieht ab jetzt die Schlinge um die Grafik, bis zum zweitenmal geklickt wird. Nach kurzer Zeit ist der gewählte Bildausschnitt zu sehen und kann verschoben werden. Die linke Maustaste setzt den Block gemäß der mit MODUS festgelegten Verknüpfungsart auf das Bild, die rechte beendet die Bearbeitung.

Prinzip der Lasso-Routine

Um einen unregelmäßig geformten Block ausschneiden zu können, muß man über eine Maske auf einem 2. Bildschirm verfügen, deren Form der des Blockes entspricht. Diese Maske wird einfach mit dem Originalbild UND-verknüpft. und der Ausschnitt steht bereit. Ist die Form ein Vieleck, reicht es. sie mit einem FILL-Befehl schwarz auszufüllen. Dieses Verfahren kann hier nicht angewandt werden, da der Benutzer mit dem Lasso jede beliebige Umrandung, also auch Überschneidungen. bestimmen können soll. Wird z.B. eine "8" als Randform gezeichnet, scheidet o.g. Methode aus, weil lediglich einer der Kreise der "8" mit einem Füllbefehl aufgefüllt werden kann. Außerdem würde bei dieser Methode die Umrandung selbst zum Ausschnitt gehören, was nicht wünschenswert ist. Aus diesem Grunde muß man im Programm den umgekehrten Weg gehen: man füllt den Teil des Bildes auf. der nicht vom Lasso umrahmt wird und bekommt somit eine Maske zu jedweder Lasso-Form. Diese Maske muß. da sie invertiert ist. mit dem Bild NICHT UND-verknüpft werden. Ein Nachteil hierbei: um eine sichere Umrandung der Form durch einen FILL-Befehl zu gewährleisten, muß an den Bildrändern jeweils 1 Punkt frei bleiben, damit die Füllroutine das gesamte Lasso umschließen kann.

Programmbeschreibung

Int Beispielprogramm wird die Prozedur einmal mit und einmal ohne UNDO-Flagge aufgerufen. wobei vorher ein Beispielbild mit gefüllten Kreisen gezeichnet wird.

Bei Aufruf der Prozedur müssen zunächst die Füll- und Linienmuster auf schwarz gesetzt werden, um eine lückenlose Füllung der Maske zu garantieren. Nach der Feststellung der Bildschirmadresse werden der Masken- und, falls gewünscht, der UNDO-Putter angelegt. Nun wird auf Mausklick gewartet und die Lasso-Anfangskoordinaten gemerkt.

In der folgenden Lasso-Schleife wählt der Benutzer den Ausschnitt, indem er die Lasso-Form mit der Maus zeichnet. Nach jeder Veränderung der Mauskoordinaten erfolgt die Ermittlung der Koordinaten des Begrenzungsrechtecks. welches den markierten Ausschnitt umschließt. Nachdem die Schleife mit Klick verlassen wurde, schließt eine Linie das Lasso durch Verbinden der Endpunkte. Das Erstellen der Maske besorgt nun ein FILL-Befehl. Das Füllen erfolgt im Programm nur innerhalb des Begrenzungsrechtecks, um Zeit zu sparen. Die Maske wird (durch BITBLT) mit dem Bild NICHT UND-verknüpft. Den so entstandenen Ausschnitt kopiert man an den Anfang des Maskenpuffers, so dali er an der Adresse PUFFERc/cL zur Verfügung steht. Wurde der UNDO-Zwischenspeicher angelegt, erfolgt jetzt die Restaurierung des Originalbildes mittels MEMORY MOVE. falls nicht, bleibt das Bild unverändert, d.h. die "Lasso-Schlinge" bleibt auf dem Bildschirm liegen.

Was noch folgt, ist die Positionierung des Ausschnitts mittels Maus auf dem Bildschirm und das Verknüpfen mit dem Bildschirm bei Betätigen der linken bzw. das kommentarlose Verlassen der Prozedur mit der rechten Maustaste. Vor Beendigung wird derdurch die Zwischenspeicher PUFFER%L und UNDO%L belegte Platz freigegeben, so daß nach Programmende der gleiche Speicher wie vorher zur Verfügung steht. Wenn der Grafikblock im späteren Verlauf noch benötigt wird, ist die entsprechende Zeile zu entfernen.

' ***********************************************
' *                 LASSO-FUNKTION              *
' *        von L. Canisius, September 1989      *
' * Aufruf: Lasso(Undo,Modus)                   *
' * Undo:   1,wenn Bild gerettet werden soll    *
' * Modus: Verknüpfungsart des Ausschnitts(0-15)* 
' * (C) MAXON Computer GmbH                     *
' ***********************************************
Zeichne_Bild 
Lasso(1,7)
Zeichne_Bild 
Lasso(0,7)
END
'
DEF PROC Zeichne_Bild
    PRINT CHR$(27);"f"' Cursor aus 
    CLS
    MODE =1
    FOR I!=1 TO 10 
        X!= RND(640)
        Y!= RND(400)
        R!= RND(100)
        PCIRCLE X!,Y!,R!
    NEXT I!
RETURN
'
'
DEF PROC Lasso(Undo%,Modus%)
    FILL STYLE =1,2 '....... schwarze Füllung
    LINE STYLE =1 '......... durchgehende Linien
    XBIOS (Bildschirm%L,2) 'phys. Bildschirmadresse
    _V_Bas_Ad#=$44E '......log. Bildschirmadresse
    Puffer%L= MEMORY(32000)'2. Bildspeicher reserv.
    '
    ' * Anfangswerte des Begrenzungsrechtecks *
    '
    Xmax%=0
    Ymax%=0
    Xmin%=640
    Ymin%=400
    '
    ' * Original retten, wenn gewünscht *
    '
    IF Undo%=1 THEN
        Undo%L= MEMORY(32000)
        MEMORY_MOVE Bildschirm%L,32000 TO Undo%L 
    ENDIF
    '
    ' * auf Mausklack warten *
    '
    MOUSEON
    REPEAT
    UNTIL MOUSEBUT 
    REPEAT
    UNTIL MOUSEBUT =0
    ' * Anfangskoordinaten merken *
    '
    Xstart%= MOUSEX 
    Ystart%= MOUSEY 
    X1%=Xstart%
    X2%=X1%
    Y1%=Ystart%
    Y2%=Y1%
    ' *
    ' * Ausschnitt mit der Maus wählen *
    ' *
    REPEAT
        WHILE MOUSEBUT =0 AND X1%=X2% AND Y1%=Y2% 
            X1%= MOUSEX 
            Y1%= MOUSEY 
        WEND
        '
        ' * Lasso nicht an den Rand lassen *
        '
        X1%= MIN(X1%,638)
        X1%= MAX(X1%,1)
        Y1%= MIN(Y1%,398)
        Y1%= MAX(Y1%,1)
        '
        ' * Ermittlung des Begrenzungsrechtecks *
        '
        Xmax%= MAX(X1%,Xmax%)
        Xmin%= MIN(X1%,Xmin%)
        Ymax%= MAX(Y1%,Ymax%)
        Ymin%= MIN(Y1%,Ymin%)
        '
        ' * Zeichnen des Lassos: *
        '
        MOUSEOFF
        '
        ' * 1) versteckt *
        MODE =1'................. OR-Modus
        LPOKE _V_Bas_Ad#,Puffer%L 
        DRAW X2%,Y2% TO X1%,Y1%
        '
        ' * 2) sichtbar *
        MODE =3 '............... XOR-Modus
        LPOKE _V_Bas_Ad#,Bildschirm%L 
        DRAW X2%,Y2% TO X1%,Y1%
        '
        MOUSEON
        X2%=X1%
        Y2%=Y1%
    UNTIL MOUSEBUT
    '
    ' * Umrandung schliessen *
    '
    MOUSEOFF
    DRAW X2%,Y2% TO Xstart%,Ystart%
    '
    ' * Schirm 1 ins BITBLT-Format bringen *
    '
    BITBLT 0,0,640,400 TO Bildschirm%L-6
    '
    ' * Ab jetzt alles im Puffer ausführen *
    '
    LPOKE _V_Bas_Ad#,Puffer%L 
    MODE =1
    DRAW X2%,Y2% TO Xstart%,Ystart%
    '
    ' * Maske durch Füllen des Begrenzungsrechtecks erstellen *
    '
    Breite%=Xmax%-Xmin%
    Hohe%=Ymax%-Ymin%
    BOX Xmin%-2,Ymin%-2,Breite%+6,Hohe%+6 
    FILL Xmin%-1,Ymin%-1,1
    '
    ' * Maske mit Bild NOT AND-Verknüpfen *
    '
    BITBLT Bildschirm%L-6 TO 0,0,640,400,2
    '
    ' * Ausschnitt nach PUFFER%L *
    '
    BITBLT Xmin%,Ymin%,Breite%,Hohe% TO Puffer%L
    '
    ' * Ab jetzt wieder alles auf sichtbarem Bildschirm ausführen *
    '
    LPOKE _V_Bas_Ad#,Bildschirm%L
    '
    ' * Bild restaurieren *
    '
    IF Undo% THEN MEMORY_MOVE Undo%L,32000 TO Bildschirm%L
    ' *
    ' * Weiterverarbeitung: Verschieben des Ausschnitts *
    ' *
    CLIP 0,0,640,400 
    X%= MOUSEX 
    Y%= MOUSEY
    BITBLT Puffer%L TO X%,Y%,Breite%,Hohe%,6 
    '
    REPEAT
        WHILE MOUSEBUT =0 AND X%= MOUSEX AND Y%= MOUSEY
        WEND
        BITBLT Puffer%L TO X%,Y%,Breite%,Hohe%,6 
        X%= MOUSEX
        Y%= MOUSEY
        BITBLT Puffer%L TO X%,Y%,Breite%,Hohe%,6 
    UNTIL MOUSEBUT 
    IF MOUSEBUT =1 THEN
        '
        ' * Ausschnitt gemäß Modus einkopieren * 
        BITBLT Puffer%L TO X%,Y%,Breite%,Hohe%,Modus% 
    ELSE
        '
        '* Ausschnitt durch XOR-Verknupfung löschen * 
        BITBLT Puffer%L TO X%,Y%,Breite%,Hohe%,6 
    ENDIF
    '
    ' * Speicher freigeben *
    '
    FRE Puffer%L 
    IF Undo% THEN FRE Undo%L 
RETURN

Ludwig Canisius
Aus: ST-Computer 05 / 1990, Seite 86

Links

Copyright-Bestimmungen: siehe Über diese Seite