Dites le avec des pétales

Gimp est le fabuleux logiciel open source de dessin 2D de qualité professionnelle.
Gimphried
Messages : 74
Inscription : 21 mai 2020, 16:52

Dites le avec des pétales

Message par Gimphried »

1. Dites le avec des pétales

Image

Make Flower a été écrit en Script-Fu par Daniel Bates en 2007.
Vous pouvez télécharger le code source gratuit Flower_Generator_Script_by_Insanity_Prevails.scm
dans le github de SamRocketMan.

Ouvrir le script .scm dans l'éditeur gratuit Notepad++.

'script-fu-register' en ligne 316 a d'étranges caractères 'NUL'.
De plus, de nos jours, la déclaration d’une fonction est en deux étapes. Nous devons indiquer le menu Gimp pour appeler le script dans une déclaration supplémentaire :

Code : Tout sélectionner

(script-fu-menu-register "script-fu-make-flower" "<Image>/Filters/Render/Make Flower/")
Cependant ne le faites pas ! Nous n'avons pas besoin de surcharger l’interface graphique (GUI) de Gimp avec des menus additionnels qui ne sont pas utilisés tous les jours.

:arrow: Nous pouvons appeler directement 'make-flower' dans la console Script-Fu de Gimp 2.10.28 sans aucune déclaration de menu.

1. Dans Notepad++, clic en début de ligne 12 avant la parenthèse ouvrante sans sélectionner quoique ce soit.
2. Appuyer sur raccourci clavier 'Ctrl+Alt+B' de Notepad++.
Notepad++ sélectionne automatiquement la fonction 'make-flower' complète de la ligne 12 à la ligne 312.
Cela signifie que bien sûr les parenthèses sont bien équilibrées.

3. Appuyer sur 'Ctrl+C' dans Windows pour copier la fonction dans le presse-papier.
4. Lancer Gimp.
5. Gimp menu 'Filtres' > 'Script-Fu' > 'Console'
;-> "Bienvenue dans TinyScheme" apparaît au sommet de la console Script-Fu.

6. Coller le contenu du presse-papier dans la zone de saisie de la console Script-Fu au-dessus du bouton 'Aide'.
Appuyer sur 'Entrée'
;-> Script-Fu répond par le nom de la fonction:
'make-flower'
Cela signifie qu'il n'y a aucune erreur de syntaxe !

7. Copier dans le presse-papier par 'Ctrl+C' l'appel suivant de la fonction avec tous ses paramètres :

Code : Tout sélectionner

(make-flower       500  2         2        30        1        5        '(230 120 210)  '(170 50 150)    '(170 170  50))
Appuyer sur 'Entrée' pour exécuter la fonction TinyScheme.
;->  :cry:
Oops:

Code : Tout sélectionner

Error: Bad syntax of binding spec in let* : ((theImage) (theActive) (base-layer) (flower-layer) (petal-layer) (petal2-layer) (petal3-layer) (petal4-layer) (petal5-layer) (petal6-layer) (shade-layer) (map-layer) (varX1) (varY1) (varX2)) 
8. Dans Notepad++, sélectionner les variables locales de 'Let*' de la ligne 26 à 46 :

Code : Tout sélectionner

	(theImage)
	(theActive)
	(base-layer)
	(flower-layer)
	(petal-layer)
	(petal2-layer)
	(petal3-layer)
	(petal4-layer)
	(petal5-layer)
	(petal6-layer)
	(shade-layer)
	(map-layer)

	(varX1)
	(varY1)
	(varX2)
La valeur initiale est manquante pour chaque variable locale. Heureusement, elles sont toutes des entiers.

10. Pour corriger le problème, Notepad++ menu 'Rechercher' > 'Remplacer...'
11. Dans la boîte de dialogue "Remplacer", second onglet "Remplacer", 
Recherche : ")"
Saisir la parenthèse fermante sans les guillemets.

Remplacer par : " 0)"
Saisir un espace séparateur avant la valeur initiale, puis la valeur initiale 0 et la parenthèse fermante.
Ne pas saisir les guillemets.

Cliquer l'option [x] Dans sélection
Appuyer sur le bouton 'Remplacer tout'
Le résultat escompté doit être :

Code : Tout sélectionner

	(theImage 0)
	(theActive 0)
	(base-layer 0)
	(flower-layer 0)
	(petal-layer 0)
	(petal2-layer 0)
	(petal3-layer 0)
	(petal4-layer 0)
	(petal5-layer 0)
	(petal6-layer 0)
	(shade-layer 0)
	(map-layer 0)

	(varX1 0)
	(varY1 0)
	(varX2 0)
12. Répéter les étapes 1-7
;-> Le script dessine la fleur rose avec 8 pétales sur 500x500 pixels.

La fenêtre des calques présentent les calques suivants :
  • Shading
  • Centre Shading
  • Centre
  • Flower
  • Background
Dernière modification par Gimphried le 23 oct. 2021, 20:47, modifié 2 fois.
Gimphried
Messages : 74
Inscription : 21 mai 2020, 16:52

Optimiser le Script-Fu

Message par Gimphried »

2. Optimiser le Script-Fu

Image

Comme la fleur est dessinée en 1 s 196 ms 518 µs selon la CPU, le propos de ce chapitre n'est pas d'optimiser la vitesse.
C'est assez rapide pour un langage interprété.

Nous souhaitons réduire le nombre de lignes de façon à mieux comprendre l'architecture du programme et comment dessiner une telle fleur.

:arrow: Télécharger make-flower.zip 3 Ko.
Dézipper le nouveau 'make-flower.scm' 9 Ko.
Le nombre de lignes a été optimisé à 130 lignes :o grâce à 8 'define' à l'intérieur du 'define' principal.
Il y a 23 lignes de commentaire soit 17.6% et une ligne blanche.

Script-Fu console: 

Code : Tout sélectionner

(make-flower       500  1         0        60        0        5        '(130  65  66)  '( 24 86  46)    '(  9  29  16))
Appuyer sur 'Entrée'
;-> La nouvelle version dessine une autre fleur avec 4 pétales.

Clic le bouton 'Parcourir' à la droite de la zone de saisie de la console Script-Fu
Chercher : "gimp-image-add-layer"
La PDB annonce : "Deprecated: Use 'gimp-image-insert-layer' instead."
Ainsi dans la nouvelle version, l’ancien :

Code : Tout sélectionner

(gimp-image-add-layer theImage base-layer 0)
est remplacé par :

Code : Tout sélectionner

(gimp-image-insert-layer image layer 0 -1)
avec parent=0

Contrairement à la version originale, noter que la nouvelle version introduit l'alignement des parenthèses --typique du style de Gimphried--.
Nous utilisons la largeur complète des écrans modernes avec en ligne 74 la ligne of code la plus longue avec son commentaire terminé au 165e caractère.

Nous introduisons l'instruction 'case'.

Pour cet exercice d'optimisation du nombre de lignes, Gimphried a résumé l'instruction complète 'case' sur seulement une ligne :

Code : Tout sélectionner

(case petalDir	((0) (set! varX1 8) (set! varY1 4)) ((1) (set! varX1 4) (set! varY1 8)) ((2) (set! varX1 8) (set! varY1 8))) ; Cloud Layer X and Y
Cependant ne faites pas comme Gimphried.

L’optimisation du 'if' + 'begin' par 'and' avec multiple paramètres pourrait être plus pertinente :
Comme il y a plus d'une instruction dans la partie 'alors', nous avons besoin de les grouper à l'intérieur d'une instruction 'begin' :

Code : Tout sélectionner

(if (> centreBump 0) ; Only bumpmap if the Centre Bump setting was not at zero. Ignore if set to zero.
	(begin
		(gimp-context-set-pattern "Leather")
		(gimp-edit-bucket-fill layerMap 2 0 100 255 FALSE 0 0) ; Add pattern for bump map purposes
		(gimp-selection-none image)
		(gimp-image-set-active-layer image layerCentre)
		(plug-in-bump-map 1 image layerCentre layerMap 135 45 centreBump 0 0 0 0 1 0 0) ; then apply bump map. 
		(gimp-selection-layer-alpha layerMap)
)	) ; Remove bump map layer and merge remaining 2 layers.
L'extrait de code ci-dessus concernant 'if' peut être optimisé par l'opérateur logique 'and' acceptant un nombre illimité de paramètres
si et seulement si chaque instruction de la partie 'alors' --regroupée à l'intérieur du 'begin'-- n'échoue jamais !

Code : Tout sélectionner

(and (> centreBump 0) ; Only bumpmap if the Centre Bump setting was not at zero. Ignore if set to zero.
	(gimp-context-set-pattern "Leather")
	(gimp-edit-bucket-fill layerMap 2 0 100 255 FALSE 0 0) ; Add pattern for bump map purposes
	(gimp-selection-none image)
	(gimp-image-set-active-layer image layerCentre)
	(plug-in-bump-map 1 image layerCentre layerMap 135 45 centreBump 0 0 0 0 1 0 0) ; then apply bump map. 
	(gimp-selection-layer-alpha layerMap)
)	; Remove bump map layer and merge remaining 2 layers.
La nouvelle version est plus lisible en réduisant le nombre de constantes codées en dur :
Comparer l’ancien :

Code : Tout sélectionner

(gimp-drawable-transform-rotate petal-layer 1.05 FALSE (/ measure 2) (/ measure 2) 0 2 FALSE 3 1)
avec les constantes nommées :

Code : Tout sélectionner

(gimp-drawable-transform-rotate layerNext angle-rotation FALSE side/2 side/2 0 2 FALSE 3 1)
Les variables suivantes sont constantes dans le contexte des paramètres d'entrée donnés :

Code : Tout sélectionner

(define side/2 (/ side 2))
(define angle-rotation (/ *pi* 3))
Exécuter la définition de la constante 'angle-rotation' dans la console Script-Fu :

Code : Tout sélectionner

(define angle-rotation (/ *pi* 3))
angle-rotation
;-> 1.047197551

Nous introduisons la convention de la flèche verte de commentaire signifiant que Script-Fu retourne le résultat reproduit après cette flèche.

Nous retrouvons l’ancien angle '1.05' en radian 
depuis que la constante globale '*pi*' est définie en ligne 350 de 'C:\Program Files\GIMP 2\shsont\gimp\2.0\scripts\script-fu-compat.init'

Code : Tout sélectionner

(define *pi*
  (* 4 (atan 1.0))
)
*pi*
;-> 3.141592654

Console Script-Fu :

Code : Tout sélectionner

(make-flower       500  0         1        60        0        5        '(228 163 255)  '(105 10 144)    '(192 225 255))
;-> Disons le avec 6 pétales
Image

Cordialement.
undertaker
Messages : 1578
Inscription : 05 janv. 2005, 19:58
Localisation : LIEGE - BELGIQUE

Re: Dites le avec des pétales

Message par undertaker »

Bonjour Gimphried.

Super boulot.
Bravo et merci.

A+
COGITO ERGO SUM.
Linux DEBIAN 10, Inkscape 1.1, Scribus 1.4.8 et aussi Gimp, Blender, ...
Répondre