2009-12-30 14 views
6

Ho un'applicazione che consente agli utenti di caricare immagini. Il test case che utilizzo è un jpeg di 1,6 MB con dimensioni 3872 x 2592 px. Lo script di upload nel back-end ridimensionerà l'immagine caricata in 6 formati aggiuntivi:Come velocizzare il ridimensionamento delle immagini in un'applicazione PHP CodeIgniter?

  • quadrato (piccole 75 x 75)
  • piccolo pollice (50 x 38)
  • pollice (100 x 76)
  • Piccolo (240 x 161)
  • medio (500 x 378)
  • grandi dimensioni (1024 x 774)

lo so E 'molto, ma credimi, ho bisogno di questo. Faccio il ridimensionamento usando la classe Manipolazione delle immagini di Code Igniter, che usa GD, GD2 o ImageMagick per eseguire il ridimensionamento. Per prima cosa l'ho configurato per usare GD2 e ho notato che il processo di ridimensionamento totale impiega 11 secondi.

Poiché l'utente deve attendere questo processo, non è accettabile. Dopo un sacco di lettura ho imparato che ImageMagick è una libreria molto più veloce ed efficiente la manipolazione, così sono passato a che:

$sourceimage = $data['filedata']['file_path'] . $data['imagedata']['user_id'] . "/" . $imageid . $data['filedata']['file_ext']; 
$resize_settings['image_library'] = 'imagemagick'; 
$resize_settings['library_path'] = '/usr/bin'; 
$resize_settings['source_image'] = $sourceimage; 
$resize_settings['maintain_ratio'] = false; 
$resize_settings['quality'] = "100%"; 
$this->load->library('image_lib', $resize_settings); 

Con mia grande sorpresa, il processo di ridimensionamento ora richiede più tempo: 15 secondi per essere precisi.

Dando un'occhiata al mio registro, vedo che ogni azione di ridimensionamento richiede 2 secondi, indipendentemente dal formato di file a cui si sta ridimensionando. Immagino sia perché ridimensiono sempre l'originale, che è molto grande.

Non vorrei scaricare il processo di ridimensionamento in un processo pianificato, perché ciò diminuirebbe l'usabilità del sito. Significa che gli utenti devono attendere qualche minuto prima di poter iniziare a vedere/lavorare con l'immagine.

Quindi, ci sono dei modi intelligenti per accelerare drasticamente questo processo di ridimensionamento in modo da poterlo mantenere in tempo reale? Basta essere chiari: consentire risoluzioni più piccole non è un'opzione, questo è un sito di fotografia che sto costruendo. Inoltre, ho davvero bisogno dei sei formati menzionati.

+0

C'è qualche possibilità ci si potrebbe fornire l'immagine originale 1.6MB JPEG? –

risposta

7

Come idea, è possibile ridimensionare la dimensione caricata in una dimensione intermedia più ragionevole e quindi utilizzarla come base per ulteriori operazioni.

In alternativa, è possibile eseguire la versione da riga di comando di ImageMagick ed eseguire (almeno la maggior parte) le trasformazioni di immagine in background utilizzando la procedura descritta in Asynchronous shell exec in PHP.

Infine, anche se è un po 'fuori tema, hai intenzione di consentire l'orientamento verticale, o non è probabile che questo sia un fattore?

+3

Grazie mille. Ora ridimensiono usando un effetto di ricaduta, ovvero comincio dal grande al ridimensionamento al medio, successivamente utilizzo l'immagine media (anziché l'immagine grande) per ridimensionarla in piccolo, ecc. Ora ci vogliono meno di 3 secondi per eseguire lo scricchiolio . Ho strappato un formato (quadrato) e sono tornato a GD2, invece di imagemagick. Per quanto posso dire, non ci sono problemi di qualità visibili con questo ridimensionamento a goccia. Grazie ancora! – Ferdy

7

Sembra che tu abbia già accettato una risposta ma inserirò ancora il mio.

Prima di tutto, davvero non c'è bisogno di utilizzare 100% in termini di qualità, un 90% o 85% valore farà bene, diminuendo i tempi di elaborazione e le dimensioni dell'immagine (se non si credimi, esegui solo alcuni test).

Ho anche fatto alcuni benchmark con this image e una funzione personalizzata JPEG(), primo banco di prova:

JPEG('./original.jpg', null, '1024*774', './output/large.jpg'); 
JPEG('./original.jpg', null, '500*378', './output/medium.jpg'); 
JPEG('./original.jpg', null, '240*161', './output/small.jpg'); 
JPEG('./original.jpg', null, '100*76', './output/thumb.jpg'); 
JPEG('./original.jpg', null, '50*38', './output/small_thumb.jpg'); 
JPEG('./original.jpg', null, '75*75', './output/square.jpg'); 

questo richiede una media di 60 secondi sul mio computer lento lento .


Secondo caso di test:

JPEG('./original.jpg', null, '1024*774', './output/large.jpg'); 
JPEG('./output/large.jpg', null, '500*378', './output/medium.jpg'); 
JPEG('./output/medium.jpg', null, '240*161', './output/small.jpg'); 
JPEG('./output/medium.jpg', null, '100*76', './output/thumb.jpg'); 
JPEG('./output/medium.jpg', null, '50*38', './output/small_thumb.jpg'); 
JPEG('./output/medium.jpg', null, '75*75', './output/square.jpg'); 

Questo si prende "solo" 16 secondi (il mio computer è molto lento ATM : P), quasi 4 volte più veloce.


Ecco la funzione JPEG() nel caso in cui si vuole fare i propri punti di riferimento:

function JPEG($source, $crop = null, $scale = null, $destination = null) 
{ 
    $source = ImageCreateFromJPEG($source); 

    if (is_resource($source) === true) 
    { 
     $size = array(ImageSX($source), ImageSY($source)); 

     if (isset($crop) === true) 
     { 
      $crop = array_filter(explode('/', $crop), 'is_numeric'); 

      if (count($crop) == 2) 
      { 
       $crop = array($size[0]/$size[1], $crop[0]/$crop[1]); 

       if ($crop[0] > $crop[1]) 
       { 
        $size[0] = $size[1] * $crop[1]; 
       } 

       else if ($crop[0] < $crop[1]) 
       { 
        $size[1] = $size[0]/$crop[1]; 
       } 

       $crop = array(ImageSX($source) - $size[0], ImageSY($source) - $size[1]); 
      } 

      else 
      { 
       $crop = array(0, 0); 
      } 
     } 

     else 
     { 
      $crop = array(0, 0); 
     } 

     if (isset($scale) === true) 
     { 
      $scale = array_filter(explode('*', $scale), 'is_numeric'); 

      if (count($scale) >= 1) 
      { 
       if (empty($scale[0]) === true) 
       { 
        $scale[0] = $scale[1] * $size[0]/$size[1]; 
       } 

       else if (empty($scale[1]) === true) 
       { 
        $scale[1] = $scale[0] * $size[1]/$size[0]; 
       } 
      } 

      else 
      { 
       $scale = array($size[0], $size[1]); 
      } 
     } 

     else 
     { 
      $scale = array($size[0], $size[1]); 
     } 

     $result = ImageCreateTrueColor($scale[0], $scale[1]); 

     if (is_resource($result) === true) 
     { 
      if (ImageCopyResampled($result, $source, 0, 0, $crop[0]/2, $crop[1]/2, $scale[0], $scale[1], $size[0], $size[1]) === true) 
      { 
       return ImageJPEG($result, $destination, 90); 
      } 
     } 
    } 

    return false; 
} 
+0

Grazie, la tua risposta sicuramente arricchisce la discussione. In realtà, ho provato a cambiare la qualità, come un caso di test estremo ho usato il 10%. Il risultato è stato che la procedura di ridimensionamento totale ha richiesto esattamente il tempo necessario. Questo mi ha portato a credere che la risoluzione fosse il problema, non la qualità. Ho appena testato nuovamente la stessa qualità del 10% nella mia logica di ridimensionamento migliorata e, di nuovo, richiede esattamente il tempo necessario per ottenere una qualità del 100%. Non so perché però. – Ferdy

+0

Un'altra osservazione, se possibile, mi piacerebbe molto stare con la classe di immagine CodeIgniter, dal momento che può gestire quasi tutti i tipi di file di immagine e nasconde la complessità di trattare con le routine di ridimensionamento delle immagini di livello inferiore. Solo se tutto il resto fallisce e se c'è un vantaggio chiaro cambierei. – Ferdy

+3

@Ferdy: Sì, non dovrebbe importare molto in termini di velocità, ma è comunque necessario utilizzare una qualità inferiore, il 90% riduce la dimensione dell'immagine della metà e mantiene tutta la qualità. –

Problemi correlati