2015-03-20 40 views
10

Sto usando PHP Imagick per ridimensionare le immagini in fase di esecuzione. Il sito ha una funzione di caricamento dell'immagine e non possiamo fidarci dell'utente di usare il web JPEGs, poiché durante lo mass-import ci sono molte 3 a 5MB immagini, e anche alcune grandi quanto 13MB. Ogni immagine viene trasformata in una miniatura (200x200) e quando si passa dalla visualizzazione elenco alla visualizzazione dettagliata viene mostrata solo un'immagine, quindi le prestazioni non sono un grosso problema, anche se non è possibile lanciarlo completamente per strada. Ecco cosa stiamo facendo finora: notaPHP Imagick JPEG Optimization

$iMagick = new Imagick($file); 
$iMagick->setImageResolution(72,72); 
$iMagick->resampleImage(72,72,imagick::FILTER_UNDEFINED,1); 
$geometry = $iMagick->getImageGeometry(); 
if ($geometry['height'] > 1920 || $geometry['width'] > 1080) { 
    $iMagick->scaleImage(1920, 0); 
    if($geometry['height'] > $resizeHeight) { 
     $iMagick->scaleImage(0, 1080); 
    } 
} 
$iMagick->setImageCompression(Imagick::COMPRESSION_JPEG); 
$iMagick->setImageCompressionQuality($compression); 
$iMagick->writeImage($file); 
$Imagick->clear(); 

laterale: Ho appena realizzato il difetto nella mia logica condizionale qui circa altezza/larghezza, in modo da ignorare che, per il momento. Elaborerò presto la domanda per riflettere i confronti delle condizioni corrette. Per coloro che non l'hanno catturato, ridimensiona tutte le immagini a 1920 di larghezza anche se si suppone che riduca l'altezza, quindi dopo la scala ridimensiona a 1080 height.

L'immagine che ho usato per il test inizia come immagine 3MB 2398×2400. Ridimensionandolo a 1079x1080 si ottiene un'immagine con 1.5MB, quindi aggiungendo la compressione JPEG alla qualità 70 si riduce a 750KB. Utilizzando kraken.io l'immagine è stata in grado di essere compressa a poco meno di 60 KB. Ci sono altre cose che posso fare a questo script dal momento che ha bisogno di ottimizzare l'immagine in fase di runtime?

Ho letto i suggerimenti per utilizzare libjpeg, che è installato, ma non riesco a trovare alcuna documentazione su quali funzioni abilita o se c'è un modo per forzare Imagick ad usarlo in modo specifico. Non sono nemmeno sicuro che Imagick non lo stia già usando.

Edit: Soluzione

function itm_optimizeImage($file, $compression = 70, $maxDimensions = ['width' => null, 'height' => null]) { 
    $save = false; 
    $fi = new finfo(FILEINFO_MIME); 
    $mime = explode(';', $fi->file($file)); 
    switch ($mime[0]) { 
     // possible to optimize other image types in the future 
     case 'image/jpeg': 
      try { 
       $iMagick = new Imagick($file); 
       if ($iMagick->getImageCompressionQuality() > $compression) { 
        $file = !itm_compressJPEG($file, $compression, $maxDimensions, $iMagick); 
       } 
      } 
      catch (Exception $e) { 
       error_log(__FUNCTION__ . " $path/$file failed: " . $e->getMessage()); 
       return false; 
      } 
      if ($file) { 
       $pathParts = pathinfo($file); 
       rename($file, $pathParts['dirname'] . '/' . $pathParts['filename'] . '.large.' . $pathParts['extension']); 
       $iMagick->writeImage($file); 
      } 
      $iMagick->clear(); 
      break; 
    } 

    return $file; 
} 

function itm_compressJPEG($file, $compression = 70, $maxDimensions = ['width' => null, 'height' => null], &$iMagick = null) { 
    try { 
     $iMagickCreated = true; 
     if ($iMagick) $iMagickCreated = false; 
     else $iMagick = new Imagick($file); 

     $iMagick->setImageResolution(72,72); 
     $iMagick->resampleImage(72,72,imagick::FILTER_UNDEFINED,1); 
     $geometry = $iMagick->getImageGeometry(); 
     if (($geometry['width']/$maxDimensions['width']) > ($geometry['height']/$maxDimensions['height'])) { 
      // scale by width 
      $iMagick->scaleImage($maxDimensions['width'], 0); 
     } else { 
      // scale by height 
      $iMagick->scaleImage(0, $maxDimensions['height']); 
     } 
     $iMagick->setImageCompression(Imagick::COMPRESSION_JPEG); 
     $iMagick->setImageCompressionQuality($compression); 
     $iMagick->setImageFormat('jpg'); 
     $iMagick->stripImage(); 

     if ($iMagickCreated) { 
      $pathParts = pathinfo($file); 
      rename($file, $pathParts['dirname'] . '/' . $pathParts['filename'] . '.large.' . $pathParts['extension']); 
      $iMagick->writeImage($file); 
      $Imagick->clear(); 
     } 
     return $file; 
    } 
    catch (Exception $e) { 
     error_log(__FUNCTION__ . " $path/$file failed: " . $e->getMessage()); 
     return false; 
    } 
} 
+0

60 KB per un'immagine 1079x1080 sembra abbastanza decente. Non penso che si possa ottenere molto più piccolo senza diminuire le dimensioni dei pixel o abbassare seriamente la qualità. – GolezTrol

+0

Il problema è che non sto arrivando da nessuna parte vicino a quello con il mio script. È a ~ 750KB in questo momento, il 60KB era un confronto (ciò che lo strumento kraken.io era capace sulla stessa immagine). Non guardo a 60KB come obiettivo preciso, ma sotto i 200KB sarebbe bello. – MaKR

risposta

9

Impostare la setImageCompressionQuality ad un valore di 70 e aggiungere queste due righe dopo.

$image->setImageFormat("jpg"); 
$image->stripImage(); 

Questo ridurrà drasticamente la dimensione delle immagini.

+1

Ho usato stripImage() prima e non ha avuto alcun effetto. L'aggiunta di setImageFormat ('jpg') senza stripImage() ha ridotto le dimensioni di ~ 20 KB in più (stavamo tentando di salvare dati exif/meta ma è secondario alle prestazioni). Usando entrambi insieme, il risultato finale di questa immagine di prova è stato di 178 KB, ovvero la perfetta combinazione di qualità e compressione. Grazie! – MaKR

+1

Qualcuno ha una spiegazione dello strano comportamento descritto da @MaKR? Perché dovrebbe essere necessario setImageFormat ('jpg') se il nome del file termina con .jpg? Perché dovrebbe essere necessario setImageCompression() in primo luogo? C'è una spiegazione a tutte queste assurdità di Imagick? – matteo

+0

Ottima soluzione ... Stavo comprimendo le immagini da 5 MB solo fino a 788 KB, con questi metodi extra i file sono in formato KB a due cifre. –