| In GIMP we can use script-fu or, more generally, any other GIMP scripting-language to re-create an effect over a drawable we already tested in a manual way. We can create an effect in two ways. |
| One - the static one - is like using a macro-events scripting language, as someone could have seen under Windows in Photoshop or Word; instructions are sequential and the result is straight-forward. In this case the programming flow is linear, i.e. the program interpreter parses one code line after the other until the end of the script. |
| A more complex and interactive way - the other way - of programming a filter for GIMP is taking decisions dynamically, in other words controlling the programming flow. |
One of the simplest way of using such a method is, for example, to check whether the image is in a particular mode (RGB, Indexed,...) and prompt the user an error message, or modifying the image mode.(if (= (gimp-drawable-type InLayer) RGBA) (gimp-message "error")) |
| As we can see the only super-type of LISP (the script-fu mother language) is the list and we can consider all the other LISP programming elements as sub-types of it. In fact the LISP parser takes its decisions based on a list of sub-types; the first element of this list determines the action to be taken, the rest of the list is (usually) a collection of options. In our case the IF clause has this general syntax: (if (control-statement) expression(s)) |
We should be aware that the LISP-parser, once it encounters the IF clause, evaluates the second element of this list (usually enclosed in brackets). The control-statement should return a boolean value and if it is TRUE the parser executes the expression(s) (the remaining elements of the list) otherwise it will skip them. So the control-statement can be any equivalence expression like(< x y)or (= x y)or any boolean value or any function that returns a boolean value (TRUE or 1; FALSE or any not-1 number). |
| As we saw the if clause creates a sort of diversion in the programming flow that will execute once a code segment. But what to do if we need to repeat an action 'n' times? |
| Any programming language has several methods to create a LOOP. Here we will take a look at WHILE loops. The general syntax for it, is something like: (while (control-statement) expression(s) )where the expression(s) will be executed until the control-statement is true.
(let* (
(k 0)
(rv 0))
(while (k <= 10)
(set! rv (+ rv 2))
(set! k (+ k 1))))
|
| In this classical example we first inizialize two values, k and rv, to 0, the first is used as a control-value (a sort of counter) for the iteration, the other is just an example purpouse value we could need later in our ipothetical script.The variable k is incremented every iteration until it equals 10; we should keep in mind to try to avoid infinite loops, like a k control-value that will never reach a value of 10. As we saw for the if clause, the control-statement could be any boolean value or any function that returns a boolean value. At the end of this loop rv will have the value of 20. |
Now let's take a look at this more complex code segment:
(let* (
(x-topleft 0)
(y-topleft 0))
(while (< y-topleft height)
(while (< x-topleft width)
(...)
(set! x-topleft (+ x-topleft block-w)))
(if (= x-topleft width) (set! x-topleft 0))
(set! y-topleft (+ y-topleft block-h))))
where the undefined variables are: height is the drawable height, width is the drawable width, block-h is the height of a sub-rectangle of the drawable, block-w is the sub-rectangle width. |
| Here we move a point of coords (x-topleft ; y-topleft) inside the drawable from its inizial position of (0 ; 0) until the far end of the right bottom corner. This point can be thought as the topleft corner of a sub-rectangle whose block-h and block-w are just a fraction of the height and width of the drawable. The two nested iteration loops move the point from left to right, and once encountered the right end of the drawable (= x-topleft width), the point will be shifted to the next row at (0 ; (+ y-topleft block-w)) until y-topleft equals the height of the drawable. |