Auf zur zweiten Sitzung in Sachen »Mikrodraw«. Wir hoffen, Ihnen hat die erste, große Portion keine Magenschmerzen bereitet. Diesmal gilt es, die Blockoperationen zu verdauen.
Konstantinos Lavassas und Ulrich Hilgefort
Nachdem wir in der ersten Folge die programmtechnischen Grundlagen unseres Grafikeditors gelegt haben, wenden wir uns nun den »Feinheiten« zu: Lupe sowie die Blockoperationen Kopieren, Bewegen, Lasso und Biegen stehen auf dem Plan. Daneben gibt es mehrere Parameterfunktionen.
Für die Blockoperationen war eine kleine Änderung an der Procedure »menu« leider nicht zu vermeiden. Die auf der Diskette befindliche Version haben wir entsprechend bearbeitet; bitte ersetzen Sie die Routine aus dem ersten Teil durch die neue.
Die Blockoperationen bilden mit den Zeichenroutinen das Rückgrat eines jeden Grafikeditors. Für Mikrodraw gilt nichts anderes. Daher baten wir unseren Programmierer, Konstantinos Lavassas, den Inhalt seiner Trickkiste nicht ganz für sich zu behalten und Mikrodraw einige interessante Block-Verfahrensweisen mit auf den Weg zu geben.
Doch zunächst bedarf es noch der Lupenfunktion, die für viele knifflige Arbeiten an riskanten Stellen unumgänglich ist. Zur Lupe sollte sich eigentlich eine Funktionserklärung erübrigen, weshalb wir gleich auf die Programmierung eingehen. Die »Vergrößerei« leisten zwei Prozeduren, »lupe« und »lupe_darstellen«. Die erste sorgt dafür, daß wir mit einem 32 mal 32 Pixel großen Auswahlquadrat bestimmen, welcher Ausschnitt in die Feinbearbeitung zu nehmen ist. Die DO-LOOP-Schleife - mit der unvermeidlichen UNDO-Abfrage - besorgt dies. Auf Mausklick links wechseln Programmlauf und Darstellung: »lupe_darstellen« zeichnet den Rahmen für die folgenden Aktivitäten, nachdem der zu bearbeitende Bildteil in »a$« abgelegt ist. Dieser Ausschnitt bildet später die Basis für die Manipulation im kleinen. Die beiden ineinander geschachtelten FOR-NEXT-Schleifen fragen die gesetzten Pixel ab und lassen entsprechend den großen Punkt »b$« erscheinen.
Nun geht's an die Pixelei. Nach der Kontrollabfrage, ob sich die Maus im Fensterbereich befindet, reagiert das Programm auf Mausklick folgendermaßen: Bei Klick links rechnet es die Lupenkoordinaten auf den in Originalgröße dargestellten Ausschnitt um, setzt dort den entsprechenden Punkt mit PLOT, rechnet wieder zurück und baut in die Vergrößerung den korrespondierenden Punkt ein. Der COLOR-Befehl wirkt sich nur auf die Darstellung in Originalgröße aus, bei Links-Klick kommt schwarz, bei Rechts-Klick weiß zum Zuge. Die Lupe verdankt ihr aktuelles Aussehen der Ausgabeform des »Großpixels« »b$« zum Invertieren bzw. Überschreiben.
Der Druck auf ESC beendet die Groß-Veranstaltung, der geänderte Block findet sich in »a$« wieder. Mit SPUT d$ erscheint der ursprüngliche Hintergrund auf dem Schirm; der PUT-Befehl setzt das bearbeitete Quadrat an Ort und Stelle. Puffer-Auffrischung und Variablen-Räumerei schließen die Routine ab.
Nach der Lupe wenden wir uns den Blockoperationen zu, deren wichtigste wohl das Kopieren ist. Unser Programm läßt sich auf mehrere Arten zum Kopieren verleiten. Die entsprechende Steuerung übernehmen zwei Parameterfunktionen, die Sie der besseren Übersicht halber zu den anderen, bereits besprochenen Steuerfunktionen schieben, »kopiermodus« gestattet den Zugriff auf die allgemein bekannten Verknüpfungsmodi, von »transparent« bis zu »XOR«. Die »kopierart« hingegen stellt etwas neues dar: Selbst die normale Kopierfunktion mit Auswahlrechteck arbeitet auf Wunsch reduzierend, d.h. der häßliche weiße Rand um das zu kopierende Bildmaterial verschwindet. Wie das funktioniert, zeigen wir gleich. Denn zuvor soll die »event_taste«-Funktion Erwähnung finden. Sie sorgt dafür, daß auch während der Kopier- und Bearbeitungsvorgänge ein Wechsel des Bildes (1 bis 15, Sie erinnern sich) mit den Pfeiltasten und des Kopiermodus mit »c« durchführbar ist, ohne den gerade eingefangenen Bildblock Zwischenlagern zu müssen. Eine UNDO-Abfrage haben wir natürlich auch eingebaut. Und bei Druck auf »b« verrät das Programm, welcher Bildschirm gerade zu sehen ist -denn während der Zeichen- und Blockoperationen ist uns der Blick auf die Menüleiste mit der Anzeige der aktuellen Bildschirm-Nummer verwehrt.
Doch nun zu »kopieren«, die auf die Vorarbeit der »raster«-Funktion aufbaut. Letztere gestattete dem Anwender, einen Bildbereich zur Bearbeitung auszuwählen. Die resultierenden Koordinaten findet »kopieren« in den Variablen »x1%«,»y1%« für die obere, linke Ecke sowie »x1%« und »y1%«, welche die Größe des Rechtecks beschreiben. Schauen wir uns gleich die schwierigere Version an, die reduzierende. Sie verfährt nach dem selben Trick, den später auch die Lasso-Funktion benutzt. Nach einer Sicherheitsabfrage zur Größe des ausgewählten Bereiches geht's los.
Das aktuelle Bild entnehmen wir dem Puffer - Ausnahme: Verzerren, dann verwenden wir das gerade sichtbare Bild - und holen den ausgewählten Bereich per GET in »bild$(3)«. Auf der gelöschten Bildschirmfläche bilden wir das Auswahlrechteck nach und setzen den gewünschten Bildbereich hinein. Durch Füllen mit Schwarz erhalten wir eine Maske, die alle umschlossenen Flächen der Vorlage als weiße Flecken enthält. Damit auch die Umrisse nicht der Maskierung zum Opfer fallen, kopieren wir die Originalvorlage im (NOT)-AND-Modus auf die vorher gefüllte Version auf. Übrig bleibt eine Maske des Originals, die außerhalb der Vorlage schwarz ist. Wem das alles zu wenig transparent erscheint, der lese etwas tiefer beim Lasso noch einmal nach.
Maske und Originalausschnitt übergibt die Funktion an »lasso_kopieren«, das den Rest - Bewegen des Ausschnitts sowie endgültige Positionierung - übernimmt.
Die normale Art zu kopieren ist dagegen einfach. Per GET-Befehl holen wir uns wieder den ausgewählten Ausschnitt, bringen das ursprüngliche Hintergrundbild auf den Schirm und lassen den Ausschnitt in der DO-LOOP-Schleife den Mausbewegungen folgen. Der BOX-Befehl am Ende zieht den Auswahlrahmen um den Ausschnitt, solange die Maustasten ungedrückt bleiben. Bekundet der Anwender die Ansicht, die Positionierung sei ihm angenehm, so setzt die Routine das augenblickliche Aussehen des Bildes als Pufferinhalt für die Flimmer-Frei-Grafik ein - fertig. Beim XOR-Kopiermodus ist ein Löschen des Mauspuffers sinnvoll, da es sonst durch Kontaktprellen zu merkwürdigen Effekten kommen kann.
Wer übrigens eine eigene Funktion für das Bewegen erwartet hatte, den müssen wir enttäuschen. Bewegen ist schließlich nichts anderes als Kopieren mit folgendem Löschen des ausgewählten Bereiches. Genau für diesen Zweck dient die Variable »move%«, die entsprechend auf 1 oder 0 gesetzt wird.
Wenden wir uns nun dem Lasso zu. Wie das Seil-Lasso sich um den eingefangenen Gegenstand schließt, so funktioniert das grafische Pendant auf dem Bildschirm. Die Bedienung solcher Grafikschlingen ist allgemein ähnlich. Mit der Maus umfährt der Anwender den Bereich des Bildes, den er kopieren möchte. Anders als die Auswahl mit einem größenveränderlichen Rechteck steht damit auch dem Herauslösen einzelner, verästelter Details aus einem größeren »Gesamtkunstwerk« nichts im Wege. Hat der Benutzer also dem Computer mitgeteilt, welchen Bereich er kopieren möchte, so zieht dieser den eingekreisten Teil aus der Grafik heraus und stellt ihn zum Kopieren bereit. Dabei sind für das Herauslösen schon einige Anstrengungen zu leisten.
Um das alles zu verkomplizieren, haben sich die Computer-Grafikexperten den Fachterminus »reduzierendes Lasso« einfallen lassen. Was sich dahinter verbirgt, verraten die Bilder 1a bis 1c.
In Bild 1a sehen wir die Zeichnung eines ebenso bekannten wie exotischen Bauwerkes, eingefaßt von einem Rahmen. Wer dieses Bild per Lasso aus dem Rahmen herauslösen will, um es auf eine gerasterte Fläche zu kopieren, der erntet womöglich ein Ergebnis wie in Bild 1b: Das Zeichenprogramm hat genau den eingegrenzten Bereich zum Kopieren genommen und ihn auf die Rasterfläche draufgesetzt - nicht ganz das, was sich unser Grafikfreund gedacht hatte. Wenn der Computer doch merken könnte, wo das Bild aufhört, und in der Lage wäre, den häßlichen, weißen Rand verschwinden zu lassen - dann käme am Ende so etwas wie Bild 1c dabei heraus.
Allerdings ist auch die Version »mit Rand« mitunter nützlich, weshalb wir beide Verfahren ins Programm eingebaut haben. Entscheidend ist die Variable »km%«, deren Wert die gewünschte Betriebsweise auslöst.
Wie das Ganze funktioniert, zeigen die Bilder 2a bis 2c. Das Bild haben wir mit einem Grau-Raster unterlegt, denn weiße Ränder sieht man auf weißem Papier so schlecht. In Bild 2a hat der Anwender das eigentliche Motiv eingekreist. Aus der »Umzingelungslinie« und dem Rechteck, das sie umschließt, entsteht die Maske Bild 2b, wenn der Zwischenraum mit schwarz gefüllt ist. Das Ergebnis einer NOT-AND-Verknüpfung zeigt Bild 2c: eine Maske, die später von »lasso_kopieren« zum Freiräumen des Hintergrundes benötigt wird. Soweit das »normale« Lasso. Die reduzierende Art funktioniert ähnlich.
Nun zur Programmierung. Nachdem wir uns genügend Puffer besorgt haben, holen wir den aktuellen Bildschirm in »bild$(1)«. Sodann erfolgt der Aufruf von »lasso_umfahren«, womit der zu bearbeitende Bereich »umzingelt« wird. »lasso_kopieren« übernimmt den Rest, also freies Positionieren und abschließendes Einkopieren.
Aus gutem Grunde hat unser Programmierer eine normale REPEAT-UNTIL-Schleife zur Darstellung der »Schlinge« verwendet und den Einsatz der GEM-Funktion »Polyline« vermieden. Diese System-Funktion kommt ganz kräftig durcheinander, wenn ein und derselbe Punkt mehrfach umfahren wurde - das GEM rechnet sich tot.
»lasso_umfahren« legt für maximal 502 Punktepaare entsprechende Felder an und startet die genannte Schleife, in welcher der neu eingegebene Punkt, mit seinem jeweiligen Vorgänger verbunden, einen Linienzug ergibt. Eine IF-THEN-Abfrage testet, ob sich der zuletzt angegebene Punkt in der Nähe des Startpunktes befindet, und schließt gegebenenfalls das Lasso selbständig. Der Wert 10 für den Fangradius ist in den meisten Fälle angemessen. Wer mag, sollte mit Zahlen zwischen 3 und 20 experimentieren. Nachdem sich die Schlinge um unser Bildschirmstück geschlossen hat, berechnet die Routine die maximale Ausdehnung der Umgrenzungslinie und legt die Abmessungen ab, damit sich daraus ein das gesamte Lasso umschließendes Rechteck bilden läßt.
Soweit zum zweiten Teil des Kurses. Wie beim ersten soll der Hinweis nicht fehlen, daß Sie ruhig auf Unverstandenes, Unverständliches oder zu Kompliziertes hinweisen dürfen. Unsere Anschrift finden Sie im Impressum. Bis zum dritten Anlauf, wenn wir die letzten Geheimnisse der Lassofunktion aufdecken und uns mit den Effekten befassen. (uh)
Teil 1: Menüleiste aufbauen, Systemfunktionen, Diskettenoperationen, Zeichenfunktionen
Teil 2: Blockoperationen wie Lassoaktionen, kopieren, bewegen, biegen
Teil 3: Grafik-Effekte, Textdarstellung, Ausgabe auf den Drucker
Teil 4: Erweiterungen und Feinheiten