16 ottobre 2010

La trasparenza, il PNG e le GD

Buongiorno a tutte le carissime lettrici ed i carissimi lettori del Bestiario!

Come forse alcuni di voi sapranno, uno degli scopi di questo blog è quello di preservare il più a lungo possibile la memoria di soluzioni che ho trovato a svariati problemi (e non solo a carattere informatico).
Sfortunatamente per chi non distingue un bit da un byte, oggi vi parlerò di come fare una pernacchia al computer dispettoso e quindi preservare la trasparenza in un'immagine ridimensionata con le care librerie GD di PHP.

Non mi soffermo a spiegare in cosa consistono, perché se non avete la minima idea di cosa sto parlando, difficilmente avrete bisogno di questo barbatrucco: vi dico solo che le GD sono una raccolta di funzioni che vi semplificano la vita quando dovete manipolare delle immagini lato server con il nostro amico PHP.

Ma passiamo subitamente ad illustrare il problema!
Abbiamo la nostra bellissima png, rappresentante un dolce velociraptor che divora un malvagio essere umano. Questa stupenderrima immagine ha uno sfondo trasparente, perché nella nostra infinita genialità vogliamo rappresentare il nostro amico dinosauro mentre divora il reo uomo in diversi ambienti, sovrapponendola ad uno sfondo ogni volta diverso: in una giungla, in metropolitana, sulla cima dell'Everest, in mezzo ad uno stadio di calcio, in un love hotel ed infine sulla Luna.
Il nostro gentilissimo velociraptor dovrà essere caricato su un server web, in modo che tutto il mondo possa esaltarne l'infinita umanità. Sorge però un problema: l'immagine ha dimensioni troppo grandi per essere caricata così come è (supponiamo sia un 18374 X 18374 pixel) e non disponiamo di un programma per ridimensionarla...o meglio ci scocciamo di farlo (il più delle volte però si tratterà di far fare l'upload a qualcuno per cui GIMP è un nuovo detersivo: e per questo verrà fatto sbranare giustamente dal velociraptor).

Comunque!
Non ci scoraggiamo! Chiediamo l'aiuto del pubblico e scopriamo che le GD ci permettono di ridimensionare le immagini come vogliamo!
Vi domanderete come! Ecco, così:


$nuovaImmagine = imagecreatetruecolor($nuova_larghezza, $nuova_altezza);
$immagineCaricata = imagecreatefrompng("DOVE_SI_TROVA_IMG_TEMP_SUL_SERVER");
$vecchia_larghezza = imagesx($immagineCaricata);
$vecchia_altezza = imagesy($immagineCaricata);
imagecopyresampled($nuovaImmagine, $immagineCaricata, 0, 0, 0, 0, $nuova_larghezza, $nuova_altezza, $vecchia_larghezza, $vecchia_altezza);
imagepng($nuovaImmagine, "PERCORSO_DEFINITIVO_DI_SALVATAGGIO");
imagedestroy($nuovaImmagine);


Rapida spiegazione:
1. creiamo un'immagine di supporto di dimensioni uguali a quelle desiderate
2. istanziamo l'immagine prelevandola dal percorso temporaneo in cui php l'ha piazzata dopo il caricamento
3. recuperiamo la larghezza dell'immagine caricata
4. recuperiamo l'altezza dell'immagine caricata
5. con imagecopyresampled, copiamo l'immagine caricata sopra quella di supporto e contemporaneamente la ridimensioniamo alle grandezze corrette, indicando anche quelle originali
6. salviamo l'immagine ottenuta come png nel percorso desiderato
7. puliamo un po' in giro per casa

Bello eh? Peccato che così facendo la vostra trasparenza va a farsi benedire, sostituita da uno sfondo nero che mal si addice alla gioiosa vivacità del nostro velociraptor.
Che fare?
Semplice! Introduciamo un paio di istruzioni che ci salvano il popò!

imagecopyresampled($nuovaImmagine, $immagineCaricata, 0, 0, 0, 0, $nuova_larghezza, $nuova_altezza, $vecchia_larghezza, $vecchia_altezza);
imagealphablending( $nuovaImmagine, false );
imagesavealpha( $nuovaImmagine, true );


Avete capito bene: subito dopo imagecopyresampled e prima del salvataggio, inseriamo i comandi per preservare la nostra trasparenza ed il gioco è fatto!
Il nostro adorato velociraptor può sbranarsi l'immondo uomo in tutti i luoghi del mondo! Persino davanti alle piramidi!

Ma andiamo un passo oltre! Ci potrebbe anche capitare di voler partire da un'immagine con trasparenza e di voler ottenere un'immagine ridimensionata ma con uno sfondo bianco. Togliamo quindi le ultime due istruzioni presentate? Col cavolo! Perché la nostra $nuovaImmagine è stata creata con imagecreatetruecolor, che, come tutti voi sapete, crea un'immagine delle dimensioni passate come parametro ma completamente ed inesorabilmente nera.
Fine dei giochi?

Tsk, la Compiuta Donzella del 2000, che poi sarei io, non si arrende così facilmente. Anche perché la soluzione è davvero una stupidaggine! XD
Teniamo il codice precedente (comprensivo di imagealphablending e imagesavealpha) e prima del imagecopyresampled piazziamo queste due istruzioni:

$white = imagecolorallocatealpha($nuovaImmagine, 255, 255, 255,0);
imagefill($nuovaImmagine, 0, 0, $white);


In parole povere, creiamo il colore bianco e diciamo alle GD di "imbiancare" la nostra immagine di supporto.
Così facendo la trasparenza del PNG caricato farà vedere il bianco dell'immagine di supporto.

Così è deciso! L'udienza è tolta!


P.S. Per la realizzazione di questo post non è stato maltrattato alcun velociraptor

Nessun commento :