⚠️ Ceci est un site de traduction non officiel, sans lien avec ImageMagick Studio LLC. Pour des informations officielles, consultez la page originale (https://usage.imagemagick.org/draw/index.html).

Exemples ImageMagick -- Dessin

Le dessin dans IM est le moyen d'ajouter de nouveaux éléments à une image existante. Alors qu'une grande partie du dessin de texte est traitée dans la page d'exemples sur les Effets de police composés et dans Annotation d'image, cette page traite des autres aspects, plus généraux, de l'opérateur « [-draw](https://imagemagick.org/command-line-options/#draw) ». La commande draw a commencé comme un moyen de créer des images simples. Mais elle s'est étendue avec le temps pour devenir l'interface de conversion des graphiques vectoriels en images matricielles.


ImageMagick Commandes de dessin Les images sont généralement enregistrées de deux manières différentes sur les ordinateurs. La première et la plus courante, que vous avez vue tout au long de ces pages d'exemples, est connue sous le nom de graphiques matriciels (Raster Graphics). Dans cette approche, les images sont stockées sous la forme d'un tableau rectangulaire de pixels. L'autre manière est moins courante et moins modifiable, mais, dans un autre sens, plus polyvalente : les graphiques vectoriels orientés objet (Object Vector Graphics). Sous cette forme, l'image est décrite en termes de lignes, d'arcs, de remplissages de couleur et, parfois, de profondeur. Cela est utile car ces images peuvent être mises à l'échelle à peu près à n'importe quelle taille tout en s'affichant parfaitement. On peut également décrire des images très grandes et complexes dans un espace bien plus réduit que l'équivalent au format matriciel. Parmi les exemples d'images vectorielles figurent le postscript et le nouveau SVG -- Scalable Vector Graphics. Les polices True-Type sont également des exemples de graphiques vectoriels, ce qui permet d'utiliser les descriptions de chaque caractère à n'importe quelle échelle. L'opérateur d'image « [-draw](https://imagemagick.org/command-line-options/#draw) » est une fenêtre ouverte sur les fonctions de dessin vectoriel d'ImageMagick, et forme un ensemble de commandes bien distinct des opérateurs d'image habituels de la ligne de commande d'IM. | _Il n'existe qu'un petit nombre de formats de fichiers vectoriels d'usage courant, chacun étant généralement très différent des autres. Il en résulte que le partage de code est très limité.

Pour cette raison, ImageMagick se préoccupe surtout d'utiliser les graphiques vectoriels pour dessiner des images au format SVG. Les graphiques postscript et les polices true-type sont transmis à d'autres bibliothèques et applications externes « déléguées », bien mieux adaptées au dessin de ces types de formats vectoriels.

Cela ne signifie pas pour autant qu'aucun délégué n'est disponible pour le SVG. Un exemple en est la bibliothèque RSVG ou la bibliothèque GTK SVG, disponible à la compilation. IM se lie à ces bibliothèques pour convertir le SVG plutôt que d'essayer de le faire elle-même._
---|---

Commandes de dessin primitives

Commençons par les primitives de dessin les plus anciennes, les plus simples et les plus courantes de l'opérateur d'image « [-draw](https://imagemagick.org/command-line-options/#draw) » des commandes MVG. Notez que tous les arguments sont traités comme des nombres à virgule flottante et n'ont pas besoin d'être des entiers, comme ceux que j'utilise généralement dans ces exemples. |

  # Dessin d'un pixel unique  (deux méthodes -- elles ont été agrandies)

  # Point « peint » le pixel de couleur
  magick -size 10x6 xc:skyblue  -fill black \
          -draw 'point 3,2'         -scale 100x60   draw_point.gif

  # Color Point « remplace » le pixel de couleur
  magick -size 10x6 xc:skyblue  -fill black \
          -draw 'color 6,3 point'   -scale 100x60   draw_color_point.gif

[IM Output]
[IM Output]
Ces deux méthodes de point produisent des résultats différents lorsque des couleurs semi-transparentes entrent en jeu, comme l'indique le commentaire donné. Voir les Primitives de remplissage de couleur ci-dessous pour plus de détails. |

  # Rectangle  /  Rectangle arrondi  /  Arc rectangulaire

  magick -size 100x60 xc:skyblue -fill white -stroke black \
          -draw "rectangle 20,10 80,50"       draw_rect.gif

  magick -size 100x60 xc:skyblue -fill white -stroke black \
          -draw "roundrectangle 20,10 80,50 20,15"  draw_rrect.gif

  magick -size 100x60 xc:skyblue -fill white -stroke black \
          -draw "arc  20,10 80,50  0,360"     draw_arc.gif

  magick -size 100x60 xc:skyblue -fill white -stroke black \
          -draw "arc  20,10 80,50 45,270"     draw_arc_partial.gif

[IM Output]
[IM Output]
[IM Output]
[IM Output]
La primitive de dessin « arc » est répertoriée avec les rectangles car il ne s'agit en réalité que d'une « ellipse » ajustée à l'intérieur du « rectangle » défini par les deux coordonnées. Les arcs partiels sont rarement utilisés, car il peut être difficile de déterminer les points d'extrémité, sauf si les angles sont limités à des multiples de quatre-vingt-dix degrés.
Les primitives « circle » et « ellipse » utilisent une coordonnée « centre » associée soit à une coordonnée « bord », soit respectivement à une « taille » et à un « angle ». |

  # Cercle  /  Ellipse    (centrés sur un point)

  magick -size 100x60 xc:skyblue -fill white -stroke black \
          -draw "circle 50,30 40,10"          draw_circle.gif

  magick -size 100x60 xc:skyblue -fill white -stroke black \
          -draw "ellipse 50,30 40,20 0,360"   draw_ellipse.gif

  magick -size 100x60 xc:skyblue -fill white -stroke black \
          -draw "ellipse 50,30 40,20 45,270"   draw_ellipse_partial.gif

[IM Output]
[IM Output]
[IM Output]
Vous pouvez également consulter Contexte Push/Pop pour un exemple de création d'une ellipse pivotée. |

  # Ligne / Polyligne / Polygone / Bézier

  magick -size 100x60 xc:skyblue -fill white -stroke black \
          -draw "line   20,50 90,10"                 draw_line.gif

  magick -size 100x60 xc:skyblue -fill white -stroke black \
          -draw "polyline 40,10 20,50 90,10 70,40"   draw_polyline.gif

  magick -size 100x60 xc:skyblue -fill white -stroke black \
          -draw "polygon  40,10 20,50 90,10 70,40"   draw_polygon.gif

  magick -size 100x60 xc:skyblue -fill white -stroke black \
          -draw "bezier   40,10 20,50 90,10 70,40"   draw_bezier.gif

[IM Output]
[IM Output]
[IM Output]
[IM Output]
Une meilleure méthode pour dessiner des lignes et des courbes consiste à utiliser le dessin de chemin SVG, bien plus polyvalent et permettant même le « dessin de ligne relatif ». |

  # dessin de texte  / image

  magick -size 100x60 xc:skyblue -fill white -stroke black \
          -font Candice -pointsize 40 -gravity center \
          -draw "text 0,0 'Hello'"   draw_text.gif

  magick -size 100x60 xc:skyblue -gravity center \
          -draw "image over 0,0 0,0 'terminal.gif'"   draw_image.gif

[IM Output]
[IM Output]
Ces deux dernières opérations de type remplissage sont actuellement les seules opérations de dessin affectées par « [-gravity](https://imagemagick.org/command-line-options/#gravity) ». Les autres modificateurs de ces opérations comprennent : « [-fill](https://imagemagick.org/command-line-options/#fill) », « [-tile](https://imagemagick.org/command-line-options/#tile) », « [-origin](https://imagemagick.org/command-line-options/#origin) », « [-stroke](https://imagemagick.org/command-line-options/#stroke) », « [-strokewidth](https://imagemagick.org/command-line-options/#strokewidth) », « [-font](https://imagemagick.org/command-line-options/#font) », « [-pointsize](https://imagemagick.org/command-line-options/#pointsize) », « [-box](https://imagemagick.org/command-line-options/#box) ». Il existe d'autres modificateurs, mais ils concernent le langage Magick Vector Graphics, plus avancé.

Primitive Bézier

La primitive « bezier » sert à dessiner des courbes. Chaque commande ne dessine qu'un seul segment de courbe. En général, on donne 4 points (8 nombres) : un point de départ « nœud », deux points de contrôle et un point d'arrivée « nœud ». Les deux points de contrôle définissent la direction et la vitesse à laquelle la courbe s'écarte des points « nœuds » d'extrémité auxquels elle est rattachée. Pour raccorder deux courbes en douceur, le point de contrôle de l'extrémité doit être reflété à travers le « nœud » pour former le point de contrôle de la courbe de Bézier suivante. Par exemple, je dessine ici deux courbes de Bézier qui se raccordent en douceur. Remarquez comment les lignes et points de contrôle (également dessinés) se reflètent parfaitement de part et d'autre de la coordonnée de jonction, à la fois en angle et en longueur. C'est important, sans quoi la courbe ne serait pas lisse. |

  points="10,10 30,90   25,10 50,50   50,50 75,90   70,10 90,40"
  clines=`echo "$points" | sed 's/   /\n/g' |\
             while read line; do echo "line $line"; done`
  symbols=`echo path "'"; for point in $points; do
             echo "M $point   l -2,-2 +4,+4 -2,-2   l -2,+2 +4,-4 -2,+2"
           done;  echo "'"`
  magick -size 100x100 xc:skyblue -fill none \
          -draw "stroke gray $clines    stroke blue $symbols " \
          -draw "stroke red  bezier 10,10 30,90   25,10 50,50 " \
          -draw "stroke red  bezier 50,50 75,90   70,10 90,40 " \
          draw_bezier_joined.gif

[IM Output]
Si je déplace l'un des points de contrôle de sorte qu'il ne soit PAS « reflété » à travers le « nœud » auquel il est rattaché, par rapport à l'autre point de contrôle de ce même « nœud », alors la courbe devient discontinue. |

  points="10,10 30,90   25,10 50,50   50,50 80,50   70,10 90,40"
  clines=`echo "$points" | sed 's/   /\n/g' |\
             while read line; do echo "line $line"; done`
  symbols=`echo path "'"; for point in $points; do
             echo "M $point   l -2,-2 +4,+4 -2,-2   l -2,+2 +4,-4 -2,+2"
           done;  echo "'"`
  magick -size 100x100 xc:skyblue -fill none \
          -draw "stroke gray $clines    stroke blue $symbols " \
          -draw "stroke red  bezier 10,10 30,90   25,10 50,50 " \
          -draw "stroke red  bezier 50,50 80,50   70,10 90,40 " \
          draw_bezier_disjoint.gif

[IM Output]
Si l'on déplace à nouveau le point de contrôle pour qu'il coïncide avec le point « nœud » associé, la ligne partira directement de ce point sans aucune « courbe ». |

  points="10,10 30,90   25,10 50,50   50,50 50,50   70,10 90,40"
  clines=`echo "$points" | sed 's/   /\n/g' |\
             while read line; do echo "line $line"; done`
  symbols=`echo path "'"; for point in $points; do
             echo "M $point   l -2,-2 +4,+4 -2,-2   l -2,+2 +4,-4 -2,+2"
           done;  echo "'"`
  magick -size 100x100 xc:skyblue -fill none \
          -draw "stroke gray $clines    stroke blue $symbols " \
          -draw "stroke red  bezier 10,10 30,90   25,10 50,50 " \
          -draw "stroke red  bezier 50,50 50,50   70,10 90,40 " \
          draw_bezier_no_curve.gif

[IM Output]
Si les deux points de contrôle sont placés sur leurs « nœuds » respectifs, une ligne droite est générée. |

  points="10,10 10,10   50,50 50,50   50,50 50,50   90,40 90,40"
  clines=`echo "$points" | sed 's/   /\n/g' |\
             while read line; do echo "line $line"; done`
  symbols=`echo path "'"; for point in $points; do
             echo "M $point   l -2,-2 +4,+4 -2,-2   l -2,+2 +4,-4 -2,+2"
           done;  echo "'"`
  magick -size 100x100 xc:skyblue -fill none \
          -draw "stroke gray $clines    stroke blue $symbols " \
          -draw "stroke red  bezier 10,10 10,10   50,50 50,50 " \
          -draw "stroke red  bezier 50,50 50,50   90,40 90,40 " \
          draw_bezier_lines.gif

[IM Output]
La primitive « bezier » n'est vraiment utile que si les 4 points sont tous spécifiés. Seuls le premier et le dernier point sont classés comme des « nœuds » par lesquels la courbe passe (ou se termine). Tous les autres points intermédiaires sont considérés purement comme des points de contrôle, influant sur la courbe dans l'ordre donné ; plus un point de contrôle est éloigné, plus son effet sur ce segment de courbe est important. |

  points="10,10 30,90   25,10    75,90   70,10 90,40"
  symbols=`for point in $points; do
             echo "M $point   l -2,-2 +4,+4 -2,-2   l -2,+2 +4,-4 -2,+2"
           done`
  magick -size 100x100  xc:skyblue  -fill none \
          -draw "stroke gray  polyline $points " \
          -draw "stroke red   bezier $points " \
          -draw "stroke blue  path '$symbols' " \
          draw_bezier_multi.gif

[IM Output]
Par souci de simplicité, il n'est pas recommandé d'utiliser plus ou moins de 4 points par segment de courbe « bezier ». En réalité, je recommande de ne pas utiliser du tout la primitive « bezier », mais d'utiliser à la place la courbe de Bézier cubique en chemin SVG pour générer des courbes. Celle-ci dispose d'une fonction spéciale de continuation de courbe « S » qui effectue automatiquement le « reflet » approprié des points de contrôle pour générer des segments de courbe se raccordant en douceur, et réduit le nombre de points de contrôle nécessaires. On peut également définir des points relatifs au dernier point d'arrivée du chemin.

Primitives de remplissage de couleur

En plus des primitives « simples » ci-dessus, « [-draw](https://imagemagick.org/command-line-options/#draw) » fournit également un ensemble de primitives de remplissage ou de modification de couleur. Celles-ci modifient la ou les couleurs de l'image à partir du point spécifié, selon la méthode choisie. Ces méthodes de remplissage ne sont en fait pas de véritables commandes « draw », mais des fonctions de remplacement de couleur. Elles ont été ajoutées à draw parce que c'était, dans une version très ancienne du programme, l'endroit le plus simple pour insérer ces opérations dans ImageMagick. Comme ci-dessus, la couleur utilisée est définie par le réglage de couleur « [-fill](https://imagemagick.org/command-line-options/#fill) », mais si elle est définie, l'image « [-tile](https://imagemagick.org/command-line-options/#tile) » sera utilisée à la place. Les autres options de réglage évoquées plus haut ne sont pas utilisées et n'ont aucun effet sur ces opérations. Deux réglages supplémentaires s'appliquent également à ces primitives : les réglages de facteur « [-bordercolor](https://imagemagick.org/command-line-options/#bordercolor) » et « [-fuzz](https://imagemagick.org/command-line-options/#fuzz) ». Cependant, ces réglages NE PEUVENT PAS être définis au sein du langage « MVG », et ne peuvent donc être définis qu'avant d'utiliser l'opérateur « [-draw](https://imagemagick.org/command-line-options/#draw) ». Le premier d'entre eux, « color point », a déjà été vu ci-dessus comme alternative à la primitive de dessin « point ». Si vous regardez attentivement, vous verrez le pixel blanc unique que nous avons défini dans notre image de test.

|

  magick color_test.png   -fill white \
          -draw 'color 30,20 point'      color_point.png

[IM Output]
Cependant, lorsqu'il s'agit de dessiner des couleurs transparentes ou semi-transparentes, ces fonctions ne se comportent pas de la même façon. Voici une image rouge de trois pixels (agrandie) : pour le deuxième pixel, celui du milieu, nous avons utilisé la fonction « point » pour peindre par-dessus le pixel rouge avec une couleur bleue semi-transparente, donnant un résultat violet. En revanche, si l'on utilise la fonction « color point » (dernier pixel, à droite), la couleur rouge est complètement remplacée par le pixel bleu semi-transparent. Elle n'est pas superposée. |

  magick -size 3x1 xc:red -alpha on -fill '#00F8' \
          -draw 'point 1,0' \
          -draw 'color 2,0 point'   -scale 33x33  draw_points.png

[IM Output]
Toutes les fonctions « color » effectuent un remplacement complet de la couleur, tandis que toutes les autres primitives de couleur « peignent » la couleur par-dessus l'image. On peut ainsi utiliser « color » pour dessiner la couleur transparente. La fonction de dessin « color replace » remplace toutes les occurrences de la couleur exacte donnée à l'emplacement indiqué. Et comme on peut le voir, les zones n'ont pas besoin d'être connectées entre elles. |

  magick color_test.png   -fill white \
          -draw 'color 30,20 replace'      color_replace.png


  magick color_test.png   -fill white   -fuzz 13%\
          -draw 'color 30,20 replace'      color_replace_fuzz.png

[IM Output]

[IM Output]
Cependant, comme on le voit dans le premier résultat, certains pixels le long des bords n'ont pas été remplacés. Ces pixels ne sont pas exactement de la même couleur que le pixel sélectionné, ils ont donc été ignorés. L'ajout d'un petit facteur de tolérance (fuzz) permet d'inclure également les couleurs proches de la couleur d'origine, comme le montre le deuxième exemple ci-dessus. Bien sûr, un « facteur de tolérance » n'est pas une solution idéale, car il ne capture pas tous ces pixels de bordure. C'est un problème récurrent avec toutes ces méthodes de « remplissage de couleur », et qui n'a pas de solution générale. Si l'on souhaite remplacer une couleur précise et connue plutôt que de sélectionner une couleur dans l'image elle-même, on peut utiliser à la place l'opérateur d'image « [-opaque](https://imagemagick.org/command-line-options/#opaque) ». Cette fonction utilise elle aussi un réglage de facteur « [-fuzz](https://imagemagick.org/command-line-options/#fuzz) » pour élargir la plage de couleurs correspondant à la couleur donnée. La méthode « floodfill » est également assez simple : elle se contente de remplir toute la zone autour du point sélectionné, sans sélectionner d'autres zones de couleurs similaires qui ne seraient pas connectées d'une manière ou d'une autre. On peut également étendre la zone remplie en utilisant « [-fuzz](https://imagemagick.org/command-line-options/#fuzz) » pour inclure des couleurs similaires. Dans ce cas, nous avons choisi une valeur suffisamment élevée pour inclure également la bordure de la croix, ce qui permet au remplissage par diffusion de « fuir » vers l'autre côté de l'image. |

  magick color_test.png   -fill white \
          -draw 'color 30,20 floodfill'      color_floodfill.png


  magick color_test.png   -fill white   -fuzz 15%   \
          -draw 'color 30,20 floodfill'      color_floodfill_fuzz.png

[IM Output]

[IM Output]
Remplir des zones par diffusion (flood-fill) n'est pas sans poser de problèmes. La couleur peut fuir à travers une frontière fine, vers des zones où elle n'était pas voulue (voir GIF sur un motif d'arrière-plan pour une démonstration). Ou bien elle peut ne pas remplir la zone sélectionnée jusqu'au bord (voir Problèmes d'anticrénelage et de remplissage par diffusion). Mais cela fonctionne. « filltoborder » ressemble à « floodfill », sauf qu'on y spécifie une couleur qui borde la zone à remplir, plutôt que la couleur à remplacer par le processus de remplissage. Bien sûr, un facteur de tolérance est également recommandé pour inclure des « couleurs similaires » dans cette sélection de couleur de bordure, afin de mieux limiter le remplissage par diffusion. |

  magick color_test.png   -fill white  -bordercolor royalblue \
          -draw 'color 30,20 filltoborder'   color_filltoborder.png


  magick color_test.png   -fill white  -bordercolor blue \
          -draw 'color 30,20 filltoborder'   color_filltoborder2.png


  magick color_test.png   -fill white  -bordercolor blue  -fuzz 30% \
          -draw 'color 30,20 filltoborder'   color_filltoborder_fuzz.png

[IM Output]
[IM Output]
[IM Output]
La dernière méthode de couleur de draw est « reset », qui se contente de remplacer, ou de réinitialiser, toute l'image avec la couleur de remplissage. Dans ce cas, le pixel réellement sélectionné n'a aucune influence sur le résultat. |

  magick color_test.png   -fill white \
          -draw 'color 30,20 reset'      color_reset.png

[IM Output]
C'est en réalité très utile, car cela offre un moyen simple de générer, à partir d'une image existante, un canevas de couleur unie (ou d'image en mosaïque). (Voir Canevas de la taille d'une image existante pour cette méthode et d'autres façons de faire la même chose). FUTUR : utiliser un motif « [-tile](https://imagemagick.org/command-line-options/#tile) » pour remplir la zone.

Primitives de remplissage alpha

La primitive de dessin « alpha » fonctionne exactement de la même façon que la primitive « color » décrite ci-dessus, à ceci près qu'elle ne remplace pas la couleur des zones sélectionnées, mais uniquement leur canal « alpha ». (C'est-à-dire que seul le canal « alpha » est ajusté par ces fonctions de remplissage). Tout comme la fonction de remplissage « color », la valeur « alpha » utilise la couleur de remplissage (sauf si « [-tile](https://imagemagick.org/command-line-options/#tile) » est utilisé comme source de la « valeur alpha »). Nous reprenons ici le même exemple de « color floodfill » que ci-dessus, mais en n'ajustant cette fois que le canal alpha, pour rendre les parties remplies entièrement transparentes. Autrement dit, la couleur d'origine est toujours présente, simplement transparente ! |

  magick color_test.png   -fill none \
          -draw 'alpha 30,20 floodfill'      matte_floodfill.png


  magick color_test.png   -fill none   -fuzz 15%   \
          -draw 'alpha 30,20 floodfill'      matte_floodfill_fuzz.png

[IM Output]

[IM Output]
La fonction « alpha reset » peut également servir à rendre toute une image semi-transparente. Bien sûr, dans ce cas, il faut produire un fichier PNG, capable d'accepter des couleurs semi-transparentes dans les images. |

  magick color_test.png   -fill '#00000080' \
          -draw 'alpha 30,20 reset'      matte_reset.png

[IM Output]
Remarquez que la composante de couleur « black » n'a pas été utilisée dans les opérations, seule la composante alpha de la couleur l'a été. La couleur d'origine des images est laissée telle quelle. FUTUR : utiliser un motif « [-tile](https://imagemagick.org/command-line-options/#tile) » pour un effet alpha intéressant. « color » et « alpha » sont tous deux des fonctions de remplacement complet de la couleur, qui produisent toujours un remplacement de couleur de type booléen (tout ou rien). Les bords de ces zones présenteront donc toujours des effets de crénelage. Pour cette raison, ce ne sont généralement pas de bons opérateurs d'image pour le développement d'image en général, sauf pour définir les zones transparentes des images GIF (elles aussi booléennes). Tout n'est cependant pas perdu, comme le montrent les exemples de suppression de l'arrière-plan.


Détails sur les commandes de dessin

Coordonnées de pixel

La commande « [-draw](https://imagemagick.org/command-line-options/#draw) » (ainsi que beaucoup d'autres dans IM) utilise ce que l'on appelle les « coordonnées de pixel ». C'est-à-dire que la coordonnée « 10,10 » est le centre du pixel situé 10 pixels plus bas et à gauche du coin supérieur gauche. Dans ce système de coordonnées, 0,0 est le centre du pixel supérieur gauche, et w-1,h-1 le centre du coin inférieur droit. Les bords réels se situent à -0.5,-0.5 et w-0.5,h-0.5, et le pixel central (si l'image a une taille impaire) se situe à « (w-1)/2,(h-1)/2 ». Cependant, lorsqu'on traite une image mathématiquement (par exemple avec distort), les pixels réels n'ont pas vraiment de sens, et l'on utilise alors les « coordonnées d'image ». Dans ce système, le bord réel de l'image se situe à « 0,0 » et « w,h ». Et le centre de l'image (qui peut ou non correspondre au centre d'un pixel) se situe à « w/2,h/2 ». Pour convertir des « coordonnées de pixel » en coordonnées d'image, on ajoute ½ Ainsi, le centre du pixel supérieur gauche est « 0.5,0.5 » et le pixel inférieur droit est « w-0.5,h-0.5 ». Exemple : centre d'un cercle dans une petite image

Dessiner avec correction de gamma et d'espace colorimétrique

Comme presque toutes les opérations d'ImageMagick, « [-draw](https://imagemagick.org/command-line-options/#draw) » est un opérateur linéaire, et fonctionne donc dans un espace colorimétrique RGB linéaire. Cela signifie que, pour obtenir de beaux bords lisses, il peut être nécessaire d'appliquer une correction de gamma aux images avant de les enregistrer, afin qu'elles soient stockées dans un espace colorimétrique sRGB non linéaire (corrigé en gamma). Par exemple, si l'on dessine un grand cercle et qu'on l'enregistre tel quel… |

  magick -size 81x81 xc:black -fill white -draw 'circle 40,40 40,3' \
          circle_raw.png

[IM Output]
Regardez les bords du cercle : ils ne semblent en réalité pas très lisses. On y observe un net effet d'escalier. Cela vient du fait que le cercle a été dessiné dans un espace colorimétrique RGB linéaire, mais que l'image a ensuite été enregistrée comme s'il s'agissait réellement de l'espace colorimétrique sRGB ! Pour corriger cela, il faut appliquer une correction de gamma à l'image avant de l'enregistrer. |

  magick -size 81x81 xc:black -fill white -draw 'circle 40,40 40,3' \
          -gamma 2.2 circle_gamma.png

[IM Output]
Cette fois, les bords du cercle paraissent bien lisses et arrondis, comme ils le devraient. Pour faire les choses correctement, il faudrait en réalité effectuer la correction via l'espace colorimétrique. Cependant, comme IM suppose que RGB est l'espace colorimétrique par défaut pour l'enregistrement, il faut recourir à une manipulation un peu délicate pour que cela fonctionne correctement. |

  magick -size 81x81 xc:black -set colorspace RGB \
          -fill white -draw 'circle 40,40 40,3' \
          -colorspace sRGB circle_sRGB.png

[IM Output]
| Notez que l'espace colorimétrique sRGB (qui est la bonne façon d'enregistrer les images) n'est pas exactement identique au simple fait d'appliquer une correction de gamma de 2.2. Cependant, les différences de résultat entre les deux sont minimes et ne sont visibles que sur des images très, très sombres.
---|---
| Avant IM v6.7.5-1, les noms d'espace colorimétrique « sRGB » et « RGB » (RGB linéaire) étaient en fait inversés. Sur les anciennes versions d'IM, il faut donc inverser les deux étiquettes ci-dessus.
---|---
Pour dessiner correctement (ou effectuer tout traitement d'image « linéaire ») sur une image réelle (dans IMv7), il faut d'abord retirer le gamma existant, traiter l'image, puis restaurer cette correction de gamma. Voir Redimensionnement avec correction d'espace colorimétrique pour plus de détails. Voici un exemple de dessin sur une image réelle… d'abord sans aucune correction de couleur (brute), puis avec des corrections de gamma et d'espace colorimétrique. |

  magick rose: -fill none -stroke white -draw 'line 5,40 65,5'  rose_raw.png

[IM Output]
|

  magick rose: -gamma .454545 \
          -fill none -stroke white -draw 'line 5,40 65,5' \
          -gamma 2.2 rose_gamma.png

[IM Output]
|

  magick rose: -colorspace RGB \
          -fill none -stroke white -draw 'line 5,40 65,5' \
          -colorspace sRGB rose_sRGB.png

[IM Output]
Comme on peut le voir, l'utilisation d'une correction de gamma ou d'espace colorimétrique rend la ligne bien plus lisse, sans l'effet de crénelage en « escalier » visible lors d'un dessin direct. (Il faut un très bon écran pour le voir) | La ligne ci-dessus a été dessinée à l'aide d'une couleur « [-stroke](https://imagemagick.org/command-line-options/#stroke) ». Vous pouvez dessiner la ligne avec « [-fill](https://imagemagick.org/command-line-options/#fill) » et obtenir le même résultat, mais vous n'aurez alors pas de contrôle sur l'épaisseur de la ligne via « [-strokewidth](https://imagemagick.org/command-line-options/#strokewidth) ». Voir le réglage de la couleur de trait ci-dessous pour plus d'informations.
---|---
| _Les noms de couleur sont en fait définis à l'aide de valeurs pour l'espace colorimétrique « sRGB », MAIS ils sont appliqués par draw comme si l'image était dans un espace colorimétrique RGB linéaire. Ainsi, l'utilisation de la correction de gamma ci-dessus avec des couleurs nommées (autres que « white » ou « black ») entraînera une distorsion de ces couleurs. Dans ces cas, il peut être préférable de ne pas utiliser de correction de gamma ou d'espace colorimétrique, afin que les couleurs nommées correspondent correctement.

La correspondance correcte des couleurs « sRGB » nommées avec l'espace colorimétrique de l'image sur laquelle on dessine sera corrigée dans le cadre du développement d'IMv7.

_
---|---

Interaction entre Stroke, StrokeWidth et Fill

Les options « [-stroke](https://imagemagick.org/command-line-options/#stroke) » et « [-strokewidth](https://imagemagick.org/command-line-options/#strokewidth) » servent à dessiner un contour autour du bord d'une police. Ces options sont couramment utilisées avec « [-fill](https://imagemagick.org/command-line-options/#fill) » pour rendre le texte plus intéressant, avec très peu d'effort.

    magick -size 380x70 xc:lightblue -pointsize 50 -font Chisel \
            -fill green  -stroke black  -draw 'text 10,55 "Black Border"' \
            stroke_font.jpg

[IM Output]

Les réglages par défaut sont « [-strokewidth](https://imagemagick.org/command-line-options/#strokewidth) 1 » et « [-stroke](https://imagemagick.org/command-line-options/#stroke) None ». Mais cela rend le trait du contour invisible, ne laissant que la couleur « [-fill](https://imagemagick.org/command-line-options/#fill) » ; vous ne le verrez donc pas. Le seul effet de « [-strokewidth](https://imagemagick.org/command-line-options/#strokewidth) » lorsque « [-stroke](https://imagemagick.org/command-line-options/#stroke) » est « invisible » concerne les attributs de taille de police, ce qui signifie qu'il peut tout de même affecter le positionnement de la police et la taille de génération d'image Label et Caption. Sinon, la largeur n'a aucun effet visible tant que le trait n'est pas rendu visible. Pour voir comment « [-strokewidth](https://imagemagick.org/command-line-options/#strokewidth) » affecte réellement l'aspect d'une police (une fois rendue visible), j'ai dessiné ici du texte avec différentes largeurs, de « désactivée » à de plus en plus grande.

    magick -size 320x420 xc:lightblue -pointsize 70 -font Vademecum \
      -fill red -stroke none                 -draw 'text 30,80  "Stroke -"' \
      -fill red -stroke black -strokewidth 0 -draw 'text 30,160 "Stroke 0"' \
      -fill red -stroke black -strokewidth 1 -draw 'text 30,240 "Stroke 1"' \
      -fill red -stroke black -strokewidth 2 -draw 'text 30,320 "Stroke 2"' \
      -fill red -stroke black -strokewidth 3 -draw 'text 30,400 "Stroke 3"' \
      stroke_table.jpg

[IM Output]

Notez, d'après les exemples ci-dessus, que régler « [-strokewidth](https://imagemagick.org/command-line-options/#strokewidth) » à « 0 » N'est PAS la même chose que de régler la couleur « [-stroke](https://imagemagick.org/command-line-options/#stroke) » sur « none » (la valeur par défaut). Le premier cas produit un contour de trait extrêmement fin, tandis que le second le désactive effectivement. Dans les deux cas, le trait est tout de même dessiné. Vous devez cependant noter que, même avec un « [-strokewidth](https://imagemagick.org/command-line-options/#strokewidth) » de « 0 », le contour de l'image sera très légèrement plus large que celui d'une image simplement « remplie » (avec une couleur « [-stroke](https://imagemagick.org/command-line-options/#stroke) » de « none »). En pratique, toute largeur inférieure à « 1.0 » ne fonctionne pas correctement. Il convient donc d'être prudent dans les cas où cela peut avoir de l'importance. Rappelez-vous cependant que « [-strokewidth](https://imagemagick.org/command-line-options/#strokewidth) » est également un réglage en virgule flottante. Autrement dit, une largeur de trait de « 0.5 » est également valide. Cela n'a toutefois généralement d'importance que lorsqu'on cherche à dessiner de fins cercles bitmap avec l'anticrénelage désactivé.
Voici un exemple d'utilisation d'une largeur de trait extrêmement grande.

   magick -size 320x100 xc:lightblue -font Candice -pointsize 72 -fill white \
           -stroke black -strokewidth 15 -draw "text 25,65 'Anthony'" \
           stroke_thick.jpg

[IM Output]

Notez que « [-strokewidth](https://imagemagick.org/command-line-options/#strokewidth) » étend le trait à la fois vers l'intérieur et vers l'extérieur. Voici le même exemple, mais avec la police redessinée, sans le contour du trait, afin de retirer la partie intérieure du trait très épais.

   magick -size 320x100 xc:lightblue -font Candice -pointsize 72 -fill white \
           -stroke black -strokewidth 15 -draw "text 25,65 'Anthony'" \
           -stroke none                  -draw "text 25,65 'Anthony'" \
           stroke_outline.jpg

[IM Output]

Pour d'autres exemples d'utilisation du trait, voir Effets de police composés. Regardez en particulier l'« effet ballon ».

Dessiner des lignes (Stroke)

Le dessin de ligne par défaut dans IM présente quelques comportements étranges qu'il vaut la peine de connaître. Voici le dessin de ligne par défaut… |

  magick -size 100x40 xc:lightblue \
          -draw "line 5,35 95,5" \
          line_default.jpg

[IM Output]
Vous pouvez définir la couleur de la ligne avec une option « [-fill](https://imagemagick.org/command-line-options/#fill) ». |

  magick -size 100x40 xc:lightblue \
          -fill white -draw "line 5,35 95,5" \
          line.jpg

[IM Output]
Vous pouvez également rendre une ligne légèrement plus épaisse en définissant la couleur « [-stroke](https://imagemagick.org/command-line-options/#stroke) ». |

  magick -size 100x40 xc:lightblue \
          -fill white -stroke black -draw "line 5,35 95,5" \
          line_stroke.jpg

[IM Output]
Mais qu'est devenue la couleur blanche spécifiée avec l'option « [-fill](https://imagemagick.org/command-line-options/#fill) » ? C'est l'aspect délicat du dessin de lignes dans ImageMagick. En réalité, le programme considère la ligne comme un objet rempli d'environ 1 pixel de large. Cela est naturel, car on utilise généralement plusieurs lignes pour balayer une zone destinée à être remplie. Ainsi, tout comme lorsque nous avons utilisé stroke avec des polices dans la section précédente, IM dessine la ligne (ou l'objet) avec la couleur de remplissage, puis dessine son contour avec la couleur de trait. Il en résulte que la ligne de couleur de trait ci-dessus est désormais légèrement plus épaisse, la couleur de remplissage étant entièrement cachée en dessous. Si vous rendez la couleur de trait semi-transparente, vous pouvez faire réapparaître cette couleur de remplissage. En résumé, les lignes semblent être dessinées avec la couleur « [-fill](https://imagemagick.org/command-line-options/#fill) », mais cette option n'a plus aucune incidence dès lors que la couleur « [-stroke](https://imagemagick.org/command-line-options/#stroke) » a été définie sur autre chose que les couleurs par défaut « none » ou « transparent ». | L'option « -linewidth » n'est en réalité qu'un alias de « [-strokewidth](https://imagemagick.org/command-line-options/#strokewidth) » et ne doit pas être utilisée.
---|---
Par exemple, on pourrait penser que cette commande produirait une ligne très épaisse. C'est effectivement le cas, mais comme la couleur « [-stroke](https://imagemagick.org/command-line-options/#stroke) » est invisible, on ne la voit pas. On ne voit que le « remplissage » intérieur de la zone d'un pixel de large de la ligne. |

  magick -size 100x40 xc:lightblue \
          -fill white -strokewidth 3 -draw "line 5,35 95,5" \
          line_fill_3.jpg

[IM Output]
| Je considère en fait le résultat ci-dessus comme un bug. Rien n'aurait dû être dessiné, puisqu'il n'y a aucune « zone » à remplir et qu'aucune « couleur de trait » de ligne n'a été définie. Si IM se comporte actuellement ainsi, c'est pour éviter de dérouter les nouveaux utilisateurs, mais en réalité, cela ne fait que poser des problèmes aux utilisateurs avancés. Voir Limites de remplissage de Draw pour plus de détails.
---|---
Mais si la couleur de trait est également définie, on obtient bien la ligne épaisse souhaitée… |

  magick -size 100x40 xc:lightblue \
          -stroke black -strokewidth 3 -draw "line 5,35 95,5" \
          line_stroke_3.jpg

[IM Output]
Si le réglage « [-strokewidth](https://imagemagick.org/command-line-options/#strokewidth) » est fixé à un, la ligne ci-dessus sera entièrement recouverte. |

  magick -size 100x40 xc:lightblue \
          -stroke black -strokewidth 1 -draw "line 5,35 95,5" \
          line_stroke_1.jpg

[IM Output]
Bien sûr, une fois muni de cette connaissance, vous pouvez l'utiliser de façon créative, tout comme pour le dessin de polices. |

  magick -size 100x40 xc:lightblue \
          -stroke black -strokewidth 5 -draw "line 5,35 95,5" \
          -stroke white -strokewidth 2 -draw "line 5,35 95,5" \
          line_multi.jpg

[IM Output]
J'ai ici utilisé le réglage « [-strokewidth](https://imagemagick.org/command-line-options/#strokewidth) » le plus fin, « 0 », tout comme je l'ai fait pour les polices ci-dessus. |

  magick -size 100x40 xc:lightblue \
          -fill white -stroke black -strokewidth 0 -draw "line 5,35 95,5" \
          line_stroke_0.jpg

[IM Output]
Cela produit le résultat très étrange d'une ligne pointillée, composée de points noirs et de segments gris. C'est le résultat d'une étrange « fréquence de battement des couleurs » entre les couleurs de trait, de remplissage et d'arrière-plan. Voici une vue agrandie de la ligne… |

  magick -size 25x10 xc:lightblue \
          -fill white -stroke black -strokewidth 0 -draw "line 2,8 22,1" \
          -scale 400%    line_stroke_0_white.jpg

[IM Output]
| L'effet de « fréquence de battement des couleurs » n'est pas sans rappeler le « battement sonore » que l'on obtient avec deux guitares très légèrement désaccordées. Dans ce cas, on obtient un point noir là où la couleur de trait recouvre entièrement la couleur de remplissage sous-jacente, et un point gris là où la couleur de trait se mélange à LA FOIS avec la couleur de remplissage et la couleur d'arrière-plan. Ce mélange de couleurs est une conséquence naturelle des processus d'anticrénelage qu'IM utilise pour tenter d'améliorer l'apparence des lignes et autres objets dessinés. Pour plus d'informations, voir ma page de discussion et d'exemples sur l'anticrénelage dans IM.
---|---
Notez que cet effet n'apparaît que sur les lignes inclinées, et non sur les lignes purement horizontales ou verticales, où le crénelage n'a aucun effet et donc aucune « fréquence de battement des couleurs ». |

  magick -size 100x40 xc:lightblue \
          -fill white -stroke black -strokewidth 0 -draw "line 5,20 95,20" \
          line_stroke_horz.jpg

[IM Output]
J'ai ici utilisé différentes couleurs de remplissage sous-jacentes dans la vue agrandie, afin que l'on puisse voir comment la couleur modifie le battement obtenu. |

  magick -size 25x10 xc:lightblue \
          -fill none -stroke black -strokewidth 0 -draw "line 2,8 22,1" \
          -scale 400%     line_stroke_0_none.jpg

[IM Output]
|

  magick -size 25x10 xc:lightblue \
          -fill red -stroke black -strokewidth 0 -draw "line 2,8 22,1" \
          -scale 400%    line_stroke_0_red.jpg

[IM Output]
|

  magick -size 25x10 xc:lightblue \
          -fill black -stroke black -strokewidth 0 -draw "line 2,8 22,1" \
          -scale 400%    line_stroke_0_black.jpg

[IM Output]
Comparons cela à un trait réglé sur none… |

  magick -size 25x10 xc:lightblue \
          -fill black -stroke none -draw "line 2,8 22,1" \
          -scale 400%    line_stroke_-_black.jpg

[IM Output]
Comme on peut le voir, lorsqu'on dessine des lignes très fines, on peut réduire ce « battement » soit en utilisant la même couleur pour le remplissage et le trait, soit en réglant l'une des deux couleurs sur none pour la désactiver. Si la seconde solution est la meilleure idée, la première peut s'avérer plus pratique selon vos besoins de programmation spécifiques. Notez que l'épaisseur de remplissage de la ligne est « 0 ». Mais la ligne de trait, elle, peut avoir une épaisseur plus grande. C'est également une valeur en virgule flottante ! Une ligne de 2.5 pixels de large est parfaitement valide. | Ces résultats sont dus non seulement à une largeur de trait 0 buggée, qui provoque un battement de couleur, mais aussi au fait que la « couleur de remplissage » est dessinée avec une épaisseur supplémentaire d'un diamètre de 1.0, alors qu'il n'y a en réalité aucune zone à remplir. Je considère également cela comme un bug. Voir Limites de remplissage de Draw.
---|---

Limites de remplissage de Draw

Il existe quelques autres points à noter concernant les diverses primitives de dessin. La largeur de trait fonctionne bien pour des valeurs en virgule flottante supérieures à 1.0, mais semble se dégrader pour des valeurs inférieures à 1.0. Cela est dû à l'algorithme d'implémentation utilisé, et pas simplement à une erreur, puisque cela fonctionne bien pour des lignes plus épaisses. En principe, en utilisant une largeur de trait de zéro, on pourrait s'attendre à ce qu'aucune couleur de trait ne soit ajoutée. On obtient à la place une sorte de motif de battement, où la couleur de trait est à pleine intensité lorsque la ligne passe exactement par le « centre » du pixel. Ce qui devrait vraiment se produire, c'est que la quantité de couleur ajoutée à un pixel reflète la surface de la ligne dessinée, et non la distance du pixel à cette ligne. Ainsi, les lignes de largeur nulle ne devraient ajouter aucune couleur à l'image, tandis que les lignes d'épaisseur inférieure à 1.0 ne devraient ajouter qu'une quantité de couleur réduite. Voir les exemples Dessiner des lignes, avec StrokeWidth et Stroke ci-dessus. L'autre problème est que la couleur de remplissage n'est pas appliquée jusqu'au bord exact de la forme (polygone) dessinée, mais ½ pixel plus loin. Cela inclut le cas où aucun « trait » n'est appliqué et où le bord devrait être exact. Cela inclut également le dessin d'une « ligne », qui n'a en réalité qu'une épaisseur de remplissage « nulle ». En principe, si l'on dessine une ligne sans activer le trait, on ne devrait techniquement voir aucune ligne, puisqu'elle n'a pas d'épaisseur de « remplissage ». Au lieu de cela, les lignes sont dessinées avec une couleur de « remplissage » d'au moins 1 pixel de large. Ceci est dû à des raisons historiques et évite généralement de dérouter les nouveaux utilisateurs d'IM. Malheureusement, ce n'est PAS correct pour les utilisateurs avancés. Cela signifie que si l'on dessine deux polygones en utilisant uniquement la couleur de remplissage, et qu'ils partagent un bord, ce bord se chevauchera sur 1 pixel, car chaque polygone est plus grand de ½ pixel sur tous ses bords. Autrement dit, les polygones et autres formes ne s'emboîtent pas parfaitement : ils se chevauchent ! Par exemple, j'essaie ici d'utiliser draw pour diviser une image en deux moitiés (en dessinant du noir sur du blanc). Pour cela, je dessine deux polygones qui partagent un bord, exactement, sans chevauchement. Les « petites » images résultantes ont été agrandies pour l'affichage.

  magick -size 10x10 xc: -draw 'polygon 2,-1 7,10 10,10 10,-1' bound_left.gif
  magick -size 10x10 xc: -draw 'polygon 2,-1 7,10 -1,10 -1,-1' bound_right.gif

  magick bound_left.gif bound_right.gif -compose Plus -composite bound_add.gif

[IM Output] [IM Output] [IM Output]

Les deux parties noires (ce qui a réellement été dessiné) se chevauchent en fait l'une l'autre ! Autrement dit, même si l'on a essayé de dessiner les deux zones séparément à l'aide de polygones, la zone remplie est légèrement plus grande que ce qui était demandé. J'ai également additionné (composition Plus) les deux images afin que l'on puisse réellement voir le chevauchement des zones noires dessinées. Si les deux polygones s'emboîtaient parfaitement, le dessin « additionné » serait d'un blanc uni. La quantité réelle de chevauchement équivaut au réglage par défaut « [-strokewidth](https://imagemagick.org/command-line-options/#strokewidth) 1.0 ». On s'attend donc normalement à ce que cette zone supplémentaire soit couverte par une largeur de trait normale. Cela peut néanmoins poser de réels problèmes. À CÔTÉ : pour tester complètement la jonction, on pourrait générer des zones grises à 50 % sur un fond noir et les additionner. On peut ainsi voir si les zones non seulement se « chevauchent » (comme montré ci-dessus), mais aussi tester si elles « sous-chevauchent » (laissant un espace entre les zones remplies) lorsqu'on les additionne. L'image résultante devrait être d'un gris à 50 % parfaitement uniforme, sans variation de couleur le long de la jonction. Une vérification de la transparence consisterait à utiliser une couleur grise à 50 % transparente et à 50 % opaque sur un fond entièrement transparent. Pour voir un exemple de découpe et de recomposition parfaites, basé sur une seule image de masque, voir les exemples de méthodes de composition, Compose DstOut. CORRECTION DE BUG FUTURE : la zone remplie devrait être exacte, mais pour compenser cela lors du dessin de formes, la « couleur de trait » par défaut devrait être réglée sur la couleur de remplissage (sauf si elle est elle-même définie explicitement).


MVG - Magick Vector Graphics

Les primitives présentées ci-dessus forment la base de toutes les opérations « [-draw](https://imagemagick.org/command-line-options/#draw) » proposées. Ensemble, elles constituent le point de départ d'un langage interne spécial d'ImageMagick, appelé le langage Magick Vector Graphics. Pour plus de détails sur ce langage, voir Résumé des primitives et de la syntaxe MVG sur le site web d'IM. Ce langage « MVG » a été conçu dans le but de permettre à ImageMagick de gérer le langage SVG (Scalable Vector Graphics), encore plus complexe. Il y parvient en tentant de convertir les images données au format SVG vers le format MVG interne, plus simple. Pour plus de détails, voir la gestion du SVG ci-dessous. Par conséquent, ce que vous avez vu ci-dessus ne représente qu'une infime partie des capacités de l'opérateur « [-draw](https://imagemagick.org/command-line-options/#draw) ». Cela dit, si vous souhaitez dessiner des objets complexes, je recommande de créer une image au format SVG séparée de cet objet à l'aide d'un éditeur SVG tel que « [Sodipodi](http://the-labs.com/Sodipodi/) ». (Voir Programmes de dessin vectoriel autres qu'IM ci-dessous). Contrairement au SVG, MVG ne dispose d'aucune forme de « conteneurs » ni d'ensembles de commandes d'image. Tout cela est supprimé lors du processus de conversion afin de produire une séquence simplifiée de commandes de dessin MVG. Il utilise à la place un concept de contextes graphiques pour sauvegarder et restaurer divers paramètres de dessin, ce que nous allons maintenant examiner.

Paramètres en ligne de commande et paramètres MVG

Tout d'abord, presque tous les réglages que vous définissez via les options de ligne de commande utilisées par les primitives de dessin ont des équivalents directs dans les commandes de dessin MVG. La principale différence entre définir un réglage via une option de ligne de commande (comme « -strokewidth ») et utiliser un réglage au sein d'une chaîne de dessin MVG (par exemple « stroke-width »), est que le réglage MVG ne dure que le temps de cette chaîne de commande MVG.

**Résumé des réglages généraux de dessin**
  __cmd_option__   __draw_MVG__        __Argument__
    -fill            fill                couleur/tuile pour l'intérieur des formes
    -tile            fill                tuile d'image, remplace la couleur fill

    -stroke          stroke              couleur/tuile de ligne autour des formes
    -strokewidth     stroke-width        largeur en pixels
    +antialias       stroke-antialias    0/1 lissage des bords de ligne

    -font            font                font_name / font_file
    -family          font-family            ?
    -weight            ?                    ?
    -stretch           ?                    ?
    -pointsize       font-size           hauteur en points
    -kerning           -                 espacement supplémentaire entre les caractères

    +antialias       text-antialias      0/1 lissage du texte dessiné
    -box             text-undercolor     couleur fill de la boîte englobante de la police
      -              decorate        (None, Underline, LineThrough ou Overline)

    -gravity         gravity             (None, North, South-East,...)
    -fuzz              -                 delta de couleur / pourcentage
    -bordercolor       -                 couleur

Remarques :
  - pas d'option correspondante      ? inconnu
Ces réglages sont généralement bien compris car ils sont régulièrement utilisés et démontrés ci-dessus. Une police, un étirement (stretch), un style et une graisse (weight) sont utilisés pour identifier une police dans la liste de polices d'ImageMagick. La plupart des gens se contentent cependant de sélectionner une police et une taille (pointsize) précises à utiliser à la place. Ils sont donc rarement utilisés dans IM.
Comme vous pouvez le voir, les réglages spéciaux des primitives de « remplissage de couleur » n'ont pas d'équivalents directs en MVG. Il s'agit du réglage « -bordercolor » et du facteur « -fuzz ». Ceux-ci doivent être spécifiés en ligne de commande avant d'utiliser l'opérateur « [-draw](https://imagemagick.org/command-line-options/#draw) ». Certains réglages MVG seraient probablement plus utiles en tant que réglages globaux en ligne de commande, comme le réglage « decorate » pour le dessin des polices. ATTENTION : « -gravity » ne fait pas partie de la spécification SVG. Au sein de MVG, il n'est utilisé que pour le placement du texte et des images, ainsi que pour la justification. Il n'existe actuellement aucun réglage de justification distinct des effets de « gravité » par défaut. Cependant, comme la justification fait partie de la gestion du texte SVG, cela changera probablement à l'avenir. Or, les réglages globaux en ligne de commande (en dehors de la chaîne de dessin MVG) servent à initialiser les réglages de chaque opération « -draw » que vous appliquez, ce qui explique pourquoi vous pouvez définir une couleur « -fill » que vous pouvez ensuite utiliser pour dessiner un cercle de cette couleur.
---
  magick -size 100x60 xc:skyblue   -fill red \
          -draw "circle 50,30 40,10"          draw_circle_global.gif

[IM Output]
Vous pouvez remplacer ce réglage global localement au sein de l'argument MVG « -draw »…


|

  magick -size 100x60 xc:skyblue   -fill red \
          -draw "fill green   circle 50,30 40,10"  draw_circle_override.gif

[IM Output]
Cependant, les réglages définis au sein d'un seul argument MVG « -draw » n'existent que pour la durée de cette opération « -draw ». C'est-à-dire que les réglages à l'intérieur d'un « -draw » sont locaux à ce draw et ne se répercutent pas sur les arguments « -draw » distincts suivants.


|

  magick -size 100x60 xc:skyblue   -fill red   -draw 'fill green' \
          -draw "circle 50,30 40,10"          draw_circle_local.gif

[IM Output]
Si vous prévoyez d'effectuer de nombreuses opérations, il peut être préférable de toutes les regrouper dans une seule chaîne MVG, plutôt que d'utiliser plusieurs opérations « -draw ».


|

  magick -size 100x60 xc:skyblue  \
          -draw "fill green  circle 41,39 44,57
                 fill blue   circle 59,39 56,57
                 fill red    circle 50,21 50,3  "  draw_circle_multi.gif

[IM Output]
Réglages spécifiques à MVG D'autres réglages MVG contrôlant la manière dont les lignes et les objets sont dessinés sont également utiles à connaître, même lors de l'utilisation des opérations primitives. En voici quelques-uns…

   __draw_MVG__       __Description/Argument__
  fill-opacity        transparence du remplissage, de 0.0 à 1.0
  clip-rule           style de remplissage pour les lignes croisées (evenodd, nonzero)

  stroke-opacity      transparence de la ligne, nombre de 0.0 à 1.0
  stroke-dasharray    liste des longueurs « on » et « off » pour les lignes
  stroke-dash
  stroke-linecap      Aspect de la fin de ligne : butt round square
  stroke-linejoin     Jonctions de lignes :  butt  miter round square
  stroke-miterlimit   Angle auquel les jonctions « miter » deviennent « bevel » (ou « butt »)

N'oubliez pas qu'une liste complète de tous les réglages et opérateurs de dessin MVG est disponible sur Résumé des primitives et de la syntaxe MVG sur le site web d'IM. Examinons les effets de quelques réglages plus simples… |

  # Opacité du trait
  magick -size 100x60 xc:skyblue -fill none -stroke black \
          -draw "                           path 'M 10,10 L 90,10'" \
          -draw "stroke-opacity 0.8         path 'M 10,20 L 90,20'" \
          -draw "stroke-opacity 0.6         path 'M 10,30 L 90,30'" \
          -draw "stroke-opacity 0.4         path 'M 10,40 L 90,40'" \
          -draw "stroke-opacity 0.2         path 'M 10,50 L 90,50'" \
          set_stroke_opacity.gif

  # Opacité du remplissage
  magick -size 100x60 xc:skyblue -fill white -stroke black \
          -draw "                    rectangle  5,10 15,50 " \
          -draw "fill-opacity 0.8    rectangle 20,10 30,50 " \
          -draw "fill-opacity 0.6    rectangle 35,10 45,50 " \
          -draw "fill-opacity 0.4    rectangle 50,10 60,50 " \
          -draw "fill-opacity 0.2    rectangle 65,10 75,50 " \
          -draw "fill-opacity  0     rectangle 80,10 90,50 " \
          set_fill_opacity.gif

[IM Output]
[IM Output]
|

  # Lignes pleines et pointillées
  magick -size 100x60 xc:skyblue -fill none -stroke black \
          -draw "                           path 'M 10,10 L 90,10'" \
          -draw "stroke-dasharray 5 3       path 'M 10,20 L 90,20'" \
          -draw "stroke-dasharray 5 5       path 'M 10,30 L 90,30'" \
          -draw "stroke-dasharray 10 3 3 3  path 'M 10,40 L 90,40'" \
          -draw "stroke-dasharray 1 6       path 'M 10,50 L 90,50'" \
          set_lines.gif

  magick -size 100x60 xc:skyblue -fill white -stroke black \
          -draw "                           path 'M 10,10 L 90,10'" \
          -draw "stroke-dasharray 5 3       path 'M 10,20 L 90,20'" \
          -draw "stroke-dasharray 5 5       path 'M 10,30 L 90,30'" \
          -draw "stroke-dasharray 10 3 3 3  path 'M 10,40 L 90,40'" \
          -draw "stroke-dasharray 1 6       path 'M 10,50 L 90,50'" \
          set_lines_fill.gif

  # Remarque : techniquement, la seconde image devrait être identique à la première,
  # puisque les lignes « remplies » ne contiennent aucune surface. Je considère cela comme un BOGUE.

[IM Output]
[IM Output]
|

  # Extrémités et jonctions de trait
  magick -size 100x60 xc:skyblue -fill white -stroke black -strokewidth 8 \
          -draw "                           path 'M 20,20 L 20,70'" \
          -draw "stroke-linecap butt        path 'M 40,20 L 40,70'" \
          -draw "stroke-linecap round       path 'M 60,20 L 60,70'" \
          -draw "stroke-linecap square      path 'M 80,20 L 80,70'" \
          set_endcaps.gif

  magick -size 100x60 xc:skyblue -fill white -stroke black -strokewidth 5 \
          -draw "                        path 'M  5,70 L 20,20  35,70'" \
          -draw "stroke-linejoin miter   path 'M 35,70 L 50,20  65,70'" \
          -draw "stroke-linejoin bevel   path 'M 55,70 L 70,20  85,70'" \
          -draw "stroke-linejoin round   path 'M 75,70 L 90,20 105,70'" \
          set_linejoin.gif

  magick -size 100x60 xc:skyblue -fill white -stroke black -strokewidth 5 \
          -draw "                        path 'M  5,70 L 20,20  35,70'" \
          -draw "stroke-miterlimit 7     path 'M 35,70 L 50,20  65,70'" \
          -draw "stroke-miterlimit 6     path 'M 65,70 L 80,20  95,70'" \
          set_miterlimit.gif

[IM Output]
[IM Output]
[IM Output]
Le réglage « stroke-miterlimit » est plutôt difficile à illustrer. Cette propriété définit l'angle à partir duquel une jonction « miter » se transforme en jonction « bevel ». En clair, pour des angles très aigus, une jonction miter peut s'étendre très loin du point de jonction réel entre les deux lignes. Ce réglage fixe une limite maximale à cette acuité, en émoussant la pointe de l'angle lorsqu'elle devient trop longue. Notez cependant qu'il représente une valeur trigonométrique d'un certain angle, et non une longueur ou une distance. La valeur doit être supérieure à 1.0. L'exemple ci-dessus montre que, pour l'angle de jonction affiché, le miter est soudainement converti en bevel quelque part entre une valeur de 6 et 7. Par exemple, un « stroke-miterlimit » de 1.414 convertit une jonction « miter » en « bevel » pour tout angle inférieur à 90 degrés. Une valeur de 4.0 (la valeur par défaut) convertit la jonction pour des angles inférieurs à environ 29 degrés. Tandis qu'une valeur de 10.0 les convertit pour un angle inférieur à environ 11,5 degrés. Dessin de chemins SVG Le chemin (path) SVG est la primitive de dessin de base du SVG. Il permet de dessiner des lignes, des formes, des cercles, des courbes, des arcs, etc. La spécification complète des chemins SVG se trouve dans le document SVG Path Specification. Ce document n'est cependant pas facile à lire, car il s'adresse réellement aux programmeurs et non aux utilisateurs ; je vais donc simplifier et résumer la spécification des chemins…

  • Les lettres sont des commandes, tandis que tous les nombres (à virgule flottante) sont des arguments.
  • Les virgules ou les espaces peuvent servir de séparateurs d'arguments ; sinon, ils sont totalement ignorés.
  • Les deux derniers arguments (x,y) de chaque composant de chemin deviennent le point final (ou « nœud ») de ce composant.
  • Les lettres majuscules indiquent les coordonnées absolues du point final.
    Les lettres minuscules sont relatives au point final du composant précédent.
    Par exemple : « M 1,2 l 3,4 l 2,-4 » équivaut à « M 1,2 L 4,6 L 6,2 ».
    C'est-à-dire que 3,4 a été ajouté à 1,2 pour tracer une ligne jusqu'à 4,6.
    Puis 2,-4 a été ajouté pour tracer une ligne jusqu'à la coordonnée finale 6,2.
  • Les arguments de chaque élément peuvent être répétés sans réémettre la même lettre de chemin, en ajoutant simplement d'autres groupes d'arguments numériques. Cependant, pour les courbes, je recommande tout de même d'ajouter les lettres de fonction, par souci de lisibilité.
  • Les arguments répétés de « M » ou « m » sont traités respectivement comme « L » ou « l ».
    Par exemple : « M 1,2 3,4 5,6 » équivaut à « M 1,2 L 3,4 L 5,6 »
    Et : « m 1,2 3,4 2,-4 » équivaut à « m 1,2 l 3,4 l 2,-4 »
  • Pour les courbes de Bézier cubiques, tous les points (points de contrôle et nœuds finaux) sont donnés par rapport au point final du composant de chemin précédent.

Remarquez que vous pouvez tout spécifier soit en coordonnées absolues, soit en coordonnées relatives. Vous pouvez ainsi définir un objet en termes de coordonnées relatives et ne fournir qu'une coordonnée de « déplacement » (move) absolue initiale pour positionner l'ensemble du chemin. D'un autre côté, vous pouvez aussi utiliser d'autres commandes de « contenu graphique » pour déplacer tout un dessin au sein d'une « viewbox » ou d'une « translation » (voir ci-dessous). Donc en réalité, peu importe que vous utilisiez des coordonnées absolues ou relatives dans les chemins SVG. Déplacements, lignes et fermetures de chemin constituent le point de départ initial pour apprendre les chemins d'objets SVG. |

  # Chemins ouverts, complétés et fermés (mêmes points)

  magick -size 100x60 xc:skyblue -fill white -stroke black \
          -draw "path 'M 40,10 L 20,50 90,10 70,40'" path_open.gif

  magick -size 100x60 xc:skyblue -fill white -stroke black \
          -draw "path 'M 40,10 L 20,50 90,10 70,40 40,10'" path_complete.gif

  magick -size 100x60 xc:skyblue -fill white -stroke black \
          -draw "path 'M 40,10 20,50 90,10 70,40 Z'" path_closed.gif

[IM Output] [IM Output]
[IM Output]
Notez cependant que « Z » se contente de fermer la boucle. Il ne crée PAS un objet distinct. Ainsi, deux chemins « fermés » restent classés comme formant un seul et même objet dessiné, qu'ils se chevauchent ou soient totalement disjoints. Nous montrons ici deux boucles fermées mais qui se chevauchent, dessinées dans le même sens. Comme un seul chemin est utilisé, l'objet est un objet unique, et le réglage « fill-rule » contrôle la façon dont la région de chevauchement doit être remplie. |

  # Chemins qui se chevauchent et règle de remplissage

  magick -size 100x60 xc:skyblue -fill white -stroke black \
          -draw "fill-rule evenodd \
                 path 'M 40,10 20,20 70,50 Z
                       M 20,40 70,40 90,10 Z' " path_evenodd.gif

  magick -size 100x60 xc:skyblue -fill white -stroke black \
          -draw "fill-rule nonzero \
                 path 'M 40,10 20,20 70,50 Z
                       M 20,40 70,40 90,10 Z' " path_nonzero.gif

[IM Output]
[IM Output]
Comme les objets ont été dessinés dans le même sens angulaire autour du centre, les deux boucles fermées délimitent une zone dont la valeur de cycle est 2 ; ainsi, la règle « evenodd » a laissé cette zone non remplie, tandis que la règle non nulle « nonzero » l'a remplie. Notez cependant que tous les chemins restent visibles, puisqu'il s'agit en réalité du même objet. Le sens dans lequel les chemins sont dessinés est très important, et en général tous les chemins devraient être dessinés exactement dans le même sens par rapport à « l'intérieur » de l'objet. Par exemple, ici je dessine le second objet dans le sens inverse du premier. Ainsi, lorsque les deux objets se chevauchent, cette zone est entourée « zéro » fois. C'est-à-dire qu'elle restera non remplie quelle que soit la « fill-rule » utilisée, créant un « trou ». |

  # Objets fermés qui se chevauchent, second objet dessiné en sens inverse

  magick -size 100x60 xc:skyblue -fill white -stroke black \
          -draw "fill-rule evenodd \
                 path 'M 40,10 20,20 70,50 Z
                       M 20,40 90,10 70,40 Z' " path_rvs_evenodd.gif

  magick -size 100x60 xc:skyblue -fill white -stroke black \
          -draw "fill-rule nonzero \
                 path 'M 40,10 20,20 70,50 Z
                       M 20,40 90,10 70,40 Z' " path_rvs_nonzero.gif

[IM Output]
[IM Output]
Cela signifie que vous pouvez générer des « trous » dans un objet en inversant le sens, de manière à garder « l'intérieur » de l'objet du même côté du sens de parcours. |

  # Un objet avec un trou dessiné en sens inverse !

  magick -size 100x60 xc:skyblue -fill white -stroke black \
          -draw "path 'M 30,10 20,55 70,50 80,5 Z
                       M 50,20 60,40 40,30 Z' " path_with_hole.gif

[IM Output]
Le résultat est le même quel que soit le réglage « fill-rule », car le trou est à la fois « pair » et « zéro », donc non rempli. Bien sûr, si vous utilisez un élément « path » totalement distinct, vous générerez un objet totalement distinct. Dans ce cas, la « fill-rule » ne s'applique pas et les objets sont simplement dessinés l'un par-dessus l'autre, dans l'ordre donné. |

  # Des chemins distincts sont des objets distincts

  magick -size 100x60 xc:skyblue -fill white -stroke black \
          -draw "path 'M 40,10 20,20 70,50 Z'
                 path 'M 20,40 70,40 90,10 Z' " path_separate.gif

[IM Output]

À VENIR : chemins alignés sur les coordonnées « H » et « V »

Les arcs elliptiques sont la fonction de dessin de cercles des chemins SVG…
Les paramètres « large » et « sweep » sont particulièrement importants, car ils déterminent laquelle des quatre façons vous allez utiliser pour tracer un « arc » depuis votre point de départ jusqu'au point d'arrivée de ce composant de chemin. Les deux indicateurs « large » et « sweep » définissent lequel des quatre arcs de ce rayon reliera les deux points. |

  #  Arcs elliptiques :   A  radius_x,y  angle   large,sweep  x,y

  magick -size 100x60 xc:skyblue -fill white -stroke black \
          -draw "path 'M 30,40  A 30,15 0 0,0 70,20'"    path_arc.gif

  magick -size 100x60 xc:skyblue -fill white -stroke black \
          -draw "path 'M 30,40  A 30,15 0 0,1 70,20'"    path_arc2.gif

  magick -size 100x60 xc:skyblue -fill white -stroke black \
          -draw "path 'M 30,40  A 30,15 0 1,0 70,20'"    path_arc3.gif

  magick -size 100x60 xc:skyblue -fill white -stroke black \
          -draw "path 'M 30,40  A 30,15 0 1,1 70,20'"    path_arc4.gif

[IM Output]
[IM Output]
[IM Output]
[IM Output]
le second indicateur « sweep » détermine simplement de quel côté du chemin en ligne droite l'arc doit être dessiné. L'indicateur « large » sert à sélectionner le chemin le plus long, passant autour du centre de l'ellipse. Autrement dit, l'angle de l'arc défini sera supérieur à 180 degrés. S'il est désactivé, vous obtenez le plus petit « arc », ne contenant pas le centre de l'ellipse, et couvrant un angle inférieur à 180 degrés. Fermer un arc avec un « Z » ne fait que tracer un dernier segment de ligne droite. Pour créer une ellipse ou un cercle complet, il vous faut au moins deux segments d'« arc », allant du premier au second point, puis revenant au premier point. Les deux arcs doivent avoir le même réglage « sweep », afin que l'arc se trouve de côtés différents, avec des sens de parcours différents. L'un des deux arcs doit avoir le réglage « large » activé. |

  # Arcs elliptiques fermés et inclinés (définis par deux points de bord)

  magick -size 100x60 xc:skyblue -fill white -stroke black \
          -draw "path 'M 30,40  A 30,20  20  0,0 70,20 Z '" path_arc5.gif

  magick -size 100x60 xc:skyblue -fill white -stroke black \
          -draw "path 'M 30,40  A 30,20  20  1,1 70,20 Z '" path_arc6.gif

  magick -size 100x60 xc:skyblue -fill white -stroke black \
          -draw "path 'M 30,40  A 30,20  20  0,0 70,20 \
                                A 30,20  20  1,0 30,40 Z '" path_arc7.gif

[IM Output]
[IM Output]
[IM Output]
Notez que si la ligne est trop longue pour tenir dans la taille d'ellipse donnée avec l'angle indiqué, la taille de l'ellipse sera agrandie pour que la ligne y tienne, l'ellipse étant centrée sur la ligne. Cela signifie qu'en utilisant de petits nombres pour les rayons des axes, vous pouvez simplement spécifier un rapport entre les longueurs d'axes, et garantir que le chemin en ligne directe passe par le point central de l'ellipse. Autrement dit, le chemin forme un diamètre elliptique d'un côté de l'ellipse à l'autre. Il ne s'agit pas nécessairement du grand axe ou du petit axe de l'ellipse, mais simplement d'un diamètre elliptique. |

  magick -size 100x60 xc:skyblue -fill white -stroke black \
          -draw "path 'M 30,40   A 3,2  45  0,0 70,20'" path_arc_x.gif

[IM Output]
Bien sûr, l'utilisation de longueurs « 1,1 » donne un demi-cercle parfait, allant d'un point à l'autre. Dans ce cas, l'angle elliptique ne fait aucune différence. |

  magick -size 100x60 xc:skyblue -fill white -stroke black \
          -draw "path 'M 30,40   A 1,1  0  0,0 70,20'" path_hcircle.gif

[IM Output]
Pour un cercle complet centré entre les deux points, utilisez… |

  magick -size 100x60 xc:skyblue -fill white -stroke black \
          -draw "path 'M 30,40   A 1,1  0  0,0 70,20
                                 A 1,1  0  1,0 30,40  Z'" path_circle.gif

[IM Output]
La définition SVG de l'« arc » précise également que si l'un des deux rayons est nul, une ligne droite doit être tracée. Ainsi, tout arc avec des rayons « 0,0 » n'est qu'un simple arc en ligne droite… |

  magick -size 100x60 xc:skyblue -fill white -stroke black \
          -draw "path 'M 30,40   A 0,0  0  0,0 70,20'" path_arc_line.gif

[IM Output]
Si vous spécifiez un rayon très grand pour l'arc, et que vous ne spécifiez pas de « large sweep » pour le chemin de retour, vous pouvez créer une forme de lentille de ce rayon entre les deux points. |

  magick -size 100x60 xc:skyblue -fill white -stroke black \
          -draw "path 'M 30,40   A 50,50  0  0,0 70,20
                                 A 50,50  0  0,0 30,40  Z'" path_lens.gif

[IM Output]
Ce type d'arc est une fonctionnalité clé. Il permet de donner très facilement, à ce qui serait sinon une ligne droite, une courbe petite mais nette. Par exemple, au lieu d'un simple triangle comme celui-ci… |

  magick -size 100x60 xc:skyblue -fill white -stroke black \
          -draw "path 'M 20,55  L 25,10  L 70,5 L 20,55 Z' "   triangle.gif

[IM Output]
Vous pouvez remplacer chaque ligne par un arc utilisant un grand rayon pour ne leur donner qu'une légère courbure. |

  magick -size 100x60 xc:skyblue -fill white -stroke black \
          -draw "path 'M 20,55  A 100,100 0 0,0 25,10
                                A 100,100 0 0,0 70,5
                                A 100,100 0 0,0 20,55 Z' " triangle_curved.gif

[IM Output]
Les points d'extrémité des lignes n'ont pas changé ; tout ce qui s'est passé, c'est que chaque « L » a été remplacé par un segment d'arc. La taille de l'arc devrait cependant être proportionnelle à la longueur de la ligne. Comme je ne l'ai pas fait, la longue ligne diagonale présente une courbe bien plus prononcée et profonde que les deux autres. N'oubliez pas que lorsque vous redimensionnez ou mettez à l'échelle l'objet dessiné, vous devez aussi mettre le rayon à l'échelle dans la même proportion que la longueur de cette ligne, afin que la courbe soit redimensionnée en conséquence et que l'arc soit lui aussi correctement mis à l'échelle. Notez que l'indicateur « sweep » contrôle si la courbe se bombe vers l'extérieur ou vers l'intérieur, selon le sens dans lequel chaque segment de chemin est dessiné (voir ci-dessus). |

  magick -size 100x60 xc:skyblue -fill white -stroke black \
          -draw "path 'M 20,55  A 100,100 0 0,0 25,10
                                A 100,100 0 0,1 70,5
                                A 100,100 0 0,1 20,55 Z' " triangle_bulge.gif

[IM Output]
Le triangle aux bords droits, qui avait l'air « statique », ressemble maintenant un peu à une voile gonflée par le vent. Si vous souhaitez vraiment rendre la ligne parfaitement droite sans la reconvertir en véritables segments de ligne, vous pouvez désactiver la courbure en utilisant un rayon d'arc nul. Les arcs ne sont donc pas seulement utiles pour générer des ellipses et des cercles, mais aussi pour dessiner des segments de ligne droits ou légèrement courbés. C'est un chemin de dessin point à point général très polyvalent. Une alternative simple à l'utilisation des arcs elliptiques pour générer des segments de ligne courbés séparés consiste à utiliser plutôt les segments de Bézier quadratiques. La principale différence est qu'un unique point de contrôle est utilisé, plutôt qu'un rayon circulaire, pour définir l'arc. Cela permet aussi d'orienter l'arc vers une extrémité du segment de ligne, mais au prix d'une plus grande difficulté à générer un arc symétrique. Vous pouvez bien sûr « combiner les deux » en les utilisant ensemble. Exemple de diagramme circulaire Pour terminer sur les arcs, donnons un exemple de leur utilisation pour générer des secteurs circulaires. Bien sûr, vous aurez peut-être besoin de recourir à quelques mathématiques trigonométriques externes (quel était votre niveau en maths au lycée ?) pour déterminer les points de chemin d'arrivée nécessaires. |

  magick -size 140x130 xc:white -stroke black \
    -fill red   -draw "path 'M 60,70 L   60,20   A 50,50 0 0,1 68.7,20.8 Z'" \
    -fill green -draw "path 'M 60,70 L 68.7,20.8 A 50,50 0 0,1 77.1,23.0 Z'" \
    -fill blue  -draw "path 'M 68,65 L 85.1,18.0 A 50,50 0 0,1  118,65   Z'" \
    -fill gold  -draw "path 'M 60,70 L  110,70   A 50,50 0 1,1   60,20   Z'" \
    -fill black -stroke none  -pointsize 10 \
    -draw "text 57,19 '10' text 70,20 '10' text 90,19 '70' text 113,78 '270'" \
    piechart.jpg

[IM Output]
Notez que tous les arcs sont dessinés à gauche du « chemin de ligne » et sont marqués en conséquence (avec l'indicateur « sweep »). Mais si l'arc couvre un angle supérieur à 180 degrés, l'indicateur « large » doit être activé — voir le dernier composant « gold » dans l'exemple ci-dessus. Notez également que chaque section doit être dessinée entièrement, même si cela signifie que vous devrez parfois tracer deux fois les lignes de bordure. Sinon, vous risquez soit de ne pas remplir complètement cette section avec la couleur, soit de voir la couleur de remplissage recouvrir le contour d'une section précédemment dessinée. La seule façon d'éviter de dédoubler plusieurs lignes est de dessiner d'abord toutes les zones remplies, puis de recommencer pour tracer les contours. C'est-à-dire qu'il vous faudra tout dessiner deux fois, en veillant à ce que tout s'aligne correctement. Le dédoublement des contours est donc probablement la solution la plus simple. Les courbes de Bézier cubiques peuvent être définies à l'aide d'une fonction « C » définissant deux points de contrôle et le point final. Pour poursuivre des courbes de Bézier cubiques en utilisant une image miroir du dernier point de contrôle (pour une courbe continue), vous pouvez utiliser une fonction « S ». En voici un exemple. En raison de la complexité de cette fonction, j'ai préparé à l'avance un canevas montrant l'emplacement des points de contrôle, ainsi que le « miroir supposé » du dernier point de contrôle. |

  # Bézier cubique :    C  control_1_x,y control_2_x,y  x,y
  # Lissée " :       S  control_2_x,y  x,y

  magick path_cubic_canvas.gif  -fill white -stroke black \
          -draw "path 'M 10,30  C 10,4 50,4 50,30  S 90,55 90,30' " \
          path_cubic.gif

[IM Output]
La ligne reliant le point de contrôle au point final sur le chemin de ce segment de chemin (ligne de contrôle) définit essentiellement la direction de la courbe en ce point du chemin. Une ligne de contrôle longue produira une courbe plus douce à cet endroit, tandis qu'une ligne courte génère une courbe plus vive à cet endroit. Si le point de contrôle coïncide avec le point de la courbe (la ligne de contrôle a une longueur nulle), la courbe présentera une discontinuité nette à cet endroit, comme si seuls des segments de ligne droite avaient été utilisés. À titre d'exemple plus concret, l'extrait de code suivant provient du script générateur du logo des IM Examples, qui crée la zone d'éclaboussure sinueuse du logo des IM Examples. La partie délicate de cet exemple est que je convertis la chaîne de chemin de Bézier cubique que j'utilise en un autre chemin montrant les lignes de contrôle utilisées pour générer la courbe de Bézier. Cela me permet de voir les angles et les longueurs des lignes de contrôle de la courbe, ce qui facilite grandement l'ajustement des résultats. Un seul jeu de points doit être ajusté pour afficher à la fois la courbe et les contrôles, ce qui réduit au minimum le risque d'erreurs. |

   curve="M 12,27  C 7,37  18,50 18,60  S  0,80 10,94
          S 40,74 50,78  S 60,99 76,95  S 72,70 75,65
          S 95,55 95,42  S 69,37 66,32  S 67,2  53,7
          S 43,17 35,22  S 17,17 12,27  Z"
   c_ctrls=`echo $curve | \
              sed '1s/\([0-9]\)  *\([0-9]\)/\1 M \2/;
                   s/S/M/g; s/C/ /;' -`
   magick -size 100x100 xc:white \
           -draw "stroke None  fill Green  path '$curve'" \
           -draw "stroke Red   fill None   path '$c_ctrls'" \
           curvy_splash.gif

[IM Output]
Si vous regardez attentivement l'image, vous verrez que le début et la fin de la courbe possèdent deux lignes de contrôle orientées dans des directions opposées. Pour un chemin continu fermé, les lignes de contrôle du début et de la fin doivent être au même angle (mais en miroir) et bien sûr de même longueur. C'est important à retenir, car il est facile de se tromper. Tous les autres points le long de la courbe n'ont qu'un seul point/ligne de contrôle, pointant dans la direction opposée à celle dans laquelle la courbe est dessinée. Plus ce segment de ligne est long, moins la courbe est « vive » à ce point de contrôle, une longueur nulle produisant une « pointe ». La fonction « S » génère en interne le point/ligne de contrôle miroir du segment suivant à partir des données du segment précédent, afin de produire une continuation lisse de la courbe. Pour d'autres exemples de cette fonction de chemin, voir SVG : commandes de courbe de Bézier cubique. Générer manuellement une courbe de Bézier est relativement simple, sans avoir besoin d'outils graphiques sophistiqués.

  • Définissez d'abord tous les points de coordonnées par lesquels vous voulez que votre courbe passe, en répétant la coordonnée de départ à la fin de la liste.
  • Développez maintenant cette liste en doublant tous les points de coordonnées x,y en paires, et ajoutez une fonction « S » (cubique lissée) avant chaque paire. Le premier nombre de chaque paire est le point de contrôle relié au second nombre, qui représente le point sur la courbe. La première paire de points fait toutefois exception : le premier point est le début de la courbe et le second représente le premier et unique point de contrôle inversé.
  • Remplacez la lettre de fonction de la première paire de coordonnées, de « S » en « M », puis ajoutez un « C » entre cette paire de coordonnées. Enfin, retirez le « S » de la deuxième paire de coordonnées pour compléter la fonction cubique (« C ») initiale.
  • Complétez le chemin en ajoutant un dernier « Z » pour fermer la courbe.
    Consultez la séquence d'exemple ci-dessus pour voir à quoi cela devrait ressembler.
  • À ce stade, vous pouvez faire un dessin d'essai de votre chemin. Il ne comportera que des segments de ligne droite, puisque toutes les lignes de contrôle auront une longueur nulle.
  • Il ne vous reste plus qu'à ajuster lentement et soigneusement la position du segment de ligne de contrôle (la première coordonnée de chaque paire « S ») pour obtenir la courbe finale souhaitée. Ne faites pas des lignes de contrôle trop longues, ni orientées dans la mauvaise direction, sous peine d'obtenir une courbe d'aspect très étrange.
  • Pour vous aider à voir vos changements et à repérer les erreurs, utilisez la commande de conversion « sed » ci-dessus pour tracer les lignes de contrôle entre les points de contrôle du chemin et le point de contrôle de la courbe. Notez cependant que les lignes de contrôle de longueur nulle ne sont pas visibles ; mais comme la ligne produira une pointe nette, la position devrait être évidente.
  • Enfin, assurez-vous que le premier point/ligne de contrôle après un « C » est exactement à l'opposé du point/ligne de contrôle final, à cette même position.

La génération interactive de courbes est également possible avec certains éditeurs graphiques vectoriels. Par exemple, Luis Guerra signale que les courbes de Bézier générées par « Inkscape » peuvent être rendues accessibles via la fonction « Edit -> XML Editor », en sélectionnant ensuite le chemin ou la forme dont vous voulez les points de contrôle.

Connaissez-vous d'autres façons d'extraire une courbe de Bézier (donnant soit deux, soit un point de contrôle par point de la courbe) à l'aide d'un outil graphique ? Ou peut-être une autre technique pour générer de telles courbes ? Écrivez-moi ! J'adorerais en entendre parler. Vous serez crédité de la technique, comme d'autres l'ont été avant vous.

La Bézier quadratique est une simplification de la fonction de Bézier cubique, lorsque les deux points de contrôle sont fusionnés en un seul point de contrôle. Là encore, vous pouvez démarrer la courbe avec une fonction « Q », puis utiliser une fonction « T » pour la poursuivre, en reflétant le dernier point de contrôle. |

  #  Bézier quadratique :  Q  control_x,y  x,y
  #  Lissée " :         T  x,y

  magick path_quad_canvas.gif  -fill white -stroke black \
          -draw "path 'M 10,30   Q 20,4 50,30   T 90,30' " \
          path_quad.gif

[IM Output]
Je dois cependant vous avertir que la fonction de continuation « T » ne fonctionne vraiment que pour les chemins reliant des points équidistants. Je n'en recommande pas l'usage. L'avantage des courbes quadratiques est de remplacer les arcs elliptiques, car elles utilisent une position réelle plutôt qu'un rayon pour l'arc. Elles permettent également d'orienter l'arc en faveur d'une extrémité plutôt que de l'autre, ce qui n'est pas pratique avec les arcs elliptiques. |

  magick -size 100x60 xc:skyblue -fill white -stroke black \
          -draw "path 'M 20,55  Q 30,32 25,10
                                Q 50,1 70,5
                                Q 50,45 20,55 Z' " triangle_bulge_2.gif

[IM Output]
Dans ce cas, les arcs sont moins uniformes, et l'on obtient quelque chose qui ressemble davantage à un aileron de requin inversé qu'à une voile. N'oubliez pas que les arcs quadratiques sont des paraboles, tandis que les arcs elliptiques génèrent essentiellement des segments circulaires. Cela peut être la clé pour déterminer quel type de segment de ligne en arc utiliser. Pour d'autres exemples de cette fonction de chemin, voir SVG : commandes de courbe de Bézier quadratique.

Déformation de la surface de dessin

En plus de ces capacités, la surface de dessin sur laquelle les objets sont dessinés peut être déformée de diverses manières, permettant de réaliser des choses étonnantes. Vous pouvez d'abord appliquer des modifications générales de la surface de dessin telles que « translate », « rotate », « scale », « skewX », « skewY » et « affine ». Par exemple, étant donné un « chemin » de lignes, on peut « translater » l'origine, ou le point 0,0, de la surface de dessin vers un autre emplacement. |

  magick -size 100x60 xc:skyblue \
          -draw "translate 50,30
                 image over 3,3 0,0 'terminal.gif'
                 fill white  stroke black
                 path 'M 0,20 -45,20 20,-25 -25,-25'
                 fill none  stroke red
                 path 'M 0,10 0,-10  M 10,0 -10,0' "  transform_translate.gif

[IM Output]
Remarquez que « 0,0 », c'est-à-dire l'origine de la zone de dessin, est maintenant centrée sur l'image, bien que l'axe Y reste négatif en haut et positif en bas de l'image. L'opération « rotate » fait pivoter la surface de dessin, si bien que tout ce qui sera dessiné ensuite sur cette surface le sera de façon pivotée. Bien sûr, la rotation se fait autour de l'origine translatée, il est donc judicieux d'utiliser les deux opérateurs de transformation ensemble. |

  magick -size 100x60 xc:skyblue \
          -draw "translate 50,30    rotate -30
                 image over 4,4 0,0 'terminal.gif'
                 fill white  stroke black
                 path 'M 0,20 -45,20 20,-25 -25,-25'
                 fill none  stroke red
                 path 'M 0,10 0,-10  M 10,0 -10,0' "  transform_rotate.gif

[IM Output]
« scale » agrandit ou réduit la surface de dessin autour de l'origine. |

  magick -size 100x60 xc:skyblue \
          -draw "translate 50,30    scale 1.5,1.5
                 image over 4,4 0,0 'terminal.gif'
                 fill white  stroke black
                 path 'M 0,20 -45,20 20,-25 -25,-25'
                 fill none  stroke red
                 path 'M 0,10 0,-10  M 10,0 -10,0' "  transform_scale.gif

[IM Output]
Une utilisation courante de « scale » est d'inverser l'axe Y afin qu'une valeur Y positive corresponde au haut. Bien sûr, l'origine doit aussi être déplacée soit vers le centre, soit vers le coin inférieur gauche, afin de garder les choses cohérentes. |

  magick -size 100x60 xc:skyblue \
          -draw "translate 50,30    scale 1,-1
                 image over 4,4 0,0 'terminal.gif'
                 fill white  stroke black
                 path 'M 0,20 -45,20 20,-25 -25,-25'
                 fill none  stroke red
                 path 'M 0,10 0,-10  M 10,0 -10,0' "    transform_flip.gif

[IM Output]
Enfin, « skewX » et « skewY » cisaillent l'image dans les directions X et Y. Par exemple, ici nous utilisons « skewX » pour donner une inclinaison à l'axe Y vertical de l'image. |

  magick -size 100x60 xc:skyblue \
          -draw "translate 50,30   skewX 20
                 image over 4,4 0,0 'terminal.gif'
                 fill white  stroke black
                 path 'M 0,20 -45,20 20,-25 -25,-25'
                 fill none  stroke red
                 path 'M 0,10 0,-10  M 10,0 -10,0' "    transform_skewY.gif

[IM Output]
Ces opérateurs ont des équivalents en dehors de la chaîne MVG « [-draw](https://imagemagick.org/command-line-options/#draw) », pour un usage général. Cependant, ces versions en ligne de commande sont des opérateurs qui s'appliquent immédiatement aux images déjà présentes en mémoire, plutôt qu'à une simple surface de dessin sur laquelle les objets vectoriels restent encore à dessiner. Pour plus de détails, voir Déformation d'images.

Déformation affine de la surface de dessin

Les cinq transformations de canevas ci-dessus peuvent toutes être combinées en un opérateur matriciel affine général, soit en utilisant la primitive MVG « affine », soit en définissant la transformation affine via « [-affine](https://imagemagick.org/command-line-options/#affine) » avant d'appeler « [-draw](https://imagemagick.org/command-line-options/#draw) ». Les transformations affines utilisent un ensemble de « coefficients de matrice » qui définit comment les coordonnées que vous fournissez doivent être modifiées pour obtenir les coordonnées de dessin réelles. Pour plus de détails sur le fonctionnement réel de ces « coefficients », voir Transformations matricielles affines. Par exemple… Pour simplement définir une origine centrale par rapport à laquelle les objets sont dessinés… |

  magick -size 100x60 xc:skyblue \
          -draw "affine 1,0,0,1,50,30
                 image over 4,4 0,0 'terminal.gif'
                 fill white  stroke black
                 path 'M 0,20 -45,20 20,-25 -25,-25'
                 fill none  stroke red
                 path 'M 0,10 0,-10  M 10,0 -10,0' "  affine_null.gif

[IM Output]
Retourner l'image…

  magick -size 100x60 xc:skyblue \
          -draw "affine 1,0,0,-1,50,30
                 image over 4,4 0,0 'terminal.gif'
                 fill white  stroke black
                 path 'M 0,20 -45,20 20,-25 -25,-25'
                 fill none  stroke red
                 path 'M 0,10 0,-10  M 10,0 -10,0' " affine_flip.gif

[IM Output]
Rotation de 30 degrés autour de l'origine…

  magick -size 100x60 xc:skyblue \
          -draw "affine .866,-.5,.5,.866,50,30
                 image over 4,4 0,0 'terminal.gif'
                 fill white  stroke black
                 path 'M 0,20 -45,20 20,-25 -25,-25'
                 fill none  stroke red
                 path 'M 0,10 0,-10  M 10,0 -10,0' "    affine_rot.gif

[IM Output]
Pour des transformations affines plus complexes, vous pouvez recourir aux scripts d'aide affine créés à cet effet. Ces scripts convertissent des éléments tels qu'un angle de rotation et un point central en coordonnées affines que vous pouvez utiliser directement dans votre réglage « [-draw](https://imagemagick.org/command-line-options/#draw) affine » ou « [-affine](https://imagemagick.org/command-line-options/#affine) ».

Contexte Push/Pop

Certaines primitives MVG reposent en réalité sur l'utilisation de ces transformations pour être employées correctement. Par exemple, la primitive Ellipse ne peut être spécifiée directement qu'avec des axes alignés orthogonalement. |

  magick -size 100x60 xc:skyblue -fill white -stroke black \
          -draw "ellipse 50,30 30,15 0,360"   ellipse_orthogonal.gif

[IM Output]
Cependant, en utilisant les transformations de dessin, nous pouvons facilement ajouter un « angle de rotation » à l'ellipse. |

  magick -size 100x60 xc:skyblue -fill white -stroke black \
          -draw "push graphic-context
                 translate 50,30   rotate 30
                 fill white  stroke black
                 ellipse 0,0 30,15 0,360
                 pop graphic-context"       ellipse_rotated.gif

[IM Output]
Notez que le « centre » de l'ellipse (le point de rotation) a d'abord été translaté, avant que la rotation ne soit appliquée. L'« ellipse » a ensuite été dessinée à cette position translatée, en « 0,0 ». L'exemple ci-dessus montre également deux nouvelles primitives de dessin MVG : « push graphic-context » et « pop graphic-context ». Elles ne sont pas strictement nécessaires dans l'exemple ci-dessus, mais elles sont recommandées lors de transformations de dessin importantes. Ce que font les primitives « push » et « pop », c'est sauvegarder l'état de dessin actuel, ou « graphic-context », puis le restaurer ensuite. Tout réglage de dessin modifié entre les deux primitives sera oublié. Cela inclut les déformations de surface, comme « translate » et « rotate », ainsi que les réglages de couleur « fill » et « stroke », ou tout autre élément ayant modifié l'« état » de dessin. Ces primitives permettent de dessiner facilement des objets très complexes comportant de nombreuses transformations, puis de revenir à une situation plus « normale » pour les opérations de dessin ultérieures. Vous pouvez en voir une démonstration plus concrète dans Dessiner des flèches ci-dessous.

Objets spéciaux Push/Pop

En construction

Réglages supplémentaires utilisés spécifiquement par MVG pour gérer le format SVG.

    font-family   font-stretch   font-style   font-weight
    encoding 'UTF-8'

    push defs

      push gradient 'def_name' linear X1,Y1 X2,Y2
        stop-color 'color' where
        stop-color 'color' where
          # where est un point entre les deux pixels donnés (0 = X1,Y1  1= X2,Y2)
        gradient-units 'objectBoundingBox|userSpaceOnUse'
        affine ....
      pop gradient

      push gradient 'def_name' radial CX,CY FX,FY R
        # Ici, CX,CY est le centre du dégradé radial de rayon R
        # FX,FY est le point focal, généralement identique à CX,CY
        # sauf si vous essayez de déformer le dégradé dans une direction spécifique
        stop-color 'color' where
        ...
      pop gradient

    pop defs

    push graphic-context
      fill 'url(#def_name)'
      ... dessinez des choses ici ...
    pop graphic-context

Pour des exemples, voir le site de développement de _Florent Monnier_…
  <http://www.linux-nantes.fr.eu.org/~fmonnier/OCaml/MVG/>

Lecture de fichiers MVG Comme vous pouvez le voir dans les exemples ci-dessus, les arguments MVG « -draw » peuvent devenir très longs. En fait, la conversion de SVG en MVG peut produire des arguments de dessin MVG extrêmement longs (voir ci-dessous). Cependant, l'interface générale en ligne de commande d'IM permet de lire n'importe quel argument de type chaîne depuis un fichier, en utilisant à la place un argument « @nomfichier ». C'est pratique, car cela signifie que vous pouvez lire vos commandes de dessin MVG très longues et complexes depuis un fichier séparé. Par exemple, si je place des opérations MVG dans un fichier appelé « draw_circles.mvg », je peux alors le dessiner ainsi… |

  magick -size 100x60 xc:skyblue  -draw @mvg_circles.mvg  mvg_draw.gif

[IM Output] | [IM Output]
Ce n'est pas tout : ImageMagick sait également lire directement le format de fichier image « MVG: », ce qui permet de dessiner de telles commandes de façon plus directe. Cependant, à moins que le fichier MVG ne définisse un canevas, vous devrez peut-être spécifier le canevas initial (« -size » et « -background ») sur lequel dessiner. |

  magick -size 100x60  -background limegreen  mvg_circles.mvg  mvg_file.gif

[IM Output] | [IM Output]
Vous pouvez déplacer les réglages initiaux du canevas dans l'image MVG en ajoutant une « viewbox » au fichier MVG, avec les dessins de remplissage de couleur d'arrière-plan appropriés. Le fichier image MVG devient ainsi une définition d'image complète. |

  magick   mvg_circles2.mvg    mvg_image.gif

[IM Output] | [IM Output]
| _Il n'existe actuellement qu'une seule façon de lire un fichier MVG externe depuis l'intérieur d'une chaîne d'argument MVG, et c'est en utilisant une primitive de dessin « image ». Malheureusement, cela convertit l'inclusion MVG en image matricielle AVANT de superposer cette image à la surface de dessin.

Autrement dit, il n'existe actuellement aucune fonction d'« inclusion » MVG._ :-(
---|---

En construction

Vous pouvez générer les opérations de dessin de bas niveau d'IM en utilisant « [+render](https://imagemagick.org/command-line-options/#render) » pour les enregistrer.

Lorsque vous donnez ensuite un réglage/opérateur « [-render](https://imagemagick.org/command-line-options/#render) », IM dessine immédiatement ces
opérations enregistrées.

Étrangement, le simple fait de produire un fichier « MVG » semble aussi provoquer cela…
     magick ...   -draw '....'  draw_commands.mvg

REMARQUE : si vous dessinez une courbe tout en produisant un fichier au format MVG, le fichier répertorie
la courbe comme une série de courts segments de ligne, plutôt que la courbe d'origine.

Vous pouvez bien sûr aller jusqu'au bout et utiliser le format SVG, plus universel.
Voir « [Gestion du format SVG](#svg) » ci-dessous.

Composition alpha MVG

En construction

Je n'ai vu aucune utilisation de la composition alpha (autre que l'algorithme du
« peintre », qui est essentiellement une composition alpha « over ») pour le dessin d'objets.

Cela ne signifie pas pour autant que ce soit impossible.

Si vous souhaitez composer votre rectangle, ellipse, cercle, ou autre, avec une
composition alpha différente (comme « DstOver », qui s'apparente à une
composition Under), dessinez alors votre figure sur un canevas transparent vide de la
même taille que l'original, puis composez-la sur votre image.

Cependant, comme le SVG permet d'utiliser la composition alpha pour dessiner du texte et d'autres
éléments sur les images, j'imagine que ce sera un ajout futur.

Restez à l'écoute !

Dessiner des symboles

Il arrive que vous ayez un ensemble de points sur une image où vous voulez dessiner des symboles de référence, comme des croix, des cercles, etc... Malheureusement, à l'heure actuelle, IM n'a pas de commandes permettant de dessiner facilement de tels symboles, mais avec un peu de travail supplémentaire, vous pouvez dessiner ces symboles.

Techniques de dessin de symboles

L'astuce pour dessiner plusieurs symboles à un ensemble de positions donné consiste à générer les commandes de dessin MVG à l'aide d'un script shell, ou de l'API que vous utilisez, afin de transformer l'ensemble de points donné en l'ensemble de commandes de dessin approprié. Par exemple, ici je convertis une ligne de points en un « plus » à chacun de ces points... |

  # Define a string of X and Y coordinates
  # comma between values, space between coordinates.
  points="6.6,7.7  25.0,75.0 42.2,85.4 75.8,94.7 51.5,39.3  92.5,66.6"

  # magick each point into a draw command for a cross (using 'awk')
  # the 'tr' converts spaces into 'newlines' (one point per line).
  crosses=`echo $points | tr -s ' ' '\012' |\
     awk -F, '{ print "line " $1-3 "," $2 " " $1+3 "," $2 ;
                print "line " $1 "," $2-3 " " $1 "," $2+3 ; }' -`

  # draw a red line between the points, and blue crosses on the points.
  magick -size 100x100 xc:white \
          -draw "fill none stroke red   polyline $points " \
          -draw "fill none stroke blue  $crosses " \
          points_plus.gif

[IM Output]
Le script ci-dessus utilise « tr» pour séparer chaque point (deux nombres) en un point par ligne, puis utilise « awk» pour effectuer tous les calculs mathématiques nécessaires pour dessiner le « plus » sur le point donné. Vous pouvez utiliser ce que vous voulez pour cela, car j'applique simplement une forme d'expansion de macro textuelle sur la liste de points en entrée. À peu près n'importe quel langage de programmation peut le faire. Pour le cas du script shell ci-dessus, j'ai simplement trouvé que « awk» était le moyen le plus simple et le plus rapide. En réalité, vous pouvez même utiliser ImageMagick lui-même pour faire cette expansion de « macro » en utilisant l'option de format « magick»... Par exemple, ici je l'utilise pour calculer un point sur la circonférence du cercle, pour ce « symbole de point ». |

  # Define a string of X and Y coordinates
  # comma between values, space between coordinates.
  points="6.6,7.7  25.0,75.0 42.2,85.4 75.8,94.7 51.5,39.3  92.5,66.6"

  # circle radius (or symbol size) to draw around each point.
  radius=3.5

  # magick each point into a draw command for a cross
  # In this case, points are space separated by the shell
  circles=$(for point in $points; do
             x=$(echo "$point" | cut -d, -f1)
             y=$(echo "$point" | cut -d, -f2)
             # use IM to do some floating point math, EG:  y2=$y+$radius
             y2=$(magick xc: -format '%[fx:'"$y"'+'"$radius"']' info:)
             echo "circle $x,$y $x,$y2"
           done)

  # Draw a red line between the points, and blue circles on the points.
  magick -size 100x100 xc:white \
          -draw "fill none stroke red   polyline $points " \
          -draw "fill none stroke blue  $circles " \
          points_circle.gif

[IM Output]
Maintenant, les chaînes de dessin que vous générez peuvent devenir assez longues, et pourraient commencer à poser des problèmes de longueur de commande finale. Ainsi, plutôt que de convertir les points en longues chaînes que vous passez ensuite à IM sur la ligne de commande, vous pouvez transmettre les commandes de dessin à IM par un tube, sous forme de fichier. J'utilise également cette fois une méthode de dessin par chemin SVG plutôt que les méthodes de primitives de dessin. De plus, les symboles que je génère sont des triangles autour de chaque point. |

  # Define a string of X and Y coordinates
  # comma between values, space between coordinates.
  points="6.6,7.7  25.0,75.0 42.2,85.4 75.8,94.7 51.5,39.3  92.5,66.6"

  # magick each point into a draw commands to draw a triangle
  for point in $points; do
     echo "path 'M $point  m 0,-5 -4,+8 +8,0 -4,-8'"
  done |\
    magick -size 100x100 xc:white \
          -fill none -stroke red  -draw "path 'M $points' " \
          -fill none -stroke blue -draw '@-' \
          points_tri.gif

[IM Output]
Le chemin SVG rend en fait cela plus facile, en permettant des déplacements de pixels relatifs, ce qui vous permet de concevoir le symbole de façon à ne nécessiter qu'un seul déplacement absolu initial « M» avant de donner la séquence de « déplacements » et de « lignes » pour dessiner le symbole. Grâce à cela, vous n'avez en fait besoin d'aucun calcul en virgule flottante, puisque le dessin d'IM effectuera lui-même les calculs de positionnement nécessaires. | L'élément de déplacement relatif duchemin SVG « m» est cassé avant IM v6.4.3-5. Si votre IM est plus ancien que cela, les exemples ci-dessus (et les suivants) risquent de ne rien dessiner. Vous pouvez corriger cela pour les anciennes versions en remplaçant les déplacements relatifs « m» ci-dessus par une séquence appropriée de lignes relatives, « l».
---|---
Vous pouvez maintenant aller encore plus loin, et transmettre un fichier MVG entièrement formé, avec la spécification du canevas de dessin, directement à IM comme un pipeline de commandes de dessin. Cette fois, faisons une « croix », similaire au premier exemple de « plus » ci-dessus qui nécessitait beaucoup de calculs. |

  # Define a string of X and Y coordinates
  # comma between values, space between coordinates.
  points="6.6,7.7  25.0,75.0 42.2,85.4 75.8,94.7 51.5,39.3  92.5,66.6"

  # Generate a MVG file for IM to draw all components
  ( echo "viewbox 0 0 100 100   fill white  rectangle 0,0 100 100"
    echo "fill none stroke red   path 'M $points'"
    echo "fill none stroke blue  path '"
    for point in $points; do
      echo "  M $point  m -2,-2 +4,+4  m -4,0 +4,-4"
    done
    echo "'"
  ) | magick mvg:- points_cross.gif

[IM Output]
Cela utilise une technique particulière de programmation shell où tout ce qui est « echoé » dans les parenthèses du shell est transmis à la commande finale « magick» comme un fichier MVG. Le premier « echo » définit et remplit le canevas de dessin de l'image, tandis que la boucle « while » convertit chaque « point » donné en un cercle du rayon donné. L'avantage de cette méthode est que vous n'avez aucune limitation de longueur de chaîne que vous pourriez rencontrer avec les deux autres méthodes. Parmi les autres symboles que vous pourriez générer figurent des carrés, des losanges, des barres d'erreur, etc... Voyez aussi « Dessiner des cercles » ci-dessous, pour d'autres méthodes de cercle, y compris un dessin de cercle en « path » relatif sans calcul.

Alternatives au dessin de symboles

Il existe d'autres moyens d'ajouter des symboles aux images, en dehors de les dessiner directement.

Polices de symboles

Vous pouvez extraire des symboles d'une police de symboles et les enregistrer sous forme de petit bitmap. Vous pouvez aussi utiliser de petites images colorées prédéfinies pour cela. Cependant, cela peut poser des difficultés pour positionner exactement la police par rapport à un pixel précis. Autrement dit, ce n'est pas une technique très précise. Mais vous pouvez composer n'importe quelle image à n'importe quelle position de pixel. Par exemple, ces symboles ont été extraits d'un certain nombre de polices, pour un usage spécifique dans ces pages d'exemples.

Des exemples de composition d'images sur un arrière-plan plus grand sont donnés dans la section sur la superposition d'images. Cependant, une méthode en boucle peut être plus utile, comme celle donnée dans le positionnement programmé d'images superposées. À VENIR : exemple de superposition d'images à l'aide de coordonnées

Morphologie

Une autre alternative consiste à utiliser la morphologie pour « dilater » un seul pixel, à l'aide de noyaux de « forme » spéciaux tels que « [Disk](morphology.html#disk)», « [Ring](morphology.html#ring)» et « [Plus](morphology.html#plus)», ou même votre propre noyau défini par l'utilisateur. Par exemple...

  magick -size 80x80 xc:black -fill white \
          -draw 'point 20,15 point 55,30 point 40,60'  points_pixels.gif
  magick points_pixels.gif -morphology Dilate Ring    points_rings.gif
  magick points_pixels.gif -morphology Dilate Plus:4  points_pluses.gif
  magick points_pixels.gif -morphology Dilate Cross:3 points_crosses.gif

[IM Output] [IM Output] [IM Output] [IM Output]

Le résultat peut ensuite être converti directement en une superposition colorée à l'aide de l'opérateur Alpha Shape. Le grand avantage de cette méthode est que vous n'avez pas vraiment besoin de connaître la position individuelle de chaque symbole. Ni même combien de symboles il y a. Mais cela peut aussi être un inconvénient. Un inconvénient majeur est que les positions ne se situent qu'à des emplacements entiers. Vous ne pouvez pas « dessiner » avec un positionnement en « sous-pixel » en virgule flottante.

Convolution

Une technique presque identique consiste à utiliser « Convolve», avec des noyaux spécialement conçus, ce qui permet de définir diverses nuances de gris, plutôt qu'un simple résultat marche/arrêt comme ci-dessus. En utilisant un noyau défini par l'utilisateur différent pour chaque canal de l'image (rouge, vert, bleu et alpha), il est même possible de créer un symbole multicolore à partir de chaque coordonnée de pixel. [IM Output] Pour cela, j'utilise un script spécial « [image2kernel](../static/img/scripts/image2kernel)» que j'ai écrit pour convertir une image colorée (voir à droite) en noyaux de convolution en virgule flottante séparés pour chacun des canaux.

  image2kernel -q marker.png marker.dat

Cela génère quatre fichiers, tels que « [marker_R.dat](../static/img/draw/marker_R.dat)», un pour chaque canal de la toute petite image d'entrée, qui sont des représentations définies par l'utilisateur de l'image (avec l'origine centrée dans l'image). Maintenant, à l'aide de ces fichiers de données de noyau, nous pouvons convoluer ces points uniques pour obtenir notre image de marqueur colorée sur un fond transparent.

  magick points_pixels.gif -alpha off \
          \( -clone 0 -morphology Convolve @marker_R.dat \) \
          \( -clone 0 -morphology Convolve @marker_G.dat \) \
          \( -clone 0 -morphology Convolve @marker_B.dat \) \
          \( -clone 0 -morphology Convolve @marker_A.dat \) \
          -delete 0 -channel RGBA -combine point_markers.png

[IM Output] [IM Output]

| Avant IM v6.7.6-9, l'opérateur Combine exige que le canal de transparence de l'image soit fourni sous forme de valeurs d'« opacité » plutôt que de valeurs alpha ; par conséquent, le canal alpha du résultat créé doit être inversé. Par exemple : |

  ... "`cat marker_A.dat`" -negate \) \

Seules de petites images doivent être utilisées, avec des points de pixels suffisamment espacés pour que les symboles ne se chevauchent pas. En effet, Convolve additionnera les zones qui se chevauchent, les rendant plus lumineuses que prévu. Ce qui précède a été converti en un script shell UNIX « [convolve_image](../static/img/scripts/convolve_image)», pour en faciliter l'utilisation.

  convolve_image  points_pixels.gif marker.png   point_markers.png

Cette technique est issue d'une discussion sur les forums IM A Fun Experience with IM. L'utilisateur voulait placer de minuscules personnages sur une image d'arrière-plan d'un terrain de football, de sorte que leurs positions épellent le nom d'une personne sur l'image.

En couches

Une technique différente, telle que les couches d'images, positionnées à l'aide d'une liste de pixels extraits de l'image source, peut être la meilleure approche. Vous pouvez superposer d'abord les images de symboles les plus éloignées, avant les images de premier plan, et vous pouvez choisir de façon programmatique, ou aléatoire, quel symbole remplace quel point. Pour un exemple de ceci, voyez Épingles sur une carte.

Dessiner des cercles

Les options de dessin vous offrent plusieurs façons de faire quelque chose de très simple... Dessiner des cercles. Vous pouvez, par exemple, dessiner un cercle passant par n'importe quel point de sa circonférence. Vous aurez donc besoin de calculer un point central et un second point qui se trouve à une distance du rayon (disons 25 pixels) du premier point. |

  magick -size 100x60 xc:  -stroke Firebrick  -fill tomato  -strokewidth 2 \
          -draw 'circle 50,30 50,55'    circle_circle.gif

[IM Output]
Fred Weinhaus a fait remarquer qu'en utilisant une translation, vous pouvez éviter d'avoir à calculer la coordonnée du bord du cercle, et donner directement le rayon. |

  magick -size 100x60 xc:  -stroke SeaGreen  -fill PaleGreen  -strokewidth 2 \
          -draw 'translate 50,30 circle 0,0 25,0'    circle_circle_trans.gif

[IM Output]
Cependant, pour dessiner plusieurs cercles, ce qui précède nécessitera soit des opérations « [-draw](https://imagemagick.org/command-line-options/#draw)» séparées pour chaque cercle, soit l'utilisation de l'empilement de contexte. En utilisant une ellipse, vous pouvez spécifier directement le rayon comme longueurs d'axes |

  magick -size 100x60 xc:  -stroke Sienna  -fill Wheat  -strokewidth 2 \
          -draw 'ellipse 50,30 25,25 0,360'    circle_ellipse.gif

[IM Output]
Vous pouvez également générer un cercle en dessinant une ligne très, très courte avec « stroke-linecap round». La largeur du trait définit alors le diamètre du cercle. NOTEZ que la ligne doit avoir une certaine longueur (aussi petite soit-elle), sinon le dessin ne dessinera rien. |

  magick -size 100x60 xc:  -stroke Blue  -strokewidth 50 \
          -draw 'stroke-linecap round line 50,30 50,30.0001' \
          circle_line.gif

[IM Output]
Cette technique, malheureusement, ne permet pas de tracer le contour du cercle généré, mais pour couvrir de grandes surfaces, de grandes largeurs de trait peuvent être utiles. Voyez Quelques exemples simples ci-dessous. Cette méthode utilise la méthode de dessin par chemin SVG, de sorte que le cercle puisse être dessiné sans avoir besoin de calculer de coordonnées supplémentaires. |

  magick -size 100x60 xc:  -stroke Blue  -fill DodgerBlue  -strokewidth 2 \
          -draw "path 'M 50,30  m 0,25  a 1,1 0 0,0 0,-50  a 1,1 0 1,0 0,50'" \
          circle_path.gif

[IM Output]
Seul le déplacement absolu initial « M» est nécessaire pour définir le centre ; les « 25» et « 50» présents dans les composants du chemin qui suivent définissent le rayon et le diamètre du cercle par rapport à ce centre. | L'élément de déplacement relatif duchemin SVG « m» est cassé avant IM v6.4.3-5. Si votre IM est plus ancien que cela, le cercle risque de n'apparaître que sous la forme d'un seul pixel. Vous pouvez corriger cela pour les anciennes versions en remplaçant le « m» ci-dessus par un « l».
---|---
Fred Weinhaus a ajouté la méthode de cercle par bézier suivante. Elle est très proche d'un vrai cercle (sans être exacte), et nécessite un calcul en virgule flottante. |

  r=25;  cx=50;  cy=30;
  x1=25;     x2=75;      # = cx ± radius
  y1=-3.25;  y2=63.25;   # = cy ± radius*1.275
  magick -size 100x60 xc:  -stroke Purple  -fill Violet  -strokewidth 2 \
          -draw "bezier $x1,$cy $x1,$y1  $x2,$y1 $x2,$cy" \
          -draw "bezier $x1,$cy $x1,$y2  $x2,$y2 $x2,$cy" \
          circle_bezier.gif

[IM Output]
Si dessiner un cercle exact n'est pas important, vous pouvez utiliser ce chemin SVG à 4 segments de bézier, qui n'utilise que les limites X et Y du cercle pour son calcul. |

  r=25;  cx=50;  cy=30;
  x1=25;    x2=75;      # X bounds = cx ± radius
  y1=5;     y2=55;      # Y bounds = cy ± radius
  magick -size 100x60 xc:  -stroke Tomato  -fill Gold  -strokewidth 2 \
     -draw "path 'M $cx,$y1 Q $x1,$y1 $x1,$cy T $cx,$y2 $x2,$cy $cx,$y1 z'" \
     circle_bezier_path.gif

[IM Output]
Si vous préférez une méthode entièrement relative à un point de départ central, vous pouvez utiliser cette technique. Seule la valeur du rayon est utilisée, ce qui rend sa génération simple, en n'utilisant que des fonctions de chaîne dans une API. |

  magick -size 100x60 xc:  -stroke Orange  -fill LemonChiffon  -strokewidth 2 \
     -draw "path 'M 50,30  m 0,25  q 25,0 25,-25  t -25,-25  -25,25  25,25 z'"\
     circle_bezier_path_rel.gif

[IM Output]
Pouvez-vous imaginer d'autres façons de dessiner des cercles ?

Dessiner des flèches -- positionner, faire pivoter et redimensionner des symboles

À l'aide des techniques ci-dessus, vous pouvez créer des symboles spéciaux tels qu'une pointe de flèche, que vous pouvez positionner de sorte que sa pointe se trouve exactement à l'extrémité d'une ligne, et dessiner par-dessus. Si vous dessinez la flèche après la ligne (situation typique), la flèche sera dessinée par-dessus la ligne. Cependant, il existe trois types de flèches, qui peuvent être définies, et chaque type est défini de manière différente selon l'usage qui en est fait.

  • Mesure, où vous voulez simplement marquer les extrémités d'une ligne avec une pointe de flèche pour indiquer les limites d'une mesure dans un schéma technique. Très simple.
  • Vecteurs, montrant la direction et l'intensité d'une valeur.
    Par exemple dans une carte des vents météorologiques. Une queue est nécessaire, et le point 0,0 est l'extrémité de la queue. On crée souvent une large grille de tels vecteurs.
  • Indicateurs, qui pointent vers un détail.
    Pour cela, le point 0,0 devrait probablement être soit la pointe, soit une certaine distance devant la flèche elle-même.

Flèches de mesure

Ajouter simplement une pointe de flèche à l'extrémité d'une ligne est relativement facile à faire. Vous créez essentiellement un symbole de « pointe de flèche », et le dessinez à la bonne position. Par exemple... |

  arrow_head="l -15,-5  +5,+5  -5,+5  +15,-5 z"

  magick -size 100x60 xc: -draw 'line 10,30 80,30' \
          -draw "stroke blue fill skyblue
                 path 'M 80,30  $arrow_head' " \
          arrow_horizontal.gif

[IM Output]
Notez que j'ai dessiné le symbole de sorte que son point de départ soit exactement l'extrémité de la ligne. Ainsi, il peut être dessiné en arrière par-dessus la ligne précédemment tracée, produisant un symbole très net et bien fini. Cependant, les flèches sont associées à une direction. Vous pourriez créer un très grand nombre de définitions de flèches selon de nombreux angles différents, et beaucoup de programmes procèdent ainsi. Mais puisque la flèche est un vecteur, pourquoi ne pas faire pivoter la flèche en tant que vecteur ? La commande de dessin d'IM intègre des rotations de dessin (déformation du canevas), alors utilisons-les. Cela a aussi l'avantage de sortir la position de la définition « path» de la pointe de flèche, ce qui vous permet de spécifier le chemin entier comme une « constante »... |

  arrow_head="path 'M 0,0  l -15,-5  +5,+5  -5,+5  +15,-5 z'"

  magick -size 100x60 xc: -draw 'line 25,55 70,10' \
          -draw "stroke blue fill skyblue
                 translate 70,10 rotate -45
                 $arrow_head
                " \
          arrow_rotate.gif

[IM Output]
Si vous souhaitez modifier la taille de la flèche, ajoutez une option de dessin « scale » après le rotate. |

  arrow_head="path 'M 0,0  l -15,-5  +5,+5  -5,+5  +15,-5 z'"

  magick -size 100x60 xc: -draw 'line 25,55 70,10' \
          -draw "stroke blue fill skyblue
                 translate 70,10 rotate -45 scale 2,2
                 $arrow_head
                " \
          arrow_scale.gif

[IM Output]
Remarquez comment l'agrandissement laisse la « pointe » de la flèche là où vous l'avez spécifiée. C'est un aspect très important de la gestion des flèches, car seuls le point d'extrémité et l'angle de la ligne à laquelle vous ajoutez la flèche importent. L'ordre des « transformations » est important, et est en réalité l'inverse de l'ordre dans lequel elles sont effectivement exécutées. C'est-à-dire que scale est appliqué aux coordonnées en premier, puis rotate, puis translate. Si les transformations de coordonnées n'étaient pas effectuées dans cet ordre, nous finirions aussi par redimensionner le placement final de la flèche, et elle ne se trouverait pas à l'endroit attendu. De plus, comme scale comporte deux nombres, et que le symbole de pointe de flèche d'origine a été conçu horizontalement (angle zéro), vous pouvez redimensionner séparément la largeur de la flèche par rapport à sa hauteur. Remarquez aussi comment la largeur du trait se redimensionne également avec la taille de la pointe de flèche, gardant ainsi une certaine cohérence. |

  arrow_head="path 'M 0,0  l -15,-5  +5,+5  -5,+5  +15,-5 z'"

  magick -size 100x60 xc: -draw 'line 25,55 70,10' \
          -draw "stroke blue fill skyblue
                 translate 70,10 rotate -45 scale 2,1
                 $arrow_head
                " \
          arrow_scale_aspect.gif

[IM Output]
Maintenant, comme vous déformez le canevas pour dessiner des flèches individuelles, peut-être avec de nombreuses autres opérations de dessin, vous voudrez peut-être toutes les effectuer en une seule opération « [-draw](https://imagemagick.org/command-line-options/#draw)». Par exemple, dessiner la ligne puis ajouter des flèches aux DEUX extrémités, nécessitant des jeux différents de couleurs, de positions, de rotations, et peut-être même d'échelles différentes. Cela signifie que nous devons limiter la portée de la déformation du canevas au dessin de chaque pointe de flèche individuelle. Si vous ne limitez pas cette portée, vous risquez de commencer à affecter d'autres opérations de dessin ultérieures et de ne jamais être vraiment sûr de ce que vous générez. Pour limiter la portée de la déformation (et de tous les autres attributs de dessin), vous enveloppez la section concernée dans un « graphic-context» ... |

  arrow_head="path 'M 0,0  l -15,-5  +5,+5  -5,+5  +15,-5 z'"

  magick -size 100x60 xc: \
          -draw "stroke black fill none
                 path 'M 10,40 A 50,50 0 0,1 90,40'
                 push graphic-context
                   stroke blue fill skyblue
                   translate 10,40 rotate 135
                   $arrow_head
                 pop graphic-context
                 push graphic-context
                   stroke firebrick fill tomato
                   translate 90,40 rotate 45
                   $arrow_head
                 pop graphic-context
                " \
          arrow_context.gif

[IM Output]
Le « push» sauvegarde essentiellement tous les attributs de dessin actuels pour un usage ultérieur, tandis que le « pop» restaure ces attributs en remplaçant les paramètres actuels (couleurs, déformations, positions, etc.) par les paramètres précédemment sauvegardés. Cela signifie qu'après le « pop », la « déformation du canevas » est annulée, et le dessin revient à l'état dans lequel il se trouvait avant les modifications. La technique ci-dessus n'est qu'une des façons de générer des flèches, une bonne façon de faire lorsqu'on dessine des flèches dans le cadre de la mesure de distances, comme dans les dessins techniques.

Flèches vectorielles

Les vecteurs, comme mentionné, montrent à la fois la direction et l'intensité d'une valeur. Cela signifie que la longueur de la flèche est variable, et que la pointe de flèche pourrait se trouver à peu près n'importe quelle position, plus ou moins éloignée du point de départ du vecteur. Or, vous pourriez faire de lourds calculs pour déterminer la position à laquelle la pointe de flèche devrait être placée en fonction de la longueur et de l'angle du vecteur, mais il existe une bien meilleure façon de faire, qui laisse ImageMagick effectuer ces calculs pour vous. La solution consiste à dessiner la longueur du vecteur sous forme d'une ligne horizontale de la bonne longueur dans l'espace de canevas déformé. Une fois cette ligne dessinée, il suffit de translater à nouveau l'espace de dessin jusqu'à l'extrémité de la ligne, tandis que le canevas reste « déformé ». Vous êtes alors correctement positionné, avec la bonne rotation, pour dessiner la « pointe de flèche » du vecteur normalement. Par exemple, voici comment je génère un vecteur de 70 pixels de long à un angle de -35 degrés. |

  vector_head="path 'M 0,0  l -15,-5  +5,+5  -5,+5  +15,-5 z'"
  indicator="path 'M 10,0  l +15,+5  -5,-5  +5,-5  -15,+5  m +10,0 +20,0 '"

  magick -size 100x100 xc: \
          -draw "stroke black fill none  circle 20,50 23,50
                 push graphic-context
                   stroke blue fill skyblue
                   translate 20,50 rotate -35
                   line 0,0  70,0
                   translate 70,0
                   $vector_head
                 pop graphic-context
                 push graphic-context
                   stroke firebrick fill tomato
                   translate 20,50 rotate 40
                   $indicator
                   translate 40,0 rotate -40
                   stroke none fill firebrick
                   text 3,6 'Center'
                 pop graphic-context
                " \
          arrow_with_tails.gif

[IM Output]

Flèches indicatrices

Dans l'exemple ci-dessus, j'ai également montré une flèche indicatrice pointant vers le point de départ de la flèche vectorielle précédente. Cependant, au lieu de dessiner la flèche comme je l'ai fait précédemment, je l'ai créée comme un symbole de flèche inversé, commençant à 10 pixels de l'origine (ou point de départ). C'est-à-dire qu'un symbole est situé à la position que je veux indiquer, donc je ne veux pas réellement que la flèche se trouve directement sur cette position, mais un peu à l'écart de celle-ci. Or, si les indicateurs sont plus simples à gérer que les vecteurs, ne nécessitant généralement pas de longueur variable, vous voulez généralement ajouter du texte à l'extrémité éloignée de l'indicateur pour préciser ce qui est indiqué. Comme précédemment, il peut être difficile de calculer cette position, alors pourquoi s'en préoccuper. La solution pour positionner le texte est également la même que pour les vecteurs. Conservez l'espace déformé d'origine utilisé pour dessiner la flèche indicatrice, et translatez l'origine jusqu'à l'extrémité de queue de cette flèche (40 pixels horizontalement dans l'espace déformé). Maintenant que les éléments ont été repositionnés, nous pouvons annuler la rotation de la déformation autour de cette nouvelle position, de sorte que vous puissiez dessiner le texte normalement (avec un léger décalage). Malheureusement, si la justification de texte par défaut « left » fonctionne dans l'exemple ci-dessus, vous ne pouvez actuellement pas spécifier une justification de texte dans MVG, en tant que paramètre distinct de gravity. Si cela pose problème, déposez une demande sur le forum des bugs d'IM, et avec un peu de chance, la justification de texte (distincte du positionnement par gravity) deviendra une réalité, d'autant plus qu'elle fait bel et bien partie de la spécification SVG.


Dessiner des objets

Larges traits de couleur

Il n'est pas nécessaire d'enfermer complètement une zone de remplissage avec un chemin ou un contour pour créer diverses formes. En utilisant des traits très grands et larges, vous pouvez générer de grandes zones et échantillons de couleur sur un canevas. Par exemple, un large trait d'arc elliptique peut générer une belle zone de couleur, que j'ai effectivement vu utilisée dans la création d'une affiche. |

  magick -size 100x100 xc: -fill none -stroke powderblue \
          -draw 'stroke-width 70 ellipse -30,0 90,90 10,50' \
          -rotate 180  arc_background.gif

[IM Output]
Ou vous pouvez générer le sourire assez complexe d'un clown. |

  magick -size 100x100 xc: \
          -draw 'fill none stroke-linecap round
             stroke-width 40 stroke tomato ellipse 50,0 70,70 65,115
             stroke-width 2  stroke black  ellipse 50,0 70,70 60,120
             stroke-width 40 stroke palegreen line 50,40 50,40.01' clown.gif

[IM Output]
Qu'arrivez-vous à imaginer ? Faites-le nous savoir.

Cylindres

Dans une discussion du forum IM, il y a eu une discussion animée sur le dessin de cylindres, et plus particulièrement de cylindres ombrés, à l'aide des commandes de dessin d'ImageMagick. L'astuce pour dessiner des cylindres consiste à dessiner des primitives « roundrectangle» de manière à ce que les extrémités forment des ovales. Autrement dit, si le cylindre fait par exemple 50 pixels de large, vous arrondissez les coins du rectangle de 25 et 12 pixels respectivement. C'est-à-dire, la moitié de la largeur du rectangle, puis encore la moitié. Un cylindre devient ainsi simplement deux rectangles arrondis dessinés l'un par-dessus l'autre. Le second « ovale d'extrémité », rempli d'une couleur plus claire, est dimensionné pour être exactement le double des deux dimensions de coin. Par exemple... |

  magick -size 60x100 xc:white -stroke snow4 \
          -fill chartreuse3    -draw 'roundrectangle 5,5 55,95 25,12' \
          -fill chartreuse2    -draw 'roundrectangle 5,5 55,29 25,12' \
          cylinder.gif

[IM Output]
En remplaçant la première couleur de remplissage par une nuance de dégradé (en utilisant une technique de mosaïque en mémoire), vous pouvez donner au cylindre un aspect un peu plus 3D... |

  magick -size 60x100 xc:white -stroke snow4 \
          \( -size 1x60 gradient:chartreuse1-chartreuse4 -rotate -90 \
             -write mpr:shading +delete \) \
          -tile mpr:shading  -draw 'roundrectangle 5,5 55,95 25,12' +tile \
          -fill chartreuse2  -draw 'roundrectangle 5,5 55,29 25,12' \
          cylinder_shade.gif

[IM Output]
En affinant progressivement le dessin du cylindre (comme cela a été discuté dans le forum IM), on peut aller très loin dans la génération de cylindres très complexes et visuellement séduisants. Cela incluait l'ajout de cylindres de verre semi-transparents englobants, d'effets d'ombre et d'étiquetage. Le résultat final de cette discussion est un script « [cylinder_bar](../static/img/scripts/cylinder_bar)», générant une barre de pourcentage cylindrique...

  cylinder_bar 95 cylinder_95.png

[IM Output]

Le script peut générer une image de n'importe quelle taille, ajustant tous les paramètres de façon appropriée en fonction de cette taille et d'autres réglages définis en tête du script. Il inclut également le concept d'une « épaisseur de verre », pour créer un espace entre un cylindre de verre semi-transparent englobant et le cylindre coloré à l'intérieur. Remarquez les nuances très subtiles du cylindre, en particulier lorsque l'extrémité du cylindre vert chevauche l'extrémité du cylindre de verre ! Il est étonnant de voir ce que l'on peut réaliser avec un peu de réflexion préalable.


Dessiner des caractères spéciaux dans la chaîne de texte

Guillemets ou barre oblique inverse ?

L'un des plus grands problèmes que rencontrent les utilisateurs avec -draw est le dessin de caractères qui ont également une signification particulière pour les shells UNIX et la ligne de commande DOS, ou même d'autres langages comme C, Perl, PHP, R ou Visual Basic. Le principal coupable à cet égard est les deux types de caractères de guillemets, ainsi que les caractères de substitution de variable comme le dollar « $» et le caractère d'échappement du shell et d'ImageMagick, la barre oblique inverse « \». Fondamentalement, comme l'argument MVG de « [-draw](https://imagemagick.org/command-line-options/#draw)» doit être mis entre guillemets, et que l'argument de chaîne « text» qu'il contient peut également nécessiter des guillemets supplémentaires. Pour résoudre cela, les utilisateurs utilisent généralement deux types de guillemets différents, un pour le shell et un autre pour la chaîne de texte MVG.

`**-draw '... text 0,0 "string" ...'**`

Notez que c'est la seule option réellement viable pour les utilisateurs de Windows, qui a ses propres problèmes et méthodes de mise entre guillemets. Autrement, ils pourraient échanger les guillemets, et utiliser...

**-draw "... text 0,0 'string' ..."**

Ce qui vous permet d'inclure des substitutions de variables shell (en utilisant « $» sans l'échapper). Le choix de la bonne forme résoudra la plupart des problèmes, mais certains caractères posent encore des difficultés, et chaque solution dépend exactement de l'ensemble de guillemets que vous utilisez, car ils définissent aussi comment les caractères spéciaux doivent être échappés. Voici les quatre cas de mise entre guillemets et de gestion des caractères spéciaux...

  • Utiliser des guillemets simples pour l'argument shell,
    avec des guillemets doubles autour de la chaîne de texte MVG. La technique la plus simple pour gérer les chaînes de texte dessinées consiste à utiliser un guillemet simple pour l'argument shell englobant. Cela signifie cependant que pour inclure une apostrophe dans la chaîne dessinée, vous devez sortir du « mode guillemet simple » du shell et fournir cette apostrophe en dehors des guillemets simples du shell. Par exemple, voici comment gérer les quatre caractères spéciaux dont j'ai parlé. |
    magick -size 250x50 xc:none  -box white  -pointsize 20 -gravity center \
              -draw 'text 0,0 "  '\''  \"  $  \\  " ' \
              -trim +repage  text_special_sd.gif
    

[IM Output]
Notez que, puisque le signe dollar n'a pas besoin d'être échappé, vous ne pouvez pas non plus l'utiliser pour substituer le contenu d'une variable shell. Il est important de se rappeler que la barre oblique inverse est le seul caractère spécial géré par la chaîne de dessin d'IM. De plus, sa raison d'être est purement de vous permettre d'échapper les « guillemets de la chaîne de dessin IM », comme nous l'avons utilisé ci-dessus pour les guillemets doubles. Au-delà de cela, toute l'autre étrangeté est causée par le shell de ligne de commande UNIX, et non par IM. PC-DOS a ses propres bizarreries, et j'apprécierais des retours sur l'échappement des caractères spéciaux lors de l'utilisation d'IM depuis cet environnement. * Utiliser des guillemets doubles pour l'argument shell,
avec des guillemets simples autour de la chaîne de texte MVG. Si vous voulez insérer une « variable shell » dans la chaîne dessinée, vous devrez alors utiliser des guillemets doubles pour l'argument shell extérieur. Cela rend l'ensemble beaucoup plus complexe, car vous perdez la protection du shell et devez maintenant échapper non seulement les signes dollar « $», mais aussi les barres obliques inverses « \». En revanche, le shell n'aura alors pas besoin d'utiliser les caractères de guillemet simple comme délimiteur de fin d'argument, ce qui simplifie cet aspect. Résumons les résultats pour notre courte liste de caractères spéciaux. |

    magick -size 250x50 xc:none  -box white  -pointsize 20 -gravity center \
              -draw "text 0,0 '  \\'  \"  \$  \\\\  ' " \
              -trim +repage  text_special_ds.gif

[IM Output]
Remarquez que si vous voulez dessiner une barre oblique inverse elle-même, la chaîne de texte MVG a besoin que la barre oblique inverse soit doublée (comme dans l'exemple précédent), mais le shell lui-même a également besoin que chacune de ces barres obliques inverses soit doublée, produisant un total de quatre barres obliques inverses juste pour produire un tel caractère. Ce doublement peut très vite devenir écrasant et déroutant, nécessitant de nombreuses barres obliques inverses pour parvenir à ce que vous voulez. Prenez simplement votre temps et allez-y doucement, et vous finirez par comprendre pour votre situation. * Utiliser des guillemets simples pour l'argument shell,
avec des guillemets simples autour de la chaîne de texte MVG. Terminons cela par un résumé des deux dernières combinaisons de guillemets. Je vous laisse le soin de comprendre comment elles sont décodées par le shell et MVG. |

    magick -size 250x50 xc:none  -box white  -pointsize 20 -gravity center \
              -draw 'text 0,0 '\''  \'\''  "  $  \\  '\'' ' \
              -trim +repage  text_special_ss.gif

[IM Output]
* Utiliser des guillemets doubles pour l'argument shell,
avec des guillemets doubles autour de la chaîne de texte MVG. |

    magick -size 250x50 xc:none  -box white  -pointsize 20 -gravity center \
              -draw "text 0,0 \"  '  \\\"  \$  \\\\  \"" \
              -trim +repage  text_special_dd.gif

[IM Output]

Comme vous pouvez le voir, les arguments « [-draw](https://imagemagick.org/command-line-options/#draw)» depuis la ligne de commande doivent gérer à la fois le shell de ligne de commande et l'échappement des barres obliques inverses et des guillemets au sein de la chaîne de texte MVG. Les résultats peuvent être déroutants et délicats. Rappelez-vous simplement que le shell traite les deux types de guillemets différemment, tandis que la chaîne de texte MVG ne le fait pas. Bien sûr, dans des scripts complexes, la meilleure façon peut être d'éviter entièrement le shell et tout problème de script. Vous pouvez le faire en lisant les arguments « [-draw](https://imagemagick.org/command-line-options/#draw)» depuis un fichier de dessin MVG.

`**-draw @drawfile.mvg**`

Bien sûr, vous devrez toujours échapper avec une barre oblique inverse le caractère de guillemet que vous utilisez, ainsi que toute barre oblique inverse présente dans le texte. Cependant, c'est beaucoup plus simple que d'essayer de gérer le propre système de guillemets et d'échappement du shell en même temps que celui d'IM. |

  magick -size 500x50 xc:lightblue  -font Candice -pointsize 36 \
          -gravity center     -draw @text_quotes.mvg      text_quotes.gif

[IM Output]
[IM Output]
La première image provient de l'un des fichiers texte « MVG» que j'ai utilisés. Il ne contient aucun échappement ni guillemet du shell. Ainsi, seuls les guillemets et échappements MVG sont présents. Notez que dans l'exemple ci-dessus, si j'avais utilisé des guillemets simples pour la chaîne de texte MVG, le seul changement aurait été de devoir échapper avec une barre oblique inverse les caractères de guillemet simple plutôt que les guillemets doubles dans la chaîne. À propos des caractères pourcentage Juste un dernier point à propos des caractères d'« échappement » spéciaux dans l'opérateur « -draw text ». Les caractères pourcentage « %» doivent être dessinés « tels quels ». Vous ne devriez avoir besoin de rien faire de spécial pour les dessiner. S'ils ne se dessinent pas « tels quels », alors vous avez une ancienne version d'IM et devriez la mettre à jour au plus vite. | Jusqu'à la version 6.2.4 d'IM, le caractère « %» était utilisé comme caractère d'échappement pour inclure des informations d'image supplémentaires dans la chaîne de texte dessinée. Ce n'est plus le cas, car de tels échappements créaient de la confusion et étaient incorrects lorsque des images SVG tentaient également de dessiner des caractères pourcentage.
---|---
Cette utilisation des « échappements » pourcentage (ainsi que des échappements de saut de ligne « \n») a été jugée incompatible avec l'opérateur « [-draw](https://imagemagick.org/command-line-options/#draw)» et l'usage prévu du format MVG pour gérer les formats d'image SVG. Ainsi, à partir de la version 6.2.4 d'IM, les échappements % ne fonctionnent plus, et les barres obliques inverses n'échappent qu'elles-mêmes et les guillemets environnants. |

    magick -size 250x50 xc:none -box white  -pointsize 20 -gravity center \
            -draw 'text 0,0 "%w\n%h"'    -trim +repage text_escapes.gif

[IM Output]
Pour plus de détails sur le « bug du pourcentage », et les façons de l'éviter lors de l'utilisation de « [-draw](https://imagemagick.org/command-line-options/#draw)» dans les anciennes versions d'ImageMagick, voyez la page Dessiner un bug de pourcentage. Annotate plutôt que Draw La meilleure façon d'éviter ce type de problème est d'utiliser « -annotate» plutôt que draw pour le dessin de texte. Cet opérateur est une enveloppe autour de l'opérateur draw et permet d'utiliser toutes les capacités de draw, mais sous une forme plus simple. Fondamentalement, cet opérateur n'a besoin que d'un seul jeu de guillemets (pour le shell). Cela rend la gestion des caractères spéciaux beaucoup, beaucoup plus simple. Malheureusement, si vous n'avez plus besoin d'échapper les guillemets pour IM, vous avez maintenant les échappements pourcentage, tels que les lectures de fichier « @», les sauts de ligne « \n», et d'autres expansions d'échappement pourcentage. Par exemple, en utilisant des guillemets simples... |

    magick -size 200x50 xc:none  -box white  -pointsize 20 -gravity center \
            -annotate 0 '\@  '\''  "  $  \\  %% ' \
            -trim +repage  annotate_s.gif

[IM Output]
et pour les guillemets doubles... |

    magick -size 200x50 xc:none -box white -pointsize 20 -gravity center \
            -annotate 0 "\@  '  \"  \$  \\\\  %% " \
            -trim +repage  annotate_d.gif

[IM Output]
Cependant, tous les guillemets et échappements d'annotate sont complètement ignorés si vous utilisez l'échappement « @» pour lire la chaîne depuis un fichier. Par exemple, voici comment inclure des informations sur la largeur et la hauteur d'une image ! |

    magick -size 200x50 xc:none -box white -pointsize 20 -gravity center \
            -annotate 0 '%w\n%h' -trim +repage    annotate_percents.gif

[IM Output]
Cependant, tous les échappements sont complètement ignorés lors de la lecture d'une chaîne d'annotation depuis un fichier. |

    echo -n '@ %w\n%h' |\
      magick -size 200x50 xc:none -box white -pointsize 20 -gravity center \
              -annotate 0 '@-'  -trim +repage  annotate_file.gif

[IM Output]
Pour plus d'informations, voyez l'opérateur de dessin de texte Annotate, et en particulier les caractères d'échappement Annotate.


Gestion d'IM et de SVG

Pilotes d'entrée SVG : RSVG contre MSVG

La gestion du format d'image SVG proprement dit est une affaire très complexe. Le moteur doit gérer tous ses aspects, tels que définis dans le document SVG -- Scalable Vector Graphics. Cela nécessite beaucoup d'efforts de programmation et de temps. C'est pourquoi ImageMagick propose deux méthodes pour la gestion des images au format SVG. La première consiste à utiliser une bibliothèque RSVG open source, pour convertir le format SVG en une image matricielle qu'IM n'a aucun problème à gérer. Ce moteur est complet sur à peu près tous les aspects de la gestion du SVG. La seconde méthode consiste, pour IM, à tenter de convertir le SVG en MVG, à l'aide d'une méthode intégrée appelée MSVG. MSVG tente de convertir une image SVG dans le langage de dessin « MVG » de l'opérateur « -draw» d'IM. Une grande partie des fonctionnalités du draw MVG a été créée spécifiquement à cette fin. Malheureusement, si le dessin de lignes de base et la coloration sont présents, on est loin d'un convertisseur SVG complet. Vous pouvez forcer l'utilisation du convertisseur MSVG interne en lisant l'image SVG à l'aide du format d'entrée spécial « MSVG:» (ajouté dans IM v6.3.4). Mais si la bibliothèque RSVG est présente, la plupart des ImageMagick l'utiliseront à la place pour rendre les images SVG. Pour savoir ce que votre IM fera, utilisez...

  magick -list format | grep SVG

[IM Text]

Comme vous pouvez le voir avec « RSVG» entre parenthèses, mon propre IM utilisera la bibliothèque RSVG, avec la version indiquée, présente sur mon ordinateur. Voici comment je « dessine » une petite image SVG faite à la main, « diagonal.svg» (fournie par l'utilisateur du forum penciledin), qui crée un rectangle avec un simple dégradé diagonal, sur un fond blanc. |

  magick diagonal.svg  diagonal_rsvg.gif

[IM Output]
Parfait. Un dégradé diagonal correct est produit. Cependant, si vous rendez cette image en utilisant le MSVG interne (la valeur par défaut si la bibliothèque RSVG n'est pas présente)... |

  magick msvg:diagonal.svg  diagonal_msvg.gif

[IM Output]
Comme vous pouvez le voir, la conversion MSVG interne échoue, produisant un dégradé vertical plutôt que diagonal. Vous pouvez aussi voir les commandes MVG réelles qu'IM génère en convertissant directement un SVG en fichier MVG.

[IM Text]

  magick msvg:diagonal.svg mvg:diagonal.mvg

[IM Text]

Vous pouvez probablement voir comment le convertisseur MSVG a tenté de convertir le SVG en commandes de dessin MVG. Voici les points sur lesquels on sait que le MSVG interne actuel échoue...

  • Dégradés non verticaux (pas de conversion vers la nouvelle gestion des dégradés MVG)
  • Texte le long d'un chemin courbe
  • Justification du texte (distincte de gravity)

Cependant, la plupart des actions de dessin de base sont gérées. Rappelez-vous également que le langage MVG peut en fait gérer des choses que le SVG ne peut pas, y compris l'utilisation de gravity pour positionner les images et le texte. Gravity ne fait pas partie de la spécification SVG, bien qu'elle soit un élément essentiel de la gestion du texte et des polices d'IM. Rappelez-vous également que MVG n'a pas le même mécanisme de conteneur que SVG. Le convertisseur MSVG interne remplace les conteneurs XML par l'empilement et le dépilement de contextes graphiques (voir la sortie MVG ci-dessus), ce qui produit le même effet.

Réglages SVG

Le format d'image SVG est un format vectoriel (voir Un mot sur les formats d'image vectoriels), et à ce titre, l'image n'a normalement pas de « taille » par défaut. Elle est plutôt « dessinée » ou « rendue » à une « [-density](https://imagemagick.org/command-line-options/#density)» particulière, tout comme postscript (la densité par défaut est 72 dpi). De même, si le SVG ne « peint » pas l'arrière-plan, vous pouvez spécifier la couleur d'arrière-plan à utiliser à l'aide du réglage « [-background](https://imagemagick.org/command-line-options/#background)». Par exemple, voici une autre petite image SVG « [home.svg](../static/img/images/home.svg)», qui a été « rendue » avec 3 densités différentes, avec 3 arrière-plans différents, y compris un arrière-plan transparent.

  magick -density 36                      home.svg  home_1.gif
  magick             -background skyblue home.svg  home_2.gif
  magick -density 144 -background none    home.svg  home_3.png

[IM Output] [IM Output] [IM Output]

Notez que j'ai utilisé une image au format PNG pour la version à arrière-plan transparent, plus grande, de l'exemple ci-dessus. Cela produit une image plus nette que ne le ferait un format d'image GIF, en raison des pixels de bord semi-transparents. Le PNG est toujours recommandé lorsque la transparence intervient dans l'image finale. | _J'ai constaté que certaines images SVG ne se redimensionnent pas. C'est-à-dire qu'elles ont été définies en termes de « pixels », plutôt qu'en longueurs réelles telles que « points », « pouces » ou « millimètres ». Par conséquent, bien que le réglage « [-density](https://imagemagick.org/command-line-options/#density)» puisse modifier la taille globale de l'image (en unités réelles), la taille des « pixels » ne change pas, et l'image elle-même ne change donc pas de taille. De telles images SVG sont cependant assez rares.

Pire encore, quelques images SVG utilisent un mélange de mesures en « pixels » et en « points », et à moins que l'auteur ne l'ait fait exprès, vous pourriez obtenir un vrai désordre en essayant de l'utiliser à une densité différente de celle prévue par l'auteur. Celles-ci sont heureusement encore plus rares.

Une correction simple consiste généralement à changer toutes les unités « pixels » du SVG en « points », mais cela ne devrait pas être fait à l'aveugle, au cas où l'usage des « pixels » aurait été délibéré._
---|---

Gestion de la sortie SVG

Depuis IM v6.4.2, IM peut convertir n'importe quelle image bitmap en un graphique vectoriel SVG ! La conversion ne réussit pas toujours, mais les images plus grandes et/ou plus simples (comme un masque bitmap) se convertiront très bien. Par exemple, voici comment je convertis une forme bitmap affreuse en une image SVG, puis la convertis à nouveau en sens inverse, de façon à lisser le bitmap en une forme correctement anticrénelée.

  magick -pointsize 72 -font Candice label:A -threshold 50% \
          -trim +repage -bordercolor white -border 5x5 A.gif
  magick A.gif  A.svg
  magick A.svg  A.png

[IM Output] | | | [IM Text]

| [IM Output]

Pour que cela fonctionne, cependant, la bibliothèque de « développement » « [AutoTrace](http://autotrace.sourceforge.net/)» doit être installée, et IM configuré avec l'option « --with-autotrace». Si la bibliothèque « [AutoTrace](http://autotrace.sourceforge.net/)» n'est pas installée et compilée dans IM, alors la sortie SVG générée sera un très grand nombre de cercles d'un seul pixel, produisant un résultat binaire, plutôt qu'une image à contour SVG lisse. De telles images sont énormes en comparaison, et prennent souvent très longtemps à être rendues par un moteur de rendu SVG. Une meilleure technique par défaut de conversion de matriciel en vectoriel est en réalité nécessaire, probablement en utilisant des techniques de squelettisation morphologique et de MAT. Il existait un délégué d'entrée « autotrace:» délégué d'entrée, pour « lisser les images bitmap en entrée », qui effectuait toutes les étapes ci-dessus en une seule fois en utilisant directement la commande « autotrace». Cependant, la dernière fois que j'ai vérifié, ce délégué avait disparu. Voici comment on l'utilisait... |

  magick autotrace:A.gif  A_traced.png

[IM Output]
Bien sûr, cela ne vous donnera PAS la sortie SVG de la commande « autotrace», mais filtrera simplement l'image d'entrée à travers SVG pour la lisser. Comme alternative, vous pouvez en fait utiliser directement la commande « autotrace », comme le montrent les exemples Contours matriciel vers vectoriel et Squelettisation avec Autotrace. Vous voudrez peut-être aussi regarder les résultats de cancerberosgx, dans Génération d'images SVG, qui s'est penché sur des solutions pour la conversion de photos.


Éditeurs de graphiques vectoriels autres qu'IM

ImageMagick est un processeur de tableaux de pixels ; il n'enregistrera généralement pas d'images vectorielles (« MVG » étant la seule exception à cela), il ne fait que les lire et les convertir en tableaux de pixels. Il en va de même pour les autres éditeurs d'images en pixels, tels que Gimp, Photoshop, etc. Pour éditer et manipuler des images vectorielles, utilisez des programmes tels que Sodipodi Éditeur de graphiques vectoriels basé sur SVG
Xfig Éditeur d'objets vectoriels simple, mais très bon
(Excellent pour les panneaux, les cartes et l'agencement de photos sur une page)
Dia
AutoTrace Convertit une forme dans un tableau bitmap en contours vectoriels
Sketch Éditeur vectoriel basé sur Python, avec texte courbé.
Ce n'est bien sûr pas une liste complète. Même de nombreux traitements de texte, tels qu'OpenOffice, Word et TeX, disposent généralement d'éditeurs d'objets simples, bien que souvent difficiles à utiliser, de diverses sortes. Cependant, pour convertir de façon générale un format graphique vectoriel vers un autre format vectoriel, n'utilisez pas ImageMagick. ImageMagick est, et sera toujours, essentiellement un convertisseur et un manipulateur d'images matricielles ou de graphiques bitmap. Pour plus d'informations, voyez Un mot sur les formats d'image vectoriels.