[PHP]: ThumbAndCrop (Resize & Crop Immagini con PHP)


Ecco a voi una nuova classe presa dalla mia dispensa, anzi dal mio cervello visto che l’ho scritta ieri notte! 🙂

Quante volte ci è capitato di dover effettuare una miniatura di un immagine via php, molte volte ci si dimentica le funzioni e i loro parametri, poi bisogna usare la funzione adatta al tipo di immagine da manipolare, ecc… ecc…

Oggi vi presento questa nuova classe php che ho nominato: Thumb And Crop ovvero rimpicciolisci e ritaglia.

Grazie a questa classe potremo:


Ottenere le dimensioni di un immagine

Ottenere le dimensioni di un immagine mantenendo le proporzioni

Creare una miniatura di un immagine

Ritagliare un pezzo di un immagine

Combinare la funzione Crop alla Thumb per avere una foto ritagliata e rimpicciolita

Manipolare un immagine Jpeg, Gif, Png, Bmp senza cambiare il codice in base al tipo di immagine.

Veniamo ora al codice della classe:

<?php
	class ThumbAndCrop
	{

		private $handleimg;
		private $original = "";
		private $handlethumb;
		private $oldoriginal;

		/*
			Apre l'immagine da manipolare
		*/
		public function openImg($file)
		{
			$this->original = $file;

			if($this->extension($file) == 'jpg' || $this->extension($file) == 'jpeg')
			{
				$this->handleimg = imagecreatefromjpeg($file);
			}
			elseif($this->extension($file) == 'png')
			{
				$this->handleimg = imagecreatefrompng($file);
			}
			elseif($this->extension($file) == 'gif')
			{
				$this->handleimg = imagecreatefromgif($file);
			}
			elseif($this->extension($file) == 'bmp')
			{
				$this->handleimg = imagecreatefromwbmp($file);
			}
		}

		/*
			Ottiene la larghezza dell'immagine
		*/
		public function getWidth()
		{
			return imageSX($this->handleimg);
		}

		/*
			Ottiene la larghezza proporzionata all'immagine partendo da un'altezza
		*/
		public function getRightWidth($newheight)
		{
			$oldw = $this->getWidth();
			$oldh = $this->getHeight();

			$neww = ($oldw * $newheight) / $oldh;

			return $neww;
		}

		/*
			Ottiene l'altezza dell'immagine
		*/
		public function getHeight()
		{
			return imageSY($this->handleimg);
		}

		/*
			Ottiene l'altezza proporzionata all'immagine partendo da una larghezza
		*/
		public function getRightHeight($newwidth)
		{
			$oldw = $this->getWidth();
			$oldh = $this->getHeight();

			$newh = ($oldh * $newwidth) / $oldw;

			return $newh;
		}

		/*
			Crea una miniatura dell'immagine
		*/
		public function creaThumb($newWidth, $newHeight)
		{
			$oldw = $this->getWidth();
			$oldh = $this->getHeight();

			$this->handlethumb = imagecreatetruecolor($newWidth, $newHeight);

			return imagecopyresampled($this->handlethumb, $this->handleimg, 0, 0, 0, 0, $newWidth, $newHeight, $oldw, $oldh);
		}

		/*
			Ritaglia un pezzo dell'immagine
		*/
		public function cropThumb($width, $height, $x, $y)
		{
			$oldw = $this->getWidth();
			$oldh = $this->getHeight();

			$this->handlethumb = imagecreatetruecolor($width, $height);

			return imagecopy($this->handlethumb, $this->handleimg, 0, 0, $x, $y, $width, $height);
		}

		/*
			Salva su file la Thumbnail
		*/
		public function saveThumb($path, $qualityJpg = 100)
		{
			if($this->extension($this->original) == 'jpg' || $this->extension($this->original) == 'jpeg')
			{
				return imagejpeg($this->handlethumb, $path, $qualityJpg);
			}
			elseif($this->extension($this->original) == 'png')
			{
				return imagepng($this->handlethumb, $path);
			}
			elseif($this->extension($this->original) == 'gif')
			{
				return imagegif($this->handlethumb, $path);
			}
			elseif($this->extension($this->original) == 'bmp')
			{
				return imagewbmp($this->handlethumb, $path);
			}
		}

		/*
			Stampa a video la Thumbnail
		*/
		public function printThumb()
		{
			if($this->extension($this->original) == 'jpg' || $this->xtension($this->original) == 'jpeg')
			{
				header("Content-Type: image/jpeg");
				imagejpeg($this->handlethumb);
			}
			elseif($this->extension($this->original) == 'png')
			{
				header("Content-Type: image/png");
				imagepng($this->handlethumb);
			}
			elseif($this->extension($this->original) == 'gif')
			{
				header("Content-Type: image/gif");
				imagegif($this->handlethumb);
			}
			elseif($this->extension($this->original) == 'bmp')
			{
				header("Content-Type: image/bmp");
				imagewbmp($this->handlethumb);
			}
		}

		/*
			Distrugge le immagine per liberare le risorse
		*/
		public function closeImg()
		{
			imagedestroy($this->handleimg);
			imagedestroy($this->handlethumb);
		}

		/*
			Imposta la thumbnail come immagine sorgente,
			in questo modo potremo combinare la funzione crea con la funzione crop
		*/
		public function setThumbAsOriginal()
		{
			$this->oldoriginal = $this->handleimg;
			$this->handleimg = $this->handlethumb;
		}

		/*
			Resetta l'immagine originale
		*/
		public function resetOriginal()
		{
			$this->handleimg = $this->oldoriginal;
		}

		/*
			Estrae l'estensione da un file o un percorso
		*/
		private function extension($percorso)
		{
			if(eregi("[\|\\]", $percorso))
			{
				// da percorso
				$nome = $this->nomefile($percorso);

				$spezzo = explode(".", $nome);

				return strtolower(trim(array_pop($spezzo)));
			}
			else
			{
				//da file
				$spezzo = explode(".", $percorso);

				return strtolower(trim(array_pop($spezzo)));
			}
		}

		/*
			Estrae il nome del file da un percorso
		*/
		private function nomefile($path, $ext = true)
		{
			$diviso = spliti("[/|\\]", $path);

			if($ext)
			{
				return trim(array_pop($diviso));
			}
			else
			{
				$nome = explode(".", trim(array_pop($diviso)));

				array_pop($nome);

				return trim(implode(".", $nome));
			}
		}
	}
?>

Salviamo il file come thumbncrop.inc.php ed apriamo il file di esempio per provare la classe e scriviamo il seguente codice:

	// includo la classe
	require_once("libs/thumbncrop.inc.php");

	// valorizzo la variabile
	$tb = new ThumbAndCrop();

Come si può vedere abbiamo solamente incluso la classe, e valorizzato la variabile $tb.

Spiegazione delle funzioni:

In anzitutto la prima funzione da utilizzare obbligatoriamente è “openImg” passando come parametro il nome del file da aprire.

$tb->openImg(“ghi.jpg”);

Dopo-di-ché abbiamo le funzioni per ottenere le dimensioni dell’ immagine aperta:

$tb->getHeight();

$tb->getWidth();

Invece se dobbiamo ridimensionare l’immagine mantenendo le proporzioni basterà usare una di queste 2 funzioni, passando come parametro la larghezza/altezza di riferimento… esempio: dopo aver aperto l’immagine, se vogliamo ridimensionarla in larghezza a 100 pixels mantenendo l’altezza proporzionata, basterà usare la funzione “getRightHeight” passando come parametro, la larghezza indicativa ovvero 100.

$newHeight = $tb->getRightHeight(100);

$newWidth = $tb->getRightWidth(75);

Dopo aver calcolato le dimensioni passiamo ora a creare la miniatura con la funzione “creaThumb” e passando come parametro la larghezza e l’altezza da ottenere.

$tb->creaThumb(100, $newHeight);

Ora possiamo scegliere se printare a video l’immagine con la funzione “printThumb” (l’header verrà inviato in automatico non bisogna inserirlo a mano), oppure salvare l’immagine su disco con la funzione “saveThumb” passando come parametro il nome del file da creare, e nel caso sia un jpg anche la qualità dell’immagine finale (default: 100).

$tb->printThumb();

$tb->saveThumb(“cropthumb.jpg”);

Dopo-di-ché non ci resta che chiudere l’immagine aperta, per liberare le risorse con “closeImg”.

$tb->closeImg();

Oltre alla miniatura possiamo creare una piccola immagine contenente un ritaglio dell’immagine sorgente, basterà usare la funzione “cropThumb” prima di “closeImg”, infatti anche dopo aver usato l’immagine originale per creare una miniatura o ritagliare un pezzo dell’immagine, utilizzando di nuovo le funzioni senza chiudere l’immagine, potremo lavorare ancora sull’immagine originale…

Quindi potremo creare N miniature per volta usando semplicemente la funzione “creaThumb” e la stessa cosa vale anche per “cropThumb”.

La funzione “cropThumb” richiede 4 parametri, e sono larghezza finale, altezza finale, coordinata X dell’immagine originale dal quale iniziare a copiare l’immagine, coordinata Y dell’immagine originale dal quale iniziare a copiare l’immagine.

E se volessimo combinare le funzione rimpicciolisci e ritaglia? Ad esempio partendo da un’immagine 400×300, creare una miniatura 100×50 partendo a 20px dall’alto. Vediamo il codice in riferimento a quello precedentemente scritto:

	// creo la miniatura con le dimensioni da me volute
	$tb->creaThumb(100, $newHeight);

	// abilito il ThumbAndCrop
	$tb->setThumbAsOriginal();

	// taglio l'img a dimensione 100x50 artendo dalla thumb x:0, y:20
	$tb->cropThumb(100, 50, 0, 20);

Come possiamo vedere creiamo prima la miniatura da 400×300 (immagine originale) a 100×75 (miniatura proporzionata), dopo-di-ché usando la funzione “setThumbAsOriginal” setto la miniatura come immagine originale, quindi a partire da questo momento, ogni operazione fatta con le funzioni verrà effettuata sulla miniatura e non più sull’immagine originale! (per ripristinare l’immagine originale basterà utilizzare la funzione “resetOriginal”. Ed ora ritaglio un’immagine di 100×50 partendo dalle coordinate della miniature X:0 ed Y:20.

Spero che la classe vi possa essere utile, lasciate qualche commento se apprezzate! 😉

Scarica i file di esempio: ThumbAndCrop



20 Commenti

  1. Loelle80 ha detto:

    niente da fare provato in mille modi e con mille immagini ma compare sempre la seguente scritta:
    The image “nome sito” cannot be displayed because it contains errors
    c’è qualche soluzione?

    • Stefano Venneri ha detto:

      Senza conoscere il tuo codice è impossibile trovare l’errore…

      in alternativa comunque puoi omettere la funzione: $tb->printThumb(); e richiamare il file per vedere chiaramente l’errore riportato ed andare a correggerlo.

      • Loelle80 ha detto:

        ok ho trovato l’errore!! cmq complimenti per lo script da manuale anche per quanto riguarda i commenti e le coding rules!!

        • Loelle80 ha detto:

          sei a conoscenza di questa cosa assurda?
          (fai conto che i numeri ovviamente non sono nel codice ma sono i primi numeri delle righe, ci son solo per provare a farti capire la situazione)

          sei nella pagina php scrivo

          1 openImg(“../upload/immagini_news/1332156668bandiera.jpg”);

          $tb->getHeight();

          $tb->getWidth();

          $newHeight = $tb->getRightHeight(100);

          $newWidth = $tb->getRightWidth(75);

          $tb->creaThumb(100, $newHeight);

          // creo la miniatura con le dimensioni da me volute
          $tb->creaThumb(100, $newHeight);

          // abilito il ThumbAndCrop
          $tb->setThumbAsOriginal();

          // taglio l’img a dimensione 100×50 artendo dalla thumb x:0, y:20
          $tb->cropThumb(100, 50, 0, 20);

          $tb->printThumb();

          $tb->closeImg();
          ?>

          funziona tutto correttamente.

          se invece do un invio all’inizio della pagina e cioè:

          1
          2 openImg(“../upload/immagini_news/1332156668bandiera.jpg”);

          $tb->getHeight();

          $tb->getWidth();

          $newHeight = $tb->getRightHeight(100);

          $newWidth = $tb->getRightWidth(75);

          $tb->creaThumb(100, $newHeight);

          // creo la miniatura con le dimensioni da me volute
          $tb->creaThumb(100, $newHeight);

          // abilito il ThumbAndCrop
          $tb->setThumbAsOriginal();

          // taglio l’img a dimensione 100×50 artendo dalla thumb x:0, y:20
          $tb->cropThumb(100, 50, 0, 20);

          $tb->printThumb();

          $tb->closeImg();
          ?>

          non funziona più e mi da a video:
          Warning: Cannot modify header information – headers already sent by (output started at xxx on line xxx
          ÿØÿàJFIFÿþ>CREATOR: gd-jpeg v1.0 (using IJG JPEG v62), default quality ÿÛC    $.’ “,#(7),01444’9=82<.342ÿÛC  2!!22222222222222222222222222222222222222222222222222ÿÀ2d"ÿÄ ÿĵ}!1AQa"q2‘¡#B±ÁRÑð$3br‚ %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyzƒ(ecc. ecc.)

          com'è possibile? hai riscontrato anche tu questo problema?

  2. Roi ha detto:

    Ciao, mi spieghi cortesemente come faccio a ritagliare in automatico le immagini che inserisco nei post wordpress con un link esterno (senza upload intendo). Nel file style.css ho inserito questa stringa:

    .entry-content img {
    width:600px;
    height:400px;
    }

    con questa però riesco solo a stabilire altezza e larghezza standard, ma non riesco a fare il crop dell’immagine, cioè a ritagliarla fino ad arrivare a queste dimensioni senza deformare l’immagine. Mi spieghi come fare? non ho trovato niente su google. Attendo tue notizie, grazie in anticipo!

    • Stefano Venneri ha detto:

      Ciao,
      considerando che tu vuoi croppare le foto automaticamente, senza upparle, e senza passare da uno script, ti consiglio di dare un occhiata ad una di queste 3 tecniche in questo tutorial per effettuare un finto crop sulle immagini con i css…

      http://css.html.it/articoli/leggi/3169/tre-tecniche-per-il-falso-cropping-di-immagini/

      Altrimenti se necessiti di un vero crop, dovrai crearti con la mia classe uno script che fa il crop on-the-fly e linkare le immagini nel tag img del tipo:

      immagine.php?foto=http://miosito.com/fotopresa.jpg&width=600&height=400&crop=1

      Per quanto riguarda questo script per il crop on-the-fly dovrai (a causa del mio poco tempo) provvedere da solo utilizzando la mia classe e un pò di calcolo delle proporzioni matematiche 😉

      • Roi ha detto:

        Ti ringrazio stefano ma non ho capito tanto :-(…. nel mio file style.css dove ho inserito

        .entry-content img {
        width:600px;
        height:400px;
        }

        cos’altro devo aggiungere per croppare la foto senza upparla e senza passare per uno script. il mio tema wordpress, nel file loop-single.php, contiene un0unica voce “entry-content”. Quindi suppongo che le modifiche da fare in style.css riguardano la riga “.entry-content img”, giusto?

        • Stefano Venneri ha detto:

          Il tema puoi benissimo modificarlo per aggiungere altri tag, o altrimenti lavorare su entry-content img.

          Segui bene il link e vedrai che riuscirai! 😉

  3. Zakamoto ha detto:

    Genio ! 🙂

  4. Olinad ha detto:

    Ahaha beh io odio wordpress quindi siamo pari 😛

    Pensavo anch’io di farmi un cms da solo tempo fa, ma non ho il tempo di starci dietro e quindi preferisco adattarmi quelli esistenti ^^

  5. StefanoV ha detto:

    Ehm… odio Joomla 😛 😛

    Di solito uso wordpress altrimenti uso il CMS che ho creato io che è ankora meglio ed integra le features di joomla, wordpress e drupal più altre chicche di mia invenzione, tipo la lettura mail dal provider tramite Imap ecc…

    Vorrei pubblicarlo ma dovrei registrarlo, metterlo sotto licenza, e poi a codice libero salterebbero molti bug fuori e i miei clienti sarebbero a rischio se non li aggiorno sempre (ad avercelo il tempo di aggiornare sempre)

    Cmq casomai mi troverò ad usare obbligatoriamente joomla (sotto catene), se avrò bisogno ti chiederlo una mano sul tuo blog 😉 Grazie mille

  6. Olinad ha detto:

    Sì, Olinad è Danilo al contrario 🙂

    Ci ho messo un po' a rispondere, sia perchè c'è stata una gita scolastica di mezzo, sia perchè non ritrovavo più il blog nei preferiti (dovrò fare le pulizie di primavera XD). Purtroppo mi sono dimenticato di mettere links nei credits -.-'' ma ovvierò nella prossima versione con un link al blog, che mi è parso pieno di robina interessante :3 Ti farò sapere se utilizzerò qualcos'altro ^^

    Anche se usi WordPress, tienimi a mente se mai utilizzerai Joomla che sarò più che contento di darti una mano 😉

  7. StefanoV ha detto:

    Ciao (Olinad è Danilo al contrario vero? 🙂 ),

    ti ringrazio per aver scelto la mia classe per il tuo modulo.

    Non sei obbligato se vuoi a mettere il credit, ma ti ringrazio per avermi comunicato l'utilizzo della mia classe 🙂

    Come link puoi usare quello di questo blog in generale, o direttamente la pagina nel blog della classe.

  8. Olinad ha detto:

    Ciao,

    ho utilizzato la tua classe nel mio modulo per Joomla, che si chiama mod_aidanews. La versione attuale ancora non la utilizza, ma stasera o domani caricherò quella nuova. Conto di mettere dei credits con un link a questo sito – fammi sapere se hai qualche preferenza al riguardo 🙂

  9. StefanoV ha detto:

    Volevo informarvi che ho riscontrato alcuni bug sulla creazione delle miniature con trasparenza, correggerò a breve…

    In più tutte le classi saranno convertire in PHP 5.3 non appena tutti gli hoster avranno questa versione (lasciando ovviamente il download anche per la versione precedente)

  10. Lotti ha detto:

    mmm…
    if(preg_match(”/[\|\\]/i”, $percorso)) –> genera errori.

    if(preg_match(”/[\|\\]]/i”, $percorso)) –> così no.. ma non sono in grado di dire se è la stessa espressione regolare del tuo eregi originale perchè non me ne intendo e non riesco a capirlo anche se mi sto documentando da 20 minuti..

  11. Lotti ha detto:

    Ciao! molto utile questa classe! 🙂 volevo farti notare che eregi è diventato deprecato con l’ultima versione del php e dovresti sostituirlo con preg_match..

    if(eregi(“[\|\\]”, $percorso))
    =====>
    if(preg_match(“/[\|\\]/i”, $percorso))

  12. StefanoV ha detto:

    😀

    Cmq annuncio che è stato rilevato un errore… per mia dimenticanza il supporto all’estensione bitmap non funziona correttamente…

    Correggerò non appena avrò 2 minuti liberi! 😉

%d blogger hanno fatto clic su Mi Piace per questo: