GIMP - Script-Fu de traitement d'images par lot


GIMP est un logiciel de création graphique gratuit, libre et performant qui permet de réaliser une grande variété de traitements graphiques sur des photos ou images.
Il peut arriver que régulièrement 'on ait besoin de réaliser certains traitements sur des lots importants d'images. Dans ce cas, il devient judicieux, pour des raisons de rapidité et d'efficacacité, de rédiger un script (appelé Script-Fu) qui réalise ses tâches automatiquement (traitement par lot ou «batch»).

Le Script-Fu est un langage de programmation interprété basé sur le langage Scheme qui est lui même dérivé du langage Lisp - List Processing). Le langage Script-Fu fait partie du noyau de Gimp. Tout comme le langage Lisp, le langage Script-Fu dispose d’une syntaxe en forme de listes encadrées par des parenthèses. Un script Gimp, écrit en langage Script-Fu, est un fichier texte (doté d’une extension .scm). Ce fichier peut être créé avec le Bloc-Notes de Windows ou avec l'Editeur de texte de Linux. Il est composé d'une succession d’instructions dont le nombre et la nature varient selon le traitement à effectuer.

Dans ce qui suit on rédige un script qui permet de placer dans un répertoire "destination" (avec un format paysage 3:2 et une dimension finale 800-533) les copies redimensionnées d'un lot d'images jpg (de dimensions quelconques) contenues dans un répertoire "source". Le traitement de redimensionnement s'effectue sans déformer les images mais en utilisant une couleur de remplissage noire si nécessaire. Après le traitement, les images présentes dans le répertoires sources restent inchangées.
Ce script a été rédigé et testé avec Gimp 2.8 :
1) Sur un PC x386 avec un système d'exploitation Windows XP
2) Sur un Raspberry Pi 3 avec un système d'exploitation Linux Raspbian

La différence suivante est à noter selon le système d'exploitation utilisé (Windows ou Linux) ::
• Sur un PC Windows, le chemin d'un fichier jpeg qui se trouve dans un répertoirre situé à la racine du disque dur s'écrit "C:\monrépertoire\monfichier.jpg
• Sur un Raspberry Pi 3 Linux Raspbian, le chemin d'un fichier jpeg qui se trouve dans un répertoirre situé à la racine du disque dur s'écrit "/home/pi/monrepertoire/monfichier.jpg"

Remarque :
Le "C:" de windows devient "/home/pi" sous Linux. D'autre part le caractère oblique de séparation utilisé dans les chemins est en sens descendant sous Windows (\) mais est en sens montant sous Linux (/).
Il faut savoir qu'en programmation, le caractère oblique descendant "\" est en fait considéré comme une séquence d'échappement associée aux caractères qui le suivent. Par exemple, \r est considéré, par les compilateurs et les interpréteurs de commandes, comme un caractère de retour chariot (CR ou Carriage Return) et non pas comme une simple chaine de caractère constituée de la lettre \ suivie de la lettre r. De même le caractère \r est considéré comme un caractère de changement de ligne (NL New Line). C'est pourquoi, en programmation, le programmeur doit écrire le caractère double barre oblique descendante \\ lorsqu'il désire écrire réellement un simple caractère barre oblique \ .
L'utilisation par Linux du caractère oblique en sens montant dans les chemins de fichiers ne pose donc pas de problème de conflit en programmation. En revanche, l'utilisation par Windows du caractère oblique en sens descendant dans les chemins de fichiers nécessite de solutionner un conflit d'interprétation, dans les chemins de fichiers, lorsqu'on fait de la programmation en environnement Windows. Sous Windows, pour pouvoir effectivement produire une barre oblique inverse descendante en tant que simple caractère dans les chemins de fichiers, sans que celle ci soit considérée comme étant un caractère d'échappement, il faut la précéder d'une autre barre oblique inverse descendante ("\\" est alors interprété comme étant "\") .

1) On écrit et on enregistre le script

Si on est en environnement Windows, on écrit le script suivant , avec le Bloc-Note, puis on le sauvegarde avec le nom «paysage-800-533-batch-version-windows.scm» (par exemple). Ce nom de fichier doit être le même que celui indiqué dans le script afin que GIMP puisse l’enregistrer correctement. Puis on place ce fichier dans le répertoire «C:/ Program Files/ GIMP/ lib/ gimp/ 2.0/ share/ gimp/ 2.0/ scripts». Bien entendu, si GIMP est installé dans un répertoire différent, dans le répertoire "GIMP2" par exemple, il faut placer le fichier dans le répertoire «C:/ Program Files/ GIMP2/ lib/ gimp/ 2.0/ share/ gimp/ 2.0/ scripts»

Si on est en environnement Linux Raspbian, on écrit le script avec les deux modifications indiquées ci-dessus puis on le sauvegarde avec le nom «paysage-800-533-batch-version-linux-raspbian.scm» (par exemple). Ce nom de fichier doit bien entendu être le même que celui indiqué dans le script afin que GIMP puisse l’enregistrer correctement. Puis on place ce fichier dans le répertoire scripts de Gimp, c'est à dire en général dans le répertoire «/usr/share/gimp/2.0/scripts».

;================================================================
; Ce script place dans un répertoire "destination" (avec un format
; paysage 3:2 et une dimension finale 800-533) un lot d'images jpg
; (de dimensions quelconques) contenues dans un répertoire" source".
; L'opération s'effectue sans déformer les images mais en utilisant
; une couleur de remplissage noire.
;
; source : chemin du répertoire où se trouvent les images à redimensionner
; listedesnomsdefichiers : liste des noms des fichiers jpg des images à traiter
; nomfichier : nom du fichier jpg de l'image en cours de traitement
; image : image en cours de traitement
; calque : calque actif de l'image en cours de traitement
; destination : chemin du répertoire où on enregistre les images redimensionnées
; h et w : hauteur et largeur initales (en pixels) de l'image en cours de redimensionnement
; nw, nh, offx, offy, u, v, i, j , k : variables utilisées pour effectuer les calculs
;
; Auteur : Claude Turrier - dernière mise à jour 16 mai 2018
;===============================================================

(;------------------------------------ Début Define
define (script-fu-paysage-800-533-batch-version-windows source destination )

(;-------------------------------------Début 1er let*
let* ((listedesnomsdefichiers (cadr (file-glob (string-append source "\\*.jpg") 1))))

(; ------------------------------------Début while
while (not (null? listedesnomsdefichiers))

(;-------------------------------------Début 2ème let*
let*
(
(nomfichier (car listedesnomsdefichiers))
(image (car (gimp-file-load RUN-NONINTERACTIVE nomfichier nomfichier)))
(calque (car (gimp-image-get-active-layer image)))
(destination (string-append destination "\\" (car (gimp-image-get-name image))))
(nw 0) (nh 0) (offx 0) (offy) (u 0) (v 0) (i 0) ( j 0) (k 0)
(h (car (gimp-image-height image))) (w (car (gimp-image-width image)))
)

; --on fixe la couleur de remplissage à noir
(gimp-context-set-background '(0 0 0))

;-- on place la hauteur et la largeur de l'image ouverte dans u et v
(set! u w) (set! v h) (set! k (* (/ 3 2) v) )

; --quel que soit le format de l'image ouverte on le transforme en un format paysage 3/2
; --si la hauteur de l'image est inférieure à sa largeur, on la complète avec du noir en haut et en bas
; --sinon on la complète avec du noir à gauche et à droite

; --cas n°1 : w > h et w > 1,5 h
(if (> u v)
(if (> u k)
(begin
(set! i (/ 2 3) ) (set! nh (* w i))
(set! i (/ 1 3) ) (set! j (* w i)) (set! i (/ h 2)) (set! offy (- j i ))
(gimp-image-resize image w nh 0 offy)
);end begin
) ; end if
) ; end if

; --cas n°3 : w > h et w < 1,5 h
(if (> u v)
(if (< u k )
(begin
(set! i (/ 3 2) ) (set! nw (* h i))
(set! i (/ 3 4) ) (set! j (* h i)) (set! i (/ w 2)) (set! offx (- j i ))
(gimp-image-resize image nw h offx 0)
);end begin
) ; end if
) ; end if

; --cas n° 4 : w < h
(if (< u v)
(begin
(set! i (/ 3 2) ) (set! nw (* h i))
(set! i (/ 3 4) ) (set! j (* h i)) (set! i (/ w 2)) (set! offx (- j i ))
(gimp-image-resize image nw h offx 0)
);end begin
);end if

; -- cas n° 5 : w = h
(if (= u v)
(begin
(set! i (/ 3 2) ) (set! nw (* h i))
(set! i (/ 3 4) ) (set! j (* h i)) (set! i (/ w 2)) (set! offx (- j i ))
(gimp-image-resize image nw h offx 0)
);end begin
);end if

(gimp-image-scale image 800 533)
(gimp-image-resize image 800 533 0 0)
(gimp-image-flatten image)
(set! calque (car (gimp-image-get-active-layer image)))

; -- on sauvegarde l'image en cours
(file-jpeg-save RUN-NONINTERACTIVE image calque destination destination 1 0 1 0 "" 2 1 0 0)

; --on ferme l'image en cours
(gimp-image-delete image)

);-------------------------------------Fin 2ème let*

; --on met à jour la liste des noms de fichiers en retirant le nom de fichier de l'image qui vient d'être traitée
(set! listedesnomsdefichiers (cdr listedesnomsdefichiers))

); -----------------------------------Fin while
);------------------------------------Fin 1er let*
);------------------------------------Fin Define

;===========================================================================
;--on enregistre le script dans gimp
(
script-fu-register "script-fu-paysage-800-533-batch-version-windows"
"<Image>/MesScripts/paysage-800-533-batch-version-windows"
"-------------------------------"
"Met automatiquement un lot d'images au format 3/2 puis en taille 800-533"
"Claude Turrier"
"2018"
"-------------------------------"
SF-DIRNAME "Source" "c:/source"
SF-DIRNAME "Destination" "c:/destination"
)

Télécharger le code source du script :
paysage-800-533-batch-version-windows.scm (version Windows, prenant en compte les remarques ci-dessus concernant la syntaxe des chemins de fichiers)
paysage-800-533-batch-version-linux-raspbian.scm (version Linux, prenant en compte les remarques ci-dessus concernant la syntaxe des chemins de fichiers)

2) On utilise le script

On commence par créer deux répertoires "source" et "destination" sur "C:" et on place dans "C:" plusieurs images jpeg à redimensionner.

1

On lance Gimp et on vérifie que le script "paysage-800-533-batch-version-windows" est bien accessible, dans la barre de menu principale de Gimp, depuis l'option de menu "MesScripts".

2

Normalement cette option de menu doit automatiquement apparaître, une fois GIMP démarré, si le fichier «paysage-800-533-batch-version-windows.scm» a bien été placé dans le répertoire «C:/ Program Files/ GIMP/ lib/ gimp/ 2.0/ share/ gimp/ 2.0/ scripts». Dans ce cas, au moment de son démarrage, gimp reconnaît l'existence du script et intégre automatiquement l'option de menu "MesScripts". Bien entendu, si GIMP est installé dans un répertoire différent (dans le répertoire "GIMP2" par exemple) il faut alors veiller à bien placer le fichier dans le bon répertoire c'est à dire, dans ce cas, dans le répertoire «C:/ Program Files/ GIMP2/ lib/ gimp/ 2.0/ share/ gimp/ 2.0/ scripts»

3

On clique l'option de menu "MesScripts/Paysage-800-533-batch-version-windows" et on voit apparaître la boîte de dialogue "Script-fu : Paysage-800-533-batch-version-windows". Dans cette boîte, les deux répertoires "source" et destination" sont automatiquement présélectionnés dans les deux listes déroulates de choix des répertoires. On clique donc directement le bouton "Valider"

4

Le traitement s'effectue automatiquement

5

À la fin du traitement, on vérifie la présence d'une copie redimensionnée de chaque image dans le répertoire "c:\destination". De leur coté, les images source restent présentes et inchangées dans le répertoire "source"

6

3) On analyse le fonctionnement du script

Les lignes qui commencent par un point virgule ";" sont des commentaires qui sont ignorés au moment de l'exécution du script.

(;------------------------------------ Début Define
define (script-fu-paysage-800-533-batch source destination )

Cette ligne définit le script comme étant un script qui prend deux variables en entrée :
1ère variable : "source", associée au chemin du répertoire où se trouvent les images jpeg à traiter
2ème variable : "destination" associée au chemin du répertoire où doivent être rangées les copies jpeg redimensionnées des images source.
Ces deux variables sont associées aux deux paramètres SF-DIRNAME situés en fin de script. Il est à noter que la syntaxe spécifique "c:/source" et "c:/destination" ( barre oblique en sens montant /) , interprété par Gimp pour les chemins indiqués après SF-DIRNAME, est de 'type Linux" et doit être scrupuleusement respectée pour que Gimp pré-renseigne ces deux chemins à l'ouverture de la boîte de dialogue.

7

(;-------------------------------------Début 1er let*
let* ((listedesnomsdefichiers (cadr (file-glob (string-append source "\\*.jpg") 1))))

Cette ligne range la liste des chemins complets des noms de fichier jpeg dans le tableau "listedesnomsdefichiers".
La fonction file-glob retourne la liste des noms de chemins complets qui conviennent. Elle prend en entrée les valeurs pattern STRING (chemin complet des fichiers ) et encoding INT32 pour définir l'encodage du nom de fichier retourné (UTF-8 ->0, filename encoding ->1). Elle retourne les valeurs num-files INT32 (1er champs : nombre de nom de chemins complets retournés) et files STRINGARRAY (deuxième champs : liste des noms de chemins complets qui conviennent).
En langage Lisp, une structure d’enregistrement qui possède deux champs est appelée paire. Ces deux champs sont accédés par la fonction car (pour le premier élément de la paire) et par la fonction cdr (pour le second élément de la paire). Par exemple, si les deux champs sont a et b, car (a, b) donne a et cdr (a,b) donne b.
La fonction cadr est l'équivalent de la fonction car(cdr()). Donc cadr (a,b) donne également b c'est à dire la liste des noms de chemins complets qui conviennent dans notre cas.

8

(; ------------------------------------Début while
while (not (null? listedesnomsdefichiers))

Tant que la liste des noms de fichiers n'est pas vide, le script va utiliser le nom de chemin complet situé en haut de la liste pour effectuer le traitement de redimensionnement de l'image correspondante puis mettre la liste à jour (en retirant de la liste le nom de chemin de l'image traitée).

(nomfichier (car listedesnomsdefichiers))

nom du chemin complet du fichier jpg de l'image en cours de traitement

(image (car (gimp-file-load RUN-NONINTERACTIVE nomfichier nomfichier)))

La fonction gimp-file-load charge en mémoire l'image contenue dans un fichier image. Elle prend en entrée les trois valeurs run-mode INT32 (RUN-INTERACTIVE 0 ou RUN-NONINTERACTIVE 1), filename STRING (nom du chemin complet du fichier à charger) et raw-filename STRING (nom du chemin complet du fichier tel qu'il est saisi par l'utilisateur). Elle retourne en sortie la valeur image IMAGE (image en cours de traitement). La fonction car permet de ranger cette valeur dans la variable image (image en cours de traitement) utilisée par le script.

9

(calque (car (gimp-image-get-active-layer image)))

La fonction gimp-image-get-active-layer retourne le calque actif de l'image en cours. Elle prend en entrée la valeur image IMAGE (image en cours). Elle retourne en sortie la valeur active-layer LAYER (calque actif associé à l'image en cours). La fonction car permet de ranger cette valeur dans la variable calque (calque actif de l'image en cours de traitement) utilisée par le script.

(destination (string-append destination "\\" (car (gimp-image-get-name image))))

La fonction gimp-image-get-name retourne le nom de l'image spécifiée. Elle prend en entrée la valeur image IMAGE de l'image spécifiée. Elle donne en sortie la valeur name STRING (nom de l'image spécifiée). Si l'image spécifiée est associée à un nom de fichier, la valeur retournée par la fonction contient le nom de fichier de cette image.

La fonction string-append joue le même rôle que la fonction strcat en langage C. Elle prend en entrée plusieurs chaines de caractères est produit en sortie une chaine de caractères constituée de la concaténations de ces chaines de caractères.
Par exemple :
string-append ("Bonjour" "mon ami" "Toto") donne "Bonjour mon ami Toto"
Cependant string-append( "C:" "\\" "monimage.jpg") donne "C:\monimage.jpg" car, là aussi, le caractère \ doit être doublé pour ne pas être interprété comme une séquence d'échappement par l'interpréteur de commandes de Gimp.
La ligne d'instruction permet donc de ranger dans la variable "destination" le chemin complet de l'image en cours de traitement ("C:\source\12.jpg" par exemple)

10

(nw 0) (nh 0) (offx 0) (offy) (u 0) (v 0) (i 0) ( j 0) (k 0)

Pour chaque nouvelle image, on met a zéro, au début des calculs de redimensionnement, l'ensemble des variables utilisées pour effectuer ces calculs.

(h (car (gimp-image-height image))) (w (car (gimp-image-width image)))

On place dans les variables h et w les valeurs de hauteur et de largeur (mesurées en pixels) de la nouvelle image en cours de traitement.

11

Les lignes suivantes constituent le calcul de redimensionnement de l'image en cours pour obtenir à la fin du traitement une image de taille 800x533 (format 3:2). Ce calcul est expliqué de façon détaillée dans la page Gimp - Script-fu - Mettre des images au format 3:2

L’instruction «(gimp-image-flatten image)» consiste à applatir l’image, c’est à dire à fusionner le calque créé (ainsi que son contenu) avec l’image en cours. Cette opération correspond à l’option de menu «Image/Applatir l’image» de GIMP.

(set! calque (car (gimp-image-get-active-layer image)))

L'instruction gimp-image-get-active-layer retourne le calque actif de l'image spécifiée. Elle prend en entrée la valeur image IMAGE de l'image en cours de traitement et produit en sortie la valeur active-layer LAYER du calque actif de l'image en cours de traitement. Si ce calque existe, la fonction retourne son identificateur (ID) sinon elle retourne la valeur -1. La fonction car permet de ranger cette valeur dans la variable calque (calque actif de l'image en cours de traitement) utilisée par le script.

12

(file-jpeg-save RUN-NONINTERACTIVE image calque destination destination 1 0 1 0 "" 2 1 0 0)

La fonction file-jpeg-save permet d'enregistrer l'image en cours de traitement dans le fichier jpeg correspondant au chemin spécifié. Cette fonction prend en entrée les 14 paramètres suivants :

13

(gimp-image-delete image)

L'instruction gimp-image-delete supprime l'image spécifiée. Elle prend en entrée la valeur image IMAGE (image en cours de traitement)

(set! listedesnomsdefichiers (cdr listedesnomsdefichiers))

Cette instruction permet de mettre à jour la variable listedesnomsdefichiers qui contient la liste des chemins complets des fichiers jpeg des images à redimensionner. la fonction cdr reporte dans listedesnomsdefichiers la llste contenue dans listedesnomsdefichiers en enlevant le chemin relatif à l'image en cours. En effet, si une liste contient n valeurs, la fonction car donne la première valeur et la fonction cdr donne l'ensemble des valeurs suivantes. Par exemple, car (a,b,c,d,e) donne a et cdr (a,b,c,d,e) donne (b,c,d,e).

14

La partie script-fu-register permet de faire enregistrer le script par Gimp. L’instruction "<Image>/MesScripts/paysage-800-533-batch-version-windows" indique à GIMP que le script doit être accessible, depuis la fenêtre principale de Gimp, avec l’option de menu "MesScripts" et l'option de sous menu «paysage-800-533-batch-version-windows».

Remarques : Création et utilisation du script en environnement Linux Raspbian

1) Ecriture et enregistrement du Script en environnement Linux Raspbian

L'écriture du script dans un fichier "paysage-800-533-batch-version-linux-raspbian.scm" peut s'effectuer tout simplement avec l'Éditeur de texte de Linux, de la même façon qu'avec le Bloc-Note sous Windows.

Sous Linux, la difficulté commence quand on veut enregistrer ou copier le fichier "paysage-800-533-batch-version-linux-raspbian.scm" dans le répertoire «/usr/share/gimp/2.0/scripts» de Linux Raspbian. L'enregistrement ou la copie du fichier sont refusés par le système d'exploitation qui indique que seul l'administrateur du système (root) possède les droits pour pouvoir effectuer une telle opération.

Pour solutionner cette difficulté, on peut procéder des deux façons suivantes :

Solution 1 : On lance le Terminal de commandes de Linux, à l'aide d'un clic droit depuis le répertoire où se trouve le fichier à copier (depuis un répertoire situé sur une clef USB par exemple). Puis on écrit, depuis le Terminal de commandes, "sudo cp paysage-800-533-batch-version-linux-raspbian.scm "/usr/share/gimp/2.0/scripts"
Le fichier "paysage-800-533-batch-version-linux-raspbian.scm" est alors ausitôt recopié dans le répertoire "/usr/share/gimp/2.0/scripts" de Gimp.

15

Solution 2 : On ouvre le Terminal de commandes de Raspbian, on se connecte en tant qu'administrateur puis on déclare le répertoire «/usr/share/gimp/2.0/scripts» comme pouvant être accédé en lecture et en écriture. Tout ceci se fait avec les commandes suivantes :
$ su
Password : ******
root@raspberrypi:/home/pi# chmod -R a+rwx /usr/share/gimp/2.0/scripts

15b

Une fois cette opération effectuée, on peut directement copier le fichier "paysage-800-533-batch-version-linux-raspbian.scm" dans le répertoire "/usr/share/gimp/2.0/scripts" à l'aide de l'Explorateur de fichier.

16

2) Utilisation du Script en environnement Linux Raspbian

En environnement Linux Raspbian, Gimp se lance en cliquant l'option de menu "Framboise/Graphics/GNu Image Manipulation Program" puis se présente sous la même forme qu'en environnement Windows.

17

18