How to run python scripts using gimpfu from command line?

10,561

To run a python script you don't need to have it register as a plugin. IMHO you should even avoid this, this unnecessarily pollutes Gimp's menus and procedure name space. Here is an example:

The batch script (saved as batch.py):

#!/usr/bin/python
# -*- coding: iso-8859-15 -*-

import os, glob, sys, time
from gimpfu import *


def process(infile):
        print "Processing file %s " % infile
        image = pdb.gimp_file_load(infile, infile, run_mode=RUN_NONINTERACTIVE)
        drawable = image.active_layer

        print "File %s loaded OK" % infile
        pdb.plug_in_photocopy(image, drawable,8.,0.8,0.2,0.2)
        pdb.plug_in_cartoon(image, drawable, 7.,0.2)
        outfile=os.path.join('processed',os.path.basename(infile))
        outfile=os.path.join(os.path.dirname(infile),outfile)
        print "Saving to %s" % outfile
        pdb.file_jpeg_save(image, drawable, outfile, outfile, "0.5",0,1,0,"",0,1,0,0)
        print "Saved to %s" % outfile
        pdb.gimp_image_delete(image)


def run(directory):
        start=time.time()
        print "Running on directory \"%s\"" % directory
#   os.mkdir(os.path.join(directory,'processed'))
        for infile in glob.glob(os.path.join(directory, '*.jpg')):
                process(infile)
        end=time.time()
        print "Finished, total processing time: %.2f seconds" % (end-start)


if __name__ == "__main__":
        print "Running as __main__ with args: %s" % sys.argv

To call it:

gimp -idf --batch-interpreter python-fu-eval -b "import sys;sys.path=['.']+sys.path;import batch;batch.run('./images')" -b "pdb.gimp_quit(1)"

The parameters in slow-motion:

  • -idf: work without user interface, and load neither data nor fonts (you may perhaps need to keep the fonts to load pdfs)
  • --batch-interpreter python-fu-eval: whatever follows -b is Python, not script-fu
  • "import sys;sys.path=['.']+sys.path;import batch;batch.run('./images')": the code that we ask Gimp to execute, namely:
    • import sys;sys.path=['.']+sys.path;: extend the import path to include the current directory
    • import batch;: import the file with our script, which is now in a directory which is part of the path.
    • batch.run('./images'): call the run() function of the batch module we imported, giving it the name of a directory containing the images to process.
  • -b "pdb.gimp_quit(1)": another piece of python: exit when done.

Note how the command line cleverly uses double and single quotes to pass all parameters to Gimp and then to Python(*). And yes, you can use forward slashes as file separators in Windows.

To debug, matters are bit complicated in Windows because there is no always a stdout stream. Things that can help:

  • remove the -i parameter temporarily so that you get the UI and perhaps a chance to see messages.
  • Add --verbose which makes Gimp start a secondary console window.
  • There are other tricks to see messages listed here.
  • You can also start Gimp normally and run your script from the Python-fu console (Filters>Python-fu>Console). You will have to extend the path and import the file "manually".

(*) In a Linux/OSX shell one would do the opposite: single quotes for the shell, double quotes for Python.

Share:
10,561
flixe
Author by

flixe

Updated on June 22, 2022

Comments

  • flixe
    flixe almost 2 years

    I'm trying to use functions of gimp 2.8.22 to convert a pdf to jpeg and i want to do that with a python script using the gimpfu library from my windows cmd (i have installed python 3.6.1).

    Right now, i't trying to do that with an example script:

    #!/usr/bin/env python
    
    # Hello World in GIMP Python
    
    from gimpfu import *
    
    def hello_world(initstr, font, size, color) :
        # First do a quick sanity check on the font
        if font == 'Comic Sans MS' :
            initstr = "Comic Sans? Are you sure?"
    
        # Make a new image. Size 10x10 for now -- we'll resize later.
        img = gimp.Image(1, 1, RGB)
    
        # Save the current foreground color:
        pdb.gimp_context_push()
    
        # Set the text color
        gimp.set_foreground(color)
    
        # Create a new text layer (-1 for the layer means create a new layer)
        layer = pdb.gimp_text_fontname(img, None, 0, 0, initstr, 10,
                                       True, size, PIXELS, font)
    
        # Resize the image to the size of the layer
        img.resize(layer.width, layer.height, 0, 0)
    
        # Background layer.
        # Can't add this first because we don't know the size of the text layer.
        background = gimp.Layer(img, "Background", layer.width, layer.height,
                                RGB_IMAGE, 100, NORMAL_MODE)
        background.fill(BACKGROUND_FILL)
        img.add_layer(background, 1)
    
        # Create a new image window
        gimp.Display(img)
        # Show the new image window
        gimp.displays_flush()
    
        # Restore the old foreground color:
        pdb.gimp_context_pop()
    
    register(
        "python_fu_hello_world",
        "Hello world image",
        "Create a new image with your text string",
        "Akkana Peck",
        "Akkana Peck",
        "2010",
        "Hello world (Py)...",
        "",      # Create a new image, don't work on an existing one
        [
            (PF_STRING, "string", "Text string", 'Hello, world!'),
            (PF_FONT, "font", "Font face", "Sans"),
            (PF_SPINNER, "size", "Font size", 50, (1, 3000, 1)),
            (PF_COLOR, "color", "Text color", (1.0, 0.0, 0.0))
        ],
        [],
        hello_world, menu="<Image>/File/Create")
    
    main()
    

    I try to run the script from my cmd like this:

    gimp-2.8 --no-interface --batch '(python_fu_hello_world RUN-NONINTERACTIVE "Hello" Arial 50 red)' -b '(gimp-quit 1)'
    

    However, no matter what i do, i always geht the same error message:

    (gimp-2.8:1020): LibGimpBase-WARNING **: gimp-2.8: gimp_wire_read(): error

    edit: Ok, thanks. I left out the interface statement and I also tried out the most simple example to figure out whats wrong:

    #!/usr/bin/env python
    
    # Hello World in GIMP Python
    
    from gimpfu import *
    
    def hello_world():
     gimp.message("Hello, GIMP world!\n")
    
    register(
     "hello_world",
     'A simple Python-Fu "Hello, World" plug-in',
     'When run this plug-in prints "Hello, GIMP world!" in a dialog box.',
     "Tony Podlaski",
     "Tony Podlaski 2017. MIT License",
     "2017",
     "Hello World",
     "",
     [],
     [],
     hello_world,
     menu="<Image>/Filters/HelloWorld",
    )
    
    main()
    

    The script actually works when i run it from Gimp itself, but when i try to run it from my cmd, Gimp opens with another cmd saying: Error: ( : 1) eval: unbound variable: hello_world

    Does someone know what i'm missing here?

  • flixe
    flixe almost 7 years
    Thank you. I've edited my original post, because i still can't get my python scripts running via gimp cmd
  • flixe
    flixe almost 7 years
    Thanks for your answer but i'm completely new to python. I tried to run you example like this: gimp -idf --batch-interpreter python-fu-eval -b "import sys;sys.path=['.']+sys.path;import batch;batch.run('C:\Path\to\image\')" -b "pdb.gimp_quit(1)" However, i get an error: batch command experienced an execution error What exactly does the script do and how do i deal with the error?
  • xenoid
    xenoid almost 7 years
    What if you use forward slashes in the path (C:/Path/to/image/)? This said, with ImageMagick, "convert foobar.pdf foobar.jpg" works and you won't have to learn Python and Gimp.
  • flixe
    flixe almost 7 years
    I managed to make your script work, yes the issue was about the slashes, thanks a lot. One more question: Were do the print messages go? They are not shown in the console nor in my stdout.txt? And yes, i read that more often to use image magick, but i have the instructions to use gimp.
  • flixe
    flixe almost 7 years
    Everything is working right now despite the fact that the cmd window, which is opened after executing gimp, only closes at user input ("press any key..."). -b "pdb.gimp_quit(1)" does not seem to work as expected (no matter if i use 0 or 1 as argument). I run gimp from within a windows batch file in the normal windows cmd. Any other method to close this process properly?
  • xenoid
    xenoid almost 7 years
    If Gimp is finished (do you still see it in the process monitor?) then this seems to be a Windows problem. It all depends how you start that window, and Gimp. Maybe you are missing some parameter to cmd or should be using start.
  • flixe
    flixe almost 7 years
    Yes, Gimp-2.8.exe is still running when the console asks me to enter any input. The console seems to be a normal cmd.exe process although its title says "GIMP-Output". The Problem is that i cannot close it from my own batch file because the batch script gets stuck at running the gimp-2.8.exe command until i close the gimp comman window manually.
  • xenoid
    xenoid almost 7 years
    Are you calling Gimp with --verbose? If so remove it.
  • flixe
    flixe almost 7 years
    No, this is how my current query looks like: "C:\Program Files\GIMP 2\bin\gimp-2.8.exe" -idf --batch-interpreter python-fu-eval -b "import sys;sys.path=['.']+sys.path;import PDF;PDF.process('%1','%2')" -b "pdb.gimp_quit(1)". It seems to me there is no method to close the whole process because gimp-quitonly gives me the "press any key to close" option.
  • alvaro562003
    alvaro562003 over 6 years
    @xenoid, Thank you very much. This the first script i made working on gimp.It works directly without change on "windows 10". The Only thing i do not like is the persistent msg "(gimp-console-2.8.exe:10020): LibGimpBase-WARNING **: gimp-console-2.8.exe: gimp_wire_read(): error"
  • xenoid
    xenoid over 6 years
    Not under anyone's control (except the Gimp developers). You have to live with it...
  • alvaro562003
    alvaro562003 over 6 years
    @xenoid, I want to thank you more than that, because i spent one day trying to figure out how gimp scripting works. I call that "Learning". Then i saw you script and in 10 minutes i have finished my job. So thank you very very much!!!!
  • Jérémy Reynaud
    Jérémy Reynaud about 5 years
    @xenoid I'm pretty new to GIMP scripting but after a day of research, trials and errors, you provide the best (and only one) solution I found to execute functions without registering as a plugin, thanks.
  • anilsathyan7
    anilsathyan7 about 2 years
    Getting error: 'Failed to load module "canberra-gtk-module", GIMP-Warning: The batch interpreter 'python-fu-eval' is not available. Batch mode disabled" on ubunut 20.04.
  • xenoid
    xenoid about 2 years
    On Ubuntu from 20.04 they removed the gimp-python package which is required to run Python scripts in Gimp (because Gimp requires Pythonv2 which is officially deprecated). There are ways to reinstate it, see here. Another solution is to use the "flatpak" version that has its own Python interpreter.