Notes on GIMP Scripting

Languages:

C, Script-fu, Python: first-class citizens
Perl, C++, C#, Ruby: need to find and build a module; not well supported.

Python

Registration:

Help strings: first is short, second is long.

Names: first is script author, second is copyright owner.

Leave output parameters blank, []

Remember to call main() at the end of your Python script.

Image type examples:

""
Create a new image -- don't run from an existing one
*
Accept any type of image
RGB
RGB only, no alpha channel (no transparency)
RGBA
Only RGB with transparency
RGB*
RGB with or without transparency
GRAY
Only grayscale, no transparency
GRAY*
Grayscale with or without transparency
INDEXED
Only indexed, no transparency
RGBA,GRAY*,INDEXED
Accept RGB with transparency, Grayscale with or without, and Indexed only without transparency.
You get the idea -- combine them as needed! But most people will only need "" and "*".

Input parameters:

For a complete list, see the pyui.py example code.

When writing a plug-in that operates on an image, the first two input parameters should be:

          (PF_IMAGE, "image", "Input image", None),
          (PF_DRAWABLE, "drawable", "Input layer", None),
and your function definition should take img and layer as its first two arguments.

For functions that create a new image, you don't need image and drawable.

Installing a Python script:

Use Preferences, Folders->Plug-ins to find location of plug-ins on your system. You'll see two: one is the system location (may be overwritten when you reinstall GIMP), one is your personal plug-ins folder.

On Linux it's ~/.gimp-2.6/plug-ins/

Don't forget to make it executable: chmod +x ~/.gimp-2.6/plug-ins/helloworld.py

Must restart GIMP when you add a script or change register(). No need to restart when changing other parts of the script -- it runs as a separate process and will be re-read from disk each time.

Custom dialogs:

Can use anything from pygtk.

See ratio_info.py or life.py for examples.

Direct pixel access:

Read pixels with tiles or pixel regions.

Write pixels with pixel regions.

Examples:

  • whirlpinch.py (tiles and pixel regions)
  • arclayer.py (pixel regions only)

Debugging:

To see output of print, run from a terminal, or tail -f ~/.xsession-errors

Python debuggers work if you can attach to the process -- plug-ins run in their own process.

Python console:

Filters->Python-Fu->Console...

dir(gimp)
dir(gimp.Image)

>>> gimp.image_list()
[<gimp.Image 'img_1444.jpg'>,
 <gimp.Image 'sea-nettle2.jpg'>]
 
>>> img = gimp.image_list()[1]

>>> dir(img)
(lots of output)

>>> layer = img.active_layer

>>> layer.width
1024

Python-Fu documentation:

Documentation on the basic GIMP Python objects, like gimp, pdb, Image, Layer, Drawable: gimp.org/docs/python

Look up PDB functions in GIMP's Procedure Browser, Help->Procedure Browser

Procedure Browser to Python:

  • Change dashes to underscores
  • Omit any run-mode parameter
  • Change -1 to None

Script-Fu

Based on Tiny Scheme.

Use the Tiny-Fu Migration Guide (from scripts written for GIMP 2.2 and earlier) -- which also points to best practices in script-fu development.

Installing script-fu:

Install to ~/.gimp-2.6/scripts/ -- or whatever Preferences says for Folders->Scripts

Then: Filters->Script-Fu->Refresh Scripts

Must Refresh Scripts every time you change a script-fu.

Defining variables:

(let* ( (var1 val)
        (var2 val)
        ...
      )
      (statement1)
      (statement2)
      ...
)

You can also use let (without the *) -- difference is that let* lets you refer to var1's value in var2 def, etc. When in doubt just use let*.

Lisp syntax:

car gives the first element of a list:

> (car '(one two three (a b c) four five))

one

cdr gives the rest of the list, e.g. (two three (a b c) four five)

(if (= (car (gimp-selection-is-empty img))
       FALSE)
    (do-stuff-to-selection)
    (gimp-message "Nothing is selected")
)
Always use car: all script-fu functions return a list:
> (gimp-selection-is-empty img)
(FALSE)

Group statements with begin:

(if (= (car (gimp-selection-is-empty img))
       FALSE)
    (begin
      (do-something)
      (do-something-else)
      (gimp-progress-update percent-done)
    )    ;; end "if selection empty"
    (gimp-message "Nothing is selected")  ;; !empty
)

Loops: use set! to update a variable you've already declared with let*:

    (while (<= y height)
           (do-stuff)
           (do-more-stuff)
           (set! y (+ y 1))
    )

Common Tiny-Fu errors (watch out for these!):

  • Using set! rather than let or let*
  • Not checking for null before using a list
  • Using nil (use '() instead)
  • Fractional numbers must start with 0: 0.5, not .5 (this one might be fixed now)

    Script-Fu Debugging:

    (gimp-message (string-append "Width is: "
                                 (number->string width)))
    
    or, sadly, binary search: delete half the file and see if the error goes away.

    Script-fu console:

    > (gimp-image-list)
    (5 #( 9 8 7 3 1 ))
    
    > (define img2 (aref (cadr (gimp-image-list)) 1))
    img2
    
    > (define layer (car (gimp-image-get-active-layer img2)))
    layer
    
    > (gimp-drawable-width layer)
    (512)
    
    > (gimp-image-width 3)
    (688)
    
    

    Script-Fu Documentation:

    Look up PDB functions in GIMP's Procedure Browser, Help->Procedure Browser

    Kevin Cozens's wiki

    Finding sample scripts:

    GIMP source -- including the online git tree:

    plug-ins/pygimp/plug-ins

    and

    plug-ins/script-fu/scripts

    Also GIMP Plug-in Registry

    or google gimp script or gimp plug-in