Kurs: Python für GIMPer

Die Freunde der Würgeschlange treffen sich hier. Übrigens kommt dieses Python von Monty Python, einem englischen Komiker

Vorwort

Beitragvon Hans » Mo 1. Nov 2010, 09:48

Wie viele wissen, komme ich aus der Ecke der Programmierer und befasse mich angeblich mit so ziemlich mit allen Skriptsprachen, welche man unter UNIX zum Laufen bringen kann. Es hat mich von Anfang an fasziniert, dass da ein Programm kommt, welches man mal so mir nichts dir nichts um eigene Funktionen erweitern kann.

Aber die ersten Skripts waren alle in Scheme, einem LISP Dialekt, geschrieben. Wenn man Pascal und C kennt, dann fragt man sich ob bei dieser Sprache ein Klammeraffe am Werk gewesen ist. Ich kann mich an die Scheme Syntax einfach nicht gewöhnen. Zu Beginn meines GIMP Schaffens war ich schon recht kräftig in Sachen Python unterwegs. Die Möglichkeiten dieser Skriptsprache sind einfach fantastisch. Lediglich die lasche Typenbehandlung stört mich. Was lag also näher, als sich einmal in pygimp zu versuchen? Der Versuch endete kläglich! Es fehlte mir an Zeit und vor allem an einführender Literatur.

Da ich jetzt etwas mehr Zeit zur Verfügung habe, finde ich es angebracht, mal eine kleine Einleitung zu schreiben. Ich gehe davon aus, dass ein Grundwissen in Python vorhanden ist. Lediglich die wichtigsten Eigenheiten dieser Sprache werde ich erörtern.

Einer der wesentlichen Merkmale von Python ist, dass die Einrückung ein wesentlicher Bestandteil von Python ist. Alles was untereinander in einer Spalte steht, wird als Block ausgeführt. Bei der Erstellung von Code ist deshalb darauf zu achten, dass nicht einmal Tabulatoren und ein anderes Mal Leerzeichen verwendet werden. Dieses führt mit ziemlicher Sicherheit dazu, dass das Skript nicht auf allen PC läuft. Der Interpreter von Python arbeitet übrigens case sensitive, d. h. er unterscheidet zwischen Groß- und Kleinschreibung.

Windows Benutzern wird dringend empfohlen, sich einen guten Editor wie notepad++ zu besorgen. Alternativ kann ein Quellcode auch über IDLE erstellt werden. Dieses ist Bestandteil von Python. Die Editoren von Microsoft sind nicht geeignet.

Für Windows Benutzer ist außerdem die Verwendung eines Packprogramms wie 7zip angeraten.

In allen Kursen wird der Sourcecode immer als HTML mit Zeilennummerierung und als .zip Datei angeboten. Der HTML Code wird für die Besprechung der Programme benötigt. Falls hier Fragen aufkommen, wie ich die HTML Datei erstellt habe, so ist das ganz einfach zu beantworten. Ich habe dafür Highlight verwendet


Abkürzungen




~ Homedirectory, Heimatverzeichnis
/ Trennzeichen für Pfade, in Windows durch \ zu ersetzen
CONST von GIMP vordefinierte Konstanten




Bild
Benutzeravatar
Hans
 
Beiträge: 2883
Registriert: So 27. Jun 2010, 12:56
Wohnort: Angeles City, PH

Kapitel 1: Procedural Database (pdb)

Beitragvon Hans » Mo 1. Nov 2010, 09:49

Jedes Python Skript für GIMP sollte wie mit folgenden Eintrögen starten:

Code: Alles auswählen
#!/usr/bin/env python
# -*- coding: utf-8 -*-

from gimpfu import *


Die Zeilen 1 und 2 sind Linux spezifisch und werden von Windows als Kommentar behandelt. Zeile 1 gibt das Programm an, mit dem diese Datei ausgeführt werde soll und Zeile2 den verwendeten Zeichensatz. Werden im Programm Umlaute verarbeitet, so sollte diese Zeile auf keinen Fall fehlen, andernfalls muss man Python jedes mal mitteilen, dass die Zeichencodierung UTF8 ist. Das geschieht dadurch, dass man der Zeichenkette ein u voranstellt, wie z. B. a=u"Tränen lügen nicht"

Die Zeile 4 hat es dann in sich. Hiermit wird der Datenaustausch zwischen GIMP und Python aktiviert. gimpfu beinhaltet eine Reihe von Definitionen für GIMP und importiert weitere für die Arbeit mit GIMP benötigte Dateien, welche ich hier aber nicht weiter ausführen möchte. Durch den Import von gimpfu werden auch GIMP - spezifische Objekte angelegt.

Das sind
  • gimp
  • pdb
  • image
  • channel
  • layer
  • drawable
  • tile
  • pr

pdb ist eine Redefinition von gimp.pdb. Weil dieses Objekt überwiegen benötigt wird, verkürzt dieses den Sourcecode erheblich.

Über das GIMP Menü Filter / Python-FU / Konsole kann die eine Arbeitsfläche geöffnet werden, welche für die Programmierung recht hilfreich ist. Einerseits kann man direkt Befehle dort eingeben, andererseits auch Informationen über die Objekte erhalten. help(object) listet alle Methoden (Funktionen) und Properties (Eigenschaften) des Objektes. dir(objekt) listet alle Methoden. probiere mal aus, was help(gimp) anzeigt. Richtig, es erscheint keine Hilfe zu GIMP sondern eine Auflistung der Methoden und Properties.

Eine weitere Eigenschaft der Konsole ist, dass sie eine Suchfunktion hat. Durch Anklicken des Buttons Durchsuchen öffnet sich ein Fenster, in dem Prozeduren und Funktionen gelistet sind. Trägt man in das Suchfeld layer ein, dann werden 149 Prozeduren und Funktionen gefiltert. Das erleichtert die Suche nach einer Funktion oder einer Prozedur. Hat man seine Funktion gefunden, so kann man diese anwenden. Durch Klick auf den Button wird der komplette Befehl incl. Übergabeparameter und ggfs. Rückgabewert angezeigt. Man kann dann die ganze Zeile kopieren und im Sourcecode eintragen. Lediglich die verwendeten Variablen müssen angepasst werden.

Bild


Wählt man eine Funktion aus, so erscheint auf der rechten Seite die Dokumentation. Ist leider nicht auf deutsch zu bekommen.

Datentypen

In pygimp werden neben den üblichen Python Datentypen auch GIMP spezifische eingesetzt. Hier nur eine kleine Auswahl:

INT32 Ganzzahl, 32 Bit
FLOAT Dezimalzahl
BOOLE kann nur True oder False (Wahr, Falsch) sein
IMAGE image, Bilddatei
LAYER Ebene
DRAWABLE Zeichenfläche
SELECTION Auswahl
DISPLAY Das Bildbearbeitungsfenster


Bild
Bild
Benutzeravatar
Hans
 
Beiträge: 2883
Registriert: So 27. Jun 2010, 12:56
Wohnort: Angeles City, PH

Kapitel 2: Hallo GIMP-Atelier.org

Beitragvon Hans » Mo 1. Nov 2010, 22:25

Source: Kurs0001.html

Neue Befehle:
  • register() : registriert die Funktion in GIMP
  • gimp.message() : Gibt eine Meldung in der Statuszeile aus

Um GIMP dazu zu bewegen, überhaupt etwas von uns Befehle entgegen zu nehmen, müssen wir ihm erst einmal klarmachen, was wir tun möchten. Das Geschieht mit der Funktion register. Der Funktionsaufruf scheint relativ einfach zu sein, aber der Teufel steckt im Detail

Register benötigt diverse Parameter, welche in der richtigen Reihenfolge angegeben werden müssen. Es müssen immer alle Parameter angegeben werden.

Code: Alles auswählen
# Register with The Gimp
register( "name",
  "Kurzhinweis",
  "Hilfe",
  "Autor",
  "Copyright",
  "Datum",
  "Menü Pfad",
  Bildtypen,
  [Parameter],
  Resultat,
  Funktionsname)


Dabei bedeuten:
  • das Zeichen # leitet in Python einen Kommentar ein, d.h. alles was danach steht, wird vom Interpreter nicht verarbeitet.
  • Der Parameter name ist vom Typ String (Zeichenkette). Dieses ist der interne Name in GIMP und wird für den Anwender nicht sichtbar sein. Dieser Name darf in GIMP noch nicht vergeben sein!
  • Der Kurzhinweis ist für den Anwender sichtbar, wenn er im Menü mit der Maus über dem Menüpunkt verweilt.
  • Die Hilfe darf über mehrere Zeilen gehen, wenn der Mehrzeilige String in drei Anführungszeichen eingeschlossen ist
  • Es gehört zum guten Ton, wenn der Autor oder die Autoren im Script genannt werden. Es ist unüblich Nicknamen zu verwenden
  • Unter Copyright sollte die Art der Lizensierung stehen, z. B. Gnu Public License
  • Unter Datum sollte das jeweils letzte Änderungsdatum der Datei stehen. Das vereinfacht die Fehlersuche
  • Mit dem Menüpfad wird festgelegt, wo das Script später zu finden sein wird. die Angabe <IMAGE> bewirkt, dass dieses Menü auch dann erscheint, wenn auf dem Bild mit der rechten Maustaste das Kontextmenü aufgerufen wird.
  • Es ist anzugeben, für welche Bildtypen das Script gültig ist, wie z. B. RGB oder RGBA. RGB* bedeutet, das alle mit Typen mit RGB zulässig sind. Versuchst du dann dieses Skript auf ein GIF anzuwenden, gibt es eine Fehlermeldung. Aber du wirst das Skript nicht einfach starten können, weil es bei GIF deaktiviert ist.
  • Was hier als Parameter angegeben ist, kann einen Anfänger zur Verzweiflung bringen. Die Variable Parameter ist eine Liste, welche nach Bedarf erweitert werden kann. Jede in Parameter angegebene Zeile beginnt mit einer vorgegebenen Constante wie PF_SLIDE, PF_STRING. Diese Konstanten geben an, welche Button und Felder angezeigt werden, wenn wir das Skript aufrufen.
  • Resultat gbt die Variable an in der das Ergebnis gespeichert wird. So lange nur Direktverarbeitung erfolgt, darf dieser Parameter leer bleiben, muss aber vorhanden sein.
  • Die hier angegebene Funktion wird aufgerufen, wenn das Skript gestartet wird.

Im Klartext sieht das dann z. B. so aus
Code: Alles auswählen
# Register with The Gimp
register( "hans_kurs0001",
  "Kurs PyGimp, Lektion 0010",
  "Create Test Application, bla bla bla",
  "Hans-G. Normann",
  "(c) 2009, Hans-G. Normann, Vervielfaeltigung und bla bla bla nur mit Genehmigung",
  "2009-05-08",
  "<Image>/Python-Fu/Kurs/Lektion 0001",
  None,
  [],
  '',
  kurs0001)


So lange die Funktion nicht registriert ist, kann sie in GIMP nicht aufgerufen werden. Werden Änderungen an der Registerfunktion vorgenommen, so muss GIMP neu gestartet werden damit die Änderungen wirksam werden.

starte GIMP von der Kommandozeile (DOS Fenster). Das hat den Vorteil, dass du im Fehlerfall mehr Informationen erhältst, wo der Fehler aufgetaucht ist.

Windows
Code: Alles auswählen
C:\Programme\GIMP-2.0\BIN\GIMP-2.6.exe
LINUX
Code: Alles auswählen
$ gimp


  • Die Zeilen 1 und 2 sind Linux spezifisch. Sie geben den Interpreter und die Zeichencodierung an. Windows interpretiert dieses als Kommentar.
  • die Zeile 4 ist jedoch unverzichtbarer Bestandteil eines jeden Python Skripts für GIMP. Hiermit wird das Interface zwischen GIMP und Python eingebunden. Ohne diese Datei, können beide Programme keine Daten austauschen.
  • Die Zeilen 6 bis 27 sind für dieses Programm nicht relevant. Ich habe sie nur einmal eingebunden um die Lizenzbedingungen näher zu erläutern.
  • Die Zeile 28 ist die Funktionsdeklaration. Diese wird immer mit def begonnen und Doppelpunkt abgeschlossen. Die Funktion muss zwingend die Parameter für Image und Drawable als erste Parameter beinhalten.
  • Zeile 29 enthält den Funktionsrumpf. Im Funktionsrumpf wird beschrieben, was das Programm ausführen soll. Wichtig ist, dass der Funktionsrumpf um mindesens ein Zeichen weiter eingerückt ist, als die Funktionsdefinition. In vorliegendem Fall erzeugt der Funktionsrumpf die Meldung "Hello World" auf der Statuszeile des Gimpfensters.

Variablen:
image : Dieses ist das Imageobjekt (Bildobjekt). Das image ist ein Container und enthält Eigenschaften (Properties) wie Höhe (height) und Breite (width) des Bildes. Man greift auf diese Werte zu, indem man das Objekt und die Eigenschaft mit einem Punkt verbindet also in diesem Fall image.height und image.width. Neben Properties enthält das Image Objekt auch Funktionen (Methods) wie add_layer() oder add_layer_mask(). Eine genaue Definition dieses Containers entnehme bitte der Dokumentation GIMP Python Documentation, Abschnitt Image Object

drawable: Bezeichnet die aktive Zeichenfläche und kann somit ein Kanal, eine Ebene, eine Ebenenmaske oder eine Auswahl sein. Eine genaue Definition dieses Containers entnehme bitte der Dokumentation GIMP Python Documentation, Abschnitt Drawable Objects

Ergebnis:
Bild


Python: Kurs0001.zip


Bild
Bild
Benutzeravatar
Hans
 
Beiträge: 2883
Registriert: So 27. Jun 2010, 12:56
Wohnort: Angeles City, PH

Kapitel 3: Neue Datei

Beitragvon Hans » Di 2. Nov 2010, 09:19

Source: kurs0010.html

neue Befehle:
    pdb.gimp_image_new() : Erzeugt eine neuen Datei und weist das Objekt einer Variablen zu
    pdb.gimp_display_new() : zeigt die Datei am Bildschirm an

Aufgabe:
Erstelle eine neue Datei per Skript. Die Größe der Datei ist variable wählbar.


Bisher hattest du nur ein Skript, welches blind etwas gemacht hat. Hier hast du nun das Problem, dass du GIMP sagen musst, das du Einstellungen vornehmen willst, nach denen zu Arbeiten ist. Für die Größenangabe eignen sich zwei Integer (Ganzzahl) Eingabefelder. Einer für die Höhe und einer für die Breite der neuen Datei. Die Maßeinheit ist Pixel.

Wie du dem Code entnehmen kannst, sieht die Registry gegenüber dem vorigen Beispiel leicht verändert aus. Die Variable hat mehr als einen Eintrag

Code: Alles auswählen
  [
    (PF_INT, "height", "Hoehe",  480),
    (PF_INT, "width",  "Breite", 640),
  ],


In Python werden Listen in eckigen Klammern notiert. Listen sind offen, d. h. sie können Null bis beliebig viele Elemente enthalten. Jedes Element ist mit runden Klammern einzuschließen. Die Elemente selbst können weitere Unterelemente beinhalten.

Die in parameter angegebenen Elemente steuern den Aufbau der GUI welche beim Start des Skriptes eingeblendet wird. Die zur verfügung stehenden Elemente sind in GIMP Python Documentation im Abschnitt Plugin Framework gelistet. Jedes dieser Elemente hat einen vorgegebenen Aufbau, welcher einzuhalten ist.

Wir hatten uns für ein Integer Einagbefeld entschieden, was die einfachste Variante ist. Die Syntax für dieses GUI Element ist
Code: Alles auswählen
(BEZEICHNER, "Variablen Name", "Bezeichnung in der GUI", default Wert)


Der Bezeichner ist Vorgegeben mit PF_INT. Dieser sorgt dafür, dass ein Eingabefeld für Ganzzahlen bereitgestellt wird. Den eingegebenen Wert findest du nach Beendigung der GUI in der Variablen "Variablen Name" wieder. Zu beachten ist, dass diese Angabe ein String ist, also in Hochkommatas einzuschließen ist! Das Feld wird mit dem unter Bezeichnung GUI angegebenen Wert beschriftet. Der default wert wird voreingestellt.

Ich habe in dem Beispiel die Variablen width und height genommen. Diese beiden Variablen müssen nun unbedingt auch in der Hauptfunktion mit eingesetzt werden, andernfalls kommt es zu Laufzeitfehlern. Der Ablauf ist jetzt so, dass wenn wir das Script aufrufen, eine GUI erzeugt wird.

Bild

Sobald nun die OK Taste gedrückt wird, wird die GUI geschlossen und die Funktion kurs0010(image, drawable, width, height) getartet. Im nächsten Schritt wird nun eine neue Datei erzeugt. Diese wird dem Objekt new_img zugewiesen. Die Datei wird zu diesem Zeitpunkt noch nicht angezeigt. Dafür musst du mit Aufruf der Funktion pdb.gimp_display_new(new_img) selbst sorgen.

Befehle :
  • pdb.gimp_image_new() :
    width, Type INT32, Breite des Bildes
    height, Type INT32, Höhe des Bildes
    type, INT32, Modus des Bildes
    SPOILER:
    RGB (0)
    GRAY (1)
    INDEXED (2)

    Rückgabewert:
    IMAGE, IMAGE, das Bildobjekt
  • pdb.gimp_display_new() :
    Parameter:
    image, IMAGE, das Objekt des Bildes
    Rückgabewert:
    DISPLAY, DISPLAY, das GIMP Fenster mit dem Bild

Pyton: kurs0010.zip


Bild
Bild
Benutzeravatar
Hans
 
Beiträge: 2883
Registriert: So 27. Jun 2010, 12:56
Wohnort: Angeles City, PH

Kapitel 4: Neue Ebene

Beitragvon Hans » Di 2. Nov 2010, 12:09

Source: Kurs0020.html

Neue Befehle:
  • pdb.gimp_layer_new() : Erzeugt eine neue Ebene
  • pdb.gimp_image_add_layer() : fügt die Ebene dem Bild hinzu
  • pdb.gimp_drawable_fill() : Füllt die Ebene mit Farbe
  • Assoziative Arrays : die "andere Art" Daten zu speichern.

Aufgabe: Nehme das Skript von vorhin und füge der Datei eine neue Ebene hinzu, welche du mit der Vordergrundfarbe füllst.

Zunächst einmal halte ich fest, dass pygimp eine ganze Reihe an vordefinierten Konstanten bereithält, die wir natürlich nutzen können. Konstanten werden üblicherweise nur in Großbuchstaben geschrieben. Das ist nicht Pflicht, erleichtert aber den Quellcode zu lesen und zu verstehen.

Auf den ersten Blick ist festzustellen, dass es offensichtlich für GIMP Funktionen gibt, welche eine Fülle an Parametern benötigen. pdb.gimp_layer_new() ist ein solcger Kandidat und er ist bei weitem nicht der schlimmste. Um eine neue Ebene zu erstellen haben wir eigentlich drei Möglichkeiten, die Funktion zu schreiben
  1. Wir schreiben alles im Klarkext in den Code. Auf Dauer geht die Übersicht jedoch verloren. Wer weiß nach einem halben Jahr schon , was der fünfte Parameter zu bedeuten hat und warum der gerade 0 ist?
  2. Wir legen für jeden Übergabeparameter eine Variable an. Wenn man aber fünf Ebenen mit unterschiedlichen Einstellungen zu versorgen hat, wird es sehr schnell sehr unübersichtlich.
  3. Wir legen ein Assoziatives Array an. Damit kann man Funktionsaufrufe Übersichtlich gestalten.

Nehmen wir an, wir haben die Vornamen der Hausbesitzer einer Straße zu speichern, in der es keine Hausnummern gibt. Jedes Haus ist nur mit dem Nachnamen seines Besitzers bezeichnet und jeder Nachname kommt nur einmal vor. Der Vorname des Besitzers ist der zu speichernde Wert. Dann kann das in Python so aussehen:
Code: Alles auswählen
HauptStrasse = {
   "Meyer" : "Herbert",
   "Müller" : "Gudrun",
  "Schulze" : "Günther"
}

Auf die Elemente kann man nun über HauptStraße["Müller"] zugreifen
Code: Alles auswählen
IDLE 2.6.2     
>>> HauptStrasse = {
   "Meyer" : "Herbert",
   "Müller" : "Gudrun",
  "Schulze" : "Günther"
}
>>> print HauptStrasse["Meyer"]
Herbert
>>> HauptStrasse["Müller"] = "Gertrud"
>>> print HauptStrasse["Müller"]
Gertrud
>>>


Da mir der Code immer noch zu lang wurde, habe ich kurzerhand die Funktion hans_layer_new() geschaffen. hier übergebe ich nur das Imageobjekt (img) und das Assoziative Array. Das schöne an der Sache ist, dass diese Funktion wiederverwendbar ist.

Welche Variante du wählst, ist eigentlich egal, aber ein gut lesbarer Code sollte auf jeden Fall entstehen.

Befehle :
  • pdb.gimp_layer_new() :
    Parameter:
    image, Type IMAGE, das Objekt des Bildes, zudem die Ebene hinzugefügt werden soll
    width, INT32, Breite der neuen Ebene
    height, INT32, Höhe der neuen Ebene
    type, INT32, Datentyp der Ebene
    SPOILER:
    RGB-IMAGE (0),
    RGBA-IMAGE (1)
    GRAY-IMAGE (2)
    GRAYA-IMAGE (3)
    INDEXED-IMAGE (4)
    INDEXEDA-IMAGE (5)

    Konstanten können mit ihrem Namen eingesetzt werden

    name, STRING, Name der neuen Ebene
    opacity, INT32, Deckkraft der Ebene, Wert zwischen 0 und 100
    mode, INT32, Modus der Ebene
    SPOILER:
    NORMAL-MODE (0)
    DISSOLVE-MODE (1)
    BEHIND-MODE (2)
    MULTIPLY-MODE (3)
    SCREEN-MODE (4)
    OVERLAY-MODE (5)
    DIFFERENCE-MODE (6)
    ADDITION-MODE (7)
    SUBTRACT-MODE (8)
    DARKEN-ONLY-MODE (9)
    LIGHTEN-ONLY-MODE (10)
    HUE-MODE (11)
    SATURATION-MODE (12)
    COLOR-MODE (13)
    VALUE-MODE (14)
    DIVIDE-MODE (15)
    DODGE-MODE (16)
    BURN-MODE (17)
    HARDLIGHT-MODE (18)
    SOFTLIGHT-MODE (19)
    GRAIN-EXTRACT-MODE (20)
    GRAIN-MERGE-MODE (21)
    COLOR-ERASE-MODE (22)
    ERASE-MODE (23)
    REPLACE-MODE (24)
    ANTI-ERASE-MODE (25)

    Rückgabewert: LAYER
  • pdb.gimp_image_add_layer() :
    Parameter:
    image, IMAGE, das Bild, zu dem eine Ebene hinzugefügt werden soll
    layer, LAYER, die Ebene, die zu dem Bild hinzugefügt werden soll
    position, INT32. die Position im Bild, wo die Ebene eingefügt werden soll. Ist die Position -1, dann wird die Ebene über der aktuellen Ebene eingefügt.
    Rückgabewert: keiner
  • pdb.gimp_drawable_fill() :
    Parameter:
    drawable, DRAWABLE, füllt die Zeichenfläche mit Farbe. Zeichenfläche ist entweder die aktive Ebene oder eine Auswahl
    fill_type, INT32, legt fest, womit die Zeichenfläche gefüllt werden soll.
    SPOILER:
    FOREGROUND-FILL (0) --> Vordergrundfarbe
    BACKGROUND-FILL (1) --> Hintergrundfarbe
    WHITE-FILL (2) --> Weiß
    TRANSPARENT-FILL (3) --> Transparent (fensterscheiben farbig)
    PATTERN-FILL (4) --> Muster
    NO-FILL (5) --> Keine Füllung
    Rückgabewert: keiner

kurs0020.zip


Bild
Bild
Benutzeravatar
Hans
 
Beiträge: 2883
Registriert: So 27. Jun 2010, 12:56
Wohnort: Angeles City, PH

Kapitel 5 : Wir zeichnen endlich etwas

Beitragvon Hans » Fr 5. Nov 2010, 13:29

Source: Kurs0030.html

Neue Befehle:
  • IMAGE.undo_group_start() : Stoppt die Undo Aufzeichnung
  • IMAGE.undo_group_end() : Aktiviert die Undo Aufzeichnung
  • pdb.gimp_context_set_foreground() : setzt die Vordergrundfarbe
  • pdb.gimp_context_set_background() : setzt die Hintergrundfarbe
  • pdb.gimp_image_get_active_layer() : ermittelt die aktive Ebene
  • pdb.gimp_drawable_has_alpha(): ermittelt, ob die Zeichenfläche einen Alphakanal hat
  • pdb.gimp_layer_add_alpha() : fügt der Ebene einen Alphakanal hinzu
  • pdb.gimp_drawable_set_name() : ändert den Namen der Zeichenfläche.
  • pdb.gimp_context_set_brush() : aktiviert einen neuen Pinsel
  • pdb.gimp_text_layer_new() : erzeugt einen neue Textebene
  • pdb.gimp_text_layer_set_color() : weist eine neue Textfarbe zu
  • pdb.gimp_layer_set_offsets() : verschiebt die Ebene
  • pdb.gimp_image_set_active_layer() : Setzt eine neue aktive Ebene
  • pdb.gimp_selection_clear() : hebt die Auswahl auf
  • pdb.gimp_edit_stroke() : Zeichnet die Auswahl nach (????)
  • pdb.gimp_context_set_gradient() : aktiviert einen neuen Farbverlauf.
  • pdb.gimp_edit_blend() : Zeichnet den Farbverlauf

ACHTUNG! Baustelle


Aufgabe:
  1. Nach Beendigung des Scripts, soll das Bild einem Befehl "Rückggängig" in den Ausgangszustand zurückversetz werden.
  2. Erstelle ein Skript, welches auf einer vorhandenen Ebene ein Polygon (Vieleck) zeichnet. Falls die vorhandene Ebene noch keinen Alphakanal besitzt, füge ihn hinzu.
  3. Erstelle eine Textebene mit dem Text GIMP-Atelier auf einer neuen Ebene. Die Koordinaten X,Y für das Textelement sind 300,300. Wähle eine nicht übliche Schriftart aus und färbe den Text ein
  4. Erzeuge eine weitere Ebene, auf welcher du eine Ellipse zeichnest. Die Ellipse ist um die vorher erzeugte Textebene zu zentrieren.
  5. Erzeuge auf einer neuen Ebene einen Farbverlauf, welcher in die Ellipse einzupassen ist

Lösung A: (undo, rückgängig machen)
Die Änderungshistorie kann man mit den Befehlen IMAGE.undo_group_start() und IMAGE.undo_group_end() beeinflussen. Diese beiden Befehle bewirken, dass alles was zwischen IMAGE.undo_group_start() und IMAGE.undo_group_end() steht als eine Änderung dargestellt wird. In unserem Skript sind das die Zeilen 133 und 236. Ich habe das hier vom Ergebnis einer Abfrage abhängig gemacht. Die Variable debug ist eine Hilfsvariable, welche steuert, wie und wann Hilfstexte auf der Eingabeaufforderung (Terminal) ausgegeben werden sollen. Während der Entwicklungsphase is es manchmal hilfreich, wenn man in der Historie nachsehen kann, wie die einzelnen Zwischenschritte aussehen. Natürlich ist hier das Objekt IMAGE in unserem Code durch img ersetzen müssen.

Als weitere Vorbereitung erzeugen wir das Array layer welchem wir sämtliche Ebenen zuweisen.

Lösung B: Polygon
Im Beispiel zeichnen wir ein Polygon mit 16 Ecken. Zunächst zerlegen wir einen Kreis in 16 Segmente. Dazu haben ich eine extra Funktion getSegmentAngel() geschrieben. Auch wenn es banal aussieht, für so wenig Code eine eigene Funktion zu schreiben, so erhöht es doch die Lesbarkeit des Codes. Die Funktion hat nur einen Parameter. Dieser gibt an, in wie viele Segmente der Kreis zu zerlegen ist.

Als erstes benötigen wir den Startpunkt, welcher bei 0 liegt. Weil alle trigonometrischen Funktionen in Python in Rad definiert sind, ist es für Ungeübte etwas gewöhnungsbedürftig, dass 2*pi einen Kreis ergeben. Wem das nicht behagt, der kann auch in Grad rechnen und dann die Werte mit math.radiants() oder math.degrees() umrechnen. Die Funktion erzeugt eine Liste, welche die Segmente des Polygons beschreibt. Die Funktion getSegmentAngel() gibt eine leere Liste zurück, wenn wir versuchen weniger als drei ecken zu definieren.

In den Zeilen 159 bis 161 legen wir die Größe des Kreises (r) fest, in welchen wir das Polygon zeichnen wollen. Der Mittelpunkt dieses Kreises würde momentan den Wert 0,0 haben. Da wir all Ecken sehen wollen, werden wir den Mittelpunkt also verschieben müssen. Die Verschiebung wird in offsetX bzw offsetY angegeben. Alle Angaben sind Pixel. Jertzt müssen wir die Eckpunkte der Segmente in Koordinaten wandeln (Zeile 164 - 168).

Zunächst erzeugen wir ein leeres Array (myway). Mit der nachfolgenden Schleife wandeln wir die in list enthaltenen Eckpunkte in xy Koordinaten um. Dazu haben wir uns die Funktion getXYCoordinates(r, i, offsetX, offsetY) erstellt. Wir geben der Funktion den Radius des Kreises, den Winkel des Segments und die Verschiebujng des Kreises um offsetX und offsetY mit. Zurück bekommen wir ein Dictionary mit zwei Werten (Y,Y). getXYCoordinates() wandeld den Winkel (angegeben in Rad) mittels Sinus und Kosinus Funktion in Koordinaten um. Zeile 172 - 173 hätte eigentlich nicht geschrieben werden müssen, weil eigentlich immer zwei Werte zurückgegeben und zu myway addiert werden. Werte in Arrays fügt man mit ARRAY.add() hinzu.

Jetzt fehlt noch der letzte Befehl pdb.gimp_paintbrush_default(draw,len(myway),myway). Es ist genau diese Funktion, welche das Polygon zeichnet. Gezeichnet wird auf das Drawable (Zeichenfläche).

Lösung C: Textebene

In Zeile 178 wird zunächst die Textebene erzeugt pdb.gimp_text_layer_new(img, 'GIMP-Atelier', "Shanghai", 3 ,10) welche dann gleich als neue Ebene definiert wird. mit pdb.gimp_image_add_layer(img, layer[1], -1) wird dem Image eine neue Ebene hinzugefügt und in der darauf folgenden Zeile mit der neuen Ebene verankert. Die Ebene wird anschließend mit pdb.gimp_layer_set_offsets(layer[1], 300,300) an ihre endgültige Position geschoben.

Lösung D: Ellipse

Ab Zeile 185 fangen wir an, eine Ellipse zu zeichnen. Der Variablen p weisen wir das globale Dictonary LayerDefaults zu. Damit haben wir jetzt alle Variablen vordefiniert (und vorbelegt) und erreichen zusätzlich eine bessere Lesbarkeit. Wir erzeugen eine leere Ebene bevor wir in Zeile 196 damit anfangen, die Ellipse aufzubauen. Auch hier weisen wir der Variablen p Defaultwerte zu, definieren noch die obere linke Ecke (x,y), die Breite (width) und die Höhe (height) der Auswahl. mit der selbst definierten Funktion hans_ellipse_select(img, p) zeichenen wir die Ellipse. Hier wird deutlich, warum es manchmal sinnvoll ist, das Handling der Funktionen zu vereinfachen. Anschließend noch Vordergrund und Hintergrundfarbe definieren und die Auswahl mit pdb.gimp_edit_stroke(layer[2]) nachziehen.

Lösung E: Farbverlauf

Ab zeile 210 Fangen wir dann an den Farbverlauf zu erstellen. Zunächst wird eine neue Ebene erzeugt. In Zeile 219 werden der Variablen P die default Werte für die erstellung eines Farbverlaufes zugewiesen. Die default Werte sind in Zeile 57 bis 74 definiert. Die Werte von P werden nur kurz angepasst und schon können wir den Farbverlauf erstellen.

Befehle:
  • IMAGE.undo_group_start() : Stoppt die Undo Aufzeichnung
    Parameter: Keine
    Rückgabewert: Keiner
  • IMAGE.undo_group_end() : Aktiviert die Undo Aufzeichnung
    Parameter: Keine
    Rückgabewert: Keiner
  • pdb.gimp_context_set_foreground() : setzt die Vordergrundfarbe
    Parameter:
    FG_COLOR: Vordergrundfarbe in RGB Notation
    Rückgabewert: Keiner
  • pdb.gimp_context_set_background() : setzt die Hintergrundfarbe
    Parameter:
    BG_COLOR: Hintergrundfarbe in RGB Notation
    Rückgabewert: Keiner
  • pdb.gimp_image_get_active_layer() : ermittelt die aktive Ebene
    Parameter:
    IMAGE Image-Objekt
    Rückgabewert:
    active Layer aktive Ebene
  • pdb.gimp_drawable_has_alpha(): ermittelt, ob die Zeichenfläche einen Alphakanal hat
    Parameter:
    Drawable Zeichenfläche
    Rückgabewert:
    True oder False
  • pdb.gimp_layer_add_alpha() : fügt der Ebene einen Alphakanal hinzu
    Parameter:
    LAYER Ebene
    Rückgabewert: keiner
  • pdb.gimp_drawable_set_name() : ändert den Namen der Zeichenfläche.
    Parameter:
    NAME OF DRAWABLE, Ebenenname
    Rückgabewert: keiner
  • pdb.gimp_context_set_brush() : aktiviert einen neuen Pinsel
    Parameter:
    NAME OF BRUSJ Names des Pinsels
    Rückgabewert: keiner
  • pdb.gimp_text_layer_new() : erzeugt einen neue Textebene
    Parameter:
    IMAGE: Image-Objekt
    TEXT Text, welcher generiert werden soll
    FONT NAME Name der Schriftart
    FONT SIZE Schriftgröße (1 bis 8192)
    UNIT Einheit der Schriftgröße
    SPOILER:
    0: Pixel
    1: Points

    Rückgabewert: neue Textebene
  • pdb.gimp_text_layer_set_color() : weist eine neue Textfarbe zu
    Parameter:
    LAYER Texteebene
    FONT COLOR Textfarbe in RGB Notation
    Rückgabewert: keiner
  • pdb.gimp_layer_set_offsets() : verschiebt die Ebene
    Parameter:
    LAYER Ebenen Objekt
    OFFSETX Verschiebung in X-Richtung (horizontal)
    OFFSETY Verschiebung in Y-Richtung (vertikal)
    Rückgabewert:
    ACTIVE LAYER aktive Ebene
  • pdb.gimp_image_set_active_layer() : Setzt eine neue aktive Ebene
    Parameter:
    IMAGE Image-Objekt
    LAYER TO ACTIVATE Ebenen Objekt, welches aktiviert werden soll
    Rückgabewert: Keiner
  • pdb.gimp_selection_clear() : hebt die Auswahl auf
    Parameter:
    IMAGE Image-Objekt
    Rückgabewert: Keiner
  • pdb.gimp_edit_stroke() : Zeichnet die Auswahl nach
    Parameter:
    DRWABLE Drawable-Objekt
    Rückgabewert: Keiner
  • pdb.gimp_context_set_gradient() : aktiviert einen neuen Farbverlauf.
    Parameter:
    GRADIENT NAME Name des Farbverlaufs
    Rückgabewert: keiner
  • pdb.gimp_edit_blend() : Zeichnet den Farbverlauf
    Parameter:
    DRAWABLE Drawable Objekt
    MODEModus
    SPOILER:
    FG_BG_RGB_MODE (0)
    FG_BG_HSV_MODE (1)
    FG_TRANSPARENT_MODE (2)
    CUSTOM_MODE (3)

    PAINT MODEZeichenmodus
    SPOILER:
    NORMAL_MODE (0)
    DISSOLVE_MODE (1)
    BEHIND_MODE (2)
    MULTIPLY_MODE (3)
    SCREEN_MODE (4)
    OVERLAY_MODE (5)
    DIFFERENCE_MODE (6)
    ADDITION_MODE (7)
    SUBTRACT_MODE (8)
    DARKEN-ONLY-MODE (9)
    LIGHTEN_ONLY_MODE (10)
    HUE_MODE (11)
    SATURATION_MODE (12)
    COLOR_MODE (13)
    VALUE_MODE (14)
    DIVIDE_MODE (15)
    DODGE_MODE (16)
    BURN_MODE (17)
    HARDLIGHT_MODE (18)
    SOFTLIGHT_MODE (19)
    GRAIN_EXTRACT_MODE (20)
    GRAIN_MERGE_MODE (21)
    COLOR_ERASE_MODE (22)
    ERASE_MODE (23)
    REPLACE_MODE (24)
    ANTI_ERASE_MODE (25)

    GRADIENT TYPE Art des Farbverlaufes
    SPOILER:
    GRADIENT_LINEAR (0)
    GRADIENT_BILINEAR (1)
    GRADIENT_RADIAL (2)
    GRADIENT_SQUARE (3)
    GRADIENT_CONICAL_SYMMETRIC (4)
    GRADIENT_CONICAL_ASYMMETRIC (5)
    GRADIENT_SHAPEBURST_ANGULAR (6)
    GRADIENT_SHAPEBURST_SPHERICAL (7)
    GRADIENT_SHAPEBURST_DIMPLED (8)
    GRADIENT_SPIRAL_CLOCKWISE (9)
    GRADIENT_SPIRAL_ANTICLOCKWISE (10)

    OPACITY Transparenz
    OFFSET Verschieben gegenüber Start und Endpunkt
    REPEAT MODE Wiederholung
    SPOILER:
    REPEAT_NONE (0)
    REPEAT_SAWTOOTH (1)
    REPEAT_TRIANGULAR (2)

    REVERSE GRADIENT Gradient umkehren, True oder False
    ADAPTIVE SUPERSAMPLING anpassende Hochrechnung (True oder False)
    MAX RECURSION maximale Rekursion Hochrechnung (0 bis 9)
    THRESHOLD Grenzwert Hochrechnung (0 bis 4)
    DITHERING Schwelle Hochrechnung
    STARTX Startpunkt x
    STARTY Startpunkt y
    STOPX Endpunkt x
    STOPY Endpunkty
    Rückgabewert: aktive Ebene

Pyton: kurs0030.zip


Bild
Bild
Benutzeravatar
Hans
 
Beiträge: 2883
Registriert: So 27. Jun 2010, 12:56
Wohnort: Angeles City, PH


Zurück zu Python

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 1 Gast