Génération de graphiques avec PHP
Dossier "SAM l'Informaticien" de novembre 2001 par Daniel Lucazeau

'internet est un outil de communication, et nous savons bien tous que si le message est important, l'enveloppe, son emballage l'est presque autant. Quand nous devons communiquer sur des séries de chiffres nous pensons tout de suite à des graphiques générés par notre tableur préféré et nous avons chacun le nôtre. Afin de garantir la compatibilité avec toutes les plate-formes et tous les navigateurs de la page contenant notre graphique, nous devons utiliser ou une applet ou une image. Nous allons survoler dans cet article, la génération à la volée d'image par PHP.

Présentation de l'exemple

Pour que cela fonctionne, il faut que la librairie GD soit installée et, suivant la version, vous pourrez générer des images au format GIF ou PNG pour les plus récentes. Une sombre histoire de licence a fait que la fabrication du GIF est soumise à des droits. Le monde de l'image a découvert alors l'exitence du format PNG, qui s'avère au bout du compte de meilleur qualité ! L'utilisation de la fonction phpinfo() vous indiquera l'existence ou non de cette librairie sur votre serveur.

Contrairement à d'autres applications avec PHP ou un autre langage, le graphisme fait un large appel aux système de coordonnées. Et dès que l'on sort de quelques lignes parallèles aux axes, il faut maîtriser un peu de trigonométrie. Cela remue les méninges ..

Je ne vais pas prendre un exemple standard de représentation graphique dune série de données numériques, mais celui du dessin d'une étoile à cinq branches. Quand on a compris le principe de tracé, on peut tout faire. Et mis à part quelques calculs trigonométriques...c'est plus simple qu'un histogramme !

Etude mathématique succinte

Notre étoile est donc tracée dans un cercle de rayon 1, le premier point est en (1.0). Les angles au centre entre deux points sont de

Mais le système de coordonnées des images n'est pas le repère mathématique habituel, le point (0,0) est le point en haut à gauche, qui correspond à notre (-1,-1)., L'image du repère a été générée avec PHP.

Nous allons donc travailler avec notre repère habituel et transformer les coordonnées par homothétie et translation.

Les sommets du pentagone ont pour coordonnées
(cos( 2*i*pi/5), sin( 2*i*pi/5)) ;-))) pour i variant de 0 à 4.
Et pour obtenir une étoile, on les joint de deux en deux, le tableau des coordonnées est mis en dur dans le script, afin de ne pas alourdir la présentation.

Création d'une image

Quel que soit le contenu de l'image, il faut commencer par la créer, du moins créer l'espace mémoire dans lequel nous allons écrire et dessiner. Nous utilisons imageCreate() qui prend deux paramètres la largeur et la hauteur, exprimés en pixels, de l'image en question. Cette fonction nous renvoie un handle ou un pointeur sur la zone mémoire, ce pointeur doit être fourni à toutes les autres fonctions de manipulation :
$hImg = imageCreate( 200, 200);

Quand nous aurons terminer de travailer notre image, nous devons la déclarer et ce n'est qu'à ce moment là que nous spécifions le type - gif, jpeg, png - de notre image. Créons une image PNG :
header("Content-type: image/png");
imagePng($hImg);
Nous devons spécifier à l'aide d'une entête spécifique au navigateur que ce qu'il va recevoir n'est pas du texte, nous lui en indiquons le type Mime.

Entre ces deux fonctions, il y a la création proprement dite de l'image.

Dessiner dans l'image

Notre étoile est juste un affaire de quleques liognes, c'est pour cela que j'ai choisi cet exemple.

La fonction imageLine sert à tracer une ligne entre les points (x1,y1) et (x2,y2):
imageLine( $hImg, $x1, $y1, $x2, $y2, $c);
où $c est une couleur déclarée par
$c = imageColorAllocate( $hImg, $r, $v, $b);
$r, $v et $b sont les valeurs RVB de la couleur, ce sont des entiers compris de façon standard entre 0 et 255.

Il suffit juste de faire un boucle pour parcourir notre tableau de coordonnées, en conservant le point d'arrivée comme départ de la ligne suivante :

// Tracé de l'étoile
$x1 = $X[0]; $y1 = $Y[0];
for( $i=1; $i<6; $i++) {
    $j=( $i%5);
    $x2 = $X[$j]; $y2 = $Y[$j];
    imageLine( $hImg, $x1, $y1, $x2, $y2, $c);
    $x1 = $x2; $y1 = $y2;
}

Les couleurs

La première couleur allouée est automatiquement utilisée comme couleur de fond. On alloue donc une couleur en premier comme couleur de fond.

Script complet

<?php
// Fonctions de service
function chgCoordX( $x) {
    global $hom;
    return $hom *( 1 + $x);
}

function chgCoordY( $y) {
    global $hom;
    return $hom *( 1 - $y);
}

// Dimension du graphique
$diagramWidth = $diagramHeight = 200;
$hom = $diagramWidth/2;

// Tableaux des coordonnées
for( $j=0; $j<5; $j++) {
    $A[$j] = cos( 2*$j*PI() / 5);
    $B[$j] = sin( 2*$j*PI() / 5);
}

// On croise les points (on les prende 2 en 2 modulo 5
$X[0] = chgCoordX( $A[0]); $Y[0] = chgCoordY( $B[0]);
$X[1] = chgCoordX( $A[2]); $Y[1] = chgCoordY( $B[2]);
$X[2] = chgCoordX( $A[4]); $Y[2] = chgCoordY( $B[4]);
$X[3] = chgCoordX( $A[1]); $Y[3] = chgCoordY( $B[1]);
$X[4] = chgCoordX( $A[3]); $Y[4] = chgCoordY( $B[3]);

// On construit l'image
$hImg = imageCreate( $diagramWidth, $diagramHeight);

// Allocation de la couleur de l'étoile
$colorBackgr = imageColorAllocate( $hImg, 255, 255, 255);
$c = imageColorAllocate( $hImg, 255, 0, 0);

// Tracé de l'étoile
$x1 = $X[0]; $y1 = $Y[0];
for( $i=1; $i<6; $i++) {
    $j=( $i%5);
    $x2 = $X[$j]; $y2 = $Y[$j];
    imageLine( $hImg, $x1, $y1, $x2, $y2, $c);
    $x1 = $x2; $y1 = $y2;
}

if ( imagetypes() & IMG_GIF) {
    header("Content-type: image/gif");
    imageGif($hImg);
} elseif (imagetypes() & IMG_PNG) {
    header("Content-type: image/png");
    imagePng( $hImg); //
} else {
    die("Pas de support graphique avec PHP sur ce serveur");
}
?>

Il y a des moyens plus rapide pour affecter les coordonnées, mais j'ai préféré détailler et isoler la partie mathématique de la partie graphisme afin que tout le monde s'y retrouve.

Voilà le résultat :

Télécharger le source au format .txt.

Conclusion

Vous pourrez vous entraîner à tracer des étoiles à plusieurs branches : 3, 4, 6, 7 etc.. Si vous tracez les polygones non croisés, on a vite fait de monter une animation qui montre que la série des polygones à n côtés tend vers le cercle quand n croit vers l'infini ...les mathématiques en douceur !

 

Daniel Lucazeau
www.ajornet.com
Chef de projet Internet

 

Tous droits réservés - Reproduction même partielle interdite sans autorisation préalable