6.Le langage PHP

6.13.Utilisation de la librairie graphique

6.13.1.Introduction

Même si PHP est principalement utilisé pour générer des pages HTML, il ne faut pas oublier qu'il s'agit d'un langage (presque) comme un autre, et qu'il fait donc simplement ce qu'on lui dit de faire. Il est ainsi possible de créer des images dynamiquement grâce à la célèbre librairie GD (qui doit être installée sur le serveur).
Créer des images dynamiquement? bah... pour quoi faire? Il y a de nombreuses (bonnes ou mauvaises) raisons de créer des images dynamiquement. Cela peut en effet permettre de créer des graphiques à partir de données stockées dans une base de données, de créer une image personnalisée pour chaque visiteur (incluant par exemple son nom) ou encore de réduire la taille d'une image que l'un de vos membres vient de vous envoyer via un formulaire.
Dans notre cas, nous dessinerons un histogramme à partir de données passées en paramètre de l'URL.

6.13.2.Installation

Pour pouvoir utiliser les exemples présentés dans ce cours, vous devrez vous assurer que votre hébergeur supporte la bibliothèque GD. Pour cela, appelez simplement un script contenant phpinfo() et vérifiez que la page générée contient bien une section relative à GD (profitez-en pour noter la liste des formats d'image supportés). Si vous faites un test en local (ou êtes votre propre hébergeur) assurer vous d'avoir installé la bibliothèque GD (sous Windows vérifiez que l'un des fichiers suivants, php_gd.dll, php_gdgif.dll ou php_gd2.dll a bien été ajouté à la liste des extensions précisées dans le fichier php.ini). Dans ce cas, aussi, faites appel à phpinfo() pour vérifier tout ça.

6.13.3.Création d'une image avec PHP

Afin de pouvoir dessiner, il faut créer une image (un contexte) et lui associer une palette de couleur (dans l'immédiat une couleur de fond).
<?php
  // Ce qui suit est le code d'une image PNG
  header("Content-type: image/png");

  // L'image fait 200x100
  $largeur = 200;
  $hauteur = 100;
  $img = imageCreate($largeur, $hauteur);

  // La première couleur de la palette
  // qui constitue la couleur de fond
  // sera le rouge
  $rouge = imageColorAllocate($img, 255, 0, 0);

  // Que l'on peut rendre transparent
  //imagecolortransparent($im,$rouge);

  // Envoyons le code de l'image 
  imagePNG($img);

  // Et liberons les ressources
  imageDestroy($img);  
?> 
Ce qui donne
L'instruction header() utilisé pour préciser l'en-tête Content-type: sert à indiquer au navigateur (Internet Explorer, Netscape ...) que ce qui suit est le code d'une image au format PNG (et non par défaut une page HTML). La création du contexte de l'image passe par l'appel à la fonction imageCreate() (ici pour une image de 200 pixels sur 100 pixels). On définit une couleur appelée $rouge en en précisant les composantes Rouge, Vert et Bleu (RGB). Chacune des 3 valeurs est entre 0 et 255. (0,0,0) correspond au noir, (255,255,255) au blanc ensuite on peut faire les mélanges que l'on veut. Par défaut, la première couleur définie (ici, $rouge) constitue la couleur de fond. Ensuite on peut définir $rouge comme étant la valeur de la couleur transparente. (ici c'est en remarque pour voir le rectangle). imagePNG() envoie l'image (au format PNG) vers le navigateur. On libère la mémoire occupée par l'image par imageDestroy()
On a un beau rectangle rouge que l'on peut appeler dans un navigateur quelconque par la commande HTML <img src="gd_01.php">

6.13.4.Ecrire du texte dans une image avec PHP

Il est heureusement possible d'ajouter du texte dans une image.
A titre, d'exemple, plaçons un titre (et éventuellement un copyright) sur le fond précédent.
<?php
  header("Content-type: image/png");
  
  $largeur = 250;
  $hauteur = 200;
  $img = imageCreate($largeur, $hauteur);
  $rouge = imageColorAllocate($img, 200, 100, 100);
  $noir  = imageColorAllocate($img, 0, 0, 0);

  // Fond transparent
  //imageColorTransparent($img, $rouge);
  
  $titre        = "Histogramme";
  $titre_police = 5;
  
  imageString($img, $titre_police,
             ($largeur-imageFontWidth($titre_police)*strlen("$titre"))/2,
             0, $titre, $noir);
  //imageTTFText($img, 15, 90, $largeur-10, $hauteur-10, $noir, "Gigi.ttf",
  //           "Copyright PHP Facile !");

  imagePNG($img);
  imageDestroy($img);  
?> 
Ce qui donne
La fonction imageString() (qui fait totalement partie de la bibliothèque GD) accepte 6 paramètres: l'identifiant de l'image la police d'écriture, les valeurs de 1 à 5 (ici on a choisi 5) sont des polices proposées par défaut. (Il est possible de définir ses propres polices). l'abscisse en pixels l'ordonnée (le point (0,0) est en haut à gauche) le texte à afficher la couleur du texte.
Ici, nous avons également fait appel à imageFontWidth() qui retourne la largeur en pixels d'un caractère dans la police sélectionnée, afin de positionner le texte au milieu de l'image.
Lorsque la bibliothèque GD supporte les polices TrueType (et à condition de posséder la police sélectionnée) il est également possible de faire appel à la fonction imageTTFText(). Cette dernière requière 8 paramètre: l'identifiant de l'image la taille de la police l'angle du texte en degrés par rapport à l'horizontal l'abscisse l'ordonnée la couleur du texte le nom de la police (mettre le chemin complet) texte à dessiner
Vous pouvez ainsi afficher du texte avec des polices originales sans vous soucier des polices installées chez le client (encore un avantage du code serveur et donc de PHP !)
Ca commence à avoir de l'allure mais il manque le principal l'histogramme ! Aller, chapitre suivant...

6.13.5.Dessiner des rectangles en PHP (histogramme)

Pour dessiner des rectangles (pleins), il suffit de faire appel à la fonction imageFilledRectangle. Celle-ci requière 6 paramètres: l'identifiant de l'image l'abscisse du coté gauche l'ordonnée du coté supérieur l'abscisse du coté droit l'ordonnée du coté inférieur la couleur de remplissage
Il nous est maintenant possible de dessiner les barres de l'histogramme.
<?php
  // On pourra supposer que les données sont lues
  // dans une base de données mais dans l'immédiat
  // a titre d'exemple elles sont simplement codées "en dur"
  $valeurs = array(12,23,9,58,23,26,57,48,12);

  header("Content-type: image/png");
  
  $largeur = 250;
  $hauteur = 200;
  $img = imageCreate($largeur, $hauteur);
  $rouge         = imageColorAllocate($img, 200, 100, 100);
  $noir          = imageColorAllocate($img,   0,   0,   0);
  $fond          = imageColorAllocate($img, 240, 240, 240);
  $barreCouleur  = imageColorAllocate($img,   0, 255,   0);
  //imagecolortransparent($im,$rouge);
  
  $titre       = "Histogramme";
  $titrePolice = 5;
  imageString($img, $titrePolice,
              ($largeur-ImageFontWidth($titrePolice)*strlen($titre))/2,
              0, $titre, $noir);
  //imageTTFText($im, 15, 90, $largeur-10, $hauteur-10, $noir, "Gigi.ttf",
  //           "Copyright PHP Facile !");

  // Tracé du fond de l'histogramme
  imageFilledRectangle($img, 10, 20, $largeur-25, $hauteur-10, $fond);

  // Connaissant le nombre de barres = sizeOf($valeurs) 
  // et la largeur de l'image (en tenant compte des bords)
  // il est possible de déterminer la largeur d'une barre
  $barreLargeur = (int)(($largeur-35)/(1.5*sizeOf($valeurs)+0.5));

  // Pour ajuster l'échelle (en hauteur) il faut déterminer
  // la plus grande valeur du tableau
  $max = 0;
  for ($i=0; $i<sizeOf($valeurs); $i++) {
    if ($valeurs[$i]>$max) $max = $valeurs[$i];
  }
  
  // Nous avons toutes les informations nécessaire
  // il est alors possible de tracer toutes les barres
  for ($i=0; $i<sizeOf($valeurs); $i++) {
    $x = 10+(int)($barreLargeur*(0.5+$i*1.5));
    $barreHauteur = (int)(($valeurs[$i]*($hauteur-40))/$max);  

    imageFilledRectangle($img, $x, 
                         $hauteur-15-$barreHauteur,
                         $x+$barreLargeur,
                         $hauteur-15,
                         $barreCouleur);
  }
  
  imagePNG($img);
  imageDestroy($img);  
?> 
Ce qui donne
On crée un premier rectangle qui va servir de fond de couleur gris clair (autant de rouge, de vert et de bleu). On calcule une largeur de barre qui conviendra pour presque n'importe quel nombre de valeurs. Le 0,5 correspond au premier espace, on compte 1,5 par valeur pour l'espace qui suit la barre. La première boucle sert à determiner la valeur maximale entrée. La seconde boucle trace les rectangles. On commence par calculer l'abscisse de départ ainsi que la hauteur en pixel d'une valeur. On dessine ensuite le rectangle correspondant aux calculs précédent.
Voilà un histogramme qui a presque de l'allure, vous pouvez maintenant paramètrer encore plus ce script. Vous pouvez aussi ajouter une légende... Libre à vous de bien utiliser les connaissances acquises.

6.13.6.Conclusion

La librairie GD est fort utile, attention cependant de ne pas générer des images trop grandes, je vous rappelle que même si votre script ne fait que quelques kilo-octets, c'est l'image gif qui transitera par Internet et là attention au massacre si vous avez créé des grandes images ! Avec ces quelques connaissances, vous pouvez imaginer pleins de choses s'appuyant dessus.
Ici vous pouvez apprendre :
Version imprimable: imprimer