Python Skript für Gimp

Hier werden alle anderen GUI-Toolkits sowie Spezial-Toolkits wie Spiele-Engines behandelt.
BlackJack

Montag 24. Juli 2017, 13:17

@Melewo: Wenn Du die Argumente sowieso nicht verwendest würde ich denen ja in der Funktionsdefinition `None` jeweils als Defaultwert verpassen, dann braucht man auch nicht unnötig etwas übergeben.
Melewo
User
Beiträge: 320
Registriert: Mittwoch 3. Mai 2017, 16:30

Montag 24. Juli 2017, 15:04

@BlackJack: Ja, der Gedanke ist erst einmal gut. Die Werte brauche ich nur beim Aufruf über die Console angeben, ohne Console, also bei Aufruf über das Menü hingegen nicht. Über Menü lässt sich jedoch bisher kein Filter aufrufen, bevor ein Image geöffnet wird ist alles grau und ein Filter bezieht sich dann auf das aktuell geöffnete Image. Mit dem vorausgehenden Beispiel wird dann ein zweites Image in einem eigenen Fenster erzeugt.

Ein anderes Beispiel habe ich unter Help/ gespeichert, das ist zwar anfänglich nicht ausgegraut, doch ich denke, es kommt auf die zu übergebenen Parameter an, denn da erfolgt eine Abfrage ob mit oder ohne None:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from gimpfu import *

def erstelle_begruessung(image=None, layer=None):
    gimpversion  = gimp.version                             # Tupel mit 3 Integer-Werten
    begruessung  = "Hello Welt!\nGimp Version "
    begruessung += ".".join(map(str, gimpversion))
    gimp.message(begruessung)

register(
    "erstelle_begruessung",                                 # Plugin Name gleich Funktions-Name
    "Begrüßung erstellen",                                  # Kurzbeschreibung
    "Einen Eintrag mit Begrüßung im Hilfe-Menü erstellen.", # Längere Beschreibung
    "Mele Melewo",                                          # Plugin Autor
    "MIT-Lizenz",                                           # Angaben zur Lizenz
    "2017",                                                 # Jahr der Veröffentlichung
    "<Image>/Help/Hinweise/Begrüßung",                      # Position im Menü mit Label
    None,                                                   # Akzeptierte Image-Typen
    [],                                                     # Input Parameter
    [],                                                     # Output Resultate
    erstelle_begruessung                                    # Name der Funktion
    )

main()
Ohne das ein Bild geöffnet ist:
Bild

Wenn bereits ein Bild geöffnet ist:
Bild

Und dann noch ein Beispiel aus diesem auf der vorausgehenden Seite erwähnten Zip-Archiv, da wird etwas übergeben, doch dafür ist es anfänglich ausgegraut und lässt sich nicht betätigen, bevor ein Image geöffnet wurde.

Code: Alles auswählen

...

    "*",
    [
        (PF_STRING, "message", "Message to display", "hello")
	],
    [],
    say_something_help)

main()
Bevor ein Image geöffnet wurde bleibt der Menüpunkt ausgegraut:
Bild

Oder einfacher, eigentlich funktioniert alles, aber selbst unter Hilfe erst dann, wenn ein Bild geöffnet wurde. Vielleicht hängt es auch damit zusammen, dass es außer <Image> für die Registrierung nichts anderes mehr geben soll, <Toolbox> wurde in neueren Versionen entfernt, las ich. Und sicherlich werde ich mich noch mit diesen Input-Parametern auseinandersetzen müssen.
Melewo
User
Beiträge: 320
Registriert: Mittwoch 3. Mai 2017, 16:30

Dienstag 25. Juli 2017, 12:39

Habe zwei Beispiele aus dem Jahre 2009 gefunden, da soll es noch funktioniert haben, eine Registrierung mit Menüeintrag nur mit menu="" zu erreichen, beide Bespiele funktionierten bei mir nicht mehr.

Code: Alles auswählen

# no image or drawable parameters
...
# enabled even if no image open
...
menu="/Filters/Languages/Python-Fu"
Heute scheint es nichts mehr außer

Code: Alles auswählen

"<Image>/Filters/Languages/Python-Fu"
zu geben. Doch damit kann man leben, wenn man sich darauf einstellt. Der Code aus dem Rumpf der Funktion lässt sich vorher in der Python-Fu-Console testen, ist kein Problem. Und das fertige Plugin lässt sich ebenfalls über die Python-Fu-Console testen. Doch ob im Funktionskopf None benutzt wird oder nicht, scheint Jacke wie Hose zu sein, denn auch mit None, wie in

Code: Alles auswählen

def erstelle_neues_image(image=None, ebene=None)
kommt:

[codebox=text file=Unbenannt.txt]Traceback (most recent call last):
File "<input>", line 1, in <module>
NameError: name 'image' is not defined[/code]
Aber auch das ist eigentlich kein Problem, da nur für einen Test

[codebox=text file=Unbenannt.txt]>>> image = None
>>> drawable = None
>>> pdb.python_fu_erstelle_neues_image(image, drawable)[/code]
oder

[codebox=text file=Unbenannt.txt]>>> image = gimp.image_list()[0]
>>> drawable = image.layers[0]
>>> pdb.python_fu_bearbeite_image(image, drawable)[/code]
einzugeben. Bei einem Aufruf über Menü ist es ja nicht erforderlich. Nur wie man Fehler bei der Registrierung zumindest in eine log.txt schreiben könnte, da sollte sich noch etwas finden lassen. Alles was ich bisher außer * Sternchen beim Import sah, war nicht einleuchtend.

Code: Alles auswählen

import gimp
from gimpfu import pdb
from gimpfu import *

# Quelle: registry.gimp.org/node/18305
Was soll das z.B., wenn in der letzten Zeile doch ein * folgt?
BlackJack

Dienstag 25. Juli 2017, 13:41

@Melewo: Wobei kommt der `NameError`?

Edit: Du rufst es dann schon *ohne* Argumente auf, und nicht mit einem nicht definierten `image` oder? Also ``pdb.python_fu_erstelle_neues_image()``.
Melewo
User
Beiträge: 320
Registriert: Mittwoch 3. Mai 2017, 16:30

Dienstag 25. Juli 2017, 15:07

Wenn ich definiere

Code: Alles auswählen

def erstelle_neues_image(image=None, ebene=None):
sieht es ohne diese beiden vorausgehenden Zeilen so aus:

[codebox=text file=Unbenannt.txt]>>> image = None
>>> drawable = None[/code]
so aus:

[codebox=text file=Unbenannt.txt]
>>> pdb.python_fu_erstelle_neues_image(image, drawable)
Traceback (most recent call last):
File "<input>", line 1, in <module>
NameError: name 'image' is not defined
>>> [/code]
Wenn ich definiere

Code: Alles auswählen

def erstelle_neues_image():
werden nicht einmal die Bindestriche vom PDB-Browser bei Apply umgewandelt:

[codebox=text file=Unbenannt.txt]>>> python-fu-erstelle-neues-image
Traceback (most recent call last):
File "<input>", line 1, in <module>
NameError: name 'python' is not defined[/code]
Wenn ich die allein korrigiere:

Code: Alles auswählen

python_fu_erstelle_neues_image()
# Oder:
pdb.python_fu_erstelle_neues_image()
[codebox=text file=Unbenannt.txt]>>> python_fu_erstelle_neues_image()
Traceback (most recent call last):
File "<input>", line 1, in <module>
NameError: name 'python_fu_erstelle_neues_image' is not defined[/code]
Oder:
[codebox=text file=Unbenannt.txt]>>> pdb.python_fu_erstelle_neues_image()
Traceback (most recent call last):
File "<input>", line 1, in <module>
TypeError: wrong number of parameters
>>> [/code]
Und irgendwann hatte ich dann auch mal einen anderen Hinweis, der besagte, dass zwei Argumente erwartet werden.

Eigentlich egal was man macht, alles bezieht sich wohl immer auf ein im Fenster geöffnetes Image und das lässt sich in der Console damit abfragen

[codebox=text file=Unbenannt.txt]>>> image = gimp.image_list()[0]
>>> drawable = image.layers[0] [/code]
und dann ist auch alles definiert und es sollte keine Probleme mehr geben und in der dritten Zeile könnte pdb.python_fu_name_des_plugins(image, drawable) folgen.

Und neben diesen bereits geöffneten Image können dann halt weitere neu erstellt oder kopiert oder verfremdet und bearbeitet oder was auch immer werden. Um diese beiden Angaben braucht man sich nicht zu kümmern, wenn man ein Plugin übers Menü aufruft, dann erledigt das Gimp automatisch.
BlackJack

Dienstag 25. Juli 2017, 15:15

@Melewo: Also die Definition sollte so aussehen:

Code: Alles auswählen

def erstelle_neues_image(image=None, ebene=None):
   ...
Und der Aufruf so:

Code: Alles auswählen

pdb.python_fu_erstelle_neues_image()
Wenn das nicht funktionieren sollte, dann ist ``pdb.python_fu_erstelle_neues_image`` eine automatisch generierte Funktion die doch wieder obligatorische Argumente hat, oder die Magie die diese Funktion erstellt erkennt keine Argumente mit Defaultwerten.

Dann kann man aber auch einfach `None` übergeben *ohne* den Wert vorher an irgendwelche Namen zu binden.
Melewo
User
Beiträge: 320
Registriert: Mittwoch 3. Mai 2017, 16:30

Dienstag 25. Juli 2017, 16:07

Die Definition sieht so aus mit (image=None, ebene=None).
Ja, hast Recht, der zweite Aufruf mit (None, None) hat funktioniert.

[codebox=pycon file=Unbenannt.txt]>>> pdb.python_fu_erstelle_neues_image()
Traceback (most recent call last):
File "<input>", line 1, in <module>
TypeError: wrong number of parameters
>>>
>>> pdb.python_fu_erstelle_neues_image(None, None)
>>> [/code]
Ich hatte die bisher mit Apply übernommen und da erschien die gleich so in der Console:

[codebox=pycon file=Unbenannt.txt]>>> pdb.python_fu_erstelle_neues_image(image, drawable)[/code]
Da könnte man sich zwei Zeilen beim Tippen dann sparen.
Melewo
User
Beiträge: 320
Registriert: Mittwoch 3. Mai 2017, 16:30

Donnerstag 27. Juli 2017, 09:45

Habe mir mal die gimpfu näher betrachtet. Wie in beinahe allen bisher gefundenen Beispielen hatte ich den "Menüpfad plus Label" bei "Label" angegeben und nach "function" nichts mehr.

Aus gimpfu.py:

Code: Alles auswählen

def register(proc_name, blurb, help, author, copyright, date, label,
             imagetypes, params, results, function,
             menu=None, domain=None, on_query=None, on_run=None):

Und das funktionierte, weil aus den Angaben bei Label dann der Menüeintrag erstellt wird, wobei dann aber nach einen von diesen 3 "<Load>", "<Image>", "<Save>" gefragt wird und params zugeordnet werden. Da könnten über menü = "" noch weitere Möglichkeiten sich eröffnen.

Aus gimpfu.py:

Code: Alles auswählen

    # if menu is not given, derive it from label
    need_compat_params = False
    if menu is None and label:
        fields = label.split("/")
        if fields:
            label = fields.pop()
            menu = "/".join(fields)
            need_compat_params = True

            import warnings
            message = ("%s: passing the full menu path for the menu label is "
                       "deprecated, use the 'menu' parameter instead"
                       % (proc_name))
            warnings.warn(message, DeprecationWarning, 3)

        if need_compat_params and plugin_type == PLUGIN:
            file_params = [(PDB_STRING, "filename", "The name of the file", ""),
                           (PDB_STRING, "raw-filename", "The name of the file", "")]

            if menu is None:
                pass
            elif menu.startswith("<Load>"):
                params[0:0] = file_params
            elif menu.startswith("<Image>") or menu.startswith("<Save>"):
                params.insert(0, (PDB_IMAGE, "image", "Input image", None))
                params.insert(1, (PDB_DRAWABLE, "drawable", "Input drawable", None))
                if menu.startswith("<Save>"):
                    params[2:2] = file_params

    _registered_plugins_[proc_name] = (blurb, help, author, copyright,
                                       date, label, imagetypes,
                                       plugin_type, params, results,
                                       function, menu, domain,
                                       on_query, on_run)
Melewo
User
Beiträge: 320
Registriert: Mittwoch 3. Mai 2017, 16:30

Donnerstag 27. Juli 2017, 16:40

Es lag an dieser veränderten Reihenfolge und den überalterten Beispielen im Web, in denen beinahe ausnahmslos noch die ältere Reihenfolge verwendet wurde und es lag nicht zuletzt an mir, weil ich mir erst viel zu spät die gimpfu.py richtig betrachtete. Nun lässt es sich mit () definieren und abfragen.

Code: Alles auswählen

def erstelle_neues_image():   
[codebox=pycon file=Unbenannt.txt]>>> pdb.python_fu_erstelle_neues_image()[/code]
Melewo
User
Beiträge: 320
Registriert: Mittwoch 3. Mai 2017, 16:30

Freitag 28. Juli 2017, 07:40

Mit dem Import ohne Sternchen hat es nun geklappt, deshalb beide Beispiele noch einmal, bei denen keine "Problemchen" mehr auftraten. Als nächster Parameter bei der Registrierung könnte eine Textdomain gesetzt werden, falls ein Plugin mehrsprachig ausgelegt werden soll.

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from gimpfu import main, register
import gimp

def erstelle_begruessung():
    gimpversion  = gimp.version                             # Tupel mit 3 Integer-Werten
    begruessung  = "Hallo Welt!\nGimp Version {}".format(
                   ".".join(map(str, gimpversion)))
    gimp.message(begruessung)

register(
    "erstelle_begruessung",                                 # Plugin Name gleich Funktions-Name
    "Begrüßung erstellen",                                  # Kurzbeschreibung
    "Einen Eintrag mit Begrüßung im Hilfe-Menü erstellen",  # Längere Beschreibung
    "Mele Melewo",                                          # Plugin Autor
    "MIT-Lizenz",                                           # Angaben zur Lizenz
    "2017",                                                 # Jahr der Veröffentlichung
    "Begrüßung",                                            # Label
    None,                                                   # Akzeptierte Image-Typen
    [],                                                     # Input Parameter
    [],                                                     # Output Resultate
    erstelle_begruessung,                                   # Name der Methode (warum Methode und nicht Funktion?)
    menu="<Image>/Help/Hinweise"                            # Position im Menü
    )

main()

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from gimpfu import pdb, register, main, RGB, RGB_IMAGE, NORMAL_MODE, BACKGROUND_FILL

def erstelle_neues_image():
    width  = 600
    height = 400

    # Ein neues Image erzeugen.
    image = pdb.gimp_image_new(width, height, RGB)
    # Für das Image mindestens eine Ebene erzeugen und die Ebene hinzufügen.
    ebene = pdb.gimp_layer_new(
            image, width, height, RGB_IMAGE, "ebenen-name", 100, NORMAL_MODE)
    pdb.gimp_image_insert_layer(image, ebene, None, 1)
    # Eine Hintergrundfarbe auswählen und das Image damit füllen.
    pdb.gimp_context_set_background((255,138,0))
    pdb.gimp_drawable_fill(ebene, BACKGROUND_FILL)
    # Da neu erzeugte Image anzeigen.
    pdb.gimp_display_new(image)


register(
    "erstelle_neues_image",                       # Plugin Name
    "Neues Image erstellen",                      # Kurzbeschreibung
    "Ein neues Image erstellen",                  # Längere Beschreibung
    "Mele Melewo",                                # Plugin Autor
    "MIT-Lizenz",                                 # Angaben zur Lizenz
    "2017",                                       # Jahr der Veröffentlichung
    "Neues Image",                                # Label
    "*",                                          # Akzeptierte Image-Typen
    [],                                           # Input Parameter
    [],                                           # Output Resultate
    erstelle_neues_image,                         # Name der Funktion
    "<Image>/Filters/Eigene"                      # Position im Menü
    )

main()
Antworten