Ein Scheme Handbuch für Gimp Anwender
© Dov Grobgeld; Last modified: 1998-02-26
Deutsche Übersetzung von Gottfried Müller
Letzte Änderungen:
19.06.1999: Ersterstellung
29.02.2000: Code-Umstellung auf XHTML 1.0, Korrekturen und
Aktualisierungen, kleinere Layout-Umstellungen
Eine der hervorragenden Eigenschaften von Gimp ist die Möglichkeit, Aufgaben durch Scripte zu lösen. Die standardmäßig vorgesehene Script-Sprache von Gimp ist Scheme. Dieses Dokument möchte eine kurze Einführung in Scheme geben, um die wichtigsten Grundbegriffe für die Erstellung von Script-Fu Programmen zu erläutern, ohne jedoch in tiefere Programmieraspekte einzutauchen.
Scheme ist eine Variante der Programmiersprache Lisp, deren auffälligstes Merkmal ist, daß alle Ausdrücke in runde Klammern eingefaßt sind. So ist zum Beispiel der folgende Ausdruck eine Liste, die die Summe der Zahlen 3 und 4 bildet:
(+ 3 4)
Das Plus-Zeichen "+" stellt die Additionsfunktion dar und die Zahlen "3" und "4" sind die beiden ersten Parameter für diese Funktion. Ausdrücke können verschachtelt sein. So wird der mathemetische Ausdruck (3+4)*(5/6) in Scheme wie folgt formuliert:
(* (+ 3 4) (/ 5 6))
Die sogenannten "white spaces" (Trennzeichen wie das Leerzeichen, Tabulatoren oder Zeilenumbruch) haben keinen Einfluß auf die Bedeutung eines Ausdruckes in Scheme. Deshalb kann der gleiche mathematische Ausdruck auch so formuliert werden:
(* (+ 3 4) (/ 5 6) )
Neben den vier arithmetischen Grundoperationen wie "+", "-", "*" und "/" exisitieren noch jede Menge weitere Built-In-Funktionen. Alle von ihnen haben die Form
(foo param1 param2 ...)
Vom Anwender können auch zusätzliche Funktionen mittels des Schlüsselwortes "define" bereitgestellt werden. Die folgende Funktion berechnet das Quadrat des einzigen übergebenen Argumentes (oder Parameters):
(define (square x) (* x x))
und sie wird zum Beispiel so aufgerufen:
(square 5)
Variable können mit dem Kommando "set!" deklariert und mit einem Wert versehen werden. Diese Variablen besitzen einen globalen Gültigkeitsbereich. Das jedoch soll dem Gimp-Programmierer nicht weiter interessieren. Hier sind ein paar Beispiele:
(set! grey_value 85) (set! angle (* (/ 30 180) 3.141)
Lisp und seine verschiedenen Spielarten machen einen starken Gebrauch von Listen. Script-Fu macht dabei keine Ausnahme. So werden die drei RGB-Farbwerte, zum Beispiel für die Farbe Orange, in Listenform geschrieben:
'(255 127 0)
Das einfache Hochkomma ' signalisiert dabei, daß es sich bei dieser Liste um ein Literal handelt. Wird das einfache Hochkomma weggelassen, versucht Scheme das erste Listenelement (hier die 255) als Funktion zu interpretieren und die restlichen Werte als dessen Aufrufparameter. Das ist aber wirklich nicht das was wir wollen.
Wir können jetzt die Variable "orange" defnieren und diese Variable benutzen, um in Gimp die Hintergrundfarbe zu setzen:
(set! orange '(255 127 0)) (gimp-set-background-color orange)
Eine Liste besteht in Scheme immer aus einem Listenkopf und dem Listenende. Der Kopf ist das erste Listenelement und das Listenende ist eben der Rest der Liste. Das bedeutet daß die Liste (255 127 63) auch so geschrieben werden kann ((255 (127 (63 ()))). Scheme unterstützt aber (dem Lisp-Entwickler sei Dank) die vorangeschriebene Möglichkeit der Kurzform. Die Funktion "car" stellt den Listenkopf bereit und die Funktion "cdr" (gesprochen "kadder", english: cudder) das Listenende.
[Die folgenden Anweisungen sind ein Test obenstehender Funktionen, die interaktiv in das Eingabefeld der Script-Fu Konsole eingetippt werden.]
=> (set! color '(255 127 63)) (255 127 63) => (car color) 255 => (cdr color) (127 63)
Um den Wert der blauen Farbkomponente (3. Listenelement) zu erhalten, ist es notwendig, die Funktion "cdr" zweimal und die Funktion "car" zuletzt anzuwenden.
=> (car (cdr (cdr color))) 63
Dies ist aber eher eine unübliche Schreibweise. Das liegt daran, daß für diese Funktionsfolgen Kurzformen existieren und zwar in der Form cadr, cddr, caddr usw. usw.. Sie verketten die Funktionen car und cdr in entsprechender Weise. Somit können wir die obenstehende Anweisung auch wie folgt formulieren:
=>(caddr color) 63
Für einen Script-Fu Programmierer stellt die Funktion car eine der wichtigsten Funktionen überhaupt dar. Sie wird benötigt, um den Rückgabewert von Built-In-Funktionen in Gimp zu erhalten. Alle Gimp-Funktionen liefern eine Liste zurück. Auch wenn die Liste nur aus einem Element besteht, erfolgt der Zugriff über die Funktion "car". Das ist zum Beispiel in den nachfolgenden Beispielen der Fall, bei denen die Funktionen gimp-new-image und gimp-new-layer benutzt werden.
Der mehr erfahrene Scheme-Programmierer setzt jedoch mehr lokale anstatt globale Variable ein. Das steht außerdem für eine bessere Programmierpraxis und diese Konstruktion sollte auch dem Vorzug gegeben werden.
Lokale Variable werden mittels des Schlüsselwortes "let*" deklariert, wie zum Beispiel:
(let* ((a 3) (b 4)) ((* a b)) )
Hier haben die Variablen "a" und "b" einen ausschließlich lokalen Geltungsbereich und besitzen ihre Werte nur innerhalb der einschließenden Klammern von let*.
5. Die prozedurale Gimp-Datenbank (Gimp PDB)
Die vollständige Funktionalität von Gimp ist über die prozedurale Gimp-Datenbank (PDB = procedural database) erreichbar. Jede Funktion in der PDB korrespondiert mit einer Scheme Funktion wie zum Beispiel:
(gimp-image-new 100 150 RGB)
Dieser Aufruf liefert ein neues Gimp-Bild vom RGB-Typ und einer Größe von 100x150 Pixeln.
In Gimp ist ein Browser zur Anzeige aller PDB-Funktionen vorhanden. Diese Anzeige ist über das Menü des Werkzeug-Fenster Xtns->DB BROWSER erreichbar. So sieht zum Beispiel die Anzeige der Funktion uni-img, die weiter unten definiert werden wird, im DB-Browser aus:
Das zeigt zum Beispiel einem Scheme-Programmierer, daß die Funktion uni-img mit drei Parametern aufgerufen wird, die vom Typ INT32, STRING und COLOR sind. Was diese Typangaben bedeuten, wird weiter unten erklärt.
6. Registrierung des Script-Fu Programms
Bevor ein kodiertes Script-Fu Programm in Gimp benutzt werden kann, ist es zu registrieren. Die Registrierung erfüllt folgende Aufgaben:
Insbesondere der obengenannte Punkt 3 bedeutet aus der Sicht von Gimp, daß es keinen Unterschied von einem Built-In- oder einem Plug-In-Kommando gibt. Sobald ein Kommando in der Gimp-PDB registriert ist, ist es durch jedes beliebige Script oder Plug-In-Kommando aufrufbar.
Die Parameter von script-fu-register teilen sich in zwei Gruppen auf. Die erste Gruppe besteht aus sieben Parametern und sind zwingend notwendig. Diese Parameter sind:
Nach diesen sieben Parametern folgt eine Liste von Parametern, die das Script für seine Funktionalität benötigt. Jeder Parameter besteht aus drei Termen, dem Parameter-Typ, dem Prompt-Text und einem Standardwert.
Typische Parameter sind zum Beispiel SF-VALUE, SF-STRING, SF-FONT, SF-COLOR, SF-TOGGLE, SF-IMAGE, SF-DRAWABLE.
Eine ausführliche und aktuelle Tabelle ist im Script-Fu-Handbuch 1 zu finden (http://www.gm4t9.de/gimp/tut01/lesson4.html
Das folgende Script uni-img.scm erhält zwei Parameter beim Aufruf, eine Bildgröße und einen Farbwert. Es erzeugt ein unifarbenes Bild in der gewünschten Größe und Farbe. Es ist nicht besonders bedeutungsschwanger, aber es zeigt wesentliche Schritte, um ein Script-Fu Programm zu schreiben:
uni-img.scm |
---|
1: ; Definiert die Funktion mit seinen Parametern 2: ; Die Parameter stimmen mit den Parametern überein, 3: ; die unten bei "script-fu-register" aufgeführt sind. 4: 5: (define (uni-img size color) 6: 7: ; Erzeugt ein Bild und eine Ebene 8: (set! img (car (gimp-image-new size size RGB))) 9: (set! layer (car (gimp-layer-new img size size RGB "layer 1" 100 NORMAL))) 10: 11: ; Die folgenden Schritte werden für alle Scripts gemacht 12: (gimp-image-undo-disable img) 13: (gimp-image-add-layer img layer 0) 14: 15: ; Hier beginnen wir mit dem Gestalten. Wir haben ein Bild und eine 16: ; Ebene und können mit Hilfe der geeigneten PDB-Funktion das Bild 17: ; ausfüllen 18: (gimp-palette-set-background color) 19: (gimp-edit-fill layer) 20: 21: ; Die folgenden Schritte werden ebenfalls für alle Scripts gemacht 22: (gimp-display-new img) 23: (gimp-image-undo-enable img) 24: ) 25: 26: ; Schließlich registrieren wir unser Script in Script-Fu 27: (script-fu-register "uni-img" 28: "<Toolbox>/Xtns/Script-Fu/Test/Uniform image..." 29: "Creates a uniform image" 30: "Dov Grobgeld" 31: "Dov Grobgeld" 32: "1997" 33: "" 34: SF-VALUE "size" "100" 35: SF-COLOR "color" '(255 127 0) 36: ) |
Um das Script zu testen, ist es in das Verzeichnis $HOME/.gimp/scripts/ zu kopieren und Die REFRESH-Funktion in Xtns/Script-Fu zu aktivieren. Das Script Uniform image sollte nun im Pulldown-Menü in Script-Fu->Test->Uniform image... erscheinen. Mit dem Aufruf dieses Menüpunktes sollte folgendes Fenster auftauchen:
Werden die Standardparameter durch Drücken von OK akzeptiert, wird folgendes Bild gneriert:
Das gleiche Bild kann erzeugt werden, wenn in der Script-Fu Konsole folgendes Kommando eingetippt wird:
(uni-img 100 '(0 255 127))
7.1. Einbinden des Script-Programms in das Image-Menü
Das Script uni-img.scm wurde unter Xtns des Gimp-Hauptmenüs plaziert. Dies geschah deshalb, weil das neue Bild unabhängig von anderen Bildern erzeugt wird. Es ist allerdings auch möglich ein Script zu schreiben, das ein bereits existierendes Bild bearbeitet. Wird in script-fu-register ein zweites Argument in der Form
<Image>/Script-Fu/...
geschrieben, dann wird die Funktionalität des Scriptes im Gimp-Menü verfügbar, wenn die rechte Maustaste über dem existierenden Bild gedrückt wird.
Hier kommt ein Beispiel-Script, welches eine Kopie der aktuellen Ebene in eine neue Ebene kopiert, eine Unschärfe darin erzeugt und danach die Ebene invertiert.
copy-blur.scm |
---|
1: (define (script-fu-copy-blur img drawable blur-radius) 2: 3: ; Erzeugen einer neuen Ebene 4: (set! new-layer (car (gimp-layer-copy drawable 0))) 5: 6: ; Ebene mit einem Namen versehen 7: (gimp-layer-set-name new-layer "Gauss-blurred") 8: 9: ; Die neue Ebene zum Bild hinzufügen 10: (gimp-image-add-layer img new-layer 0) 11: 12: ; Das Blur-Plug-In (Gauss) aufrufen, um die Unsärfe zu erzeugen 13: (plug-in-gauss-rle 1 img new-layer blur-radius 1 1) 14: 15: ; Invertieren der Bildebene 16: (gimp-invert new-layer) 17: 18: ; Ergebnis anzeigen 19: (gimp-displays-flush) 20: ) 21: 22: (script-fu-register "script-fu-copy-blur" 23: "<Image>/Script-Fu/Test/copy-blur..." 24: "Copy and blur a layer" 25: "Dov Grobgeld" 26: "Dov Grobgeld" 27: "1998" 28: "RGB*, GRAY*" 29: SF-IMAGE "Image" 0 30: SF-DRAWABLE "Layer to blur" 0 31: SF-VALUE "Blur strength" "5" 32: ) |
Im Script uni-img wurde die Prozedur gimp-edit-fill aufgerufen, um des gesamte Bild mit einer Farbe zu füllen. Wenn wir in die Information des DB-Browsers sehen, finden wir folgende Information:
Name: | gimp-edit-fill | ||
Blurb: | Fill selected area of drawable | ||
In: | drawable | DRAWABLE | The drawable to fill to |
Ist jedoch eine Bereichsselektion aktiv wenn die Funktion gimp-edit-fill aufgerufen wird, wird nur in diesen Bereich aufgefüllt. Es gibt viele Wege um eine Selektion zu aktivieren, wie man leicht mittels der "select"-Suche in der Gimp-PDB sehen kann. Wir werden die Funktion gimp-rect-select verwenden, die in der PDB-Info folgende Angaben zeigt:
Name: | gimp-rect-select | ||
Blurb: | Create a rectangular selection over the specified image | ||
In: | image | IMAGE | The image |
x | FLOAT | x coordinate of upper-left corner of rectangle | |
y | FLOAT | y coordinate of upper-left corner of rectangle | |
width | FLOAT | the width of the rectangle: 0 < width | |
height | FLOAT | the height of the rectangle: 0 < height | |
operation | INT32 | the selection operation: {ADD (0), SUB (1), REPLACE (2), INTERSECT (3) } | |
feather | INT32 | feather option for selections | |
feather_radius | FLOAT | radius for the feather operation |
Im folgenden Beispiel ist eine Bildselektion für ein Rechteck mit den Eigenschaften (x,y,breite,hoehe) = (0,25,10,50) kodiert.
(gimp-rect-select img 0 25 100 50 REPLACE 0 0) (gimp-palette-set-background '(0 0 255)) (gimp-edit-fill layer-one) (gimp-selection-none img)
Die einzige Schleifenkonstruktion, die in Script-Fu exisitiert, ist while.
[Hinweis: Diese Einschränkung gilt für den gegenwärtigen Scheme Interpreter SIOD, der für Script-Fu eingesetzt wird. Es ist geplant, auf den Guile-Interpreter umzusteigen, der möglicherweise mehr an Schleifenkonstrukten bietet.]
Die "while"-Schleife sieht folgendermaßen aus:
(while (condition) (statement1) (statement2) : )
Hier ist ein Beispiel, in dem horizontale Linien, 16 Pixel hoch, auf ein Bild gezeichnet werden:
(set! y 0) (while (< y size) (gimp-rect-select img 0 y size 16 REPLACE 0 0) (gimp-edit-fill layer-one) (set! y (+ y 32)))
10. "Floating Selection" - Die temporäre Arbeitsebene
Wird ein Bild von der Zwischenablage (Clipboard) eingefügt, oder wird ein Text in den Arbeitsbereich (Drawable) erzeugt, dann wird das Ergebnis nicht unmittelbar in diesen Bereich eingefügt. Stattdessen wird es in eine spezielle temporäre Arbeitsebene der sogenannten "Floating selection" abgelegt (oder schwebende Auswahl). Dieser Arbeitsbereich kann auf verschiedene Art und Weise nachbearbeitet werden und wird schließlich mit seiner zugeordneten Ebenen überlagert. Dieser Prozess ist auch als Verankern (anchoring) bekannt.
10.1. "Hello World" - einen Text in das Bild einfügen
Wird ein Text mittels der Funktion gimp-text erzeugt, wird er immer in den temporären Arbeitsbereich abgelegt, der abschließend verankert werden muß. Das wird hier im Beispiel gezeigt:
hello-world.scm |
---|
1: (define (script-fu-hello-world img drawable) 2: 3: ; Beginn einer UNDO-Gruppe. Die Aktionen zwischen diesem Beginn 4: ; und dem Ende werden bei einem UNDO rückgängig gemacht. 5: (gimp-undo-push-group-start img) 6: 7: ; Generieren eines Textes (vgl. Parameter im DB-Browser) 8: (set! text-float (car (gimp-text 9: img 10: drawable 11: 10 10 12: "Hello World" 13: 0 14: TRUE 15: 30 16: PIXELS 17: "*" "Helvetica" "medium" "r" "*" "*" "*" "*"))) 18: 19: ; Verankern des temporären Arbeitsbereiches (Floating selection") 20: (gimp-floating-sel-anchor text-float) 21: 22: ; Abschließen der UNDO-Gruppe 23: (gimp-undo-push-group-end img) 24: 25: ; Ausgabe bereitstellen 26: (gimp-displays-flush) 27: ) 28: 29: (script-fu-register "script-fu-hello-world" 30: "<Image>/Script-Fu/Test/Hello World" 31: "Write Hello World in the current image" 32: "Dov Grobgeld" 33: "Dov Grobgeld" 34: "1998" 35: "RGB*, GRAY*" 36: SF-IMAGE "Image" 0 37: SF-DRAWABLE "Layer" 0 38: ) |
Dieses Script zeigt eine weiteres neues Element, daß vorher noch nicht auftauchte, die UNDO-Gruppe. Alle Kommandos zwischen den Kommandos gimp-undo-push-group-begin und gimp-undo-push-group-end werden mit nur einem UNDO-Schritt rückgängig gemacht (sofern ein UNDO gemacht wird).
Um einen selektierten Bereich zu kopieren, wird das Kommando gimp-edit-copy verwendet. Es legt eine Kopie des selektierten Bereiches in die Zwischenablage ab. Der Inhalt der Zwischenablage kann dann zu einem späteren Zeitpunkt in die gleiche oder eine andere Ebene eingefügt werden. Nach dem Einfügen steht der Inhalt wieder im temporären Arbeitsbereich, der "Floating selection".
Im folgenden Beispiel wird der selektierte Bereich kopiert und in der gleichen Ebene mit einer festen Verschiebung wieder eingefügt und dann verankert. Die Wirkung kann in einem Beispielbild überprüft werden.
sel-copy.scm |
---|
1: (define (script-fu-sel-copy img drawable) 2: 3: (gimp-undo-push-group-start img) 4: 5: (gimp-edit-copy drawable) 6: (set! sel-float (car (gimp-edit-paste drawable FALSE))) 7: (gimp-layer-set-offsets sel-float 100 50) 8: 9: ; Anchor the selection 10: (gimp-floating-sel-anchor sel-float) 11: 12: ; Complete the undo group 13: (gimp-undo-push-group-end img) 14: 15: ; Flush output 16: (gimp-displays-flush) 17: ) 18: 19: (script-fu-register "script-fu-sel-copy" 20: "<Image>/Script-Fu/Test/Selection Copy" 21: "Copy the selection into the same layer" 22: "Dov Grobgeld" 23: "Dov Grobgeld" 24: "1998" 25: "RGB*, GRAY*" 26: SF-IMAGE "Image" 0 27: SF-DRAWABLE "Layer" 0 28:) |