L’argomento di questa settimana riguarda la gestione del ridimensionamento delle immagini in PHP.
Un problema ampiamente discusso sul web. E’ facile, infatti,
trovare script già pronti che permettono il ridimensionamento delle
immagini che, però, troppo spesso ci costringono
ad intervenire per correggere errori inaspettati.
Più che fornire un codice già pronto, l’intenzione è di far
capire al meglio come php ragiona con il ridimensionamento delle immagini.
Le librerie GD
Innanzitutto, precisiamo che la gestione delle immagini attraverso
il PHP è resa possibile grazie alle famose librerie GD. In base al formato di
immagine che vogliamo supportare potremmo avere bisogno di altre librerie. Per
quest’ultimo caso consiglio di leggere la documentazione dal sito ufficiale di
php.
Considerando i soli formati PNG, JPEG e GIF di
nostro interesse possiamo dire che sono tutti supportati, in particolare il
formato jpeg è supportato dalle versioni maggiori e uguali alla 1.8 mentre le
immagini GIF non sono supportate per le versioni tra 1.6 e 2.0.28.
Per tutte le informazioni sulla nostra installazione è
sufficiente utilizzare la funzione gd_info().
A questo punto, affrontiamo il problema di dover caricare
delle immagini con i formati menzionati e di fare in modo di ottenere un
ridimensionamento di esse ottenendo una immagine quadrata, con dimensione
scelta a priori. Vogliamo che questa immagine sia centrata rispetto
all’immagine originale.
La funzione di interesse, disponibile dalla versione 5 del
php è:
bool imagecopyresampled ( resource
$dst_image
, resource $src_image
, int $dst_x
, int$dst_y
, int $src_x
, int $src_y
, int $dst_w
, int $dst_h
, int $src_w
, int $src_h
)
questa funzione copia una porzione rettangolare da una
immagine ad un’altra. Tale attività comprende una operazione di interpolazione
tra i valori dei pixel per ridurre la dimensione di una immagine e conservare
comunque maggiore qualità possibile.
Facendo riferimento ai parametri indicati, la funzione
prende una area rettangolare dall’immagine src_image di larghezza src_w e
altezza src_h partendo dal punto (src_x,src_y) e la posiziona in una area
rettangolare di una immagine di destinazione (dst_image) di larghezza dst_w e
altezza dst_h alla posizione (dst_x,dst_y).
Se la sorgente e la destinazione hanno misure differenti,
vengono eseguite le operazioni di stretching o shrinking (allungamento o
riduzione) del frammento dell’immagine che si sta copiando. Le coordinate
indicate presuppongono che l’origine (cioè il punto 0,0) sia l’angolo in alto a
sinistra.
A questo punto, avendo a disposizione tutte le conoscenze
“tecniche” torniamo nel nostro caso di studio. Come già detto, vogliamo
ottenere una immagine quadrata di dimensione qualsiasi purché sia recuperata in
maniera tale che il centro di essa coincida con quello dell’immagine originale.
Prima di fornire il codice in PHP è meglio far chiarezza su
come bisogna ragionare per non incappare in errori di calcoli. Supponiamo di
avere una immagine di grandezza 4272x2848 pixel (le misure sono puramente
inventate l’importante è che la larghezza sia maggiore dell’altezza). Per fare
in modo che il ridimensionamento vada a buon fine, dobbiamo considerare un
aspetto cruciale: la porzione dell’immagine originale da ridimensionare deve
essere quadrata. Ma ciò non basta, il centro della porzione deve corrispondere
all’immagine originale. Per questo motivo, il nostro script dovrà fare dei
calcoli per recuperare la parte contornata in rosso in Figura
1
. Una volta fatto ciò, il metodo imagecopyresampled farà tutto per noi e
riusciremo ad ottenere l’immagine con le dimensioni scelte.
Figura 1 - Ridimensionamento immagini
Nel caso in esame i valori saranno:
- $dst_image = immagine ridimensionata
- $src_image = immagine originale
- $dst_x = 0
- $dst_y = 0
- $src_x = Coordinata x del centro dell’immagine originale – coordinata y del centro dell’immagine originale
- $src_y = 0
- $dst_w = 300
- $dst_h =300
- $src_w= 2848
- $src_h =2848
Nota: la coppia di valori ($src_x,$src_y) è il valore del punto che corrisponde all’angolo in alto a sinistra del quadrato rosso disegnato sull’immagine originale.
L'esempio è relativo al caso in cui l'immagine sia rettangolare, il codice che implementeremo farà differenza tra diversi casi: immagine rettangolare con larghezza maggiore dell'altezza o immagine rettangolare con altezza maggiore della larghezza. Nei due casi i ragionamenti sono gli stessi. Un ultimo caso che sarà considerato in fase di implementazione è quello in cui la dimensione dell'immagine è minore della misura indicata per il ridimensionamento. Ovviamente, in questo caso nessuna operazione verrà eseguita.
Implementazione
A questo punto possiamo passare all’implementazione del
codice che ho suddiviso in un file html e tre file php ciascuno con i seguenti
compiti:
- index.html : pagina che visualizza la form per il caricamento dell’immagine
<html>
<head>
<title>Ridimensionamento immagine</title>
</head>
<body>
<form method="post" action="sendImage.php" enctype="multipart/form-data">
<label>Nome file:</label>
<input type="text" name="nome" />
<br/>
<label>Carica la tua immagine da ridimensionare:</label>
<input type="file" name="userimg" />
<br />
<input type="submit" value="Invia" />
</form>
</body>
</html>
- sendImage.php : pagina richiamata dalla form
<?php
require_once( 'UFileSystemManager.php' );
require_once( 'UImage.php' );
if(isset($_FILES['userimg']))
{
$file = $_FILES['userimg'];
if($file['error'] == UPLOAD_ERR_OK and is_uploaded_file($file['tmp_name']))
{
$imgToProcess=$file['tmp_name'];
}
}
if(isset($_POST['nome']))
{
$nome=$_POST['nome'];
}
$UImage= new UImage();
$infoimmagine=getimagesize($imgToProcess);
$tipo=$UImage->GetTypeImage($infoimmagine[2]);
$UFileSystemManager=new UFileSystemManager();
$newImage=$UImage->Ridimensiona($imgToProcess,300);
$UFileSystemManager->SalvaImmagine($nome,$newImage,$tipo);
?>
- UFileSystemManager.php : pagina che contiene la classe con responsabilità di salvare l’immagine sul file system
<?php
class UFileSystemManager
{
public function __construct() {}
public function SalvaImmagine($nomeImmagine,$immagine,$tipo)
{
$istruzione='image'.$tipo.'($immagine,$nomeImmagine.\'.\'.$tipo);';
eval($istruzione);
return $nomeImmagine.".".$tipo;
}
}
?>
- UImage.php : la classe con il compito di interagire con le librerie grafiche per il ridimensionamento
<?php
class UImage
{
public function __construct() {}
public function GetTypeImage($var)
{
switch($var)
{
case 1:
return 'gif';
case 2:
return 'jpeg';
case 3:
return 'png';
default:
return false;
}
}
public function Ridimensiona($src,$dim)
{
$dst_w=$dim;
$dst_h=$dim;
$size = getimagesize($src);
if( $size[2] == 2 ){$src_image = @imagecreatefromjpeg($src);}
elseif( $size[2] == 1 ){$src_image = @imagecreatefromgif($src);}
elseif( $size[2] == 3 ){$src_image = @imagecreatefrompng($src);}
$dst_x=0;
$dst_y=0;
if( $size[0]>$dim or $size[1]>$dim )
{
$centerX = $size[0]/2;
$centerY = $size[1]/2;
if( $size[0] > $size[1] ){
$src_y = 0;
$src_x = $centerX-$centerY;
$src_h = $size[1];
$src_w = $size[1];
}
else{
$src_x = 0;
$src_y = $centerY-$centerX;
$src_w = $size[0];
$src_h = $size[0];
}
$dst_image = imagecreatetruecolor($dim, $dim);
imagecopyresampled ( $dst_image , $src_image , $dst_x , $dst_y , $src_x , $src_y , $dst_w , $dst_h , $src_w , $src_h );
}
else{
$dst_image = $src_image;
}
return $dst_image;
}
}
Sviluppi futuri:
- Supporto alla trasparenza
- Caricamento immagini con visualizzazione dell’anteprima sul browser
- Possibilità di scegliere come centrare l’immagine
0 commenti:
Posta un commento