PHP – GD: Ridimensionare le immagini mantenendone le proporzioni

Ciao ragazzi,
come è ben noto a chi per lavoro o per passione sviluppa pagine web, le immagine che vengono elaborate in una pagina, hanno un aspetto molto importante e sicuramente non trascurabile, in quanto un’immagine di grande dimensioni in termini di MB andrà ad influenzare sul tempo di caricamento della pagina.

Ipotizziamo di dover sviluppare una galleria di immagini per un sito web commissionato da un concessionario di auto, ed immaginate che la pagina di anteprima delle auto visualizzerà a schermo una matrice di immagini 4×4 e se in gioco ci sono delle immagini ad alta risoluzione con un peso medio di 4MB a foto, fatti due calcoli al otteniamo:

foto da visualizzare: 4×4 = 16 Foto
peso totale: 16×4 = 64 MB

Ovviamente con cifre del genere la cosa non è assolutamente ragionevole!!
Possiamo risolvere il problema ridimensionando “al volo” le immagini da visualizzare nella galleria tramite una libreria grafica php chiamata GD.

I passi da compiere nella pagina che si occuperà per ridimensionamento delle immagini sono i seguenti:

  • recuperare le informazioni dell’immagine
  • scegliere una dimensione di larghezza (width) fissa
  • calcolare le nuove dimensioni dell’immagine in proporzione alla nuova larghezza
  • creare la nuova immagine
  • creare l’header per visualizzare l’immagine “al volo”

Vediamo adesso la funzione che si occuperà di creare la nuova immagine, ed i suoi parametri:

imagecopyresampled($image_thumb, $image_src, a, b, c, d, $new_width, $new_height, $width, $height);
  • $image_thumb sarà il “box” dove sarà salvata l’immagine ridimensionata.
  • $image_src è l’immagine che vogliamo ridimensionare
  • a e b sono delle coordinate che indicano il punto di partenza da dove sarà creata l’immagine all’interno del del box cioè:facciamo finta che l’immagine da ridimensionare misuri: 1920×1080
    e abbiamo deciso che la galleria dovrà visualizzare immagini di larghezza pari a 400, facendo i calcoli per trovare la nuova l’altezza in modo proporzionale alla nuova larghezza, otteniamo:
    nuova_altezza = 400 * 1080 / 1920 = 225
    quindi la nuova immagina misurerà : 400x225Precedentemente abbiamo anche detto che $image_thumb andrà a contenere la nuova immagine come se fosse un box quindi, di conseguenza dovrà misure 400x225A questo punto immaginate tale box come se fosse quel riquadrino con i bordi neri disegnato sugli album delle figurine, i quali delimitano la zona dove andare ad incollare la figurina,
    adesso se pensate a l’angolo alto a sinistra di tale riquadrino vi sarà già tutto chiaro,
    in pratica l’uso delle coordinate a e b, non farà altro che permettervi di spostare ( OffSet ) l’immagine più a destra(a) e più in basso(b) rispetto i lati che compongono tale angolo cioè i bordi del box.Ecco un’immagine con OffSet a=10 b=50 che rende la cosa più chiara:

php_GD_offset

Le coordinate c e d invece indicano il punto di partenza da dove sarà ritagliata l’immagine, impostando sempre un OffSet partendo dai lati che formano l’angolo alto sinistro dell’immagine.
A cosa servono invece questi parametri??
Se abbiamo ad esempio un header con una misura ben precisa, ad esempio 600×200
è chiaro che se andremo a ridimensiore un’immagine con un Aspect ratio diverso dalle dimensione dell’header l’immagine risulterà uno schifo !!!
Quindi conviene ritagliare una parte a nostra scelta dell’immagine che poi andremo ad inserire nel nostro header.

Vediamo un esempio utilizzando sempre l’immagine precedente:

creiamo un box ($image_thumb) che misuri 500×200 ed impostiamo un OffSet di ritaglio rispettivamente c=70 e d=60 però questa volta senza ridimensionare l’immagine, mantendendo $new_width e $new_height uguali a $ width e $ height cioè uguali alle misure dell’immagine originale.
Tutto questo ritaglierà l’immagine iniziando da 10px da sinistra e 30px dall’alto, ottenendo il seguente risultato:

php_GD_crop

A questo punto vi sarà sicuramente chiaro che:

  • $new_width e $new_height servono a specificare le nuove dimensione che dovrà avere l’immagine, che come abbiamo visto, nel primo caso le abbiamo calcolate per ottenere la nuove immagine con senza perdere Aspect ratio originale, mentre invece nel secondo coincidevano con le dimensioni dell’immagine originale.

In fine

  • $width e $ height indicano semplicemente le dimensioni dell’immagine che intendiamo ridimensionare.

Ok, fatta la teoria si passa alla pratica, vediamo il codice della pagina php che si occuperà di ridimensionare le immagini:

<?php

$image = $_GET["img"];

list($width, $height, $type) = getimagesize($image);


if        ($type == 1) $image_src = imagecreatefromgif($image);
else if   ($type == 2) $image_src = imagecreatefromjpeg($image);
else if   ($type == 3) $image_src = imagecreatefrompng($image);
else                   echo "Formato immagine non valido!";

$new_width = 400;
$new_height = $new_width * ( $height / $width );
$image_thumb = imagecreatetruecolor($new_width, $new_height);

imagecopyresampled($image_thumb, $image_src , 0, 0, 0, 0, $new_width, $new_height, $width, $height);


if ($type == 1) {
  header("Content-type: image/gif");
  imagegif($image_thumb);
  imagedestroy($image_thumb);
  imagedestroy($image_src);
}
else if ($type == 2) {
  header("Content-type: image/jpeg");
  imagejpeg($image_thumb);
  imagedestroy($image_thumb);
  imagedestroy($image_src);
}
else if ($type == 3) {
  header("Content-type: image/png");
  imagepng($image_thumb);
  imagedestroy($image_thumb);
  imagedestroy($image_src);
}

?>

In fine vediamo come richiamare il tutto dalla pagina che si occuperà di visualizzare la galleria immagini

<!doctype html>
<html lang="it">
<head>
  <title>PHP - GD | Galleria immagini - Ridimensionare immagini al volo</title>
</heaa>
<body style="text-align:center;">
  
  <h1>PHP - GD | Galleria immagini - Ridimensionare immagini al volo</h1>
  <img src="/thumb.php?img=immagini/immagine1.jpg" title="immagine.jpg" />
  <img src="/thumb.php?img=immagini/immagine2.jpg" title="immagine2.jpg" />
  <img src="/thumb.php?img=immagini/immagine3.jpg" title="immagine3.jpg" />
  
</body>
</html>

a questo punto è giusto anche farvi sapere, che si potrebbe anche intervenire sulla qualità dell’immagine riducendone ad esempio un 20%.
Per fare ciò basta andare a sostituire l’ultima parte del codice, nella pagina che si occupa si ridimensionare l’immagine in questo:
(per rendervi tutto pronto al copia-incolla vi riporto di nuovo tutta la pagina con l’ultima parte modificate)

<?php
 
$image = $_GET["img"];
 
list($width, $height, $type) = getimagesize($image);
 
if        ($type == 1)  $image_src = imagecreatefromgif($image);
else if   ($type == 2)  $image_src = imagecreatefromjpeg($image);
else if   ($type == 3)  $image_src = imagecreatefrompng($image);
else                    echo "Formato immagine non valido!";
 
$new_width = 400;
$new_height = $new_width * ( $height / $width );
$image_thumb = imagecreatetruecolor($new_width, $new_height);
 
imagecopyresampled($image_thumb, $image_src , 0, 0, 0, 0, $new_width, $new_height, $width, $height);
header("Content-type: image/jpeg");
 
 
// con 80 andiamo a ridurre la qualità dell'immagine dal 100% all'80%;
// che andrà ad incidere POSITIVAMENTE sul peso dell'immagine

imagejpeg($image_thumb, NULL, 80)
imagedestroy($image_thumb);
imagedestroy($image_src);
 
?>

abbiamo finito e come al solito vi auguro buon lavoro ;)