>binaervarianz >projects >perl-gimp

Gimp ist das (!) freie Grafikbearbeitungsprogramm überhaupt. Einen Vergleich mit Photoshop braucht es vom Funktionsumfang nicht zu scheuen, kostet dafür aber nix und steht unter der GPL. Ein weitere Vorteil ist die beliebige Erweiterbarkeit durch Skripte. Dies ermöglicht es jedem, Gimp für sich und andere auszubauen. Als Standard-Skript-Sprache ist hierfür Scheme vorgesehen. Über Vor- und Nachteile dieser Sprache kann man denken was man will, für alle Perl-Freunde wurde jedenfalls eine Gimp-Perl-Erweiterung geschrieben.

Wie man diese nutzt, und sich somit bestimmte Arbeiten erleichtern kann möchte ich hier erklären, wobei zumindest grundlegende Perl-Kenntnisse vorausgesetzt werden. Ein typisches Beispiel sind grafische Buttons für eine Homepage. Möchte man diese per Hand erstellen, so muss man jeden Button einzeln machen, und das obwohl doch bis auf den Text alle gleich aussehen sollen. Nunja, auf Dauer sicher langweilig. Richtig ärgerlich wird das ganze beispielsweise dann, wenn die Buttons plötzlich etwas anders aussehen sollen (zum Beispiel eine andere Hintergrundfarbe haben sollen). Doch zum Glück kann man so etwas ja auch mit einem Skript erledigen...

Ich habe dieses Tutorial mit Gimp 1.2 unter Linux getestet, an Erfahrungen mit anderen Versionen bin ich natürlich interessiert. Wer das hier also unter anderen Bedingungen probiert hat, kann sich gerne mit Erfolgen oder Problemen bei mir unter <michael at binaervarianz dot de> melden.


Was wir brauchen

Erst einmal muss die Perl-Erweiterung für Gimp installiert sein. Diese ist bei jeder größeren Linux-Distribution dabei, bei Debian heißt das Paket gimp1.2-perl (für Gimp Version 1.2), woanders sicher ähnlich. Außerdem brauchen wir das Perl-Modul Gimp. Es gehört zu den Standard-Modulen und ist deshalb bei Debian im Paket perl-modules enthalten. Alternativ kann man es sich auch bei cpan.org besorgen.

In unser Skript eingebunden sieht das ganze dann wie folgt aus:

1 #!/usr/bin/perl -w
2 
3 use strict;
4 use Gimp ":auto";
5 use Gimp::Fu;

Neben dem obligatorischen "strict", brauchen wir das Haupt-Modul "Gimp". Mit ":auto" holen wir alle später benötigten Funktionen und Konstanten in unseren Namesraum. "Gimp::Fu" setzt auf "Gimp" auf und stellt eine relativ einfache Schnittstelle zur Verfügung.


Grundlegendes

Für alles, was man mit Gimp so machen kann gibt es eine Funktion. Eine Übersicht über diese Funktionen findet man in Gimp selbst im Menü: Xtns - PDB-Explorer. Alternativ kann auch der DB-Browser verwendet werden, wobei mir ersterer besser gefällt. Zu jeder Funktion werden die Ein- und Ausgabeparameter, eine Beschreibung sowie einige andere Angaben angezeigt. Sucht man beispielsweise nach gimp_image_new, so findet man folgende Einträge:

Befehl gimp_image_new
Beschreibung Creates a new image with the specified width, height, and type.
Eingabe-Parameter
INT32 width The width of the image
INT32 height The height of the image
INT32 type The type of the image: { RGB (0), GRAY (1), INDEXED (2) }
Ausgabe-Parameter
IMAGE image The ID of the newly created image

Die Parameter dieser Funktion haben die Typen INT32 und IMAGE. Insgesamt gibt es 22 solcher Typen, wobei manche dasselbe meinen - die folgende Übersicht empfehle ich erst einmal nur zu überfliegen, um später bestimmte Typen nachzuschauen:

Typ-Name Beispiel Bemerkung
PF_INT8
PF_INT16
PF_INT32
PF_INT
23 eine Zahl (wobei 8,16 und 32 die Größe des reservierten Speichers angeben), PF_INT ist dasselbe wie PF_INT32
PF_FLOAT 3.142 eine Fließkommazahl
PF_STRING
PF_VALUE
"Hallo Welt!" ein String
PF_COLOR
PF_COLOUR
#040CAF
[255, 0, 0]
eine Farbe, kann je nach Geschmack in zwei verschiedenen Formen angegeben werden
PF_IMAGE - ein Gimp-Bild
PF_DRAWABLE - ein Bild, eine Ebene oder ein Kanal
PF_TOOGLE
PF_BOOL
1 ein Boolscher Wert (wahr oder falsch)
PF_SLIDER - ein Integer-Wert, der durch einen Regler festgelegt wird
Anfangs- und Endwert, sowie die Schrittgröße können festgelegt werden
PF_SPINNER - dasselbe wie PF_SLIDER, nur dass der Wert nicht über einen Regler sondern einen Einstellungskreis gewählt wird
PF_RADIO - Auswahlbuttons
PF_FONT -b&h-lucida-medium-r-normal-
*-*-100-*-*-p-*-iso10646-1
eine Schriftart, angegeben im XLFD (X Logical Font Descriptor) - Format
PF_BRUSH Circle (15) (15 X 15) ein Pinsel
PF_PATTERN Craters (115 X 115) ein Muster
PF_GRADIENT Greens ein Farbverlauf
PF_CUSTOM - ein selbstdefinierbarer Typ
PF_FILE - ein File-System-Objekt, meist eine Datei, kann aber auch ein Verzeichnis oder ein Link sein
PF_TEXT Hallo Welt auch ein String, nur dass bei manueller Eingabe mehr Platz zur Verfügung steht, und "Laden" und "Speichern" Buttons vorhanden sind

Das erste Skript

Unser erstes Gimp-Skript wird ein Bild erzeugen, dessen Größe und Hintergrundfarbe festgelegt werden kann (atemberaubend - ich weiß ;-). Es besteht aus 2 großen Teilen, dem Register-Teil und einer Subroutine. Im Register-Teil werden allgemeine Dinge zum Skript festgelegt, während die Subroutine die auszuführenden Schritte beinhaltet.

bild-hg.pl:
 1 #!/usr/bin/perl -w
 2 
 3 use strict;
 4 use Gimp ":auto";
 5 use Gimp::Fu;
 6 
 7 sub bild_hg {
 8     # übergebene Werte in einzelne Variablen schreiben
 9     my ($size, $color) = @_;
10     
11     # neues Bild erzeugen
12     my $img = gimp_image_new($size, $size, RGB);
13     
14     # neue Ebene erzeugen
15     my $layer = gimp_layer_new($img, $size, $size,
                   RGB_IMAGE, "Ebene 1", 100, 0);
16     
17     # Ebene dem Bild hinzufügen
18     gimp_image_add_layer($img, $layer, -1);
19     
20     # Hintergrundfarbe setzen
21     gimp_palette_set_background($color);
22     
23     # Ebene mit Hintergrundfarbe einfärben
24     gimp_edit_fill($layer, BG_IMAGE_FILL);
25     
26     # Bild zurückgeben
27     return $img;
28 }
29 
30 register
31   # Name
32   "Bild mit HG-Farbe"
33   # Beschreibung
34   "Ein Bild mit festlegbarer Hintergrund-Farbe.",
35   # Hilfetext
36   "hier wohl nicht notwendig",
37   # Autoren-Name
38   "Michael Pradel",
39   # Copyright
40   "Michael Pradel",
41   # Datum
42   "13-07-2002",
43   # Pfad
44   "<Toolbox>/Xtns/Perl-Fu/Bild-HG",
45   # Bildarten
46   "*",
47   # zu übergebene Werte
48   [
49    [PF_INT, "size", "Bildgroesse", 100],
50    [PF_COLOR, "color", "Hintergrundfarbe", '#71a5f2']
51   ],
52   # Aufruf der Subroutine
53   \&bild_hg;
54 
55 exit main();

Der Register-Teil

Der Register-Teil wird durch das Schlüsselwort register am Anfang gekennzeichnet. Hier werden durch Komma getrennt 10 Angaben zum Skript gemacht. Die Zeilen 31-42 sollten selbsterklärend sein, als sechte Register-Angabe (Zeile 44) wird der Pfad erwartet, wo das Plugin zu finden sein soll. Dieser kann entweder mit <Toolbox> beginnen, also im Gimp-Hauptfenster, oder mit <Image>, also in dem Menü was sich öffnet, wenn man mit der rechten Maustaste auf das Bild klickt. Der achte Teil (Zeile 46) gibt an, für welche Bildarten das Plugin verfügbar sein soll (z.B. RGB), "*" meint alle.

Die neunte Angabe ist der wohl komplizierteste Teil des Register-Teils. Hat man es einmal verstanden aber auch nicht weiter schlimm. Hier wird angegeben, welche Werte beim Aufruf des Skripts vom Benutzer angegeben werden können. Sowohl das gesamte Übergabe-Array, als auch jedes zu übergebende Element werden durch eckige Klammern eingegrenzt. Für jedes Element sind (mindestens) 4 Angaben zu machen:

  • der Typ des Wertes (siehe Übersicht)
  • ein Name
  • eine Beschreibung (das was der Benutzer sieht)
  • ein Standard-Wert
Für die Typen PF_SLIDER und PF_SPINNER sind außerdem noch Start- und Endwert, wowie Schrittgröße anzugeben:

[PF_SLIDER, "slider", "Hier kann man etwas einstellen", 20, [0, 100, 1] ]

bedeuted beispielsweise dass man einen Wert von 0 bis 100 mit einer Genauigkeit von 1 einstellen kann.
Als letzte Angabe folgt der vom Skript auszuführende Teil. Der Übersichtlichkeit wegen stecken wir diesen in eine Subroutine und rufen diese im Register-Teil einfach auf (Zeile 53).


Die Subroutine

Bevor wir mit den einzelen Schritten beginnen, müssen wir die vom Benutzer festgelegten Werte in einzelne Variablen kopieren (Zeile 9). Alle in Punkt neun des Register-Teils festgelegten Werte befinden sich in der richtigen Reihenfolge im Array @_. Nun rufen wir die bereits oben vorgestellte Funktion gimp_image_new auf (Zeile 12). Sie erwartet zwei Parameter zur Größe (horizontal und vertikal), sowie die Art des Bildes (bei uns RGB). Als Rückgabewert erhalten wir die ID des Bildes, welche wir in $img speichern.

Als nächstes erstellen wir eine neue Ebene (Zeile 15), und fügen diese unseren Bild hinzu (Zeile 18). Dieser Schritt ist notwendig, da ein erstelltes Bild standardmäßig keine Ebene hat. Die genaue Syntax der einzelnen Funktionen könnt ihr im PDB-Browser nachschauen.

Nun setzen wir noch die Hintergrundfarbe auf den vom Benutzer gewünschten Wert (welcher ja in $color gespeichert ist), und füllen unser Bild damit. Zum Schluss muss noch das Bild an Gimp zurückgegeben werden (Zeile 27).


Einbinden in Perl

Unser Skript muss jetzt noch ausführbar gemacht werden. Außerdem empfiehlt sich immer der Perl-Syntax-Check:

  chmod u+x bild-hg.pl
  perl -cw bild-hg.pl

Anschließend kopiert man das Skript ins Verzeichnis ./gimp-1.2/plug-ins im Home-Verzeichnis. Alternativ kann man auch den offiziellen Weg über gimptool wählen. Hierzu muss man allerdings erst die Gimp-Entwickler-Pakete installieren (bei Debian libgimp1.2-dev), und kann anschließend mit

  gimptool -install-bin bild-hg.pl

bzw. falls das Plugin für alle User verfügbar sein soll

  gimptool -install-admin-bin bild-hg.pl

für die korrekte Einbindung des Skripts sorgen. Der erste Weg ist einfacher und reicht für den Anfang völlig aus.

Jetzt müssen wir nur noch Gimp (neu)starten und können das Plugin starten. Es befindet sich in dem von uns angegebenen Pfad (<Toolbox>/Xtns/Perl-Fu/Bild-HG). Wenn alles geklappt hat bekommen wir folgendes Bild als Ergebnis:


Button mit Schatten

Wie am Ergebnis zu sehen ist, war das letzte Beispiel recht einfach. Nun wollen wir ein etwas umfangreicheres Beispiel durchgehen, dass den praktischen Nutzen von Perl-Skripten in Gimp schon eher verdeutlicht: ein Button mit Schatten.

Das Plugin ist so geschrieben, dass der Anwender die Größe, die verwendeten Farben und natürlich den Button-Text bestimmen kann. Es ist grundsätzlich für einen einzelnen Button gedacht, man kann aber mit einer einfachen Schleife auch mehrere Buttons mit verschiedenen Texten erstellen.

button.pl:
  1 #!/usr/bin/perl -w
  2 
  3 use strict;
  4 use Gimp ":auto";
  5 use Gimp::Fu;
  6 
  7 sub button {
  8     my ($hsize, $vsize, $bgcolor, $frcolor, $font, $text) =
        @_;
  9     
 10     # neues Bild erzeugen
 11     my $img = gimp_image_new($hsize, $vsize, RGB);
 12     
 13     # Vorder- und Hintergrundfarbe setzen
 14     gimp_palette_set_foreground($frcolor);
 15     gimp_palette_set_background($bgcolor);
 16     
 17     # neue Ebene erzeugen
 18     my $layer1 = gimp_layer_new($img, $hsize, $vsize,
                     RGB_IMAGE, "Ebene 1", 100, 0);
 19     my $layer2 = gimp_layer_new($img, $hsize, $vsize,
                     RGBA_IMAGE, "Ebene 2", 100, 0);
 20     
 21     # Ebene dem Bild hinzufügen
 22     gimp_image_add_layer($img, $layer1, -1);
 23     gimp_image_add_layer($img, $layer2, -1);
 24     gimp_edit_clear($layer2);
 25     
 26     # Ebene 2 mit Rahmenfarbe füllen
 27     gimp_edit_fill($layer2, FG_IMAGE_FILL);
 28     
 29     # Ebene 1 mit Hintergrundfarbe füllen
 30     gimp_edit_fill($layer1, BG_IMAGE_FILL);
 31     
 32     # eine 15 Pixel vom Rand entfernte Auswahl wählen
 33     gimp_selection_all($img);
 34     gimp_selection_shrink($img, 15);
 35     
 36     # Auswahl ausschneiden
 37     gimp_edit_cut($layer2);
 38     
 39     # Ebene 2 kopieren
 40     my $layer3 = gimp_layer_copy($layer2, 0);
 41     
 42     # Kopierte Ebene dem Bild hinzufügen
 43     gimp_image_add_layer($img, $layer3, -1);
 44     
 45     # Ebene 2: minimale Helligkeit, maximaler Kontrast
 46     gimp_brightness_contrast($layer2, -127, 127);
 47     
 48     # Ebene 2: Weichzeichnen
 49     plug_in_gauss_iir2(0, $layer2, 15, 15);
 50     
 51     # Schatten nach rechts-unten verschieben
 52     gimp_layer_translate($layer2, 7, 7);
 53     
 54     # Deckkraft der Schatten-Ebene (Ebene 2) verringern
 55     gimp_layer_set_opacity($layer2, 60);
 56     
 57     # Text-Farbe wählen
 58     gimp_palette_set_foreground('#000000');
 59     
 60     # Text erstellen
 61     my $textlayer = gimp_text_fontname($img, -1, 20, 20,
                        $text, 1, 1, $vsize - 40, 0, $font);
 62     
 63     # Text zentrieren
 64     perl_fu_center_layer($img, $textlayer);
 65     
 66     # Bild zusammenfügen (sichtbare Ebenen)
 67     $layer1 = gimp_image_flatten($img);
 68     
 69     # Bild zurückgeben
 70     return $img;
 71 }
 72 
 73 register
 74   # Name
 75   "Button",
 76   # Beschreibung
 77   "Ein einfacher Button mit Schlagschatten",
 78   # Hilfetext
 79   "Erzeugt einen Button, dessen Rahmen einen
 80   Schatten auf das Innere wirft.\n
 81   Achtet darauf, dass die Breite für den
 82   Text reicht!",
 83   # Autoren-Name
 84   "Michael Pradel",
 85   # Copyright
 86   "Michael Pradel",
 87   # Datum
 88   "07-2002",
 89   # Pfad
 90   "<Toolbox>/Xtns/Perl-Fu/Button",
 91   # Bildarten
 92   "*",
 93   # zu übergebene Werte
 94   [
 95    [PF_INT, "Bildbreite", "Bildbreite", 300],
 96    [PF_INT, "Bildhoehe", "Bildhoehe", 70],
 97    [PF_COLOR, "HG-Farbe", "Hintergrundfarbe", '#71a5f2'],
 98    [PF_COLOR, "Rahmen-Farbe", "Rahmenfarbe", '#9d1912'],
 99    [PF_FONT, "Schrift", "Schrift",
    '-b&h-lucida-medium-r\normal-*-*-190-*-*-p-*-iso10646-1'],
100    [PF_STRING, "Text", "Text", "Ein Button"]
101   ],
102   # Aufruf der Subroutine
103   \&button;
104 
105 exit main();

Der Register-Teil ähnelt dem aus dem ersten Beispiel, allerdings werden mehr Werte übergeben. Zu Beginn der Subroutine werden wir gehabt zunächst die übergebenen Werte aus dem Array @_ in einzelne Variablen kopiert (Zeile 8). Anschließend erzeugen wir ein neues Bild und setzen die Vorder- und Hintergrundfarbe wie vom Benutzer angegeben.

Nun erzeugen wir 2 neue Ebene, wobei die zweite vom Typ RGBA_IMAGE, statt wie bisher RGB_IMAGE sein muss (Zeile 19). Das zusätzliche A bedeutet das ein Alpha-Kanal existiert, also Transparenz möglich ist. Die neuen Ebenen fügen wir unserem Bild hinzu und wenden gimp_edit_clear auf die zweite Ebene an, so dass diese vollständig transparent ist (Zeile 24). Jetzt füllen wir die Ebenen mit je einer Farbe und wählen eine Auswahl, welche alles bis auf einen 15 Pixel breiten Rand umfasst. Hierzu wählen wir zunächst alles (Zeile 33), und verkleinern die Auswahl anschließend mit gimp_selection_shrink. Diese Auswahl schneiden wir auf Ebene 2 weg, so dass wir folgenden Zwischenstand erhalten:

Nun folgt das wichtigste an diesem Beispiel: der Schatten: Ebene 2 (also die mit dem Rahmen) kopieren wir, nennen sie $layer3 und fügen sie dem Bild hinzu. Mittels gimp_brightness_contrast setzen wir die Helligkeit auf das Minimum und den Kontrast auf das Maximum, so dass die kopierte Ebene dunkler wird (Zeile 46). Der Schatten soll natürlich nicht so scharf sein, weswegen wir ihn mit plug_in_gauss_iir2 weichzeichnen (Zeile 49). Zwischenstand:

Der Schatten befindet sich jetzt genau unter dem Rahmen, was uns nicht gefällt. Wir verschieben ihn deshalb mit gimp_layer_translate je 7 Pixel nach rechts und unten (Zeile 52). Anschließend verringern wir die Deckkraft der Schatten-Ebene ($layer3) auf 60%. Alles was uns jetzt noch zum fertigen Button fehlt ist der Text. Diesen machen wir schwarz (wer eine andere Farbe bevorzugt kann dies gern ändern, man kann es aber beispielsweise auch dem Benutzer überlassen die richtige zu wählen), stellen also die Vordergrundfarbe auf #000000 (Zeile 58).

Der Text kommt (wie immer in Gimp) in eine eigene Ebene ($textlayer). Was die an gimp_text_fontname übergebenen Parameter bedeuten empfehle ich wie bei allen anderen Funktionen auch im PDB-Explorer nachzuschauen. Nun zentrieren wir den Text noch, wozu wir die Ebene-Zentrieren-Funktion nehmen können, da der Text ja in einer eigenen Ebene ist und diese genau die Größe unseres Textes hat. Zum Schluss fügen wir alle sichtbaren Ebenen (also bei uns alle die es gibt) zusammen (Zeile 66). Das Endergebnis schaut je nach Einstellung dann z.B. so aus:

       

Weitere Quellen

Das wohl wichtigste Werkzeug ist zweifelsohne der PDB-Explorer (in Gimp im Xtns-Menü zu finden). Außerdem gibt es Manpages zu den Perl-Modulen:

  man Gimp
  man Gimp::Fu

Diese sind unter goof.com/pcg/marc/gimp.html auch online verfügbar. Allgemeine Infos zu Gimp gibt es unter gimp.org, hier könnt ihr auch das Gimp Manual runterladen.

>binaervarianz >projects >perl-gimp