Tkinter-Fenster in Gimp

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

Hier bitte `os.path.join()` verwenden. Wäre doch doof wenn Gimp unter Windows und Linux funktioniert, das Plugin dann aber nur unter Windows. :-)
gahleitner
User
Beiträge: 35
Registriert: Montag 1. Mai 2017, 09:57

Hallo!

Hier ein Code:

Code: Alles auswählen

#!/usr/bin/env python
import os
from gimpfu import *

def batch(img, layer, inputFolder, outputFolder, radius, staerke,schwelle,farbe,hsv,scharf):

    # Iterate the folder	
    for file in os.listdir(inputFolder):
        try:
            # Build the full file paths.
            inputPath = inputFolder + "\\" + file
            outputPath = outputFolder + "\\" + file
        
            # Open the file if is a JPEG or PNG image.
            image = None
            if(file.lower().endswith(('.jpeg', '.jpg'))):
                image = pdb.file_jpeg_load(inputPath, inputPath)
                
            # Verify if the file is an image.

            if(image != None):
                # Invert the image.
                if(len(image.layers) > 0):
                    layer = image.layers[0]
                    if farbe==1:
                        pdb.plug_in_color_enhance(image,layer) 
                    if hsv==1:
                        pdb.plug_in_autostretch_hsv(image,layer)
                    if scharf==1:
                        pdb.python_fu_regle_schaerfe(image,layer,radius,staerke,schwelle) 
                    
                    # Save the image.
                    if(file.lower().endswith(('.jpeg', '.jpg'))):
                        pdb.file_jpeg_save(image, image.layers[0], outputPath, outputPath, 0.9, 0, 0, 0, "Creating with GIMP", 0, 0, 0, 0)
        except Exception as err:
            gimp.message("Unexpected error: " + str(err))

register(
    "python_fu_automatic",
    "Automatik",
    "Apply the cartoon filter to the PNG and JPEG images of a folder.",
    "Gerhard Gahleitner",
    "Open source (BSD 3-clause license)",
    "2017",
    "<Image>/Filters/Test/Macro",
    "*",
    [    
        (PF_DIRNAME, "inputFolder", "Eingabeordner", ""),
        (PF_DIRNAME, "outputFolder", "Ausgabeordner", ""),
        (PF_TOGGLE, "farbe",   "Farbverbesserung:", 1), # initially True, checked.  Alias PF_BOOL
        (PF_TOGGLE, "hsv",   "HSV strecken:", 1),
        (PF_TOGGLE, "scharf",   "Schaerfen:", 1),
        (PF_SLIDER, "radius", "Radius", 4, (0,100,0.1)),
        (PF_SLIDER, "staerke", "Menge" , 5, (0.0,10,0.01)),
        (PF_SLIDER, "schwelle", "Schwellwert:", 0, (0, 255, 1))
    ],
    [],
    batch)

main()
Anscheinend stimmt was mit den Abfragen nicht: Schreibe ich if farbe: dann macht es alle Bearbeitungen, bei if farbe==1 macht es keine Bearbeitung - in beiden Fällen ist es egal, ob ich "Yes" oder "No" wähle. Beim Schärfen sieht man am Macrorecorder, dass es arbeitet - am Bild sieht man aber, dass es nicht geschärft ist. Das Schärf-Tool funktioniert aber als Standalone einwandfrei. Hier noch der Code für das Schärftool:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-
 
from gimpfu import pdb, register, main, PF_IMAGE, PF_DRAWABLE, PF_SLIDER
 
def regle_schaerfe(image, layer, radius, staerke, schwelle):

    ww=pdb.gimp_image_width(image)
    hh=pdb.gimp_image_height(image)
	
    pdb.gimp_image_undo_group_start(image) #(img)
	
    pdb.gimp_edit_copy(image.layers[0])	#HSV kann nur im RGB Modus nachbearbeitet werden.
    rgb_layer=pdb.gimp_layer_new(image,ww,hh,0,"Neue Ebene",100,0)#RGB_IMAGE
    pdb.gimp_image_add_layer(image,rgb_layer,-1)
    floating=pdb.gimp_edit_paste(rgb_layer,True)
    pdb.gimp_floating_sel_anchor(floating)

##    pseudolab_layer=image.layers[1]
    
    pdb.gimp_image_undo_group_start(image)
 
    temp_image = pdb.plug_in_decompose(image, layer, "HSV", 0)
    arbeits_ebene = pdb.gimp_image_get_active_layer(temp_image[2])
    pdb.plug_in_unsharp_mask(image, arbeits_ebene, radius, staerke, schwelle)
    view_image = pdb.plug_in_compose(temp_image[0],arbeits_ebene,temp_image[1],temp_image[2],temp_image[3],"HSV")
    pdb.gimp_image_undo_group_end(image)
#    pdb.gimp_display_new(neues_image)

    view_image_layer=pdb.gimp_image_get_active_layer(view_image)	
    pdb.gimp_edit_copy(view_image_layer)
    floating=pdb.gimp_edit_paste(image.layers[0],True)
    pdb.gimp_floating_sel_anchor(floating)

    pdb.gimp_image_set_active_layer(image,image.layers[0])
#    pdb.gimp_image_set_active_layer(view_image,view_image_layer)
    pdb.gimp_image_undo_group_end(image) 
#    pdb.gimp_display_new(view_image)
#    pdb.gimp_image_delete(image)

	
    for i in range(len(temp_image)):
        if temp_image[i] is not None:
            pdb.gimp_image_delete(temp_image[i])
    pdb.gimp_image_remove_layer(image,image.layers[1])
 
register(
    "regle_schaerfe",
    "Test Schärferegler",
    "Nur ein Test mit einem Schärferegler",
    "Gerhard Gahleitner",
    "MIT-Lizenz",
    "2017",
    "Schärfen",
    "RGB*",
    # PF_SLIDER - Voreinstellung, (min, max, Schrittweite)
    [
        (PF_IMAGE, "image", "Input Image", None),
        (PF_DRAWABLE, "layer", "Input Ebene", None),
        (PF_SLIDER, "radius", "Radius", 4.0, (0.1, 100, 0.1)),
        (PF_SLIDER, "staerke", "Stärke", 5.0, (0.1, 10, 0.01)),
        (PF_SLIDER, "schwelle", "Schwellwert:", 0, (0, 255, 1))
    ],
    [],
    regle_schaerfe,
    menu="<Image>/Colors/Auto")
 
main()
Ich wollte nicht, dass sich eine neue Datei erstellt wird, hab es daher ein bisschen erweitert.
Gibt es eine Doku über die PF_ Module und deren Definitionen?
Gibt es auch eine Möglichkeit, den "Macrorecorder" auch ohne geöffnetes Bild zu starten? Wenn ich bei RGB das * entferne, bekomme ich beim Ablauf eine Fehlermeldung.
Kannst du mir helfen?

Tschüss
Gerhard
Melewo
User
Beiträge: 320
Registriert: Mittwoch 3. Mai 2017, 16:30

gahleitner hat geschrieben:Kannst du mir helfen?
Ja, das könnte ich, nur nicht unbedingt in den nächsten zwei Tagen.
gahleitner hat geschrieben:Gibt es eine Doku über die PF_ Module und deren Definitionen?
Das wird aber alles nichts, wenn Du Dich nicht weiter in Python einarbeitest, um Anmerkungen und Hinweise, wie z.B. von BlackJack gegeben, aufzunehmen und umzusetzen und um den Unterschied zwischen Konstanten und Modulen zu erkennen.

Und wo stehen Konstanten, na z.B. in der gimpfu.py, in die man ja zumindest ab und an mal einen Blick werfen könnte. Der Rest lässt sich dann wohl von allein erahnen, wenn man liest:

Code: Alles auswählen

# In Zeile 116
PF_BOOL = PF_TOGGLE

# In Zeile 153
PF_TOGGLE : PDB_INT32,

# In Zeile 190
PF_TOGGLE : bool,
Und wenn es sich nicht von allein ergibt, muss man halt auch noch einmal in Python von vorn beginnen. Gut, das hatte bei mir auch länger als 3 Wochen gedauert.
Und nach der gimpfu.py könnte man sich auch gimp und die libgimp von innen ansehen, alles zu finden unter "git.gnome.org". Nun gut, wichtiger ist erst einmal Python, man kann kein Plugin in Python entwickeln wollen, wenn man Python noch nicht besser kennt.

Und was nicht minder wichtig ist, wenn etwas nicht gleich wie erwartet funktioniert, dann lieber in kleineren Schritten vorgehen, bis man die einzelnen Schritte versteht oder zumindest denkt, diese zu verstehen. Bei größeren Anwendungen kann es nicht schaden, sich einen Ablaufplan zu erstellen. Meist wird es im Kopf gehen, doch Zettel mit Notizen und Kommentare in den Scripts helfen auch bei kleineren Abläufen. Testreihen von einzelnen Schritten tragen immer oder zumindest meisten zum besseren Verständnis bei.

Code: Alles auswählen

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

from gimpfu import main, register, PF_TOGGLE
import gimp

def checke_werte(name, data):
    if data is True:
        return "{0} ist {1}\n".format(name, data)
    elif data is False:
        return "{0} ist {1}\n".format(name, data)

def checke_toggle(farbe, hsv_typ, scharf):
    # Ausgabe in Widget
    gimp.message(
        "{0}{1}{2}".format(
            checke_werte("Farbe", farbe),
            checke_werte("HSV", hsv_typ),
            checke_werte("Schaerfen", scharf)
            )
        )

register(
    "checke_toggle",
    "Beispiel mit Toggle",
    "Nur ein Beispiel mit PF_TOGGLE",
    "Mele Melewo",
    "MIT-Lizenz",
    "2017",
    "Beispiel Toggle",
    None,
    [
        (PF_TOGGLE, "farbe", "Farbe: ", True),
        (PF_TOGGLE, "hsv_typ", "HSV: ", False),
        (PF_TOGGLE, "scharf", "Schaerfen: ", True)
    ],
    [],
    checke_toggle,
    menu="<Image>/Eigene/PF-Tests"
    )

main()
gahleitner
User
Beiträge: 35
Registriert: Montag 1. Mai 2017, 09:57

Hallo!
Hab den Fehler gefunden. Die Toggle hatten die Werte der Slider und umgekehrt. Wie kann das kommen? Hab ich auch schon behoben.
Kann der Macrorecorder auch ohne geöffnetes Bild laufen?
@Blackjack: Wo muss os.path.join() verwenden? Bei Import os?

Tschüss
Gerhard
BlackJack

@gahleitner: `os.path.join()` verbindet Pfadteile. Und zwar plattformunabhängig. Das hier: ``inputFolder + "\\" + file`` wird unter Linux oder MacOS zum Beispiel nicht funktionieren weil dort der \ nicht der Pfadtrenner ist.
Melewo
User
Beiträge: 320
Registriert: Mittwoch 3. Mai 2017, 16:30

gahleitner hat geschrieben:Gibt es eine Doku über die PF_ Module und deren Definitionen?
...
Kannst du mir helfen?
So, nun noch einmal zum Helfen.
Was verstehst Du unter Hilfe?

Nur aufzeigen, wie man etwas schreiben könnte, bringt ja nichts, wenn der andere am Ende nicht versteht, warum es so geschrieben werden könnte. Zum Verstehen gehören Grundkenntnisse in Python und zu diesen Grundkenntnissen wiederum gehören z.B. die wichtigsten Datentypen, wie String, Integer, Floot oder Bool und die stehen in jedem für Einsteiger geeigneten Buch recht weit vorn. Wenn man diese aber kennt, ist es einfach in der gimpfu.py nachzulesen, zu welchem Datentyp eine für die Parameterübergabe gebräuchliche Konstante gehört, insofern sich das nicht bereits aus dem Namen einer Konstanten ableiten lässt.
Wo die gimpfu.py bei Dir liegt, bekommst Du heraus, in dem Du in der Python-Fu Konsole einfach nur

[codebox=pycon file=Unbenannt.txt]import gimpfu
help(gimpfu)[/code]
eingibst, der Pfad zur Datei wird mit aufgeführt. Beispiel:

[codebox=pycon file=Unbenannt.txt]>>> import gimpfu
>>> help(gimpfu)

Help on module gimpfu:

NAME
gimpfu - Simple interface for writing GIMP plug-ins in Python.

FILE
c:\program files\gimp 2\32\lib\gimp\2.0\python\gimpfu.py[/code]
Die Konstanten plus Datentypen werden in den Dictionaries "_type_mapping" und "_obj_mapping" aufgeführt. Weiterhin sollte man die Beschreibung in der gimpfu.py mindestens einmal gelesen haben. Nun weiß ich nicht, wie Deine Englischkenntnisse sind, ich muss mir alles was wichtig ist zumindest erst einmal von Google übersetzen lassen, doch meisten sind die Übersetzungen verständlich genug.

Beispiel aus der gimpfu.py
[codebox=text file=Unbenannt.txt]You can use any of the PF_* constants below as parameter types, and anappropriate user interface element will be displayed when the plug-in is run in interactive mode. Note that the the PF_SPINNER and PF_SLIDER types expect a fifth element in their description tuple -- a 3-tuple of the form (lower,upper,step), which defines the limits for the slider or spinner.[/code]
Übersetzung mit Google:
[codebox=text file=Unbenannt.txt]Sie können eine beliebige der folgenden PF_ * Konstanten als Parametertypen verwenden und ein passendes Benutzerschnittstellenelement wird angezeigt, wenn das Plug-In im interaktiven Modus ausgeführt wird. Beachten Sie, dass die PF_SPINNER- und PF_SLIDER-Typen ein fünftes Element in ihrem Beschreibungstupel erwarten - ein 3-Tupel des Formulars (unten, oberer, Schritt), der die Grenzen für den Schieberegler oder den Spinner definiert.[/code]
Die zweite Quelle für Konstanten und anderes wäre dann diese bereits oft verlinkte Seite:

https://www.gimp.org/docs/python/

Die habe ich mir gleich zweisprachig ausgedruckt. Das hat dann zwar etwas länger als eine Stunde gedauert, weil ich die Übersetzungen absatzweise einfügte und die englischen Texte dabei etwas ausgraute, doch dafür habe ich etwas zu liegen, mit dem man gut arbeiten kann.

Aus dem Original:
[codebox=text file=Unbenannt.txt]These values map onto the standard PARAM_* constants. The reason to use the extra constants is that they give gimpfu more information, so it can produce a better interface (for instance, the PF_FONT type is equivalent to PARAM_STRING, but in the GUI you get a small button that will bring up a font selection dialog).

The PF_SLIDER, PF_SPINNER and PF_ADJUSTMENT types require the extra parameter. It is of the form (min, max, step), and gives the limits for the spin button or slider.

The results parameter is a list of 3-tuples of the form (type, name, description). It defines the return values for the function. If there is only a single return value, the plugin function should return just that value. If there is more than one, the plugin function should return a tuple of results.[/code]
Übersetzung mit Chrome ist etwas gebrochenes, dennoch verständliches Deutsch:
[codebox=text file=Unbenannt.txt]Diese Werte werden auf die Standard-PARAM_ * -Konstanten abgebildet. Der Grund, die zusätzlichen Konstanten zu verwenden, ist, dass sie gimpfu mehr Informationen geben, also kann es eine bessere Schnittstelle produzieren (zum Beispiel ist der PF_FONT-Typ äquivalent zu PARAM_STRING, aber in der GUI bekommst du eine kleine Schaltfläche, die eine Schriftartauswahl hervorbringt Dialog).

Die Typen PF_SLIDER, PF_SPINNER und PF_ADJUSTMENT benötigen den zusätzlichen Parameter. Es ist von der Form (min, max, step), und gibt die Grenzen für die Spin-Taste oder Schieberegler.

Der Ergebnisparameter ist eine Liste von 3-Tupeln des Formulars (Typ, Name, Beschreibung). Sie definiert die Rückgabewerte für die Funktion. Wenn es nur einen einzigen Rückgabewert gibt, sollte die Plugin-Funktion nur diesen Wert zurückgeben. Wenn es mehr als eins gibt, sollte die Plugin-Funktion ein Tupel von Ergebnissen zurückgeben.[/code]

Dann noch eine dritte Quelle, zwar in Scheme beginnend mit SF- und nicht mit PF_, doch dafür in deutscher Sprache und mit richtiger Beschreibung, so dass nur kleinere Anpassungen erforderlich sind:

https://docs.gimp.org/de/gimp-using-scr ... cript.html

Dann allgemein etwas zu den Beispielen, die sind alle gut und schön und die Leistung von den jeweiligen Script-Autoren sollte durchaus anerkannt werden. Nur die Beispiele sind halt in die Jahre gekommen und man sollte sich halt die "PEP 8 - Style Guide for Python Code" einmal durchlesen und eigene Scripts dann danach ausrichten. Auf der Vorseite verlinkt und auf dieser Seite übernimmst Du bereits wieder ein Beispiel mit Sternchenimport und Variablen in camelCase-Schreibweise, statt diese gleich zu korrigieren. Irgendwie so, als hättest Du Dir die Seite nicht einmal angeschaut, wo sich doch vieles bereits ohne zu lesen aus "Yes:" und "No:" ergibt.

Also, helfen ja, doch Hilfe ist auch darauf zu verweisen, wo sich Erklärungen und Lösungen befinden, statt diese nur wiedergeben zu wollen. Und da wurde bereits auf sehr vieles verwiesen, würde ich meinen.
Melewo
User
Beiträge: 320
Registriert: Mittwoch 3. Mai 2017, 16:30

Oben ist mir ein dummer Fehler passiert, Floot sollte selbstverständlich Float heißen.
Jedenfalls werden die Datentypen alle in der gimpfu aufgeführt.
gahleitner
User
Beiträge: 35
Registriert: Montag 1. Mai 2017, 09:57

Hallo!

Wie kann ich erreichen,dass das Skript auch das Bildformat erkennt - hab es mit if width>height und image_width, image_height versucht, konnte auch sonst nichts passendes finden.
Außerdem möchte ich auch ein Bild skalieren können, mit gimp_image_scale und gimp_context_set_interpolation gehts es schon ganz gut, aber die auflösung kann ich nirgends einstellen.
Wie ich schon mal geschrieben habe, möchte ich - wenn es möglich ist - das Skript auch ohne geöffnetes Bild starten. Wenn ich in register das Sternchen (*) entferne, geht es, aber es werden 2 zusätzliche Sachen (input Image und Input Drawable) angezeigt. Kann man das unterbinden?

@BlackJack: inputFolder + "\\" + file müßte also inputFolder + os.path.join() + file heißen, oder?

Tschüss
Gerhard
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Nur zum letzten: nein. os.path.join(a, b, ...)
Melewo
User
Beiträge: 320
Registriert: Mittwoch 3. Mai 2017, 16:30

gahleitner hat geschrieben:Wie ich schon mal geschrieben habe, möchte ich - wenn es möglich ist - das Skript auch ohne geöffnetes Bild starten. Wenn ich in register das Sternchen (*) entferne, geht es, aber es werden 2 zusätzliche Sachen (input Image und Input Drawable) angezeigt. Kann man das unterbinden?
Und das hatte ich hier bereits geschrieben. Wenn bei der Registrierung die neue Reihenfolge nicht beachtet wird, greift ein "Notfallplan", beim dem es zu einer Zwangszuweisung von "file_params" kommt, damit ältere Plugins weiterhin lauffähig bleiben:

viewtopic.php?f=4&t=40877&start=15#p312607

Selbstverständlich muss darüber hinausgehend, wie bei allen Funktionen, die Anzahl der definierten Parameter mit denen im Funktionskopf übereinstimmen. Bei Deinen letzten Beispielen sehe ich aber

Code: Alles auswählen

def regle_schaerfe(image, layer, ...):
und somit müssen image und layer auch mit übergeben oder mit None belegt werden, wodurch die aber überflüssig wären.
Antworten