Since I’ve been shooting film in Ireland, I’ve been facing scanning noise even with low grain films. It was my father who wisely suggested a Selective Gaussian Blur filter to reduce this noise, with parameters blur radii = 3 and delta max = 176.

Applying this filter with GIMP in a one by one basis is fine for a few files but, even though I don’t usually post many film pictures, it started to be quite annoying having to do this interactively. New challenges have driven me to the necessity of scripting this, using GIMP for preference.

Best option seems to be GIMP Batch Mode, which lets you do the same operation on a blob of files. This nice feature (file-blob) is available from GIMP 2.2 and at this point GIMP 2.4 is already available!

The tutorial example is so handy that I had only to change the plug-in-unsharp-mask function by the Selective Gaussian Filter function: plug-in-sel-gauss. The Procedure Browser (found in the Xtns menu in the GIMP toolbox) gives you a detailed list of all commands.

Once I found this function, modifying the tutorial example was pretty straight forward, just save the following code to ~/.gimp-2.2/scripts/batch-noise-reduction.scm and that’s all.

(define (batch-noise-reduction pattern
                               radii
                               delta)
(let* ((filelist (cadr (file-glob pattern 1))))
  (while (not (null? filelist))
         (let* ((filename (car filelist))
                (image (car (gimp-file-load RUN-NONINTERACTIVE
                                            filename filename)))
                (drawable (car (gimp-image-get-active-layer image))))
           (plug-in-sel-gauss RUN-NONINTERACTIVE
                              image drawable radii delta)
           (gimp-file-save RUN-NONINTERACTIVE
                           image drawable filename filename)
           (gimp-image-delete image))
         (set! filelist (cdr filelist)))))

From now on, all I need to do to apply noise reduction filter to a lot of files is run this command:

gimp -i -b '(batch-noise-reduction "*.jpg" 3.0 176)' -b '(gimp-quit 0)'

Note that the blob pattern must be quoted, “*.jpg” will act on all .jpg files, but *.jpg will act only on the first one, be careful with this!

I’m even lazier than you can imagine, so I wrote a tiny script to avoid having to type that long command and being able to use shell blobs:

#!/bin/sh
#
# Apply batch-noise-reduction GIMP 2.2+ script to a blob of files ($1)
RADII="3.0"
DELTA="176"
echo $*
for f in $*
do
  echo -n "$f ... "
  gimp -i --batch-interpreter='plug-in-script-fu-eval' -b "(batch-noise-reduction \"$f\" $RADII $DELTA)" -b '(gimp-quit 0)'
  echo "done"
done

And last, but not least, the example output:

miguev@binky:/tmp$ ls -l *.jpg
-rw-r--r-- 1 miguev miguev  391503 2007-12-25 14:09 cnv00021a.jpg
-rw-r--r-- 1 miguev miguev  391211 2007-12-25 14:09 cnv00021b.jpg
-rw-r--r-- 1 miguev miguev 1127064 2007-12-25 14:09 cnv00021.jpg
miguev@binky:/tmp$ ./batch-noise-reduction.sh "*.jpg"
cnv00021.jpg cnv00021a.jpg cnv00021b.jpg
cnv00021a.jpg ... batch command: executed successfully.
done
cnv00021.jpg ... batch command: executed successfully.
done
cnv00021b.jpg ... batch command: executed successfully.
done
miguev@binky:/tmp$ ls -l *.jpg
-rw-r--r-- 1 miguev miguev 304600 2007-12-25 14:10 cnv00021a.jpg
-rw-r--r-- 1 miguev miguev 304507 2007-12-25 14:10 cnv00021b.jpg
-rw-r--r-- 1 miguev miguev 391211 2007-12-25 14:10 cnv00021.jpg

The script can be anywhere, so you can put it somewhere in your path (e.g. /usr/local/bin) and call it without ./

Now I can leave the computer working on that tedious task while I do more interesting tasks 🙂