Cyril Rabat


Génération d'un histogramme en PHP

 10/11/2016     16/11/2017      Programmation PHP      Programmation client/serveur      Approche par composants   

Histogramme et image avec GD

   Cet article propose une classe Histogramme simplifiée, à modifier, et présente comment l'utiliser dans un document HTML, via un script PHP.

Mots-clefs :   PHP     GD   

Archive contenant les fichiers de cet article :

 histogramme.zip

La classe Histogramme

Le script PHP suivant correspond à la classe Histogramme qui permet de créer un histogramme dans une image à l'aide de GD.

<?php
define("BORD_HAUT", 10);                     
define("BORD_BAS", 10);                      
define("BORD_DROITE", 10);
define("BORD_GAUCHE", 10);
define("POLICE_AXE_X", 5);
define("POLICE_AXE_Y", 1);
define("ESPACE_BARRE", 20);
define("LARGEUR_AXE_Y", 30);
define("HAUTEUR_AXE_X", 20);
define("ESPACE_AXE", 5);
define("TAILLE_TEXTE_AXE_X", 10);
define("TAILLE_TEXTE_AXE_Y", 5);
 
class Histogramme {
 
    private $largeur;
    private $hauteur;
 
    /**
     * Construit un histogramme.
     * @param largeur la largeur
     * @param hauteur la hauteur
     */
    function __construct($largeur, $hauteur) {
		$this->largeur = $largeur;
        $this->hauteur = $hauteur;
	} 
 
    /**
     * Calcule la hauteur et la largeur d'un texte.
     * @param image l'image
     * @param texte le texte
     * @param police le numéro de la police
     * @return un tableau contenant la largeur et la hauteur
     **/
    public static function getTaille($image, $texte, $police) {
        return array(imagefontwidth($police) * strlen($texte), imagefontheight($police));
    }    
 
    /** 
     * Trace les axes.
     * @param image l'image de l'histogramme
     * @param nbBarres le nombre de barres     
     * @param largeurBarre la largeur des barres
     */
    function traceAxes($image, $nbBarres, $largeurBarre) {
        $couleurAxe = imagecolorallocate($image, 255, 255, 255);
 
        // Affichage des axes
        imageline($image, 
                  BORD_GAUCHE + LARGEUR_AXE_Y - ESPACE_AXE, 
                  BORD_HAUT, 
                  BORD_GAUCHE + LARGEUR_AXE_Y - ESPACE_AXE,
                  $this->hauteur - BORD_BAS - HAUTEUR_AXE_X + ESPACE_AXE,
                  $couleurAxe);
        imageline($image, 
                  BORD_GAUCHE + LARGEUR_AXE_Y - ESPACE_AXE,
                  $this->hauteur - BORD_BAS - HAUTEUR_AXE_X + ESPACE_AXE,
                  $this->largeur - BORD_DROITE,
                  $this->hauteur - BORD_BAS - HAUTEUR_AXE_X + ESPACE_AXE,
                  $couleurAxe);
 
        // Affichage de la légende de l'axe des ordonnées
        $texte = "0%";
        list($largeurTexte, $hauteurTexte) = Histogramme::getTaille($image, $texte, POLICE_AXE_Y);
        imagestring($image, POLICE_AXE_Y,
                    BORD_GAUCHE + LARGEUR_AXE_Y - $largeurTexte - ESPACE_AXE * 2,
                    $this->hauteur - BORD_BAS - HAUTEUR_AXE_X - $hauteurTexte,
                    $texte, $couleurAxe);
 
        $texte = "50%";
        list($largeurTexte, $hauteurTexte) = Histogramme::getTaille($image, $texte, POLICE_AXE_Y);
        imagestring($image, POLICE_AXE_Y,
                    BORD_GAUCHE + LARGEUR_AXE_Y - $largeurTexte - ESPACE_AXE * 2,
                    BORD_HAUT + ($this->hauteur - BORD_HAUT - BORD_BAS - HAUTEUR_AXE_X - $hauteurTexte) / 2,
                    $texte, $couleurAxe);
 
        $texte = "100%";
        list($largeurTexte, $hauteurTexte) = Histogramme::getTaille($image, $texte, POLICE_AXE_Y);
        imagestring($image, POLICE_AXE_Y, 
                    BORD_GAUCHE + LARGEUR_AXE_Y - $largeurTexte - ESPACE_AXE * 2,
                    BORD_HAUT, 
                    $texte, $couleurAxe);
 
        // Affichage du numéro de la question
        for($i = 0; $i < $nbBarres; $i++) {
            $texte = "".($i + 1);
            list($largeurTexte, $hauteurTexte) = Histogramme::getTaille($image, $texte, POLICE_AXE_X);
            imagestring($image, POLICE_AXE_X,
                        BORD_GAUCHE + LARGEUR_AXE_Y + $i * ($largeurBarre + ESPACE_BARRE) + ($largeurBarre - $largeurTexte) / 2,
                        $this->hauteur - BORD_BAS - HAUTEUR_AXE_X + 2 * ESPACE_AXE,
                        $texte, $couleurAxe);                     
        }
    }
 
    /**
     * Construit l'image à partir de données.
     * @param donnees les données
     * @return l'image créée
     */
    function getImage($donnees) {
        // Création de l'image
        $image = imagecreatetruecolor($this->largeur, $this->hauteur);
 
        // Définition des couleurs : le texte et les couleurs pour l'histogramme
        $couleurs = array(imagecolorallocate($image, 255, 255, 0),     // Couleur pour la réponse A
                          imagecolorallocate($image, 255, 128, 0),     // Couleur pour la réponse B
                          imagecolorallocate($image, 255, 130, 130),   // Couleur pour la réponse C
                          imagecolorallocate($image, 255, 0, 0),       // Couleur pour la réponse D
                          imagecolorallocate($image, 150, 150, 150));  // Couleur pour autres réponses
 
        // Calcul des dimensions des barres
        $nbBarres = sizeof($donnees);
        $largeurBarre = ($this->largeur - BORD_DROITE - LARGEUR_AXE_Y - BORD_GAUCHE - ESPACE_BARRE * ($nbBarres - 1)) / $nbBarres;
        $hauteurBarre = $this->hauteur - BORD_BAS - BORD_HAUT - HAUTEUR_AXE_X;
 
        // Affichage des axes et de la légende
        $this->traceAxes($image, $nbBarres, $largeurBarre);
 
        // Affichage des barres
        for($i = 0; $i < $nbBarres; $i++) {
            $max = $donnees[$i]['nb'];
            $total = 0;
 
            // Affichage des différents carrés correspondant aux réponses
            for($j = 0; $j < sizeof($donnees[$i]['reponses']); $j++) {
                $hauteurRect = $donnees[$i]['reponses'][$j] * $hauteurBarre / $max;
                imagefilledrectangle($image, 
                                     BORD_GAUCHE + LARGEUR_AXE_Y + $i * ($largeurBarre + ESPACE_BARRE),
                                     $this->hauteur - BORD_BAS - HAUTEUR_AXE_X - $total * $hauteurBarre / $max,
                                     BORD_GAUCHE + LARGEUR_AXE_Y + $i * ($largeurBarre + ESPACE_BARRE) + $largeurBarre,
                                     $this->hauteur - BORD_BAS - HAUTEUR_AXE_X - $hauteurRect - $total * $hauteurBarre / $max,
                                     $couleurs[$j]);            
                $total += $donnees[$i]['reponses'][$j];
            }
 
            // Affichage du cadre pour le reste des questions
            if($total != $max) {
                $hauteurRect = ($max - $total) * $hauteurBarre / $max;
                imagefilledrectangle($image, 
                                     BORD_GAUCHE + LARGEUR_AXE_Y + $i * ($largeurBarre + ESPACE_BARRE),
                                     $this->hauteur - BORD_BAS - HAUTEUR_AXE_X - $total * $hauteurBarre / $max,
                                     BORD_GAUCHE + LARGEUR_AXE_Y + $i * ($largeurBarre + ESPACE_BARRE) + $largeurBarre,
                                     $this->hauteur - BORD_BAS - $hauteurRect - HAUTEUR_AXE_X - $total * $hauteurBarre / $max,
                                     $couleurs[4]);
            }
        }
 
        return $image;
    }    
}
?>

 Télécharger le fichier

Génération d'un histogramme

Pour générer l'histogramme, nous choisissons de passer par un script intermédiaire PHP qui exploite la classe Histogramme. Les dimensions de l'image contenant l'histogramme sont spécifiées en GET. Les données sont stockées en dur dans le script PHP.

<?php
include("Histogramme.php");
 
// Constantes
define("LARGEUR", 300);                   // Largeur par défaut de l'image
define("HAUTEUR", 300);                   // Hauteur par défaut de l'image
 
// Récupération de la largeur et de la hauteur envoyées au script via la méthode GET
if(isset($_GET['largeur']))
    $largeur = intval($_GET['largeur']);
else
    $largeur = LARGEUR;
if(isset($_GET['hauteur']))
    $hauteur = intval($_GET['hauteur']);
else
    $hauteur = HAUTEUR;
 
// Création de l'histogramme
$histo = new Histogramme($largeur, $hauteur);
 
// Données quelconques pour l'histogramme
$donnees = array(array("nb" => 100, "reponses" => array(40, 30)),
                 array("nb" => 80, "reponses" => array(10, 20, 20)),
                 array("nb" => 90, "reponses" => array(40, 20, 10, 10)),
                 array("nb" => 60, "reponses" => array(10, 10, 40)),
                 array("nb" => 80, "reponses" => array(40, 0, 40)),
                 array("nb" => 100, "reponses" => array(0, 90)),
                 array("nb" => 40, "reponses" => array(10, 10, 10, 10)),
                 array("nb" => 160, "reponses" => array(10, 10, 40)));   
 
// Envoi de l'image
header("Content-type: image/png");
imagepng($histo->getImage($donnees));
?>

 Télécharger le fichier

Document HTML

Le document HTML suivant inclut simplement l'histogramme généré par le script PHP dans une balise img. La taille de l'image est spécifiée dans l'URL.

<html lang="fr">
    <head>
        <title>Exemple de création d'un histogramme</title>
        <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
        <meta name="description" content="Histogramme et image GD"/>
        <meta name="author" content="Cyril Rabat"/>
    </head>
    <body>
        <h1>Exemple d'utilisation de la classe histogramme</h1>
 
        <p>Voici un histogramme généré avec la classe Histogramme</p>
 
        <img src='generateur.php?largeur=500&hauteur=300'/>
    </body>
</html>

 Télécharger le fichier

Exécution

Pour exécuter les différents codes, il faut utiliser un serveur Web (par exemple Wamp ou UWamp, sous Windows). Les fichiers doivent être placés dans le répertoire www : on suppose ici qu'ils sont placés dans un sous-répertoire histogramme. Une fois le serveur exécuté, on accède à la page  http://localhost/histogramme/, suivi par le nom du script. Nous obtenons ainsi, l'histogramme suivant :

Articles connexes


Version de cette page Mercredi 16 Décembre 2015

© Cyril Rabat 2018

Connexion

Mot de passe perdu

Dernières nouvelles

15/10/2018 Tous les étudiants de la Licence Informatique ont réunion sur la mobilité internationale, Mercredi 17 Octobre, de 13h30 à 14h00 (et non à 12h30), en Amphi 3.
02/10/2018 Pour la deuxième année consécutive, l'URCA est partenaire de l’événement Coding Battle. Tous les étudiants de Licence et de Master sont appelés à y participer le 17 octobre de 19h à 21h.
01/10/2018 Les emplois du temps sont maintenant accessibles depuis la page de la scolarité.
27/09/2018 Une page a été créée pour vous permettre d'obtenir toutes les informations concernant les stages pour la Licence. Contactez le responsable pour plus d'informations.

Contact

Courriel :
cyril.rabat [at] univ-reims.fr

Téléphone :
+33-326-91-33-81

Fax :
+33-326-91-33-97

Facebook :
lien Facebook direct