How to run python scripts using gimpfu from command line?
Asked Answered
U

2

11

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?

Ugh answered 8/6, 2017 at 8:6 Comment(3)
unbound variable: hello_world: missing underscore between python_fu and hello_world?Feces
I guess your are talking about the first code sample right? The error message unbound variable is related to the second code sample...Ugh
I'm talking about the command line you use. Thhe message is from Scheme, and there isn't a lot of Scheme in your whole process, nor is the "python-fu" string used in many places. OTOH, see my second answer.Feces
F
33

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.

Feces answered 8/6, 2017 at 12:16 Comment(15)
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?Ugh
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.Feces
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.Ugh
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?Ugh
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.Feces
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.Ugh
Are you calling Gimp with --verbose? If so remove it.Feces
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.Ugh
@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"Mask
Not under anyone's control (except the Gimp developers). You have to live with it...Feces
@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!!!!Mask
@Feces 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.Oldfangled
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.Gentilis
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.Feces
If you're running this inside a docker container, make sure you use xvfb-run to run a virtual X server environment in which GIMP can run as if it had access to a display. (using ubuntu:18.04 I had to do this in order to make it work)Acquire
F
1

Because the script you are using creates the image and then shows it in a window.... But you are calling Gimp with the --no-interface flag so the window is not shown.

IMHO to convert from PDF to JPEG, ImageMagick's convert command would be a lot simpler.

Also, in Windows Gimp comes with its own built-in Python 2.7 interpreter, so you have to write your Python code for that version, and there is no need to install another one.

Feces answered 8/6, 2017 at 9:29 Comment(1)
Thank you. I've edited my original post, because i still can't get my python scripts running via gimp cmdUgh

© 2022 - 2024 — McMap. All rights reserved.