Retrouvez cet article dans : Linux Magazine HS 19
- un plugin Python est un véritable programme, exécuté par l'interpréteur Python du système, et non par un autre plugin de Gimp : toutes les extensions du langage sont donc disponibles ;
- là où Script-Fu utilise un identifiant pour manipuler les images, calques et autres objets, Gimp-Python stocke ceux-ci en tant qu'objets, exploitant les aspects orienté objet de Python ;
- enfin, l'ensemble de la bibliothèque
libgimpest accessible depuis le script Python, donnant ainsi accès à des fonctions de bas niveau inconnues pour Script-Fu.
Mise en place et outils
Pour commencer, il faut installer le module de Gimp qui permet l'exécution du code Python. Selon votre distribution, le nom du paquetage correspondant devrait ressembler à quelque chose comme
01: #!/usr/bin/python 02: from gimpfu import * 03: def test() : 04: pass 05: register( 06: "nom_de_la_fonction", 07: "description", 08: "texte d'aide", 09: "auteur", 10: "copyright", 11: "date", 12: "<Toolbox>/Xtns/Python-Fu/LinuxMag/test", 13: "RGB*", 14: [], # liste de parametres 15: [], # resultats 16: test) # fonction appellee 17: main()Inutile de préciser que ce programme ne fait à peu près rien. Normalement, dans votre répertoire personnel vous avez un répertoire caché dédié à Gimp :
yves@kafka plug-ins $ pwd /home/yves/.gimp-2.0/plug-ins yves@kafka plug-ins $ chmod +x test.pyMaintenant, lancez Gimp. Dans le menu Xtns|Python-Fu, vous devriez voir apparaître un sous-menu LinuxMag, qui contient une entrée test : le nom de cette entrée est celui du fichier, c'est celui que nous venons de créer ! Dans ce répertoire Xtns|Python-Fu devrait également se trouver une entrée PDB Browser : elle donne accès à la liste complète des fonctions disponibles. Sélectionnez-la, normalement vous devriez trouvez notre fonction dans la liste, préfixée par

Structure générale
Au minimum, un script Gimp-Python se compose :- de l'import du module
gimpfu(ligne 2) ; - d'une fonction Python tout ce qu'il y a de plus classique, où se déroulent les traitements voulus (lignes 3-4) ;
- d'un appel à la fonction
register(), fournie pargimpfu, pour référencer notre fonction dans Gimp (lignes 5 à 16) ; - d'un appel à la fonction
main()(également dansgimpfu), qui sera effectivement appelée au moment où le script sera exécuté (ligne 17).
Dessin dans une image existante
Nous voulons définir deux nouvelles commandes, l'une s'appliquant à une image existante, l'autre créant une nouvelle image. Les deux situations étant très proches, notre script va commencer par définir une fonction " interne " qui fait l'essentiel du travail. Voici le début du script :001: #!/usr/bin/python 002: 003: import math 004: from gimpfu import * 005: from gimpenums import *Le module
007: def texte_et_cadre(image, 008: texte, font, taille_texte, couleur_texte, antialias, 009: epaisseur_cadre, couleur_cadre, marge) : 010: 011: marge_totale = int(2*(epaisseur_cadre+marge)) 012: save_fg = gimp.get_foreground() 013: save_bg = gimp.get_background()Les paramètres correspondent aux choix offerts à l'utilisateur, tels que montrés dans la capture d'écran en début d'article. Le premier paramètre est une instance d'un type Image, défini dans le module
015: gimp.set_foreground(couleur_texte) 016: layer_texte = gimp.pdb.gimp_text_fontname(image, None, 017: 0, 0, texte, 0, antialias, taille_texte, POINTS, font)La première ligne définit la couleur d'avant-plan, qui sera celle du texte. Les deux suivantes sont un seul appel à une fonction, qui crée le texte et le calque pour le contenir. Ou plus précisément, il s'agit de l'invocation d'une autre commande de Gimp. L'ensemble des commandes est accessible depuis le script par l'objet
gimp.pdb["une-commande"](parametres)Je ne m'étendrai pas sur les paramètres de la commande
019: largeur_cadre = layer_texte.width + marge_totale 020: hauteur_cadre = layer_texte.height + marge_totale 021: layer_cadre = gimp.Layer(image, "Cadre", largeur_cadre, hauteur_cadre, 022: RGBA_IMAGE, 100, NORMAL_MODE) 023: image.add_layer(layer_cadre, 0)Pour déterminer les dimensions de ce cadre, nous utilisons la valeur retournée par
- l'image qui doit contenir le calque ;
- le nom de ce calque ; si l'image contient déjà un calque de ce nom, Gimp va automatiquement le modifier en ajoutant un compteur sous la forme
"#1","#2", etc. ; - les dimensions du calque ;
- le type de calque, l'une des valeurs
*_IMAGE(GRAY_IMAGE,INDEX_IMAGE, etc.) définies dans gimpenums ; ici nous demandons un calque de type RGB avec un canal de transparence ; - l'opacité, un réel entre 0 et 100 ;
- le mode, qui a la même signification que la propriété du même nom dans la fenêtre de gestion des calques (l'une des valeurs
*_MODEdansgimpenums).
024: layer_cadre.fill(TRANSPARENT_FILL)Ceci a pour effet de remplir le calque avec des points transparents. Sans cette opération, vous risquez de récupérer un contenu aléatoire et probablement disgracieux. Nous pouvons maintenant dessiner notre cadre, ce que nous allons faire en manipulant une sélection :
025: gimp.set_foreground(couleur_cadre) 026: gimp.pdb.gimp_image_set_active_layer(image, layer_cadre) 027: gimp.pdb.gimp_rect_select(image, 0, 0, 028: largeur_cadre, hauteur_cadre, CHANNEL_OP_REPLACE, FALSE, 0) 029: gimp.pdb.gimp_rect_select(image, 030: epaisseur_cadre, epaisseur_cadre, 031: largeur_cadre-2*epaisseur_cadre, hauteur_cadre-2*epaisseur_cadre, 032: CHANNEL_OP_SUBTRACT, FALSE, 0) 033: gimp.pdb.gimp_edit_fill(layer_cadre, FOREGROUND_FILL)La ligne 26 a pour effet de rendre actif le calque devant contenir le cadre : ainsi les opérations suivantes s'effectueront sur ce calque, sans altérer les autres. Ensuite on sélectionne la partie de l'image qui nous intéresse, par la commande
035: layer_texte.translate(int(epaisseur_cadre+marge), 036: int(epaisseur_cadre+marge))La fin de la fonction se contente de désactiver la sélection encore active, et de rétablir les couleurs d'avant et d'arrière-plan :
038: gimp.pdb.gimp_selection_none(image) 039: gimp.set_foreground(save_fg) 040: gimp.set_background(save_bg) 041: return (layer_texte, layer_cadre)Pour mémoire, il ne s'agit ici que d'une fonction " utilitaire " : ce n'est pas la commande qui sera lancée par Gimp, que nous allons découvrir maintenant.
Commande pour une image existante
Première commande que nous allons créer, celle qui ajoute le texte avec son cadre dans une image existante, préalablement ouverte dans Gimp. Voici le code de cette commande :043: def texte_et_cadre_dans_image(image, drawable, 044: texte, font, taille_texte, couleur_texte, antialias, 045: epaisseur_cadre, couleur_cadre, marge) : 046: 047: image.undo_group_start() 048: (layer_texte, layer_cadre) = texte_et_cadre(image, 049: texte, font, taille_texte, couleur_texte, antialias, 050: epaisseur_cadre, couleur_cadre, marge) 051: x = (image.width - layer_cadre.width) / 2 052: y = (image.height - layer_cadre.height) / 2 053: layer_cadre.translate(x, y) 054: layer_texte.translate(x, y) 055: image.undo_group_end()Passons pour l'instant sur les paramètres, nous les retrouverons bientôt. Remarquez simplement le premier, qui est l'objet image que nous allons manipuler. La première instruction, ligne 47, est liée à la dernière, ligne 55. Les manipulations qui interviennent entre ces deux instructions seront référencées dans un " groupe d'annulation " : elles pourront toutes être annulées en une fois, par exemple lorsque vous utilisez la combinaison de touches Ctrl+Z. Sans cela, pour annuler notre commande, il faudrait annuler chacune des actions que nous avons effectuées : création des calques, translations, sélections, remplissages... ce qui serait extrêmement fastidieux. Lorsque vous créez une commande pour modifier une image existante, il est généralement souhaitable d'utiliser cette paire d'instructions. Ligne 48, nous utilisons simplement notre fonction utilitaire, décrite précédemment. Les lignes 51 à 54 ont pour effet de centrer les deux calques nouvellement créés dans l'image de départ. Voyons maintenant le référencement de notre commande dans Gimp :
057: register( 058: "texte_et_cadre_dans_image", 059: "Ecrit un texte dans un cadre (dans une image)", 060: "Pour le LinuxMagazine HS sur Gimp 2.0", 061: "Yves Bailly", 062: "Yves Bailly", 063: "2004", 064: "<Image>/Python-Fu/LinuxMag/Texte et cadre", 065: "RGB*", 066: [ 067: (PF_STRING, "texte", "Texte", "coucou"), 068: (PF_FONT, "font", "Police", "Helvetica"), 069: (PF_SPINNER, "taille_text", "Taille en points", 20, (0,100,5)), 070: (PF_COLOR, "couleur_texte", "Couleur du texte", (64,128,255)), 071: (PF_TOGGLE, "antialias", "Antialising ?", 1), 072: (PF_INT, "epaisseur_cadre", "Epaisseur du cadre", 8), 073: (PF_COLOR, "couleur_cadre", "Couleur du cadre", (255,128,64)), 074: (PF_SLIDER, "marge", "Marge interieur", 4, (0,24,2)) 075: ], 076: [], 077: texte_et_cadre_dans_image)Je ne reviens pas sur les six premiers paramètres. Le septième, qui indique dans quel menu la commande doit apparaître, influe sur les paramètres qui seront passés à la fonction Python. Ici, le premier élément est
| Type | Description |
| PF_STRING | Une chaîne de caractères, qui se traduit dans l'affichage par un simple champ de saisie. |
| PF_INT | Une police de caractère, représentée par une chaîne. En mode interactif, un bouton est affiché pour choisir la police dans une liste. |
| PF_COLOR | Une couleur, représentée par un triplet de valeurs rouge-vert-bleu entre 0 et 255. En mode interactif, se présente sous la forme d'un bouton de la couleur sélectionnée, qui ouvre une boîte de sélection de couleur quand on clique dessus. |
| PF_TOGGLE | Valeur booléenne, de type oui/non, ou vrai/faux. |
| PF_SPINNER | Un entier, à choisir entre deux bornes. Se présente sous la forme d'un champ de saisie, avec deux boutons pour incrémenter ou décrémenter la valeur. Le tuple supplémentaire (ligne 69) donne les bornes minimum et maximum, ainsi que la valeur de l'incrément. |
| PF_SLIDER | Un nombre réel, à choisir entre deux bornes. Se présente sous la forme d'un curseur à déplacer dans une glissière. Le tuple supplémentaire (ligne 74) donne les bornes minimum et maximum, ainsi que la valeur de l'incrément si on clique en-dehors du curseur. |
Commande créant une nouvelle image
Nous allons cette fois créer une nouvelle image. Un calque de fond sera ajouté " sous " les deux autres calques (du texte et du cadre), un paramètre de couleur supplémentaire permettant de définir, justement, sa couleur. Voici le code :079: def texte_et_cadre_nouveau( \ 080: texte, font, taille_texte, couleur_texte, antialias, 081: epaisseur_cadre, couleur_cadre, marge, 082: couleur_fond) : 083: image = gimp.Image(1024, 1024, RGB) 084: image.disable_undo() 085: (layer_texte, layer_cadre) = texte_et_cadre(image, 086: texte, font, taille_texte, couleur_texte, antialias, 087: epaisseur_cadre, couleur_cadre, marge) 088: image.resize(layer_cadre.width, layer_cadre.height, 0, 0) 089: gimp.set_background(couleur_fond) 090: fond = gimp.Layer(image, "Arriere-plan", image.width, image.height, 091: RGB_IMAGE, 100, NORMAL_MODE) 092: image.add_layer(fond, 2) 093: gimp.pdb.gimp_edit_fill(fond, BACKGROUND_FILL) 094: image.enable_undo() 095: gimp.Display(image)Première action, création d'une image, ligne 83. Nous ne savons pas a priori quelle taille est nécessaire, aussi donnons-nous des valeurs quelconques - ce sera ajusté par la suite. Sachez toutefois que ces dimensions sont une limite aux sélections, donc prévoyez suffisamment large. Par exemple, si j'avais créé une image en 10x10, le cadre ne serait que très partiellement dessiné. L'instruction ligne 84, qui va avec celle ligne 94, désactive l'enregistrement des manipulations que nous allons effectuer : elles ne pourront pas être annulées, ce qui est généralement souhaitable lorsqu'on crée une image de toute pièce. Puis nous créons nos calques de texte et de cadre, ligne 85. La ligne 88 ajuste la taille de l'image sur la taille du calque du cadre, les deux derniers paramètres étant la position à laquelle doit être déplacé l'ancien contenu de l'image (on retrouve ces paramètres dans la boîte de dialogue correspondant à cette méthode). Il s'agit bien d'un changement de dimensions de l'image, et non d'une mise à l'échelle (scale) : cette opération peut être effectuée avec la méthode
Il ne reste plus qu'à référencer notre commande : 097: register( 098: "texte_et_cadre_nouveau", 099: "Ecrit un texte dans un cadre (nouvelle image)", 100: "Pour le LinuxMagazine HS sur Gimp 2.0", 101: "Yves Bailly", 102: "Yves Bailly", 103: "2004", 104: "<Toolbox>/Xtns/Python-Fu/LinuxMag/Texte et cadre", 105: "RGB*", 106: [ 107: (PF_STRING, "texte", "Texte", "coucou"), 108: (PF_FONT, "font", "Police", "Helvetica"), 109: (PF_SPINNER, "taille_text", "Taille en points", 20, (0,100,5)), 110: (PF_COLOR, "couleur_texte", "Couleur du texte", (64,128,255)), 111: (PF_TOGGLE, "antialias", "Antialising ?", 1), 112: (PF_INT, "epaisseur_cadre", "Epaisseur du cadre", 8), 113: (PF_COLOR, "couleur_cadre", "Couleur du cadre", (255,128,64)), 114: (PF_SLIDER, "marge", "Marge interieur", 4, (0,24,2)), 115: (PF_COLOR, "couleur_fond", "Couleur de fond", (255,255,255)) 116: ], 117: [], 118: texte_et_cadre_nouveau) 119: 120: main()Voyez ligne 104, le premier élément de la chaîne étant





Donnez votre avis
Vous devez avoir ouvert une session pour écrire un commentaire.