Variable Bildausschnitte (GFA)

Jedes anspruchsvolle Mal- und Grafikprogramm verfügt über eine Funktion, die es gestattet. Bildausschnitte von beliebiger Größe auf dem Bildschirm zu verschieben bzw. zu kopieren. Hierbei besteht der Unterschied zwischen „Verschieben“ und „Kopieren“ darin, daß bei der Funktion „Verschieben“ der Ausschnitt im wahrsten Sinne aus dem Bild „herausgeschnitten“ wird. Bei der Funktion „Kopieren“ verbleibt der Originalausschnitt im Bild, die Kopie des Ausschnitts läßt sich an anderer Stelle beliebig positionieren.

Das Verschieben von grafischen Einheiten stellt den wesentlichen Bestandteil des sogenannten Layouts etwa einer Druckvorlage dar. Die in diesem Artikel gezeigten Routinen lassen Schere und Klebstoff - Hauptwerkzeuge beim Layout - endgültig überflüssig werden: Alle grafischen Einheiten, seien es Texte, Bilder oder auch Notensysteme, können mit der Maus auf dem Bildschirm druckfertig arrangiert werden.

Das Prinzip

Der zu verschiebende Bildausschnitt wird mit dem „Gummifaden“ eingerahmt. Dieser eingerahmte Bildschirmbereich wird in geeigneter Weise zwischengespeichert - gepuffert - und kann dann an beliebiger Stelle mit der Maus wieder auf dem Bildschirm plaziert werden. Bei der Funktion „Verschieben“ wird der Bereich unter dem Rahmen gelöscht.

Die Realisierung

Die Realisierung dieses an sich einfachen Prinzips findet sich in der Procedure Verschieben(Copy%). Betrachten wir das Listing:

Die Do-Loop-Hauptschleife ist nur notwendig, falls nach dem Aufruf der Prozedur die Möglichkeit bestehen soll, mehrere Verschiebungen unmittelbar nacheinander vornehmen zu können.

Die erste While-Wend-Schleife wird bis zum Mausklick mit der linken Taste durchlaufen. Dabei ist die Menüüberwachung eingeschaltet. Erfolgt nun ein Mausklick, wird mit MOUSE xl%, yl%,k% die augenblickliche Bildschirmposition der Maus festgehalten und der Variablen xl% bzw. yl% übergeben.

Der Rahmen

Die Werte der Koordinaten xl% und yl% bleiben in der nun folgenden Rahmenschleife konstant, da hier mit MOUSE xr%,yr%,k% eine eigene Mausstatusauswertung erfolgt. Der Grund für diese zweifache Statusermittlung liegt in dem Prinzip, nach dem der “Gummifaden” auf dem Bildschirm erzeugt wird: Für das Zeichnen des Rahmens mit dem BOX-Befehl werden vier Koordinaten benötigt, zwei für die linke obere Ecke (xl%,yl%) und zwei für die rechte untere Ecke (xr%,yr%). Da die Größe des Rahmens mit der Maus eingestellt wird und diese nur zwei Koordinaten liefert, müssen die Werte der linken, oberen Koordinaten konstant bleiben, wahrend die Werte der Koordinaten der rechten, unteren

Ecke analog zur Mausbewegung verändert werden können. Zur Realisierung des “Gummifadens' benötigt man demnach prinzipiell zwei Schleifen mit zwei unabhängigen Statusermittlungen.

Nach einer Bewegung der Maus muß vor dem Zeichnen des neuen Rahmens der alte Rahmen gelöscht werden, da andernfalls nach mehreren Mausbewegungen nur noch ein schwarz ausgefülltes Rechteck auf dem Bildschirm verbleiben würde. Das Löschen das alten Rahmens geschieht mit dem zweiten BOX-Befehl innerhalb der Rahmenschleife. Die beiden gleichartigen BOX-Befehle sind durch eine Repeat-Until-Schleife voneinander getrennt. Diese Schleife wird nach einer Mausbewegung verlassen, und das zweite BOX xl%,yl%,xr%,yr% überschreibt (im Graphmode 3) den alten Rahmen.

Die Rahmenschleife wird verlassen, sobald die linke Maustaste losgelassen wurde. Der eingerahmte Bereich wird jetzt mit GET xl%,yl%,xr%,yr%,Snp$ gepuffert. Findet die Verschiebung/Kopie in einem GEM-Fenster statt, muß zur y-Koordinate der Wert 38 hinzuaddiert werden. Der Grund hierfür: Die Grafikbefehle in GEM-Fenstern haben einen anderen Bezugspunkt als die Rasterbefehle GET und PUT, die immer vom Punkt (0,0) ausgehen.

Soll der Ausschnitt verschoben, aber dabei nicht kopiert werden, überdeckt ein Rechteck von der Größe des Ausschnitts den eingerahmten Bereich mit PBOX xl%,yl%,xr%,yr% bei Deffill 0. Die Füllmusterfarbe wird danach sicherheitshalber mit Deffill 1 wieder auf "Objektfarbe” festgelegt. Die Entscheidung, ob der Ausschnitt verschoben oder kopiert wird, übergibt man schon beim Aufruf der Prozedur mit dem Wert der Variablen Copy%. Nach dem Verlassen der Rahmenschleife würde sich ohne weitere Maßnahmen der Mauscursor an der rechten unteren Ecke des Rahmens befinden. Damit in der folgenden Verschiebeschleife der Mauscursor sofort wieder an der linken oberen Ecke des Ausschnitts erscheint, wird mit DPOKE 9952,xl%+1 bzw. DPOKE 9954,yl%+38 der Cursor dorthin zurückgesetzt. Eine beliebige Mausposition kann also bestimmt werden, indem einfach die entsprechenden Werte plus GEM-Offset an diese Adressen ge” de poked” werden.

Verschieben und Kopieren

In der Verschiebeschleife wird nach erneuter Statusermittlung zunächst der Originalhintergrund mit SGET Bild$ gepuffert. Nun zeigt PUT x%,y%+38,Snp$,7 den Ausschnitt, was allerdings erst ab dem zweiten Schleifendurchlauf, d.h. nach der ersten Verschiebung, deutlich wird: Nach einer Mausbewegung wird die While-Wend-Warteschleife verlassen und mit SPUTBild> der Ausschnitt an seiner alten Position überdeckt. Die Verschiebeschleife wird erneut durchlaufen, und jetzt zeigt der PUT-Befehl den Ausschnitt an seiner neuen Position.

Erfolgt nun ein abschließender Mausklick, wird die Verschiebeschleife verlassen, und der Ausschnitt befindet sich an seiner endgültigen Position.

Die Möglichkeit zum Verschieben des Ausschnitts resultiert demnach aus dem Zusammenwirken der Befehle SPUT für den Hintergrund und PUT für den Ausschnitt. Die Tatsache, daß der Ausschnitt nach einer Mausbewegung an seiner alten Position mit SPUT überdeckt wird, ist übrigens die Ursache für ein leichtes Flackern des Ausschnitts während des Verschiebens. Die Warteschleife sorgt dafür, daß bei unbewegter Maus kein solches Flackern entsteht. Für den jeweiligen PUT-Modus stehen prinzipiell die Werte 0 bis 15 zur Verfügung, wobei die wichtigsten die Modi 3 (Graphmode 1), 6 (Graphmode 3), 7 (Graphmode 2) und 4 (Graphmode 4) sind.

Die beschriebene Prozedur kann in jedes Grafikprogramm integriert werden. In dieser Demoversion werden mit der Procedure Flaechen bzw. Procedure Text einfache grafische Einheiten zum Ausprobieren der Verschiebe- bzw. Kopierfunktion erzeugt.

' (c) MAXON Computer GmbH 1988
'
DIM m$(22)            !Menü erstellen
RESTORE mmenue
FOR z%=0 TO 21
  READ m$(z%)
NEXT z%
mmenue:
DATA DESK  ,  Info ,--------------------
DATA 1,2,3,4,5,6,""
DATA GRAFIK  ,  Flächen  ,  Text  ,---------------,  Quit,""
DATA LAYOUT  ,  Verschieben  ,  Kopieren  ,---------------,"","",""
MENU m$()
FULLW 1               !GEM-Fenster öffnen
'
GOSUB menu
PROCEDURE menu
  DEFMOUSE 0
  DO                  ! Auf Ereignis
    ON MENU           ! warten
    REPEAT            ! und wenn
    UNTIL MOUSEK=0    ! Maustaste losgelassen
    ON MENU  GOSUB auswahl    ! verzweigen
  LOOP
RETURN
'
PROCEDURE auswahl     !Auswahl treffen
  IF MENU(0)=1
    MENU OFF
    GOSUB copyright
  ENDIF
  IF MENU(0)=11
    MENU OFF
    GOSUB flaechen
  ENDIF
  IF MENU(0)=12
    MENU OFF
    GOSUB text
  ENDIF
  IF MENU(0)=14
    MENU OFF
    END
  ENDIF
  IF MENU(0)=17
    MENU OFF
    GOSUB verschieben(0)
  ENDIF
  IF MENU(0)=18
    MENU OFF
    GOSUB verschieben(1)
  ENDIF
RETURN
'
'
PROCEDURE verschieben(copy%)
  DEFMOUSE 5        ! Fadenkreuz
  DO                ! Hauptschleife
    WHILE MOUSEK=0
      ON MENU
    WEND
    ON MENU
    MOUSE xl%,yl%,k% ! Mauskoordinaten links-oben
    GRAPHMODE 3
    DEFLINE 2,1,,
    '
    ' ***** Rahmen zeichnen *****
    '
    WHILE MOUSEK=1
      MOUSE xr%,yr%,k% ! Mauskoordinaten rechts-unten
      BOX xl%,yl%,xr%,yr% ! Verschiebe-Bild umrahmen
      REPEAT
      UNTIL MOUSEK=0 OR MOUSEX<>xr% OR MOUSEY<>yr% ! Wenn Maus bewegt
      BOX xl%,yl%,xr%,yr% ! alten Rahmen loeschen
    WEND
    DEFLINE 1,1,,
    GET xl%,yl%+38,xr%,yr%+38,snp$ ! Ausschnitt puffern
    IF NOT copy%=1 ! Nicht kopieren?
      DEFFILL 0    !
      GRAPHMODE 1  !
      PBOX xl%,yl%,xr%,yr% !dann Original überdecken
      DEFFILL 1
    ENDIF
    DPOKE 9952,xl%+1 ! Mauscursor nach links-oben
    DPOKE 9954,yl%+38! zurücksetzen
    '
    ' ***** Verschieben/Kopieren *****
    '
    WHILE MOUSEK=0
      ON MENU
      MOUSE x%,y%,k%
      SGET bild$     ! Hintergrund puffern
      PUT x%,y%+38,snp$,7 ! Ausschnitt zeigen
      WHILE MOUSEX=x% AND MOUSEY=y% AND MOUSEK=0 ! Auf Mausbewegung warten
        ON MENU
      WEND
      SPUT bild$   !Hintergrund über Ausschnitt legen
    WEND
    PUT x%,y%+38,snp$,7
    WHILE MOUSEK=1  !Warten bis Taste losgelassen
    WEND
  LOOP
  DEFTEXT ,0,,13
RETURN
'
PROCEDURE flaechen
  GRAPHMODE 1
  FOR z%=1 TO 3 STEP 2
    DEFFILL ,2,RANDOM(24)
    PBOX 50*z%,50*z%,100*z%,100*z%
  NEXT z%
  DEFFILL 1
  GOSUB menu
RETURN
'
PROCEDURE text
  GRAPHMODE 2
  FOR z%=60 TO 300 STEP 80
    TEXT 340,z%," Verschieben oder kopieren   "
  NEXT z%
  GOSUB menu
RETURN
'
'
PROCEDURE copyright
  CLS
  BOX 120,70,530,270
  DEFTEXT ,,,13
  TEXT 150,130,"Verschieben und Kopieren von Bildausschnitten"
  DEFTEXT ,,,13
  TEXT 260,170,"in GfA-Basic"
  DEFTEXT ,,,6
  TEXT 230,210,"MAXON Computer 1988"
  DEFTEXT ,,,13
  PAUSE 100
  CLS
  GOSUB menu
RETURN

Hans-H. Ackermann
Links

Copyright-Bestimmungen: siehe Über diese Seite