Introduzione al disegno con le librerie GD e PHP
Iniziamo subito col fare due importanti distinzioni, attualmente è
possibile reperire su internet due versioni delle librerie GD, le 1.6.x e
le 2.x. Questo perché in passato è stata mossa una causa legale
contro gli autori di queste utilissime librerie, il formato GIF è proprietario,
ciò significa che bisogna pagare dei diritti per poterlo utilizzare.
La soluzione è stata eliminare il supporto per le GIF dalle librerie
in quanto le GD fanno parte di un progetto Open Source. In definitiva le differenze
principali fra le due versioni facilmente reperibili in rete sono queste:
- con le versioni <= 1.6.x si ha pieno supporto per GIF, JPEG e PNG (in modo limitato),
inoltre si ha a disposizione un set limitato di funzioni grafiche.
- con le versioni >= 2.x si ha pieno supporto per JPEG e PNG ma non per
le GIF, tuttavia si dispone di un set più ampio di funzioni grafiche.
Per praticità menzionerò nel codice la compatibilità
con le funzioni introdotte nelle due versioni.
Per utilizzare un'immagine generata con queste librerie si può semplicemente
effettuare la richiesta di questa pagina nel browser oppure, più pratico,
inserire il percorso del file php che genera l'immagine, nel tag <img>
in questo modo: <img src="miaPagina.php">
Con questo sistema è possibile passare anche dei parametri nella query
string dell'immagine aumentandone notevolmente le potenzialità.
L'installazione
Sotto windows l'installazione è abbastanza semplice, basta infatti
procurarsi la dll relativa alla libreria che si intende utilizzare, copiarla
nella directory PHP/extension e decommentare, all'interno del php.ini
la riga corrispondente, ad esempio, per installare le GD2 bisogna decommentare
questa linea:
;extension=php_fdf.dll
;extension=php_filepro.dll
;extension=php_gd.dll
extension=php_gd2.dll
;extension=php_gettext.dll
;extension=php_hyperwave.dll
;extension=php_iconv.dll
Mentre sotto Linux è più complesso. Per installarle servono
le "Jpeg lib" e le "libpng". Le "libpng" necessitano
di "zlib". Inoltre si possono usare le "freetype" (1 o
2) per l'utilizzo dei Font. Una volta scaricati i vari file da shell bisogna
eseguire:
# Jpeg
./configure --enable-shared --enable-static --prefix=/usr/local/jpeg; make;
make test; make install
# zlib
./configure --shared --prefix=/usr/local/zlib; make; make test; make install
# libpng (zlib)
make; make test; make install
# freetype2
./configure --prefix=/usr/local/freetype2; make; make install
# GD 2 (jpeg,
libpng, freetype2)
'./configure'
'--prefix=/usr/local/gd2'
'--with-zlib=/usr/local/zlib'
'--with-png=/usr/local/libpng'
'--with-freetype=/usr/local/freetype2'
'--with-jpeg=/usr/local/jpeg/lib';
make;
make install
Per attivarle bisogna aggiungere al compile le seguenti opzioni:
--with-gd=dir --enable-exif --enable-gd-native-ttf --with-gd=dir
--with-jpeg-dir=dir --with-png-dir=dir --with-freetype-dir=dir --with-ttf
Cinque passi per la propria applicazione con le GD
Iniziamo col descrivere i passi fondamentali per la generazione di un'immagine
con le librerie GD.
- Istanziare una nuova immagine
- Allocare i colori da utilizzare.
Nota: questa operazione
deve essere effettuata necessariamente prima dell'utilizzo di tale colore - Disegnare l'immagine
- Inviare in output o salvare l'immagine.
Nota: prima di inviare
in output l'immagine, bisogna impostare gli header corretti - Distruggere l'immagine liberando la memoria
Vi propongo quindi un piccolo script che vi faccia comprendere tale funzionamento.
Le funzioni utilizzate saranno esplicitate in seguito.
<?
// istanzio una nuova immagine di dimensioni x=200 e y=300
$immagine = imageCreate(200, 300);
// assegno il primo colore, questo colore sarà anche lo sfondo dell'immagine
$bianco = imageColorAllocate($immagine, 255, 255, 255);
// assegno un secondo colore, da utilizzare per colorare il testo
$nero = imageColorAllocate($immagine, 0, 0, 0);
// visualizzo il testo "HTML.IT"
imageString($immagine, 2, 100, 100, "HTML.IT", $nero);
// imposto correttamente gli header
header("Content-type: image/png");
// invio l'output come immagine PNG
imagePng($immagine);
// libero la memoria
imageDestroy($immagine);
?>
Nelle pagine successive descriveremo le singole funzioni.
1. Istanziare una nuova immagine
Ci sono vari modi per creare una nuova immagine, se si desidera creare un'immagine
vuota esistono essenzialmente due funzioni:
- imageCreate($x, $y)
prende solo due parametri, le dimensioni x e y
dell'immagine espresse in pixel. Questa funzione è disponibile sin
dalle prime versioni delle GD e proprio per questo gli anni iniziano a pesarle.
La limitazione che affligge tale funzione è il set di colori che
si può usare. Infatti con essa è possibile usare solo 256
tonalità di colore diverse, inoltre non è possibile utilizzare
il canale Alpha (la trasparenza, ma lo vedremo in seguito). Quando si cercherà
di allocare un nuovo colore in realtà si allocherà un colore
il più vicino possibile a quello desiderato, ma non esattamente quello
voluto! Con questa funzione, il primo colore allocato sarà anche
il colore di sfondo dell'immagine.
Nota: il punto (0, 0)
corrisponde all'estremità superiore sinistra dell'immagine - imageCreateTrueColor($x, $y)
il funzionamento è analogo a quello di imageCreate()
solo che con questa funzione è possibile utilizzare tutte le tonalità
dello standard RGB, vale a dire 16.581.375 colori! Questa funzione è
stata introdotta nelle GD 2.0 quindi non è possibile utilizzarla
con versioni precedenti. Con questa funzione è possibile utilizzare
colori dotati anche dell'alpha channel. C'è anche un'altra
differenza rispetto ad imageCreate(), vale a dire che il colore
di sfondo qui è sempre nero. Se si desidera cambiarlo quindi occorrerà
coprirlo, magari utilizzando la funzione imageFilledRectangle()
menzionata più avanti.
È possibile tuttavia creare una nuova immagine partendo da un'immagine già
esistente, è possibile caricare anche file residenti su server remoti,
solo se è stata abilitata allow_url_fopen nel php.ini (abilitata
per default nelle ultime versioni). Nota: la possibilità
di caricare un file da server remoto non è disponibile nelle versioni
Windows di PHP, in ogni caso ci sono alcune funzioni a tal proposito che possono essere molto utili:
- imageCreateFromJpeg($path)
cerca di istanziare una nuova immagine basandosi su un'immagine preesistente
in formato JPEG, specificando il path nell'unico paramentro che prende.
Questa funzione crea sempre un'immagine dotata di tutte le tonalità
dei colori RGB, ma solo nelle GD 2.x. Altrimenti si avrà una notevole
perdita di colore, l'interprete dovrà infatti riadattare i colori
con quelli più vicini a quelli dell'immagine originale, avendo a
disposizione però, solo 256 colori. - imageCreateFromPNG($path)
funziona in modo analogo a imageCreateFromJpeg() solo che
carica un'immagine PNG. Questa funzione è disponibile solo nelle
GD 2.x dato che il supporto per tale formato non era stato ancora introdotto
nelle versioni precedenti. - imageCreateFromGIF($path)
funziona in modo analogo alle funzioni sopra descritte, carica un'immagine
in formato GIF. L'unico neo è che questa funzione non è più
disponibile nelle GD 2.x. Il supporto per tale formato, come indicato all'inizio,
è stato stato bloccato, è quindi possibile utilizzare le GIF
solo con le GD 1.6.x
È possibile risalire alle dimensioni originali dell'immagine utilizzando
le funzioni imagesx($imageRef) e imagesy($imageRef). Ritornano
un'intero che rappresenta rispettivamente la dimensione x e la dimensione
y dell'immagine passata come parametro.
2. Allocare i colori da utilizzare
Adesso le cose si fanno interessanti. Infatti esistono molte funzioni in
grado di effettuare questa operazione. Ma dopo una prima analisi sono giunto
alla conclusione che molte di esse sono ridondanti e in alcuni casi anche
superflue. Le uniche due funzioni a cui ho attribuito imporanza sono solo
2:
- imageColorAllocate($imageRef, $red, $blue, $green)
questa funzione alloca nella palette dell'immagine $imageRef il
colore RGB espresso dalla combinazione dei 3 colori fondamentali (rosso,
verde, blu) e ne restituisce l'indice. In caso si stia lavorando in un'immagine
true color verrà assegnato anche il canale alpha, posto
ovviamente a 0 (visibile). Questa funzione è disponibile a partire
dalla versione 1.6.x delle GD.
Nota: i colori possono
essere espressi da un numero compreso tra 0 e 255, valori fuori da questo
range genereranno un errore - imageColorResolveAlpha($imageRef, $red, $blue, $green, $alpha)
questa funzione cerca nella palette dell'immagine un colore che ha
l'esatta combinazione di colori specificati come parametri e ne ritorna
l'indice, altrimenti ne alloca uno nuovo, comprensivo di canale Alpha.
Nota: il canale Alpha può
assumere solo valori compresi tra 0 (visibile) e 127 (trasparente)
Vale la pena soffermarsi ulteriormente su quest'ultima funzione. Iniziamo
con il canale alpha. Se non si utilizza un'immagine true color si
avrà come risultato un colore visibile quando specifichiamo 0, è
invisibile per tutti gli altri valori! Questa funzione non è la più
adatta per allocare un colore dotato di canale alpha, la più adatta
sarebbe imageColorAllocateAlpha() solo che per un'insipegabile motivo
questa funzione non è disponibile nelle GD attualmente distribuite
con PHP. Quindi ho fatto a meno di utilizzarla. Va inoltre detto che la palette
di colori allocabile in un'immagine è limitata notevolmente in un'immagine
non true color. Inoltre se noi cancelliamo il riferimento ad un colore
precedentemente allocato, cioò non ne determinerà la deallocazione
del colore dall'immagine. Per fare ciò dovremo utilizzare la funzione
imageColorDeallocate($imageRef, $color). Un semplice sistema per
ottenere i 256 colori esatti disponibili con imageCreate(), è
verificare che essi siano divisibili per 0x33 (51 in decimale).
3. Disegnare l'immagine
Le GD mettono a disposizione degli sviluppatori PHP un arsenale di funzioni
legate a questo scopo. Ne illustrerò solo alcune, infatti queste funzioni
sono tutte molto simili tra loro, per informazioni aggiuntive rimando al manuale
online.
- imageLine($imageRef, $x1, $y1, $x2, $y2, $color)
disegna una linea nell'immagine $imageRef unendo i punti ($x1,
$y1) e ($x2, $y2) di colore $color - imageRectangle($imageRef, $x1, $y1, $x2, $y2, $color)
disegna un rettangolo nell'immagine $imageRef partendo da
due punti, il vertice superiore sinistro ($x1, $y1) e il vertice
inferiore destro ($x2, $y2) del rettangolo con il colore $color.
Questa funzione disegnerà solo il bordo del rettangolo lasciandone
vuoto il contenuto. Il bordo di questo rettangolo sarà di 1 px. - imageFilledRectangle($imageRef, $x1, $y1, $x2, $y2, $color)
funziona in modo analogo alla funzione precedente, solo che disegnerà
il riempimento del rettangolo. Se vogliamo quindi queste due funzioni sono
complementari. - imageString($imageRef, $font, $x, $y, $text, $color)
inserisce all'interno dell'immagine $imageRef il testo $text
alle coordinate del punto ($x, $y) utilizzando il font $font e
il colore $color. Per quanto riguarda il font bisogna citare il fatto che
sono messi a disposizione 5 font inclusi nelle librerie, è quindi
possibile specificare un numero intero compreso tra 1 e 5 per usare quelli
interni, oppure specificare il path di un font residente sul disco del server. - imageFill($imageRef, $x, $y, $color)
per farvi capire meglio il funzionamento di questa funzione, immaginate
il classico paint di windows. Questa funzione corrisponde al secchiello,
facendo click nel punto ($x, $y) riempiremo del colore $color
la porzione di immagine che racchiude quel punto.
Per completezza è bene menzionare le altre funzioni che php mette
a disposizione del programmatore:
- imageEllipse()
disegna un'ellisse
- imageArc()
disegna un arco, o un ellisse parziale
- imagePolygon()
disegna un poligono indicato dai punti passati come parametro
- imageFilledEllipse()
disegna il riempimento di un'ellisse (disponibile solo
nelle GD 2.x)
- imageFilledArc()
disegna il riempimento di un arco, o ellisse parziale (disponibile
solo nelle GD 2.x)
- imageFilledPolygon()
disegna il riempimento di un poligono.
4. Inviare in output o salvare l'immagine
Le operazioni per l'invio in output sono molto semplici, tuttavia è
necessario cambiare il tipo MIME del file PHP, per impostazione predefinita
infatti è su text/html, noi dobbiamo portarlo sul tipo della
nostra immagine. Per fare questo ci serviamo della funzione header().
Prima del richiamo della funzione di output è bene quindi utilizzare
questa funzione nel modo seguente:
- header("Content-type: image/png") se si vuole inviare
in output un'immagine PNG
- header("Content-type: image/jpeg") se si vuole inviare
in output un'immagine JPEG
- header("Content-type: image/gif") se si vuole inviare
in output un'immagine GIF
Infine le funzioni vere e proprie che mandano in output l'immagine creata sono queste:
- imagePng($imageRef)
invia in output l'immagine $imageRef nel formato PNG - imageJpeg($imageRef [, $path [, $qualità]])
specificando solo il primo parametro invia in output l'immagine $imageRef
in formato JPEG, specificando anche il secondo l'immagine non verrà
inviata in output ma salvata con il nome indicato in $path, il
terzo parametro, sempre opzionale, ne definisce la qualità, si può
inserire un valore compreso tra 0 (immagine scadente) e 100 (immagine ottimale).
Se omesso viene usato 75 come valore predefinito. La qualità dell'immagine
influirà ovviamente sulle dimensioni finali del file. - imageGif($imageRef[, $path])
invia in output l'immagine $imageRef come GIF, se si utilizza
anche il secondo parametro, l'immagine sarà salvata e non inviata
in output. Questa funzione, come tutte le funzioni collegate alle GIF, non
è disponibile se si utilizza una versione 2.x delle GD
5. Distruggere l'immagine liberando la memoria
È possibile eliminare l'immagine dalla memoria prima che lo script sia terminato
utilizzando la funzione imageDestroy($imageRef). L'utilizzo di questa
funzione è superfluo se l'output dell'immagine è l'ultima operazione
dello script in quanto l'interprete libererà automaticamente la memoria
impiegata dal programma. Tuttavia è vivamente consigliabile usarla
se lo script non termina li! Se ad esempio volete salvare delle informazioni
nel database dopo aver inviato l'output è meglio liberare un po' di
memoria o si rischia di occupare tutta la memoria che il server mette a disposizione
di ogni thread php (per impostazione predefinita 8 MB).
Funzioni utili
Siamo quasi giunti al termine di questo lungo articolo ma ho ancora qualcosa
da esporvi. Ci sono alcune funzioni utili che vengono spesso utilizzate all'interno dei
programmi che utilizzano le GD.
Esse sono:
- imageCopyResized($imgDest, $imgSource, $destX, $destY, $srcX, $srcY,
$dstW, $dstH, $srcW, $srcH)
la classica funzione tanto usata per creare le thumbnail. Copia il rettangolo
dell'immagine $imgSource che ha come vertice superiore sinistro
il punto ($srcX, $srcY) ha come larghezza $srcW e altezza
$srcH nell'immagine $imageDest, più precisamente
nella porzione delimitata dal rettangolo avente come vertice superiore sinistro
il punto ($destX, $destY), ha come altezza $destH e larghezza
$destW. - imageCopyResampled($imgDest, $imgSource, $destX, $destY, $srcX, $srcY,
$dstW, $dstH, $srcW, $srcH)
è analoga alla funzione precedente solo che ad essa aggiunge
il resampling, vale a dire una correzione dell'errore e della precisione
del ridimensionamento. Molte volte risulta superfluo ma in caso ne abbiate
il bisogno, esiste! Questa funzione è stata introdotta nelle GD a
partire dalla versione 2.0. - getImageSize($path)
questa funzione restituisce in un array associativo le informazioni
dell'immagine specificata in $path. Fra queste informazioni c'è
il tipo dell'immagine (jpeg, gif, ecc), le dimensioni, e alcune utili informazioni
aggiuntive, come il tipo MIME o la stringa dei parametri HTML relativa alle
dimensioni. Questa funzione non richiede le librerie GD, vale a dire che
è possibile utilizzarla anche se non si dispone delle GD sul proprio
server.