GD è una libreria grafica che viene fornito in bundle con PHP, a partire dalla versione 4.3.0. GD è un progetto open source, sotto la guida di Thomas Boutell. Maggiori informazioni si possono trovare sul sito libgd.org che contiene immagini e documentazione su l’ultima versione (2.1.00 alla data di questo articolo).
GD consente ai programmatori PHP di generare immagini dinamiche in formato JPEG e PNG, è scritta in C ed è disponibile per i sistemi Unix, Windows e derivati. Anche se la libreria viene comunemente usata con PHP, le implementazioni sono disponibili anche per altri linguaggi di programmazione, ad esempio il Perl.
Per capire la potenza della libreria GD, ecco alcune delle sue principali caratteristiche:
- Supporto per il disegno di forme primitive, quali linee, archi, ellissi, poligoni etc con parametri variabili previste dal codice PHP
- Supporto per immagini a colori e canale alfa per la trasparenza nelle immagini
- Supporto per la fusione di due immagini
- Supporto per il testo con font e il supporto per i font TrueType antialised tramite la libreria FreeType
- Supporto per primitive antialised
- Ricampionamento opzionale di immagini ridimensionate
Per poter utilizzare GD 2, è necessario disporre di un server web con PHP installato, insieme al supporto GD abilitato dalla configurazione di PHP. Di solito la libreria è inclusa nel bundle di PHP per la maggior parte dei sistemi operativi.
Per quanto riguarda i possibili usi per GD, ecco alcuni suggerimenti:
- I grafici che analizzano dati memorizzati su database
- GIS (Geographical Information System)
- Strutture organizzative, per la costruzione di organigrammi aziendali basati su un database dei dipendenti
- Strutture ad albero, come gli alberi binari o qualsiasi altra raccolta di dati che contenga relazioni padre / figlio che hanno bisogno di essere rappresentati graficamente
Come si può vedere, GD può avere molti usi. Le immagini dinamiche offrono un ulteriore livello di funzionalità che permettono di fare quel salto dall’essere un semplice sito web all’essere una vera web application.
Disegnare delle forme con GD
In questo esempio, partiremo con la creazione delle forme più semplici, la gestione dei colori per poi passare alla creazione di un grafico a barre. Il grafico in questione sarà un istogramma di 4 colonne con valori diversi. Per i dati, faremo riferimento a un sondaggio su qual è l’animale preferito chiesto a un campione di 25 persone: gatti: 6, cani: 8, pecore: 3, balene: 8.
Iniziamo a disegnare un semplice rettangolo rosso, che poi rappresenterà la barra del nostro grafico. Iniziamo a creare un’immagine vuota
$img = imagecreatetruecolor(200, 150);
Con questo codice abbiamo definito un rettangolo di larghezza 200 e altezza 150 pixel. Adesso definiamo alcuni colori (nero, bianco e rosso), che possono sempre tornarci utili
$black = imagecolorallocate($img, 0, 0, 0); $white = imagecolorallocate($img, 255, 255, 255); $red = imagecolorallocate($img, 255, 153, 153);
Per la funzione imagecolorallocate() abbiamo usato 4 parametri, di cui il primo è l’immagine che abbiamo creato in precedenza mentre i tre parametri successivi rappresentano il colore in RGB. Adesso, impostiamo uno sfondo bianco per la nostra l’immagine
imagefill($img, 0, 0, $white);
Ora disegniamo un rettangolo a tinta unita rossa. Per la funzione imagefilledrectangle() bisogna passare 5 argomenti: il primo è l’immagine, poi rispettivamente le coordinate X e Y, la larghezza del rettangolo, l’altezza del rettangolo e, infine, il colore.
imagefilledrectangle($img, 10, 15, 100, 50, $red);
Successivamente dobbiamo specificare in che formato visualizzare l’output. Se vogliamo che l’immagine creata sia in formato PNG, allora dovremo scrivere:
header('Content-Type: image/png'); //imposta il content type dello stream output imagepng($img); //visualizza l'immagine imagedestroy($img); //distrugge l'oggetto e libera la memoria
Se poi vogliamo aggiungere un bordo al nostro rettangolo, dobbiamo utilizzare la funzione imagerectangle(), subito sotto la funzione imagefilledrectangle() con gli stessi parametri, escluso l’ultimo che rappresenta il colore del bordo.
imagerectangle($img, 10, 15, 100, 50, $black);
Il risultato dovrebbe essere questo:
Disegnare qualcosa di più complesso
Per aggiungere più rettangoli, dobbiamo solo duplicare due linee di codice per ogni rettangolo. Per il nostro grafico abbiamo bisogno di un’immagine più grande, infatti:
- Il grafico sarà largo 400 px e alto 350 px
- Per ogni unità (valore 1) aggiungeremo 35px, quindi ad esempio, il valore 8 = 280
- Tutte le barre saranno larghe 50 px
- Lo spazio tra ogni barra sarà di 20 px
Vediamo adesso come creare rapidamente i grafici con le dimensioni e le coordinate corrette:
//Gatti imagefilledrectangle($img, 10, 15, 60, 210, $red); imagerectangle($img, 10, 15, 60, 210, $black); //Cani imagefilledrectangle($img, 80, 15, 130, 280, $red); imagerectangle($img, 80, 15, 130, 280, $black); //Pecore imagefilledrectangle($img, 150, 15, 200, 105, $red); imagerectangle($img, 150, 15, 200, 105, $black); //Balene imagefilledrectangle($img, 220, 15, 270, 280, $red); imagerectangle($img, 220, 15, 270, 280, $black);
Da notare che per tutti i parametri relativi ai valori orizzontali (asse x) viene sommato il valore 70, mentre per quanto riguarda i valori verticali (asse y) viene semplicemente moltiplicato il valore per 35. Le barre del grafico, come si può notare in figura, sono allineate nella parte superiore dell’immagine.
Quello che dobbiamo fare è allinare le barre correttamente, cioè alla base dell’immagine. Per fare questo, dobbiamo aggiungere un valore per ogni valore y. Prima di tutto dobbiamo definire un valore y che vogliamo essere la linea di base, per esempio 320 px. Quello che faremo è posizionare ogni rettangolo a y = 320 px e poi sottrarre a questo valore, l’altezza calcolata per la barra, quindi:
//Gatti imagefilledrectangle($img, 10, 320, 60, 320-(6*35), $red); imagerectangle($img, 10, 320, 60, 320-(6*35), $black); //Cani imagefilledrectangle($img, 80, 320, 130, 320-(8*35), $red); imagerectangle($img, 80, 320, 130, 320-(8*35), $black); //Pecore imagefilledrectangle($img, 150, 320, 200, 320-(3*35), $red); imagerectangle($img, 150, 320, 200, 320-(3*35), $black); //Balene imagefilledrectangle($img, 220, 320, 270, 320-(8*35), $red); imagerectangle($img, 220, 320, 270, 320-(8*35), $black);
Con queste correzioni, il grafico dovrebbe apparire così:
Se poi abbiamo bisogno di aggiungere gli assi X e Y al grafico, dobbiamo spostare tutte le barre verso destra, per fare spazio all’asse Y. Per quanto riguarda l’asse X è semplice perchè sappiamo che la base del grafico è 320 px. Quindi dobbiamo solo capire dove inizia e dove finisce la linea analizzando la posizione della prima e dell’ultima barra. Per quanto riguarda la prima barra si trova a 10 px a partire dal lato sinistro. Se dobbiamo aggiungere i 20 px di spazio come già fatto per ciascuna barra, dovremo posizionare la linea a -10 px, che produrrebbe una linea al di fuori della nostra immagine. Quindi siamo costretti a spostare tutte le barre di altri 30 px per rispettare la spaziatura tra barre di 20px, quindi in definitiva avremo:
//Gatti: 6 imagefilledrectangle($img, 40, 320, 90, 320-(6*35), $red); imagerectangle($img, 40, 320, 90, 320-(6*35), $black); //Cani: 8 imagefilledrectangle($img, 110, 320, 160, 320-(8*35), $red); imagerectangle($img, 110, 320, 160, 320-(8*35), $black); //Pecore: 3 imagefilledrectangle($img, 180, 320, 230, 320-(3*35), $red); imagerectangle($img, 180, 320, 230, 320-(3*35), $black); //Balene: 8 imagefilledrectangle($img, 250, 320, 300, 320-(8*35), $red); imagerectangle($img, 250, 320, 300, 320-(8*35), $black);
Dopo aver corretto tutte i valori, possiamo disegnare la linea relativa all’asse X, utilizzando la funzione imageline():
imageline($img, 20, 320, 320, 320, $black);
Per quanto riguarda l’asse Y, deve seguire le stesse coordinate dell’asse X, ma l’altezza deve essere calcolata relativamente all’altezza della barra più alta, aggiungendo poi altri 20 px per maggiore sicurezza. Per farlo, occorre sottrarre a 320 (che ricordo è la base del nostro grafico) l’altezza massima e uno spazio di 20 px aggiuntivo:
imageline($img, 20, 320, 20, 320-(8*35)-20, $black);
Il risultato sarà questo: