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?

Martin Valgur
  • 5,793
  • 1
  • 33
  • 45
flixe
  • 626
  • 1
  • 11
  • 36
  • `unbound variable: hello_world`: missing underscore between `python_fu` and `hello_world`? – xenoid Jun 08 '17 at 11:56
  • I guess your are talking about the first code sample right? The error message `unbound variable` is related to the second code sample... – flixe Jun 08 '17 at 12:24
  • 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. – xenoid Jun 08 '17 at 12:29

2 Answers2

29

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.

Martin Valgur
  • 5,793
  • 1
  • 33
  • 45
xenoid
  • 8,396
  • 3
  • 23
  • 49
  • 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? – flixe Jun 08 '17 at 12:50
  • 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. – xenoid Jun 08 '17 at 13:25
  • 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 Jun 09 '17 at 07:28
  • 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? – flixe Jun 14 '17 at 07:24
  • 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`. – xenoid Jun 14 '17 at 07:41
  • 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. – flixe Jun 14 '17 at 09:24
  • Are you calling Gimp with `--verbose`? If so remove it. – xenoid Jun 14 '17 at 09:49
  • 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-quit`only gives me the "press any key to close" option. – flixe Jun 14 '17 at 10:12
  • @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" – alvaro562003 Sep 18 '17 at 11:45
  • Not under anyone's control (except the Gimp developers). You have to live with it... – xenoid Sep 18 '17 at 11:49
  • @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!!!! – alvaro562003 Sep 18 '17 at 12:03
  • @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. – Jérémy Reynaud Feb 04 '19 at 14:04
  • 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. – anilsathyan7 Apr 23 '22 at 07:21
  • 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](https://www.gimp-forum.net/Thread-Heal-Selection-Missing-from-Gimp-on-Ubuntu-20-04?pid=18351#pid18351). Another solution is to use the ["flatpak" version](https://www.gimp.org/downloads/) that has its own Python interpreter. – xenoid Apr 23 '22 at 08:01
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.

xenoid
  • 8,396
  • 3
  • 23
  • 49
  • Thank you. I've edited my original post, because i still can't get my python scripts running via gimp cmd – flixe Jun 08 '17 at 11:20