Script numérotation automatique?

Gimp est le fabuleux logiciel open source de dessin 2D de qualité professionnelle.
Dravahavaard
Messages : 1
Inscription : 23 janv. 2014, 11:35

Script numérotation automatique?

Message par Dravahavaard »

Bonjour gimpmen,
Savez-vous si il existe un script permettant de numéroter automatiquement des invitations avec la police et la couleur souhaitée?
C'est assez urgent, je dois vite savoir si je dois le faire à la main (500 invits...)...
Merci de votre attention and long live to gimp surtout si ya les scripts qui vont bien.
Gimphried
Messages : 65
Inscription : 21 mai 2020, 16:52

Gimp Script-Fu NumInvit : structure du projet

Message par Gimphried »

Bonjour,

1. Gimp Script-Fu NumInvit : structure du projet de numérotation d'invitation

Le projet NumInvit est structuré en un dossier racine comprenant deux sous-dossiers "source" et "target" :
  • créer le dossier racine : C:\Tool\Gimp\forum\Linuxgraphic\NumInvit
    => Si vous créez le dossier "NumInvit" ailleurs, adaptez les chemins.
  • créer le sous-dossier "source" : C:\Tool\Gimp\forum\Linuxgraphic\NumInvit\source
    => Vous devez créer une première invitation au format .jpg par exemple last_first.jpg
  • créer le sous-dossier des résultats "target" : C:\Tool\Gimp\forum\Linuxgraphic\NumInvit\target
Gimphried
Messages : 65
Inscription : 21 mai 2020, 16:52

Gimp Script-Fu NumInvit : analyse syntaxique du chemin

Message par Gimphried »

2. Gimp Script-Fu NumInvit : analyse syntaxique du chemin

Pour aller au plus vite, le débutant en programmation de script Gimp Script-Fu préfère généralement fusionner les dossiers "source" et "target".
Autrement-dit, le script écrase l'image d'origine avec l'image modifiée par le script. :roll:
C'est une erreur de conception parce qu'elle oblige à sauvegarder d'une façon ou d'une autre le dossier "source" avant que les images soient traitées.

La séparation en sous-dossier "source" à lire par le script et "target" à écrire par le script est vivement conseillée. :idea:
Car le développement du script demande souvent de relancer plusieurs fois le script jusqu'à la fin de sa mise au point.
Au moins le dossier "source" est préservé.
Avant chaque exécution du script, il suffit de vider le dossier "target" des éventuelles images plus ou moins bien générées.

L'inconvénient de la séparation "source" / "target" est qu'il faut écrire une analyse syntaxique du chemin "source" pour que le script puisse passer de la lecture "source" à l'écriture dans "target".
Selon votre niveau en TinyScheme, vous pouvez considérer cette analyse syntaxique comme élémentaire. 8)
Dans ce cas, quand vous savez déjà, lisez en diagonale et passez à la suite.

Au départ, ce tuto s'adresse au grand débutant. :oops:

L'objectif de l'analyse syntaxique est d'extraire le chemin racine du chemin de l'invitation "source".
Ensuite il faut compléter le chemin racine par le dossier des résultats "target".
Pour simplifier, le nom d'image est identique que ce soit dans "source" ou dans "target".

Pour connaître le mode d'emploi de la console Script-Fu dans Gimp, consulter l'usage du projet GenCards.
Noter que dans le projet NumInvit (contrairement au projet GenCards plus complexe), les backslahs Windows sont à doubler en TinyScheme.
Rappelons que le code suivant est à copier-coller dans la zone de saisie de la console Script-Fu.

Code : Tout sélectionner

(define filename "C:\\Tool\\Gimp\\forum\\Linuxgraphic\\NumInvit\\source\\last_first.jpg")
filename

Quand la console Scipt-Fu répond par le nom du define, c'est que la syntaxe Lisp est correcte.

La tokenisation (séparation en token = symbole = mot) utilise la fonction strbreakup qui sépare les dossiers selon le séparateur de chemin DIR-SEPARATOR.
Sous Windows, DIR-SEPARATOR est la chaîne backslash. Sous Linux, DIR-SEPARATOR est la chaîne (forward) slash.

Ci-dessous deux instructions sont à copier-coller. Il faut donc s'attendre à deux résultats retournés collés par la console Script-Fu :

Code : Tout sélectionner

(define lstDirSource (strbreakup filename DIR-SEPARATOR)) ; split according to Windows path separator
lstDirSource
lstDirSource("C:" "Tool" "Gimp" "forum" "Linuxgraphic" "NumInvit" "source" "last_first.jpg")

lstDirSource est la liste des dossiers du chemin source sans les séparateurs de chemin ainsi que le nom de l'invitation.
Coupons le nom de l'image en fin de liste :

Code : Tout sélectionner

(butlast lstDirSource)
("C:" "Tool" "Gimp" "forum" "Linuxgraphic" "NumInvit" "source")

Coupons en plus le dossier "source" pour obtenir la liste des dossiers du chemin racine du projet :

Code : Tout sélectionner

(butlast (butlast lstDirSource))
("C:" "Tool" "Gimp" "forum" "Linuxgraphic" "NumInvit")

Reconstituons la liste du chemin des résultats "target" et de l'image cible :

Code : Tout sélectionner

(cons "target" (last lstDirSource))
("target" "last_first.jpg")

Il ne reste plus qu'à concaténer la liste des dossiers du chemin racine du projet avec la liste cible :

Code : Tout sélectionner

(append (butlast (butlast lstDirSource)) (cons "target" (last lstDirSource)))
("C:" "Tool" "Gimp" "forum" "Linuxgraphic" "NumInvit" "target" "last_first.jpg")

Pour reconstituer le chemin Windows de la cible, faisons l'opération inverse de tokenisation avec unbreakupstr :

Code : Tout sélectionner

(unbreakupstr (append (butlast (butlast lstDirSource)) (cons "target" (last lstDirSource))) DIR-SEPARATOR)
"C:\\Tool\\Gimp\\forum\\Linuxgraphic\\NumInvit\\target\\last_first.jpg"

strbreakup, butlast, last, unbreakupstr sont déjà définies dans C:\Program Files\GIMP\share\gimp\2.0\scripts\script-fu-compat.init
chargé au démarrage du plug-in Script-Fu dans Gimp.

Conclusion : filename est le chemin "source" de la première invitation. Un des outils utilisé plus tard impose ce nom.
L'analyse syntaxique a permis de générer le chemin "target" que l'on nommera par la suite par la variable bien connue filout.
Gimphried
Messages : 65
Inscription : 21 mai 2020, 16:52

Gimp Script-Fu NumInvit : optimisation string-replace

Message par Gimphried »

2.1 Gimp Script-Fu NumInvit : optimisation de l'analyse syntaxique du chemin

Ce chapitre est optionnel.

La méthode précédente est suffisante car il n'y a rien à installer à part Gimp mais elle peut être optimisée.

Si vous avez fait le tuto GenCards, vous connaissez string-replace.

Alternativement, si le define de string-replace est dans un fichier texte, avec l'extension de fichier .scm, chargé au démarrage de Gimp,
vous pouvez plus simplement résumer l'analyse syntaxique du chemin source par :

Code : Tout sélectionner

(string-replace filename "source" "target")
"C:\\Tool\\Gimp\\forum\\Linuxgraphic\\NumInvit\\target\\last_first.jpg"

Par rapport à la méthode syntaxique strbreakup + 2 butlast + last + unbreakupstr,
string-replace gagne une seconde pour cent invitations à numéroter.

Cependant elle impose que Gimp Script-Fu a enregistré le define de string-replace.
Autrement-dit vous avez déjà mis le define de string-replace dans un .scm chargé dans le dossier :

Code : Tout sélectionner

C:\Users\Chess\AppData\Roaming\GIMP\2.10\scripts
en remplaçant "Chess" par votre nom utilisateur.

Si lors de l'exécution de "(string-replace filename "source" "target")", vous obtenez le message :
"Error: eval: unbound variable: string-replace"
C'est que la fonction string-replace n'a pas été chargée par Gimp.
Dans ce cas, utiliser la première méthode syntaxique strbreakup + 2 butlast + last + unbreakupstr.
Gimphried
Messages : 65
Inscription : 21 mai 2020, 16:52

Gimp Script-Fu NumInvit : numéroter une invitation

Message par Gimphried »

3. Gimp Script-Fu NumInvit : numéroter la première invitation

Fermer Gimp. Rouvrir Gimp et sa console Script-Fu.

Définir la couleur d'avant-plan qui sera utilisée pour la numérotation.
Initialiser le compteur d'invitation.

Code : Tout sélectionner

(gimp-context-set-foreground '(14 17 170)) ; bleu foncé RGB "0e11aa"
(define countPic 1)
(#t)countPic

Lister les invitations au format JPG du dossier "source" :
Sous Windows 10, rappelons que dans ce projet, il faut doubler chaque backslash.
Le nom du fichier générique est exprimé par le joker *.jpg capturant toutes les images au format .jpg

Code : Tout sélectionner

(with-files "C:\\Tool\\Gimp\\forum\\Linuxgraphic\\NumInvit\\source\\*.jpg"
            (display filename) (newline)
            (set! countPic (+ countPic 1))
)
countPic
countPic
C:\Tool\Gimp\forum\Linuxgraphic\NumInvit\source\last_first.jpg
()2

Le compteur global countPic est bien passé à 2.
S'il y avait plusieurs JPG, le compteur indiquerait le nombre d'images plus un.
Cependant dans un premier temps, il est conseillé de n'avoir qu'une seule invitation.

Remettre à 1 le compteur global d'invitation :

Code : Tout sélectionner

(define countPic 1)
countPic
countPic1

Le bloc let* qui introduit la définition des variables locales a été abordé dans le chapitre 8 de GenCards.
Notons que le compteur global de numérotation doit être converti explicitement en chaîne par (number->string countPic) que vous pouvez tester individuellement dans la console.

Code : Tout sélectionner

(with-files "C:\\Tool\\Gimp\\forum\\Linuxgraphic\\NumInvit\\source\\*.jpg"
	(let*   (   (width  (car (gimp-drawable-width layer)))
				(height (car (gimp-drawable-height layer)))
				(posX   (- width 50))  ; distance to the right border
				(posY   (- height 30)) ; distance to the bottom
				(hndTxt 0) ; handle of text to display the global counter
				(lstDirSource (strbreakup filename DIR-SEPARATOR)) ; split according to Windows path separator
				(filout (unbreakupstr (append (butlast (butlast lstDirSource)) (cons "target" (last lstDirSource))) DIR-SEPARATOR))
			) ; end of local variables
		(set! hndTxt (car (gimp-text-fontname image layer posX posY (number->string countPic)  0 TRUE 18 POINTS "Sans")))
		(gimp-floating-sel-anchor hndTxt)
		(display "Numbering ") (display countPic) (display ": ") (display filout) (newline)
		(gimp-image-clean-all image)
		(file-jpeg-save RUN-NONINTERACTIVE image layer filout filout 0.8 0 1 1 "" 2 1 0 0)
	) ; end of block let*
	(set! countPic (+ countPic 1)) ; increment the global counter
)
Numbering 1: C:\Tool\Gimp\forum\Linuxgraphic\NumInvit\target\last_first.jpg
()

Dans l'Exporateur de fichiers, vérifier que last_first.jpg a été généré dans le dossier "target".
La numérotation de l'invitation apparaît en bleu foncé dans le coin inférieur droit.
Gimphried
Messages : 65
Inscription : 21 mai 2020, 16:52

Gimp Script-Fu with-files : + loin avec les macros

Message par Gimphried »

4. Gimp Script-Fu with-files : pour aller plus loin avec les macros

with-files est-elle une macro ?

Code : Tout sélectionner

(macro? with-files)
#t

Oui.

with-files est définie ligne 73 dans C:\Program Files\GIMP\share\gimp\2.0\scripts\script-fu-util.scm

Code : Tout sélectionner

(define-macro (with-files pattern . body)
...
)
Le point entre "pattern" et "body" signifie une paire :
  • pattern : "C:\\Tool\\Gimp\\forum\\Linuxgraphic\\NumInvit\\source\\*.jpg"
    => Pour la syntaxe Linux avec des slashs sous Windows 10, voir notre file-global ci-dessous.
  • body : le bloc let* et l'incrémentation du compteur global.
    => le corps est une suite d'instructions TinyScheme.
Pourquoi ce projet NumInvit est-il plus simple que GenCards ?

La macro with-files définit déjà les strings filename et basename ainsi que les handles image et layer.

Comme file-glob Windows est utilisé par la macro, cela impose la syntaxe de chemin avec backslashes doublés.
Sinon, il faudrait réécrire la macro en adaptant file-glob par notre file-global.

L'image d'origine est préservée dans le dossier "source" qui n'est que lu.
L'invitation numérotée est générée dans le dossier "target" grâce à une analyse syntaxique minimale.

Aucun calque n'est déplacé. Il n'y a pas de gabarit ou d'icône à importer sous forme de calque.

La numérotation est positionnée relativement au bord droit inférieur comme une pagination.
le script retrouve les dimensions du calque layer.

La macro with-files génère la boucle sur la liste des fichiers répondant au pattern *.jpg

Par contre, la conception d'une macro est plus complexe qu'une fonction TinyScheme standard.
Une macro est un générateur de code qui sera ensuite exécuté. C'est une sorte de métaprogrammation.

Le passage de paramètres se fait "par nom". C-a-d que l'expression Lisp en paramètre n'est pas encore évaluée.
Dans une fonction standard, on accède au contenu de la variable passée en paramètre.
Une macro est capable d'accéder au nom des variables dans l'expression Lisp passée en paramètre.

`(function prms) -> (quasiquote (function prms)) ; retarde l'évaluation de la fonction
,(function prms) -> (unquote (function prms)) ; force l'évaluation de l'expression.
,@(map function prms) -> (unquote-splicing map function prms) ; force l'évaluation de la fonction sur chaque élément de la liste

Attention à la quasiquote ` (AltGr+7 + space) à ne pas confondre avec la simple quote standard ' (touche 4 clavier azerty).

Code : Tout sélectionner

`(list ,(+ 2 3) 7)
(list 5 7)

L'expression quasiquotée est équivalente à :

Code : Tout sélectionner

(quasiquote (list (unquote (+ 2 3)) 7))
(list 5 7)

Conclusion : la macro with-files a été bien pratique pour itérer un traitement sur l'ensemble des images d'un dossier répondant au pattern *.jpg
Répondre