Creating thumbnail images with the Gimp

(Updated 2008-01-23)

Shortly after acquiring a digital camera, I felt the need to be able to make the images available via the Internet. The standard size of the images was too large (at over 0.5MB) to make downloading convenient. I therefore needed a process which could turn the images (automatically) into a reasonable size.

The Gimp seemed the first choice. I was pleased to learn that the Gimp's script language was Scheme, a variant of Lisp. Since I'd been learning Common Lisp for a little while (via Object Oriented Common Lisp by Stephen Slade), it seemed a happy coincidence.

Scheme is a little different to CL, but that wasn't really an issue for the size of program I wanted to write; it's the usual grappling with a new, undigested command set. After much googling, trial and error, I arrived at the following gimp script. It produces a cut-down image and a thumbnail from the original jpeg file.

;;;; Thumbnail Creation Gimp script
;;;;
;;;; To run this from the command prompt:
;;;; gimp -c -d -i -b '(script-fu-thumbnail "file.jpg" tw th fw fh)' -b '(gimp-quit 0)'
;;;;
(define (script-fu-thumbnail filename t-width t-height f-width f-height)
  (let* ((img 0) (drw 0) (fileparts (strbreakup filename ".")))
    ;; car needed here because gimp functions return values as lists
    (set! img (car (file-jpeg-load 1 filename filename)))
    ;; set image resolution to 72dpi
    (gimp-image-set-resolution img 72 72)
    ;; create 'full-size' image
    (gimp-image-scale img f-width f-height)
    ;; also flatten image to reduce byte storage even further
    (set! drw (car (gimp-image-flatten img)))
    ;; save at quality level of .75 (gimp default) - saves storage
    (file-jpeg-save 1 img drw
                    (string-append (car fileparts) "-f.jpg")
                    (string-append (car fileparts) "-f.jpg")
                    .75 0 0 0 " " 0 1 0 1)
    ;; create thumbnail image
    (gimp-image-scale img t-width t-height)
    (file-jpeg-save 1 img drw
                    (string-append (car fileparts) "-t.jpg")
                    (string-append (car fileparts) "-t.jpg")
                    .75 0 0 0 " " 0 1 0 1)
))

(script-fu-register "script-fu-thumbnail"
                    "<Toolbox>/Xtns/Script-Fu/Utils/Thumbnail..."
                    "Thumbnail"
                    "Mark Willson"
                    "Mark Willson"
                    "Dec 2003"
                    ""
                    SF-VALUE "Image Name" " "
                    SF-VALUE "Thumbnail Width" "256"
                    SF-VALUE "Thumbnail Height" "192"
                    SF-VALUE "Full Width" "1024"
                    SF-VALUE "Full Height" "766")

Here's another version of the script, modifications by Martin Bradley, which preserves the aspect ratio of the original image.

;;;; Thumbnail (Keep Aspect Ratio) Gimp script
;;;;
;;;; To run this from the command prompt:
;;;; gimp -c -d -i -b '(script-fu-thumbnail-kar
;;;;                       "file.jpg" thumb-width full-width)' -b '(gimp-quit 0)'
;;;;
(define (script-fu-thumbnail-kar filename t-width f-width)
  (let* ((img 0) (drw 0) (fileparts (strbreakup filename ".")) )
    ;; car needed here because gimp functions return values as lists
    (set! img (car (file-jpeg-load 1 filename filename)))
    ;; set image resolution to 72dpi
    (gimp-image-set-resolution img 72 72)
    ;; determine original aspect ratio and preserve w.r.t width required
    (let* ((original-width  (car (gimp-image-width  img)))
           (original-height (car (gimp-image-height img)))
           (t-height (* original-height (/ t-width original-width)))
           (f-height (* original-height (/ f-width original-width))))
      ;; create 'full-size' image
      (gimp-image-scale img f-width f-height)
      ;; also flatten image to reduce byte storage even further
      (set! drw (car (gimp-image-flatten img)))
      ;; save at quality level of .75 (gimp default) - saves storage
      (file-jpeg-save 1 img drw
                      (string-append (car fileparts) "-f.jpg")
                      (string-append (car fileparts) "-f.jpg")
                      .75 0 0 0 " " 0 1 0 1)
      ;; create thumbnail image
      (gimp-image-scale img t-width t-height)
      (file-jpeg-save 1 img drw
                      (string-append (car fileparts) "-t.jpg")
                      (string-append (car fileparts) "-t.jpg")
                      .75 0 0 0 " " 0 1 0 1))))

(script-fu-register "script-fu-thumbnail-kar"
                    "<Toolbox>/Xtns/Script-Fu/Utils/Thumbnail (KAR)..."
                    "Process Image"
                    "Mark Willson/Martin Bradley"
                    "Mark Willson/Martin Bradley"
                    "Jan 2008"
                    ""
                    SF-VALUE "Image Name" " "
                    SF-VALUE "Thumbnail Height" "192"
                    SF-VALUE "Full Height" "766")

As you can see, it's not exactly easy to kick off the gimp script from the command line, so here's a shell script to drive it. This script invokes the original script-fu-thumbnail, but it is a simple matter to modify it to use the alternate version.

#!/bin/bash
#  SYNOPSIS
#     prjpg file [file ...]
#
#  DESCRIPTION
#     Script to produce 'thumbnails' and images for web consumption
#
#     <prefix>-t.jpg = thumbnail (currently set to 256x192)
#     <prefix>-f.jpg = full image (currently set to 800x600)
#
#  MODIFICATION HISTORY
#  Mnemonic    Rel Date    Who
#  PRJPG       1.0 01Feb04 mpw
#      Written.
#  PRJPG       1.1 30May05 mpw
#      Revised argument interface to use list of files
#  PRJPG       1.2 08Feb10 mpw
#      -b only takes one gimp expression, hence "(gimp-quit 0)" prefixed by -b

# Process files via the Gimp
for x in $*
do
  if [ -r $x ]; then
      echo "..processing $x"
      nice -n 19 gimp -c -d -i -b "(script-fu-thumbnail \"$x\" 256 192 800 600)" -b "(gimp-quit 0)"
  else
      echo "$0: unable to read $x"
  fi
done