Script-fu

From OSP Wiki

Jump to: navigation, search

This tutorial was last tested for the Gimp 2.2.13 (and is also valid for Gimp 2.3)

Contents

Overview

GIMP Script-fu is based on the LISP/Scheme programming language, I did it as a subject in Uni before I dropped out. I know just enough to get by and create Script-fu script's for GIMP. Some of the information may not be complete or even accurate but I will do my best.

I will update this page as I learn more about GIMP scripting.

Command syntax

Scheme has a weird command syntax, everything is in parenthesis and it is in the format of:

(function parameter1 parameter2 .... parameterX)

Each parameter can be a set value, a variable or even another calculation inside a set of parentheses. To do a addition of 10 and 5 it would look something like this:

(+ 10 5)

Scheme will work out the value of a calculation until it hits another open parenthesis, then it caculates what's inside the parenthesis before continuing the calculation. An example would be like this:

The code:
------
(set! X 5)
(set! Y (* 10 (+ 3 (* 18 X))))
------

How scheme does the calculations:
------
(* 10 (+ 3 (* 18 5)))
(* 10 (+ 3 (90)))
(* 10 (+ 3 90))
(* 10 (93))
(* 10 93)
(930)
------

GIMP script parts

To use functions scheme has to know what they are first, that's why the order of the script is:

  1. Mini functions (BTW this is not an official term, just something I made up, it's explained later)
  2. Main script function
  3. Script-fu register
  4. Script-fu menu register

Scheme has to know the least important piece first so I will explain sections in reverse order. I will be using my "Double Border" script as an example.

Script-fu menu register

(script-fu-menu-register "script-fu-double-border"
                         _"<Image>/Script-Fu/Decor")

There are two windows where you can place your script, the Image window and the Toolbox window. Scripts that create a new image from scratch are placed in the Toolbox windows, those that alter an image (or create a new one from the current one) are put in the Image window.

In the example above it tells Script-fu to put my function "script-fu-double-border" under the menu "Script-Fu / Decor". You can put your script anywhere in any menu and even create a new top layer menu. The tradition is to put the script under the "Script-Fu" menu. I think it is possible to have this section of the script as part of the next but I haven't figured out how to do that yet. It is possible to not have this section at all and have this setting in the next section instead, doing so saves entering the same text twice.

Script-fu register

(script-fu-register "script-fu-double-border"
            _"_Double Border..."
            "Gives two border with a drop shadow"
            "Harry Phillips"
            "Harry Phillips"
            "30 July 2007"
            "*"
            SF-IMAGE		"Image"     0
            SF-DRAWABLE		"Drawable"  0
            SF-COLOR		"Inner colour" '(255 255 255)
            SF-ADJUSTMENT	_"Inner size"     '(25 0 1024 1 10 1 0)
            SF-COLOR 		"Outer colour" '(217 217 217)
	    SF-ADJUSTMENT	_"Outer size"      '(50 0 1024 1 10 1 0)
            SF-COLOR 		"Shadow colour" '(0 0 0)
	    SF-ADJUSTMENT	_"Shadow size"         '(10 5 1024 1 10 0 1)
	    SF-ADJUSTMENT	_"Shadow blur"    '(10 0 1024 1 10 0 1)
	    SF-ADJUSTMENT	_"Shadow opacity"        '(80 0 100 1 10 0 0)
	    SF-TOGGLE     	_"Outer border is full width past shadow"       FALSE

The first line is the function name, it has to be unique. I believe it is possible to use one script from inside another but I have not needed or tested that yet.

The second line is the text uses in the GIMP menu. If you don't want to have the seperate Script-fu menu register section above this line can include the menu location as well as the menu item text. In this example the line would be changed to _"<Image>/Script-Fu/Decor/Double Border..."

A quick note on the naming of the menu item, if you have it popping up a dialog box you normally have the "..." at the end of the name, if it just performs a specific action with no further input from the user you don't have them.
Note two, if it is an Image script you put an underscore before the entry, if it a Toolbox script you don't have the underscore, eg "<Toolbox>/Script-Fu/Happy/Place..."

Line three is just a short description.

For lines four and five I just put my name, I am not sure exactly what they are for, probably something to do with the copyright and/or creator.

Line six is the date you created and/or updated the script.

I always use a star for line seven and have no idea what it is supposed to do.

I have further testing to do but I think that if there is a star the script will only be active if you have an image open. If it is a Toolbox script I think you need to delete the star.

The rest of the lines in that section are options on a dialog box that pops up when you run the script. There are various types that you can use here and they will be explained later. I don't know them all but I will explain the ones I do know on the Script-fu Dialog box page. The values the dialog box returns to Script-Fu are the parameters that get passed to the main function.

Main script section

(define (script-fu-double-border	theImage
					theLayer
					innerColour
					innerSize
					outerColour
					outerSize
					shadowColour
					shadowSize
					shadowBlur
					shadowOpacity
					shadowInclude
	)

    ;Check that the outer size is larger than the required sie for the shadow
    (if (> outerSize (+ shadowSize shadowBlur))
	(begin


    ;Start an undo group so the process can be undone with one undo
    (gimp-image-undo-group-start theImage)

    (let* 
    (
	;Read the current colours
	(myBackground (car (gimp-context-get-background)))

	;Calculate the size of the inner layer
	(innerWidth (+ imageWidth (* innerSize 2)))

	(shadBlur (+ shadowSize shadowBlur)) 
	(innerLayer)

    )

    ;Resize image
    (gimp-image-resize theImage innerWidth innerHeight innerSize innerSize)

    ;Add the inner layer to the image
    (set! innerLayer (layer-add-fill innerWidth innerHeight "Inner" 100 innerColour theImage))

Scheme is a language where you create your own functions using built-in functions (like add, subtract etc) and the functions already provided by GIMP. The main script section is where all the heavy lifting is done. I have not put all of the script here, just bits and pieces for the example.

The lines starting with a semi-colon are comments and are not executed. I suggest to at least put what the line does for you. At a later date you may need to update or even copy a line or two from it. Commenting not only makes it easier for you to understand but others that might want to update or even use part of your script.

The first section defines the name of the function (script-fu-double-border) and gives names to the parameters it is being passed from the dialog box (theImage, theLayer, innerColour, innerSize, .....etc). You decide what names to give the passed variables but it is easier if they are related to what information they provide. The convention I use for the variables is two names together using a lower case on the first word and an Uppercase on the second.

The next section is the "let" section. Here you initialise and/or set the value of any variables used within the function but not passed to it (eg the "innerWidth"). The minimum is that you have to initialise the variable*, you don't have to set it to any value but you do need to at least put it's name in brakets (eg "innerLayer").

*This is not strictly true when using Gimp 2.2, you don't have to initialise the variable in the "let" section you can just set! a new variable anywhere in the script. There are two problems with that, it is sloppy programming and it makes the script bomb out in Gimp 2.3. Even if you are only scripting for 2.2 still initialise the variable in the let section so that it won't have to be "fixed" when 2.4 comes out and people using the beta 2.3 can use your script.

To see what the included GIMP functions do and what parameters they need to be given you can use the "Procedure Browser". In the example above to resize the image the "gimp-image-resize" function has to be given:

  1. What image to be resized
  2. The new width
  3. The new height
  4. The X offset
  5. The Y offset

The last line of the above example is not using a built-in function but what I call a mini function from within the script and is explained below.

Mini functions

In my "Double Border" script I add a layer and fill it with colour, I do this 3 times. One option is to just copy and paste the same code 3 times then alter the variable names. This can be rather messy and get out of control when you figure out a better way to write the code. You would have to alter the code, test to make sure it works, copy and paste it multiple times and alter the variables.

The best option is to create what I term "mini functions", I call them that because these functions are only available inside the script you are currently running.

(define (layer-add-fill width height label opacity colour image)

	(let* ((newLayer (car (gimp-layer-new image width height 1 label opacity 0))))
	
	;Set the background colour
	(gimp-context-set-background colour)

	;Add the layer
	(gimp-image-add-layer image newLayer 100)

	;Fill the shadow layer
	(gimp-drawable-fill newLayer 1)
	
	newLayer)
)

This function is just like the main script function except for one line, the last one. The mini function above takes 6 parameters (width, height, label, opacity, colour and image) and returns a single value using the last line. In this mini function it returns a layer with the specified height and width, filled with the specified colour, to the specified opacity, named using the specified name.

Personal tools