Plus loin en script-fu

Mais où est donc Ornicar ?

... 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).

Fais moi une liste

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.

L'extraction en action

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 :

L'affectation sans ostentation

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 : set!, let et let*.

La première définit une variable globale, par exemple :

(set! gris-clair '(200 200 200))

mais utiliser une variable globale n'est généralement pas considéré comme une bonne pratique de programmation car le contenu d'une telle variable est plus difficile à maîtriser, son emploi peut entraîner des erreurs difficiles à identifier. Il est généralement recommandé de s'en tenir à l'emploi de variables locales, en vue d'une modularité du code qui contribue à sa lisibilité et à sa robustesse.

Les deux autres instructions 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*.

Du rythme dans l'algorithme

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

Un utile exemple inutile

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 ?


Retour à l'accueil LINUX