The quest of using GIMP in batch mode
I needed to convert a large (and growing) number of Postscript files to jpeg images and thumbnails. I knew that GIMP could be used in batch mode, and it seemed the best choice for the quality of the results.
So I dove into GIMP Python documentation and the very nice internal PDB browser and I produced something working. But it hasn’t been a very pleasant experience.
It turns out you can actually write plugins in Python, but the batch mode only works with Scheme (and it is quite cumbersome too), so you have to write a plugin for your batch procedure and then call it with the Scheme batch evaluator. It would be nice to have everything self-contained in a single file, but that just isn’t possible if you want to write Python: you also need a shell script to call your plugin. Maybe you can do it with Scheme and Script-fu, but I haven’t tried nor I have found examples of others doing it.
The documentation in the PDB seems wrong as some functions have incorrect parameters reported (file_jpeg_save, for example), so some trial-and-error and reading other people’s code from around the web was needed to get going.
And then you have the brilliant error reporting and debugging capabilities which challenge your imagination:
batch command: experienced an execution error.
I ended up writing the script in the console (interactive development will never be praised enough) and pasting it line-by-line in the plugin file. At the end I started the script from a shell, with no GIMP running and I got:
batch command: experienced an execution error.
I don’t remember how I came to understand it, as I can’t find it written anywhere, but you must make the plugin script executable or GIMP will not find it.
My last problem was that I needed to scale an image, so I used the gimp_image_scale function, but that doesn’t allow me to specify how the image should be interpolated when scaled. After some more digging and searching around, I found a small note somewhere (not on gimp.org) that the interpolation mode selected in the preferences will be used. But depending on the user’s configuration isn’t a good idea, I dug some more and I found that I could use gimp_drawable_transform_scale and that allows me to specify the interpolation mode (and here I could put a very funny story about an IRC conversation on this topic…).
So here I am at the end. I finally have my Python GIMP plugin (put it in ~/.gimp-2.2/plug-ins/):
#!/usr/bin/env python
# (c) 2006 - Michele Campeotto <micampe@micampe.it> - GPL v2
import sys, os, re
from gimpfu import *
def ps_to_jpeg(src, dest_width):
src = os.path.abspath(src)
if not os.path.exists(src):
print "Couldn't find source file %s" % src
pdb.gimp_quit(1)
print "Loading file %s..." % src
pdb.file_ps_load_setargs(100, 1, 1, 1, "1", 6, 4, 2)
img = pdb.file_ps_load(src, 1)
dest_small = os.path.splitext(src)[0] + '_small.jpg'
print "Resizing image..."
pdb.gimp_drawable_transform_scale(
pdb.gimp_image_flatten(img),
0.0, 0.0, dest_width, img.height * dest_width / img.width,
TRANSFORM_FORWARD, INTERPOLATION_CUBIC, 1, 3, 0)
print "Saving file %s..." % dest_small
pdb.file_jpeg_save(img, img.layers[0],
dest_small, dest_small,
1.0, 0.0, 1, 0, "", 0, 1, 0, 1)
register("ps_to_jpeg",
"Convert and resize a PS file to a JPEG image",
"Convert and resize a PS file to a JPEG image",
"Michele Campeotto", "Michele Campeotto", "2006",
"<Toolbox>/Xtns/Python-Fu/PS to JPEG",
"", [ (PF_FILE, "source", "Source file", ""),
(PF_INT, "dest_width", "Small image width", 0) ], [],
ps_to_jpeg)
main()and the shell script to call it:
#!/bin/bash
# (c) 2006 - Michele Campeotto <micampe@micampe.it> - GPL v2
if [ "x$1" == "x" -o "x$2" == "x" ]; then
echo "usage: $0 <source file> <width>"
exit 1
fi
gimp --console-messages --no-data --no-interface \
--batch-interpreter "plug_in_script_fu_eval" --batch \
"(python-fu-ps-to-jpeg RUN-NONINTERACTIVE \"$1\" $2)" \
"(gimp-quit 0)"I hope this post provides useful information to the next person trying to do this and searching for hints on the web.