... Est la bonne question car car est l'une des premières fonctions de script-fu à maîtriser pour prétendre manipuler des éléments d'image... Quelques explications préalables sont nécessaires sur le langage utilisé pour écrire un script-fu (Scheme est son nom).
En Scheme, tout se fait à l'aide de listes. Une liste est une suite d'éléments placés entre parenthèses. Par défaut, une liste exprime une action à accomplir avec la convention que le premier élément de la liste est le nom de la fonction à effectuer et que les suivants sont ses paramètres :
(fonction param1 param2 etc)
et l'on peut noter tout de suite que le mot fonction est ici employé pour évoquer aussi bien une vraie fonction qu'une procédure, une instruction ou l'action d'un opérateur.
Si nécessaire, pour faire comprendre à l'interpréteur du GIMP que la liste qu'on lui donne ne contient pas une fonction et ses paramètres mais une simple suite de valeurs, il suffit de faire précéder la première parenthèse d'une apostrophe. L'expérience suivante peut être faite avec la console script-fu (disponible dans le menu Script-fu du GIMP) :
(+ 3 2)
renvoie la valeur qui est le résultat de l'addition :
5
tandis que
'(+ 3 2)
renvoie la liste :
(+ 3 2)
qui contient 3 valeurs.
Parmi les fonctions disponibles dans Scheme, deux sont essentielles à connaitre, qui permettent d'extraire du contenu d'une liste. Ce sont les fonctions car et cdr. Ces deux fonctions s'appliquent à une listes de valeurs (donc avec apostrophe si donnée explicitement).
ATTENTION
Ces deux fonctions ont des sorties de natures différentes. La fonction car renvoie la valeur qui est en tête de liste tandis que cdr renvoie la liste des valeurs qui suivent la première. Exemple sur la liste '(3 2) :
(car '(3 2))
3
c'est donc bien la valeur entière 3 qui est renvoyée tandis que :
(cdr '(3 2))
(2)
c'est donc ici la liste qui contient la deuxième valeur qui est renvoyée et, pour accéder à la valeur elle-même, il faut donc demander la (première) valeur de la liste renvoyée par cdr, soit :
(car (cdr '(3 2)))
2
Démonstration à la console :
Voilà une source d'erreurs prometteuse, surtout si l'on ne perd pas de vue qu'une liste peut lister des listes et qu'une fonction peut produire une valeur (comme + et car) ou une liste (comme cdr)... Bon, mais chaque chose en son temps !
Pour accéder à la valeur du Nième élément de la liste, il faut itérer cdr. Au total, il faut N appels de fonctions = 1 fois car et (N-1) fois cdr. D'ailleurs, on peut alléger l'écriture en écrivant une seule fonction notée cadddr, en répétant d ou a jusqu'à 4 fois.
Démonstration à la console :
Extraire une donnée d'une liste, c'est bien mais, si on ne l'utilise pas tout de suite, il faut pouvoir la ranger dans une variable pour usage ultérieur. Scheme offre plusieurs possibilités pour définir une variable et lui affecter un contenu, notamment: define, set!, let et let*.
La première attache une variable à un emplacement mémoire et inscrit une valeur dans cet emplacement. L'expression set! affecte une valeur à une variable. Cette variable doit avoir été préalablement déclarée soit dans un domaine local contenant l'expression set!, soit au niveau global du programme. Il y a plusieurs manières de faire cela. Par exemple:
(define var 3)
(+ var 4)
(set! var 12)
(+ var 4)
Dans cet exemple, define crée une variable globale et lui affecte la valeur 4 puis set! change cette valeur à 12. Ainsi, (+ var 4) donne 7 la première fois puis 16 la seconde.
Attention, define peut s'utiliser au niveau global du programme ou dans un domaine local (auquel cas la définition est valable dans ce seul domaine) mais une variable ne peut être ainsi définie qu'une seule fois dans un domaine donné.
Les deux instructions let, let* s'appliquent à des variables locales. Cependant, avec let, les variables ne sont déclarées ensemble qu'à la fin de l'instruction, ce qui est moins souple d'emploi. Il est ainsi permis de faire :
(let ( (zwei 2) (deux 2) ) (+ zwei deux))
4
mais non :
(let ( (zwei 2) (deux zwei) ) (+ zwei deux))
Error: eval: unbound variable: zwei
car la variable zwei n'est pas encore initialisée au moment où l'addition est appelée. Au contraire, la variante let* déclare et initialise les variables au fur et à mesure :
(let* ( (zwei 2) (deux zwei) ) (+ zwei deux))
4
et se trouve donc en général préférée. Il est rappelé que la portée des variables est limitée à l'instruction let et que, en conséquence, les appels aux fonctions qui utilisent ces variables doivent se trouver avant la parenthèse fermante ) associée à la parenthèse ouvrante qui précède let*.
Une fois que l'on sait manipuler les variables, la route est ouverte... Il ne reste plus qu'à enchaîner les opérations. D'ailleurs, si l'on a besoin de faire plus qu'une simple succession de procédures fournies avec GIMP, on peut le faire puisque Scheme est un langage de programmation à part entière. Une initiation complète dépasserait l'ambition de la présente page mais de nombreux sites sur l'internet permettent de se former. Les suivants constituent de bonnes entrées en matière.
Scheme sur Wikipedia
3. Didacticiel pour Script-Fu
L'abc du GIMP (page sur Scheme).
Welcome to TinyScheme sur SourceForge
Tiny-Fu sur le site de Kevin Cozens
Pour aller plus loin, il est aussi possible de se plonger dans le Revised5Report on the Algorithmic Language Scheme (en anglais). L'interpréteur de GIMP ne prend pas en charge toutes les fonctions de Scheme mais, si une fonction est prise en charge, alors elle devrait l'être comme indiqué dans ce rapport.
Le script suivant ne fait aucun traitement d'image mais illustre le maniement des variables et l'emploi d'un test logique pour disposer d'une calculette à 2 opérations (!)...
(define (script-fu-calculette logique x y ; Trois variables entrantes : une valeur logique et deux nombres ) ; ce script fournit une magnifique calculette à deux opérations ! ; et ne fait aucun traitement d'image (gimp-context-push) ; sauvegarde le contexte (let* ( (somme (+ x y)) (produit (* x y)) ) ; initialise la somme et le produit (if (eq? logique FALSE) ; teste si logique est FALSE (case non cochée) (gimp-message (number->string somme)) ; dans ce cas, affiche la somme (gimp-message (number->string produit)) ; sinon, affiche le produit ) ; fin du if ) ; fin du let* (gimp-context-pop) ; replace le contexte ) ; fin du define (script-fu-register "script-fu-calculette" ; le nom choisi pour la fonction dans define ! "<Image>/Filters/Mes scripts/Calculette..." ; nom et place pour affichage dans le menu du GIMP "Ce script-fu calcule" ; description de l'action du script-fu "Sellig Zed" ; nom de l'auteur "(c) Sellig Zed, 2010, sous Cecill-C" ; licence libre - voir le site "http://www.cecill.info". "10 avril 2010" ; la date en forme libre comme 30 mars 2011 ou 1.1.98 "" ; type d'image (ne rien mettre ou indiquer RVB ou RVBA ou GRAY ou GRAYA...) ; descriptions des champs de la boite de dialogue SF-TOGGLE "Cocher pour multiplier au lieu d'additionner" FALSE SF-VALUE "Valeur 1" "2.50" SF-VALUE "Valeur 2" "3.00" )
Partant de là, il est temps de s'essayer à une application plus réaliste... Pourquoi pas un traceur mathématique ?