HBS GIMP 2 13 Skripte Jannik Quehl Und noch ein weiteres Mal darf ich mich an dieser Stelle zu Wort melden, um ein wenig über das Erstellen von eigenen Filtern und Gimp-Skripten zu erzählen. Alle Angaben in diesem Kapitel beziehen sich nicht mehr auf Gimp 2.2, sondern auf Gimp 2.4. Jedoch gibt es, was dieses Kapitel angeht, keine nennenswerten Unterschiede zwischen beiden Versionen, abgesehen davon, dass sich Script-Fu nun unter „Filter“ statt unter „Extras“ in der Menüleiste befindet. Im Kapitel 12 haben wir bereits Filter kennengelernt. Gimp hat bereits eine große Anzahl von zum Teil praktischen, zum Teil weniger nützlichen Filtern vorinstalliert und wenn der Filter, den man sucht nicht vorhanden ist, so ist er doch meist im Internet nach kurzer Suche gefunden. Jedoch haben es die Entwickler von Gimp dem User freigestellt, sich selber auch an der Programmierung von Filtern und Routinen für Gimp zu versuchen. Script-Fu (bzw. in der Deutschen Gimp-Version Skript-Fu) heißt das Zauberwort, das dies möglich macht. Was ist Skript-Fu? Unter dem Namen Script-Fu versteht Gimp die Möglichkeit mittels Scheme-Programmierung auf die Gimp-eigene Datenbank zuzugreifen und so bestimmte Abläufe zu automatisieren. Grundsätzlich sind hier Gimp keine Grenzen gesetzt. Script-Fu kann alle Funktionen, Filter und Plugins von Gimp aufrufen und hat so beinahe so viele Möglichkeiten wie der Nutzer selbst. Das Einzige, was sich der Automatisierung weitestgehend entzieht, ist der freie Umgang mit den Werkzeugen, da diese per Hand bewegt und angewendet werden und so schwierig zu automatisieren sind. Eine Automatisierung mittels Script-Fu ist insbesondere dann sinnvoll, wenn sie − regelmäßig ausgeführt werden sollen, oder − kompliziert in der Ausführung und so schwer zu merken sind. Gimp selbst hat bereits etliche Plugins vorinstalliert, die alle auf Script-Fu-Basis programmiert sind und als Orientierung für eigene Scripte dienen können. Sie sind aber auch hilfreich als Vorlage zum Lernen der Programmierung eigener Script-Fu-Plugins. Wo sich diese Plugins befinden und von wo die eigenen Plugins geladen werden, kann ganz einfach unter Bearbeiten => Einstellungen => Ordner => Skripte eingesehen und eingestellt werden. 163 HBS GIMP 2 Weitere solche Skripte gibt es in großen Mengen im Internet zu finden. Ihre Installation ist sehr einfach: Gimp lädt bei jedem Start alle Skripte im richtigen Format aus den in den Einstellungen angegebenen Ordnern. Das heißt, wenn ein bestimmtes Skript aus dem Internet in Gimp geladen werden soll, muss es entweder in einen entsprechenden Ordner gepackt werden, oder es muss der das Skript beinhaltende Ordner in die Ordnerliste eingefügt werden. Anschließend kann man entweder Gimp neu starten, oder – was die einfachere Methode ist, wenn Gimp gerade läuft – man wählt unter Filter => Skript-Fu => Skripte auffrischen, um alle Filter und Skripte neu laden zu lassen. Das richtige Format für solche Scripte ist das .scm – Format, das aber im Prinzip ein normales Textdokument ist, dessen Endung von .txt zu .scm geändert wurde und den Quelltext des Skriptes enthält. Die Standard-Sprache für Script-Fu-Programmierung ist Scheme, jedoch kann Gimp per Plugin auch noch weitere Sprachen, wie Perl oder Tcl „lernen“. Diese werde ich jedoch in diesem Kapitel nicht behandeln. Im Folgenden werde ich eine kurze Einführung in die Programmiersprache Scheme geben und anschließend anhand eines Beispieles zeigen, wie das Ganze dann als Gimp-Script aussieht und wie man dann damit arbeitet. Scheme Scheme ist eine Variation von der Programmiersprache LISP. Scheme folgt dem Prinzip der Präfixnotation. Das heißt, dass alle Funktionen bzw. Operatoren vorangestellt werden. Alle Anweisungen in Scheme stehen in runden Klammern. Hierbei ist das erste Element der Liste immer die eigentliche Funktion, während die nachfolgenden Elemente Parameter der Funktion sind. Auch mathematische Operatoren, wie +, -, *, / gelten als Funktionen und müssen ebenso als erstes Element der Klammer stehen. Eine einfache Addition der Zahlen 2 und 7 sieht also in Scheme so aus: (+ 2 7 ) Jedoch ist der Operator + nicht auf 2 Parameter beschränkt. Außerdem ist es möglich, eine weitere Klammer mit einem weiteren Operator als Element der Liste zu benutzen. Daher sind auch Rechnungen möglich, wie: (+ 5 3 (* 4 (- 3 1 )) 1) 164 HBS GIMP 2 Für uns Programmierer hält Gimp dabei ein besonderes Tool bereit, das uns ermöglicht ein wenig mit Scheme zu experimentieren: Die Konsole. Unter Filter => Skript-Fu => Konsole, bekommt man die Möglichkeit einzeilige Scheme-Anweisungen auszuprobieren und auf ihre Richtigkeit zu überprüfen. Geben wir also unsere beiden ersten Rechnungen ein, so erhalten wir von Gimp sofort die Ergebnisse. Auffällig ist hierbei, dass die Klammern von innen nach außen aufgelöst werden. Eine Punkt-Vor-StrichRegel gibt es nicht, da immer nur ein Operator in einer Klammer steht und erst die inneren Klammern ausgeführt werden. Wichtig ist dabei, dass man auf korrekte Leerzeichen achtet. Bei vielen anderen Programmiersprachen, wie C, C# oder auch Java und Perl ist es erlaubt Leerzeichen weitestgehend nach Belieben zu setzen. Nicht so in Scheme. Während bei C# zum Beispiel auch so etwas erlaubt ist, wie: 3+4 , muss bei Scheme nach dem Operator unbedingt ein Leerzeichen folgen: (+ 3 4) Andernfalls würde Scheme nicht nach dem Operator + in seiner Datenbank suchen, sondern nach der Funktion +3 , welche er natürlich nicht finden würde. Um mit Scheme ein wenig vertraut zu werden, empfiehlt es sich, erst einmal ein paar einfache Rechenoperationen auszuführen oder vielleicht ein paar Mathematikaufgaben statt mit dem Taschenrechner mit Scheme zu lösen. Nach einigem Herumprobieren, wird man sogar feststellen, dass Scheme selbst trigonometrische Rechnungen mühelos bewältigt, so lange man sich an die richtige Form hält. Variablen in Scheme Wie in allen anderen gewöhnlichen Programmiersprachen auch, kann man in Scheme ebenfalls Variable benutzen. Die einfachste Methode mit Variablen zu arbeiten ist ein let*Konstrukt. Mit let* können lokale Variablen festgelegt werden, welche innerhalb dieses Konstruktes gültig sind. Das let* - Konstrukt besteht aus 2 Teilen. Im ersten Teil ist es dem User möglich die Variablen zu deklarieren, während im 2. Teil des Konstruktes diese Variablen dann verwendet werden können. Die Struktur sieht also so aus: (let* ( Deklaration der Variablen) Arbeiten mit den Variablen ) 165 HBS GIMP 2 Dabei ist es egal, ob das ganze als Einzeiler eingegeben wird, oder in mehreren Zeilen – was in der Gimp-Konsole jedoch nicht möglich ist. Wir können jetzt zum Beispiel einfach mal zwei Variablen A und B mit den Zahlen 5 und 2 belegen und anschließend miteinander multiplizieren. Das sähe dann so aus: (let* ( (A 5) (B 2) ) (* A B) ) Was sagt die Gimp-Konsole? 10 – die Rechnung hat funktioniert. Jeder, der bereits mit anderen Programmiersprachen Kontakt hatte, wird aufgefallen sein, dass nirgends festgelegt wurde, was für ein Typ die Variablen sind. Sind sie eine Zeichenkette (String) ? Oder eine Zahl (Double, Int64 etc.)? Sind sie lediglich mit TRUE oder FALSE belegt (Boolean)? Die Antwort ist: Es ist egal! Scheme ist eine typfreie Sprache. Man kann Variablen erst mit einer Zahl belegen, dann mit gleich mehreren Zahlen in einer Liste und auch Zeichenketten können auf Variablen gelegt werden – alles ohne irgendwann einen Typ in einen anderen konvertieren zu müssen. Dies spart einiges an Zeit, da nicht ständig hin und her konvertiert werden muss, jedoch kann es nach wie vor zu Fehlern kommen, wenn eine Funktion mit falschen Parametern gefüttert wird. Nach der Deklaration einer Variablen, kann der Variablen innerhalb des let*-Konstruktes jederzeit ein neuer Wert zugewiesen werden. Dies passiert mit der set!-Anweisung. Im Folgenden sehen sie, wie der Variablen „dieZahl“ erst der Wert 10 zugeordnet wird... und dann? (let* ( (dieZahl 5) ) (set! dieZahl (+ dieZahl dieZahl) ) ) zur Übung: Gebt diese Zeile in die Gimp-Konsole ein und überlegt euch, was herauskommen muss, bevor auf Enter gedrückt wird. Waren eure Vermutungen richtig? Nicht nur eigene Variablen, sondern auch eigene Funktionen können in Scheme deklariert werden. Dies passiert mit define ganz ähnlich, wie beim let*-Konstrukt: (define ( Funktionsname Parameterliste ) Was soll die Funktion tun? ) Auch hier ist es gleichgültig, ob wir eine Zeile, oder mehrere Zeilen verwenden. 166 HBS GIMP 2 Um zum Beispiel eine Funktion namens Plus, die einfach zwei Zahlen addiert, zu definieren und anschließend auf die Zahlen 7 und 8 anzuwenden müsste man Folgendes in die Gimp-Konsole eingeben: (define (Plus A B) (+ A B) ) Anschließend gibt man dann nur noch (Plus 7 8) ein und erhält sofort als Ergebnis 15. Wer sich bereits mit Programmieren einigermaßen auskennt, dem fällt sofort auf, dass wir keine Angaben darüber gemacht haben, was diese Funktion letzten Endes ausgeben soll. Scheme gibt immer das Ergebnis der letzten Anweisung innerhalb der Funktion aus. Listen Ein weiteres wichtiges Element für die Script-Fu Programmierung sind Listen. Die meisten Gimp-Funktionen geben als Ergebnis keine konkreten Werte aus, sondern stattdessen Listen. Listen sind – wie der Name bereits vermuten lässt – eine Aneinanderreihung von mehreren Elementen. Diese Elemente können Zeichenketten, Zahlen und sogar selber eigene Listen sein. Eine Liste muss nicht einmal nur Elemente der gleichen Art beinhalten und Listen können selber auch auf Variablen geschrieben werden. Eine Liste deklariert man mit '(). Das sieht dann zum Beispiel so aus: '(1 2 3) Um innerhalb einer Liste eine weitere Liste zu deklarieren, wird das ' nicht noch ein weiteres Mal benötigt: '(1 (2 3) 4) Neben '(Listenelemente) gibt es noch weitere Möglichkeiten Listen zu erzeugen, wie die cons-Anweisung, welche zwei Listen verbindet, oder die list-Anweisung, welche die Werte der Variablen als Listenelemente ausliest, jedoch interessieren die im Rahmen dieser Einleitung nicht. Wichtig jedoch ist noch die Art und Weise auf die man einzelne Listenelemente auslesen kann. Eine Liste muss man sich als aus zwei Teilen bestehend vorstellen: Dem ersten Element, dem Kopf und dem Rest der Elemente dem Schwanz. Der Befehl car liest den Kopf der Liste aus, während der Befehl cdr den Schwanz ausliest. Um ein bestimmtes Element der Liste auszulesen, kombiniert man jetzt diese beiden Befehle, um sich zum richtigen Glied durchzuarbeiten. 167 HBS GIMP 2 Dabei kann man (car (cdr (cdr '(1 2 3 4 5) ) ) ) (das erste Element des Restes des Restes – also 3) auch schreiben als: (caddr '(1 2 3 4 5) ) wobei beliebig viele a bzw. d zwischen das c und das r eingefügt werden können. Skript – Fu So viel zu Scheme allgemein. Wie sieht das ganze jetzt konkret aus, wenn wir einen Filter programmieren wollen? Für diese Einführung habe ich mich dafür entschieden einen relativ einfachen Schrifteffekt zu automatisieren: Dabei darf der Benutzer eine ganze Menge eingeben: 1. Was soll da stehen? 2. Welche Schriftart soll verwendet werden? 3. Welche Textgröße? 4. Schriftfarbe? 5. Hintergrundfarbe? 6. Die Farbe des inneren Glühens? 7. Die Farbe des äußeren Glühens? 8. Die stärke des Gaußschen Weichzeichners 9. Der Radius des Glühens 10. Wie viel Platz soll außen herum gelassen werden? 11. Sollen am Ende alle sichtbaren Ebenen vereint werden? Der Vorgang ist schnell erklärt: Es wird ein Text erstellt, aus dessen Alphakanal eine Auswahl erstellt wird. Die Auswahl wird vergrößert und in einer neuen Ebene mit der Farbe des inneren Glühens gefüllt. Anschließend wird die Auswahl erneut vergrößert und wieder in einer neuen Ebene mit der Farbe des äußeren Glühens gefüllt. Die Bildgröße wird an die Größe der Textebene angepasst und die beiden neuen Ebenen werden weichgezeichnet. Zum Schluss muss nur noch die Hintergrundfarbe angepasst und die Ebenen in die richtige Reihenfolge gebracht werden. 168 HBS GIMP 2 Versuchen wir also das ganze umzusetzen. Um mit Scheme zu programmieren müssen wir uns zuerst einmal ein dafür geeignetes Programm zulegen. Prinzipiell reicht dafür jedes Programm, das .txt – Dateien öffnen und bearbeiten kann. (wie z.B. der Editor für Windows) Ich persönlich favorisiere das Notepad++, ein einfaches Freeware-Tool, das einfache Strukturen, wie zum Beispiel Klammern erkennt und so eine gute Strukturierung des Quellcodes ermöglicht. Mit diesem – oder einem anderen – Editor öffnen wir jetzt einfach ein neues leeres Textdokument (.txt) und benennen es so um, dass die Endung nun .scm lautet. Alles was wir jetzt an diesem Skript programmieren wird in dieser Datei abgespeichert. Um das Skript anschließend auszuprobieren, muss es, wie oben beschrieben, in den Skript-Ordner von Gimp kopiert werden. Beginnen wir also nun mit der Erstellung des Skriptes. Ein Skript-Fu-Skript braucht allgemein folgende Elemente: 1. Die Definition der Hauptfunktion des Skriptes, die aufgerufen wird, sobald das Skript gestartet wird 2. Einen Aufruf der script-fu-register Anweisung, die angibt, was der User selber eingeben darf und wie sich das Script dem Benutzer präsentiert. Diese Funktion wird benötigt um das Skript in der Gimp-Datenbank zu registrieren und so den Zugriff von Gimp aus zu ermöglichen 3. Einen Aufruf der script-fu-manu-register Anweisung, welche angibt, wo man das Skript in Gimp finden kann Wo diese Elemente sich im Skript befinden ist irrelevant, ich stelle sie jedoch voran an den Anfang des Skriptes, damit ich diese Elemente und den Rest auch optisch auseinander halten kann. Anmerkung: Im Folgenden werde ich die wesentliche Vorgehensweise, sowie den Aufbau meines Skriptes beschreiben, werde dabei jedoch nicht mein gesamtes Skript hier durchgehen. Am Ende dieses Kapitels findest Du (aus Platzgründen) die undokumentierte Version des Skriptes. Die ausführlich dokumentierte fertige scm-Datei kann gesondert heruntergelassen werden. Fangen wir also an: Als erstes wird die Registrierung des Skriptes bei Gimp vorgenommen. Dafür rufen wir die Gimp-Funktion script-fu-register auf. Die Parameter dieser Funktion beschreiben als erstes wesentliche Eigenschaften des Skriptes, während die nachfolgenden definieren, was der Benutzer auf welche Art und Weise eingeben darf: 169 HBS GIMP 2 der erste Teil: (script-fu-register "script-fu-text-glowing" "Gluehende Schrift" "Erstellt einen einfachen Text\ und fuegt ihm ein Glühen hinzu" "Jannik Quehl" "Copyright (c) 2008 Jannik Quehl." "Dezember 2008" "" Als erstes steht der Name der Funktion, die von uns im Skript definiert werden wird. Der zweite Parameter gibt dem ganzen Skript einen Namen Es folgt eine kurze Beschreibung des Skriptes. \ gibt dabei einen Zeilenumbruch wieder. Als nächstes darf sich der Autor des Skriptes verewigen. Dann kommen Anmerkungen zum Copyright. (z.B. nach der GPL) Der sechste Parameter soll sagen, wann das Skript erstellt wurde. Und der letzte hier angegebene Parameter soll sagen, auf welchen Bildtypen dieses Skript arbeitet. (RGB, GRAY etc.) Da durch dieses Skript ein neues Bild erstellt wird, können wir dieses Feld frei lassen. Anschließend gibt jeder weitere Parameter eine Eingabemöglichkeit für den Benutzer an. Als erstes gibt man dabei an, um was für eine Art von Eingabemöglichkeit es sich handelt. Als nächstes erfolgt die Beschriftung dieser Eingabe und als letztes erfolgen die Voreinstellungen: SF-STRING SF-FONT SF-ADJUSTMENT SF-COLOR SF-COLOR SF-COLOR SF-COLOR SF-ADJUSTMENT SF-ADJUSTMENT SF-ADJUSTMENT SF-TOGGLE "Text" "Hallo" "Schriftart" "Arial Bold" "Textgroesse" '(50 1 1000 1 10 0 1) "Schriftfarbe" '(0 0 0) "Hintergrundfarbe" '(0 0 0) "Gluehen 1" '(255 255 255) "Gluehen 2" '(0 0 255) "Weichzeichnen" '(10 1 100 1 10 1 0) "Gluehradius" '(2 1 20 1 10 1 0) "Platz aussen" '(100 0 300 1 10 1 0) "Sichtbare Ebenen vereinen?" TRUE ) SF-STRING gibt hier zum Beispiel an, dass die Eingabemöglichkeit eine einfache Textbox ist, in welcher als Text bereits „Hallo“ eingetragen ist. Beschriftet ist die Box mit „Text:“ wobei der Doppelpunkt von Gimp automatisch hinzugefügt wird. 170 HBS GIMP 2 Auf der Abbildung rechts kann man sehen, welcher Art von SF-Parametern welche Eingabemöglichkeit als Resultat hat. Auffällig ist, dass sowohl der Parametertyp SFCOLOR, als auch SF-ADJUSTMENT aus Listen bestehen, welche von Gimp eingelesen werden. Bei SF-COLOR entsprechen die drei Elemente den Farbwerten der RGB – Farben (nein, nicht rosa, grau, braun, sondern Rot, Grün, Blau). Bei SF-ADJUSTMENT gibt das erste Element die Voreinstellung an, das 2. das Minimum, das 3. das Maximum der einstellbaren Werte. Element 4 gibt die Schrittgröße an in der der Wert verstellt wird, wenn die kleinen Pfeile verwendet werden. Das Element 5 gibt die Schrittgröße an wenn Bild hoch / runter verwendet wird und Element 6 sagt die Anzahl der Nachkommastellen an. Der letzte Wert gibt an, was für eine Eingabeart verwendet werden soll. (zum Vergleich Textgröße hat den Wert 1, die anderen SF-Adjustment den Wert 0) Als nächstes müssen wir Gimp sagen, wo es das Skript hin packen soll. Das machen wir dieses Mal mit der Funktion script-fu-menuregister. (script-fu-menu-register "script-fu-text-glowing" "<Toolbox>/Xtns/Skript-Fu/Text") Der erste Parameter hierbei ist der Name der Funktion dieses Skriptes. Der zweite gibt den Pfad an. Bei diesem Beispiel erscheint das Skript unter Filter => Skript-Fu => Text => Gluehende Schrift. Die letzte Anweisung, die unbedingt benötigt wird, um ein Skript-Fu-Skript auszuführen, ist das Definieren der eigentlichen Funktion. Dies geschieht, wie oben bereits geschrieben mit dem Befehl define. Zusätzlich zum Namen der Funktion unter dem Gimp dieses Skript ausführen kann, müssen in der Define-Anweisung alle Parameter angegeben werden mit denen das Skript arbeiten wird. Damit alle Eingaben des GUI richtig verarbeitet werden, muss die Reihenfolge der Parameter dieselbe sein, wie die der Eingaben in der Funktion script-fu-register (siehe oben). Bei meinem Script sieht das ganze dann so aus: 171 HBS GIMP 2 (define (script-fu-text-glowing inText inSchriftart inTextgroesse inSchriftfarbe inHintergrundfarbe inGluehen1 inGluehen2 inWeichzeichnen inGluehradius inPlatzaussen inVereinen) ;hier kommt alles rein was die Funktion tun soll ) Kurz zur Namensgebung: Um beim Programmieren der Funktion nicht durcheinander zu kommen, benenne ich alle Eingabewerte, die an die Funktion als Parameter gegeben werden, mit der Vorsilbe „in“. (z.B. inText als Eingabe des SF-STRING Wertes) Lokalen Variablen hingegen, welche ich später in der let*-Funktion definiere, werde ich jeweils ihren Artikel als Vorsilbe voranstellen, um sie eindeutig erkennen und ihre Namen einfacher merken zu können. (z.B. dieBildbreite als Variable auf die später die breite des Bildes in Pixeln gelegt wird) Natürlich ist jedem freigestellt, seine Parameter und Variablen nach eigenem Belieben zu benennen, jedoch kann ich empfehlen, sich dabei an bestimmte selbst festgelegte Regeln zu halten, damit eine gewisse Ordnung erhalten bleibt und das Skript leicht zu verstehen ist. Außerdem wird bereits aufgefallen sein, dass ich Umlaute, sowie das ß innerhalb des Skriptes vermeide. Gimp hat nämlich mit Sonderzeichen so seine Probleme und stellt diese meistens nicht korrekt dar. Bevor wir nun jedoch zu dem Punkt kommen, an dem wir sagen müssen, was tatsächlich getan werden soll, müssen wir erst noch unsere Variablen definieren. In meinem Skript habe ich das ganze, wie oben beschrieben, mit lokalen Variablen und der let* - Funktion verwirklicht. Wir basteln uns also eine let*-Struktur zusammen und fangen an unsere Variablen zu deklarieren: (let*( (dieBildbreite 5) (dieBildhoehe 5) (derText) (derFreiraum) (dasGluehen1) (dasGluehen2) (derRadius) (dasBild(car (gimp-image-new dieBildbreite dieBildhoehe RGB) ) ) (dieEbene1 (car (gimp-layer-new dasBild dieBildbreite dieBildhoehe RGB-IMAGE „ebene 1“ 100 Normal) ) ) ) ;hier kommt dann hin, was mit den Variablen angestellt werden soll ) 172 HBS GIMP 2 Wir haben in diesem Skript also jetzt insgesamt neun Variablen deklariert, die wir nun im 2. Teil der let*-Struktur zum programmieren benutzen können. Vier der Variablen haben in der Deklaration auch gleich noch einen Wert zugeordnet bekommen: dieBildbreite und dieBildhoehe haben jeweils den Wert 5 zugewiesen bekommen. Mit diesen beiden Werten wurde mit Hilfe der Gimp-Funktion gimp-image-new Funktion ein neues Bild erstellt, das vorerst nur die Größe 5 x 5 Pixel besitzt und auf die Variable dasBild gelegt wird. Auch dieEbene 1 hat etwas zugewiesen bekommen, nämlich eine neue Ebene, welche im Bild dasBild angelegt wird. Wie man sieht, braucht man jetzt immer mehr gimpeigene Funktionen, da man sonst keine Möglichkeit hat mit Gimp zu kommunizieren. Jedoch kann sich wohl niemand alle Funktionen und Parameter merken, die die umfangreiche Gimp-Bibliothek zur Verfügung stellt. Doch zum Glück kann man bei Gimp alles was man wissen muss finden. Unter Hilfe => ProzedurenBrowser besteht nämlich die Möglichkeit sich alle Funktionen, die in Gimp bereits definiert sind, mit Parametern und Erklärung anzeigen zu lassen. Über die Suche des Prozedurenbrowsers finden sich so schnell alle Funktionen, die man benötigt. Zur Übung: Sucht im Prozeduren-Browser die Funktion gimp-layer-new, mit der wir dieEbene1 deklariert haben und versucht nachzuvollziehen, was die Parameter bedeuten, die in der Deklaration zu sehen sind. Nachdem wir also unsere Variablen deklariert haben, fangen wir nun endlich mit dem richtigen Programmieren an. Im 2. Teil der let*-Struktur kann man, wie bereits erklärt, nun mit den Variablen Programmieren. Das Programmieren sieht im Wesentlichen so aus, dass der Programmierer der Reihe nach die Gimp-Prozeduren angibt, die aufgerufen werden sollen. Dabei sollte man so strukturiert wie möglich vorgehen und am besten den gesamten Vorgang in mehrere Untervorgänge im Kopf aufzugliedern, die der Reihe nach durchlaufen werden. Denn der Programmierer muss sich bei der Eingabe jedes einzelnen Befehls bewusst sein, was bereits geschehen ist, was noch geschehen muss und welche Variablen dazu notwendig sind – eine gute Übersichtlichkeit ist da ein Muss. Mein Skript habe ich grob in 5 Schritte aufgeteilt: 1. Bild und Ebene zusammenfügen und die Textebene erstellen 2. Den meisten Variablen Werte zuweisen und die Bildgröße anpassen 3. Das äußere Glühen wird als Ebene eingefügt 4. Das innere Glühen wird als Ebene eingefügt 5. Die Glühebenen werden weichgezeichnet und alles, was noch nicht stimmt, wird korrigiert 173 HBS GIMP 2 Wie jeder Schritt im Detail aussieht, kann im beiliegenden Script eingesehen werden. Ich habe zu jedem Funktionsaufruf einen Kommentar hinzugefügt, der erklärt, was dort jeweils gemacht wird. Kommentare innerhalb des Quellcodes können eingefügt werden, indem man ihnen ein Semikolon (;) voran stellt. Alles was hinter dem ; steht, wird von Gimp ignoriert und dient lediglich der Erklärung des Skriptes. Mit den bisherigen Informationen sollten alle Schritte mit Hilfe des Prozeduren-Browsers für den (eifrigen) Leser dieses Skriptes nachzuvollziehen sein. Auf einen besonderen Punkt möchte ich zum Schluss noch eingehen: If-Abfragen Gegen Ende des Skriptes befindet sich eine etwas merkwürdige Anweisung: (if (= inVereinen TRUE) (gimp-image-merge-visible-layers dasBild EXPAND-AS-NECESSARY) ) Die if-Abfragen sind eine Möglichkeit bestimmte Zustände abzufragen. Die Struktur dabei ist: (if ( Bedingung ) Anweisung(en), die im Falle der erfüllten Bedingung ausgeführt werden soll ) In unserem Fall wird abgefragt, ob der Benutzer einen Haken gesetzt hat bei „Sichtbare Ebenen vereinen?“. Ist dies der Fall, soll Gimp am Ende alle Ebenen, die vom Skript erstellt wurden, vereinen und so zu einer einzigen zusammenzufügen. Ebenso können zum Beispiel bestimmte Werte abgefragt werden, oder geprüft werden, ob bestimmte Werte über oder unter einem bestimmten Wert liegen. Auch hierbei ist jedoch nie die Präfixnotation zu vergessen, die uns zwingt immer erst die Funktion nach der abgefragt wird (z.B. <, =, > ...) vor die eigentlichen Parameter zu stellen. Ausprobieren: Sobald das Skript lauffähig ist, kann das Skript, wie oben beschrieben, installiert werden. Sobald das Skript dann in Gimp aufgerufen wird, kann getestet werden, ob alles nach Wunsch funktioniert. Ich empfehle hierbei, das Skript auch vor seiner endgültigen Fertigstellung öfters in Gimp auszuprobieren, um immer schon zu wissen, ob man bereits Fehler gemacht hat, denn sobald die Grundstruktur des Skriptes steht, sollte es auch ohne Fehlermeldung ausgeführt werden können. In Zeiten der Trial-and-ErrorProblemlösung ist dies vermutlich sowieso der Weg den die Meisten einschlagen, um mit der Programmierung eigener Skripte voranzukommen. Wichtig ist nur, dass man die finale Version des Skriptes gründlich testet, indem man überprüft ob jede einzelne Benutzereingabe den gewünschten Effekt erzielt und ausprobiert, ob es nicht doch irgendwo zu einer Fehlermeldung kommen kann. Zusammenfassung: Hier noch einmal das einfachste Gerüst, aus dem sich das Skript 174 HBS GIMP 2 zusammensetzt, und nach dessen Vorbild man ebenfalls andere Skripte gestalten kann: (script-fu-register PARAMETER) (script-fu-menu-register PARAMETER) (define (Name_der_Funktion PARAMETER) (let* (VARIABLEN) ANWEISUNGEN ) ) Schlusswort: Gimp als Open-Source-Programm ist darauf angewiesen, dass es immer Leute gibt, die ohne finanzielles Interesse helfen wollen, Gimp weiterzuentwickeln und neue Fähigkeiten beizubringen. Photoshop ist nach wie vor die Referenz wenn es um professionelle Bildbearbeitung geht, doch ist Photoshop auch sehr teuer und für Hobby-Fotographen und Laien lohnt sich eine Anschaffung oft nicht. Mit Skript-Fu liegt es jedoch in der Hand jedes einzelnen Gimp-Nutzers das Programm ihrer Wahl auf eigene Faust zu verbessern und den eigenen Bedürfnissen anzupassen. Heute gibt es in verschiedenen Communities rund um Gimp unzählige Filter, Skripte und Plugins von Benutzern für Benutzer, die zum Teil großartige Arbeit leisten und manchmal sogar ihren Weg in das nächste Stable-Release von Gimp schaffen. (Man denke nur an das Siox-Plugin zum Freistellen von Objekten im Vordergrund) Das Ziel meiner kleinen Einführung in Skript-Fu ist es nicht einen perfekten Einblick in die Feinheiten der Programmiersprache Scheme zu geben, oder dem Leser beizubringen großartige Filter aus dem Ärmel zu schütteln. Stattdessen soll diese Einleitung nur andeuten, dass es prinzipiell jedem mit ein wenig Lernaufwand möglich ist, seine eigenen Ideen zur Fotobearbeitung in Gimp zu realisieren und die einfachsten Grundlagen hierfür festhalten. Wer Gefallen an Skript-Fu gefunden hat und mehr lernen möchte, dem kann ich nur empfehlen unterschiedliche Skripte anderer Programmierer durchzulesen und nachzuvollziehen. Ansonsten ist der beste Weg meiner Meinung nach immer noch der des learning-by-doing-Prinzips. (Man könnte zum Beispiel nach Tutorials für Gimp googlen und versuchen solche Tutorials mit Skript-Fu zu automatisieren) Meine persönlichen Favoriten, wenn es um Gimp und Skript-fu geht sind: http://gimpforum.de/ Eine nette Community rund um Gimp. (Hat ein tolles Gimp-Wiki mit vielen Tutorials) http://registry.gimp.org/ Ein sehr umfangreiches Archiv mit unzähligen Filtern, Plugins und Skripten. http://www.gimpusers.de/ Alles rund um Gimp. 175 HBS GIMP 2 Unkommentiertes Script: (Textboxscript.scm) (script-fu-register "script-fu-text-glowing" "Gluehende Schrift" "Erstellt einen einfachen Text\ und fuegt ihm ein Gluehen hinzu" "Jannik Quehl" "Copyright (c) 2008 Jannik Quehl." "Dezember 2008" "" SF-STRING "Text" "Hallo" SF-FONT "Schriftart" "Arial Bold" SF-ADJUSTMENT "Textgroesse" '(50 1 1000 1 10 0 1) SF-COLOR "Schriftfarbe" '(0 0 0) SF-COLOR "Hintergrundfarbe" '(0 0 0) SF-COLOR "Gluehen 1" '(255 255 255) SF-COLOR "Gluehen 2" '(0 0 255) SF-ADJUSTMENT "Weichzeichnen" '(10 1 100 1 10 1 0) SF-ADJUSTMENT "Gluehradius" '(2 1 20 1 10 1 0) SF-ADJUSTMENT "Platz aussen" '(100 0 300 1 10 1 0) SF-TOGGLE "Sichtbare Ebenen vereinen?" TRUE ) (script-fu-menu-register "script-fu-text-glowing" "<Toolbox>/Xtns/Skript-Fu/Text") (define (script-fu-text-glowing inText inSchriftart inTextgroesse inSchriftfarbe inHintergrundfarbe inGluehen1 inGluehen2 inWeichzeichnen inGluehradius inPlatzaussen inVereinen) (let* ( (dieBildbreite 5) (dieBildhoehe 5) (dasBild(car (gimp-image-new dieBildbreite dieBildhoehe RGB ) ) ) (derText) (derFreiraum) (dieEbene1 (car (gimp-layer-new dasBild dieBildbreite dieBildhoehe RGB-IMAGE "ebene 1" 100 NORMAL ) ) ) 176 HBS GIMP 2 (dasGluehen1) (dasGluehen2) (derRadius) ) (gimp-image-add-layer dasBild dieEbene1 0) (gimp-context-set-background inGluehen2 ) (gimp-context-set-foreground inSchriftfarbe) (gimp-drawable-fill dieEbene1 BACKGROUND-FILL) (set! derText (car (gimp-text-fontname dasBild -1 00 inText 0 TRUE inTextgroesse PIXELS inSchriftart) ) ) (set! dieBildbreite (car (gimp-drawable-width derText) ) ) (set! dieBildhoehe (car (gimp-drawable-height derText) ) ) (set! derFreiraum (* dieBildhoehe (/ inPlatzaussen 100) ) ) (set! dieBildhoehe (+ dieBildhoehe derFreiraum derFreiraum) ) (set! dieBildbreite (+ dieBildbreite derFreiraum derFreiraum) ) (gimp-image-resize dasBild dieBildbreite dieBildhoehe 0 0) (gimp-layer-resize-to-image-size dieEbene1) (gimp-layer-set-offsets derText derFreiraum derFreiraum) (gimp-selection-layer-alpha derText) (gimp-selection-grow dasBild (+ inGluehradius inGluehradius)) (gimp-edit-copy dieEbene1) (gimp-edit-paste dieEbene1 FALSE) (set! dasGluehen2 (car (gimp-image-get-floating-sel dasBild))) (gimp-floating-sel-to-layer dasGluehen2) (gimp-layer-resize-to-image-size dasGluehen2) (gimp-context-set-background inGluehen1 ) (gimp-drawable-fill dieEbene1 BACKGROUND-FILL) (gimp-selection-layer-alpha derText) (gimp-selection-grow dasBild inGluehradius) (gimp-edit-copy dieEbene1) (gimp-edit-paste dieEbene1 FALSE) (set! dasGluehen1 (car (gimp-image-get-floating-sel dasBild))) (gimp-floating-sel-to-layer dasGluehen1) (gimp-layer-resize-to-image-size dasGluehen1) (gimp-context-set-background inHintergrundfarbe ) (gimp-drawable-fill dieEbene1 BACKGROUND-FILL) (set! derRadius inWeichzeichnen) (plug-in-gauss-rle2 TRUE dasBild dasGluehen2 derRadius derRadius) (plug-in-gauss-rle2 TRUE dasBild dasGluehen1 derRadius derRadius) (gimp-image-raise-layer dasBild derText) (gimp-image-raise-layer dasBild derText) (if (= inVereinen TRUE) 177 HBS GIMP 2 (gimp-image-merge-visible-layers dasBild EXPAND-ASNECESSARY) ) (gimp-display-new dasBild) ) ) 178