Porting a GIMP2 python script to GIMP3 (original) (raw)

Hello all,
I am using Gimp2 since years and therefore I have implemented some for me useful python scripts. If I try to use them with Gimp3 (putting them to the plugin folder) they are not recognized at startup and I can not use them.
I attached one of my plugins at the end, maybe someone of the community could help me porting that in the way that I could use it with Gimp3.

I would be glad about some hints and help.

Kind regards Christoph

PS: If I am here with my question at the wrong place, please let me know.

#!/usr/bin/env python

from gimpfu import *

# script ##########################################################
def scaleH540(image, drawable) :
    gprint("Function: scaleH540")
    height = 540
    numLayer, layer_ids = pdb.gimp_image_get_layers(image)
    gprint("Number of layers: "+str(numLayer))
    for i in range(0, numLayer):        
        layer=image.layers[i]        
        layerName=str(layer)        
        if layerName.upper().find('JPG') != -1:
            aspect_ratio=float(layer.width)/float(layer.height)
            newWidth = int(round(height*aspect_ratio))
            gprint(str(i)+ ": "+layerName.upper().replace("<GIMP.LAYER '", "").replace("'>", "")+" - NewWidth: "+str(newWidth))
            pdb.gimp_layer_scale(layer,newWidth,height,FALSE)    
    return

# script ##########################################################
# This is the plugin registration function
register(
    "ScaleLayer",     
    "Scale 540 Height",   
    "This script does scale marked layers of the image",
    "Christoph Raber",
    "Christoph Raber", 
    "May 2021",
    #"<Image>/MyScripts/My First Python-Fu",
    #"<Image>/MyHelpers/Scale 6000",
    "<Image>/MyHelpers/Scale Layers H540",
    "*", 
    [
    ], 
    [],
    scaleH540,
    )

main()

nelo March 30, 2025, 9:24am 2

Instead of your script: could Kamil Burda’s “batcher” help?

alex666 March 30, 2025, 5:12pm 3

Great in principle!
But

This batcher does not help really because I would like to write my own scripts and so I am searching for help to port/use my old ones or at least for examples how to write and integrate scripts for and into the new Gimp3.

nelo March 30, 2025, 5:47pm 5

Official tutorial is here
https://testing.developer.gimp.org/resource/writing-a-plug-in/tutorial-python/

A good example also is the foggify.py plug-in which comes with GIMP

And api-docs are here:

Trouble with those docs: they are for C and not specifically for python.
But one can imagine most of the time what the python-terms are.

Using the search field can be a help.

Thank you for your fast response. I have found foggify.py in the plug-ins, and after some search in my german menu structur of GIMP3. But I have got the fear that it is not so easy to port my old scripts. In foggify.py for me it is not obvious at the first view, what happens, buy i will give it a try.
More hints and easier examples would be welcomed.

nelo March 31, 2025, 2:07pm 7

@Christoph_Raber,
you can download a “starter script” from here

unpack, put the scale_layer.py in a folder named scale_layer. Put that altogether in the plug-ins folder for GIMP.
When starting, it should produce a GIMP message.
I’ve placed your code as a comment into the right place. All you have to do now is to convert to GIMP3 terminology.
(Lots of comments left in the whole script, which of course can be deleted when production-ready.)
Hope that helps.

Hello Nelo, thank you very much, I now checked your adaption of my code, and it helped me really a lot.
Now I have a menu entry with the script and some outputs in the (error)consol of GIMP. But I am still struggeling with the translation of the C API to Python.
When I write

newWidth = 20
newHeight = 40
for layer in layers: 
    layerName=layer.get_name()
    Gimp.message("layerName " + layerName)           
    layer.scale(newWidth, newHeight, FALSE)

the layerName is printed as expected but calling the “scale” interface produces an error. I tried different versions how to call the interface I found in the API reference

gimp_layer_scale (  GimpLayer* layer,  gint new_width,  gint new_height,  gboolean local_origin)

but nothing had the expected result. Could you please support me here again?
Kind regards
Christoph

jboerema (Jacob Boerema) April 17, 2025, 9:42pm 9

Using False instead of FALSE should fix it.

My next question.
I try to call the filter “Enhance/Sharpen (Unsharp mask)” in my python script.

In the past (with Gimp2) I used the interface “pdb.plug_in_unsharp_mask()”,
but in Gimp3 I do not find this procedure/plugin, whenever it is available via the same menu.

How could I find the new name?
Kind regards
Christoph

nelo April 18, 2025, 2:38pm 12

That’s a GEGL filter now and goes like this:

f = Gimp.DrawableFilter.new(your_layer, "gegl:unsharp-mask", "")
filter_config = f.get_config()
filter_config.set_property('std-dev', 3.0)  # radius
filter_config.set_property('scale', 0.25)  # amount
filter_config.set_property('threshold', 0.0)
# your_layer.append_filter(f)
your_layer.merge_filter(f)

replace your_layer with the appropriate name, of course

PS.: you find GEGL operations here
https://gegl.org/operations/index.html

Hi Nelo,

again thank you for your fast and great support.

And also thank you for the link with the GEGL operations.
Where do I find information about “append/merge_filter”? Are there more such interfaces that could be or have to be used with the GEGL operations?

I will go on transform my scripts to the new interfaces. I hope it is ok if i will ask again, if there is the next question :slight_smile:
Kind regards and a relaxing weekend
Christoph

Ofnuts April 18, 2025, 7:30pm 14

(search for “filter” in that page: 22 hits)

Some hints for inferring how Python works from that documentation: Converting the API doc to Python

Thank you for help, but there is the next problem I have got.

def generateBackgroundLayer(image, drawable, width, height):
    Gimp.message("enter generateBackgroundLayer")
    new_layer = image.layer_new ("Background", width, height, GIMP_RGB_IMAGE, 100, GIMP_LAYER_MODE_NORMAL_LEGACY)
    image.insert_layer (new_layer, NULL, -1)
    image.lower_item_to_bottom (new_layer)  
    Gimp.message("exit generateBackgroundLayer")
    return

The call layer_new() is not working, what is wrong?

GimpLayer*
gimp_layer_new (
  GimpImage* image,
  const gchar* name,
  gint width,
  gint height,
  GimpImageType type,
  gdouble opacity,
  GimpLayerMode mode
)

And is there a possiblity to debug something like this in a better way than only putting Gimp.messages() behind each line of code.

Kind regards
Christoph

nelo April 19, 2025, 5:45pm 16

This is my “template” for inserting new layers:

layer_new = Gimp.Layer.new(image, 
                               "Name", 
                               width, 
                               height, 
                               Gimp.ImageType.RGBA_IMAGE, 
                               100.0,
                               Gimp.LayerMode.NORMAL)
image.insert_layer(layer_new, drawable.get_parent(), len(layers) + 1)

Instead of drawable.get_parent() you can also use None if there are no groups.

For debugging, I start GIMP from the terminal (I’m on Linux).
Then I can see what messages GIMP/ Python produces and normally see what the problem is.

Ofnuts

April 19, 2025, 8:17pm 17

One thing that helps a lot in Gimp3 is using an IDE, and adding “types hints”. This gives you useful code completion while writing code and lots of problems are caught before you even try to execute the code(*).

image

On Linux at least, you can have the plugin execute under the Python built-in debugger. You just change the “shebang” from a regular call:

#!/usr/bin/env python3 

to a version that invokes the debugger

#!/usr/bin/env -S python3 -m pdb

This may need to be refined because the debugger is invoked every time the code runs (registrations, and execution). And of course Gimp must be started from a terminal:

image

But I don’t know if:

  1. Gimp on Windows abides to the shebang or just says “ends in .py let’s launch Python” and in which case if this can be changed by hacking the interpreters/default.interp file
  2. If you can interact with the debugger if the gimp-console.exe window.

Anyway, In practice, a CLI debugger is IMHO(**) not that much better than a couple of print instructions.

There may be a GUI debugger for Python on your OS somewhere, in which case it could just be a matter of changing the shebang. This would also be a solution on Linux and OSX.

(*) In Gimp2/Python v2.7, it usually took me 5-6 executions before the code even registered, due to various mistakes (bad function names, etc…). In Gimp3/python3.12 with an IDE, registration often works on first try.

(**) I learned programming before GUI IDEs were in fashion, so I could be biased.

Again thank you for your replay.
The line Gimp.Layer.new works, but the image.insert_layer now stops the execution of the plugin.
I am working on a Windows10 platform and there also with starting Gimp form command shell with “–verbose --stack-trace-mode=always --debug-handlers” does not show any errors. Only in the Warning window of Gimp I see that the plugin does not finish correctly.

Back to the call of Gimp.Layer.new. I thought that if I have got an object of type image or drawable, I could use one of its procedures to add a layer, instead of using something general like Gimp.Layer. But I think I not yet understand the object model of gimp.

Long writing, short message, I am still struggeling to add a layer to my image via python script. I hoped this is a very basic funtionality. :frowning:

Hi Ofnuts, thank you for your support.
I am running gimp on a windows 10 platform. If I try to use a IDE like VSC, the code completion does not really work because it does not know the imported libs. If I try to install them via pip I struggle also with problems. So I think I have to work with printf, but sometimes that is a quite slow kind of working.

Ofnuts April 20, 2025, 9:39am 20

Normally no need to add them. You see may need to set up your Python path in the IDE to include the directories with the Python modules that come from Gimp.