17 février 2020

Librairie graphique GD

GD est une librairie graphique écrite en C qui permet de créer ou ouvrir des images (jpg, png, gif, etc.) et de tracer dedans des formes géométriques (ligne, rectangle, cercle, etc.). Elle permet aussi quelques manipulations élémentaires. Le langage est C.

Premiers pas

Premier exemple

Code provenant du site officiel, dont le résultat est l'image ci-contre.

/*
gd-ex1.c
gcc gd-ex1.c -o gd-ex1 -lgd
*/
#include "gd.h"
#include <stdio.h>
 
int main() {
   gdImagePtr im; // déclare l'image
   FILE *jpegout; // déclare le fichier de sortie
   int black; // index des couleurs
   int white;
   // Alloue une image 128×128 pixels
   im = gdImageCreate(128, 128);
   // Allocation des couleurs RGB
   black = gdImageColorAllocate(im, 0, 0, 0); // fond
   white = gdImageColorAllocate(im, 255, 255, 255); // couleur de tracé
   // Dessine une ligne entre le coin supérieur gauche et le coin opposé
   gdImageLine(im, 0, 0, 127, 127, white);
   // ouvre le fichier en écriture
   jpegout = fopen("gd-ex1.jpg", "w");
   // écrit l'image sur le disque avec les réglages par défaut -1
   gdImageJpeg(im, jpegout, -1);
   // ferme le fichier et libère la mémoire de l'image
   fclose(jpegout);
   gdImageDestroy(im);
}

C'est remarquablement simple et efficace.

Remarque : Il se compile en C++ normalement

Source : l'exemple du site officiel

Deuxième exemple

Il est inspiré du Linux journal et permet de travailler sur une image existante. Dans cet exemple nous rajouterons une barre au pingouin en utilisant ligne et rectangle.

/* gd-eg2.c */
fonction#include <gd.h>
#include <stdio.h>
 
int main() 
{
   gdImagePtr tux;
   FILE *out, *in;
   int black, grey, white;
 
   in = fopen("tuxin.jpg","r");
   tux = gdImageCreateFromJpeg(in);
   fclose(in);
   // couleurs
   black = gdImageColorAllocate(tux, 0, 0, 9); 
   grey = gdImageColorAllocate(tux, 160, 160, 200); 
   white = gdImageColorAllocate(tux, 200, 200, 200); 
   // ligne et rectangles
   gdImageLine(tux, 12, 50, 88, 50, white);
   gdImageFilledRectangle(tux, 11, 51, 89, 52, grey);
   gdImageFilledRectangle(tux, 11, 53, 89, 60, black);
 
   out = fopen("tuxout.jpg", "w");
   gdImageJpeg(tux, out, -1); 
   fclose(out); 
 
   gdImageDestroy(tux);
}

Il y avait des erreurs dans l'article du Linux Journal que je n'ai pas su élucider.

Programme de tracé du graphe d'une courbe

J'ai fait des tas de programmes pour tracer le graphe d'une courbe. En général c'est pour illustrer les articles de ce site. Mais celui qui me plait le plus c'est celui présenté ci-dessous. Il me plait parce que je dessine directement dans l'image en création. Plus j'utilise GD, plus je le trouve génial. Il y a tout ce qu'il faut, et tout y est extêmement simple.

Code source de gd-plot.c

 1 /* gd-plot.c
 2 :w | !gcc \% -o \%< -lgd && ./\%< && display gd-plot.jpg
 3 */
 4 #include <stdio.h>
 5 #include <stdlib.h>
 6 #include <string.h>
 7 #include <gd.h>
 8 
 9 #define round(x) ((x)>=0?(long)((x)+0.5):(long)((x)-0.5))
10 
11 gdImagePtr im; // image pointer
12 FILE *jpeg;
13 int bg, fg; // background and foreground colors
14 const int pad = 8; // padding
15 float xO = 1.5, yO = 1.5; // origin
16 int sx = 25, sy = 25; // scales
17 int W = 100 + 2*pad, H = 125 + 2*pad; // image width, height
18 
19 float _x = 0, _y = 0; // last position
20 // x, y to screen X, Y coordinates
21 int X(float x) {return round(x*sx + xO*sx) + pad; }
22 int Y(float y) {return H - round(y*sy + yO*sy) -pad;}
23 // convenience drawings
24 void line(float, float, float, float);
25 void lineto(float x, float y) {line(_x, _y, x, y);}
26 void str(char *, float, float);
27 void axis();
28 
29 void plot(float, float); // plotting
30 float f(float x) {return x*x - 1;} // example function to plot
31 
32 int main(int argc, char *argv[])
33 {
34    im = gdImageCreate(W, H);
35    bg = gdImageColorAllocate(im, 255, 255, 255);
36    fg = gdImageColorAllocate(im, 0, 0, 0);
37    axis();
38 
39    plot(-1, 2);
40    str("x ∈ [-1, 2]  ↦  x² - 1", 5, 10);
41    jpeg = fopen("gd-plot.jpg", "w");
42    gdImageJpeg(im, jpeg, -1);
43    fclose(jpeg);
44    gdImageDestroy(im);
45 }
46 
47 void line(float x1, float y1, float x2, float y2) {
48    gdImageLine(im, X(x1), Y(y1), X(x2), Y(y2), fg);
49    _x = x2; _y = y2;
50 }
51 
52 void str(char *s, float x, float y)
53 {
54    int brect[8];
55    char *font= "/usr/share/fonts/TTF/DejaVuSans.ttf";
56    gdImageStringFT(im, brect, fg, font, 8, 0, x, y, s);
57 }
58 
59 void axis()
60 {
61    float d = 0.05; // units 
62    line(-xO, 0, (W - 2*pad)/sx -xO, 0);
63    line(1, d, 1, -d);
64    line(0, -yO, 0, (H - 2*pad)/sy- yO);
65    line(-d, 1, d, 1);
66    str("O", X(-0.4), Y(-0.4));
67    str("1", X(1.02), Y(-0.4));
68    str("1", X(-0.4), Y(1.02));
69 }
70 
71 void plot(float a, float b)
72 {
73    gdImageSetThickness(im, 2); // thickness
74    float xi = 0.05; // step
75    line(a, f(a), a + xi, f(a + xi)); // starting line
76    for(float x=a+2*xi; x<b; x+=xi) lineto(x, f(x));
77    gdImageSetThickness(im, 1); // reset thickness
78 }

Résultat ci-contre :

Commentaires

Ligne 34 : Création d'une image

C'est la fonction gdImageCreate qui alloue le pointeur im et crée l'image avec la couleur de fond fg qui est la première couleur allouée dans le programme. ligne 35.

Voir gdImageCreate et couleur de fond dans les commentaires du code donné en exemple : /* Allocate the color ....

Ligne 42 : Enregistrement de l'image

gdImageJpeg enregistre l'image pointée par im au format JPEG. Voir gdImageJpeg et Image formats dans la side bar du site.

D'autres formats sont possibles.

Ligne 47 : Fonction line

On utilise la fonction gdImageLine.

La fonction gdImageThickness permet de définir l'épaisseur du trait. Par exemple après l'appel de gdImageThickness(im, 3) tous les tracés dans l'image pointée par im auront une épaisseur de 3 pixels. Pour changer cette propriété il faut l'appeler à nouveau.

La fonction lineto (Ligne 25) est une commodité qui permet d'enchaîner les tracés en fournissant les coordonnées du point suivant.

Voir gdImageLine et la rubrique other de gd.c, Summary.

Ligne 52 : Fonction str

C'est une fonction de tracé de texte. On y utilise la fonction gdImageStringFT. Voir les fonctions de la rubrique FreeType font rendering.

Ligne 71 : Fonction plot

On fixe l'épaisseur du trait à 3, on trace la courbe, puis on remet l'épaisseur du trait à 1. Sait-on jamais.

Remarque : La ligne 2 fera l'objet d'un article Vim.

Conclusion

Cette bibliothèque est géniale. Elle fourmille de potentialités. Je regrette de ne l'avoir pas découverte plus tôt. Par exemple pour faire une image d'illustration, une courbe ou une représentation graphique, elle constitue l'outil idéal. Car pour nous qui programmons, nous n'avons pas besoin d'usine à gaz qui s'adapte à tout sauf à ce qu'on a prévu de faire.


Réalisé avec Qlam - LGPL