2015-03-20 28 views
10

Görüntüleri çalışma zamanında yeniden boyutlandırmak için PHP Imagick kullanıyorum. Site bir görüntü yükleme özelliğine sahiptir ve , mass-import sırasında için 5MB görüntülere ve hatta 13MB kadar büyük olan kullanıcılara web-dostu JPEGs'u kullanma konusunda güvenemiyoruz. Her görüntü bir küçük resme (200x200) dönüşür ve liste görünümünden ayrıntılı görünüme geçilirken yalnızca bir görüntü gösterilir, bu nedenle performans çok büyük bir anlaşma değildir. Burada hiç yapıyoruz ne:PHP Imagick JPEG Optimizasyon

$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(); 

Yan Not: Burada sadece yükseklik/genişlik hakkında benim koşullu mantık kusur fark, bu yüzden şimdilik bunu görmezden. Doğru durum karşılaştırmalarını yansıtmak için soruyu yakında düzenleyeceğim. Yakalamayanlar için, tüm görüntüleri 1920 genişliğine kadar ölçeklendirerek, yüksekliği ölçeklendiriyor olsa bile, ölçek sonra 1080 height'a geri boyutlandırıyor.

Test etmek için kullandığım görüntü, 3MB 2398×2400 görüntüsü olarak başlar. 1079x1080'a ölçeklendirme, 1.5MB görüntü sonuçlarıyla sonuçlanır, daha sonra sıkıştırmasını 70 kalitesinde ekleyerek 750KB adresine getirebilirsiniz. Kraken.io kullanarak görüntü, 60 KB'ın biraz altına sıkıştırılmıştı. Görüntünün çalışma zamanında optimize edilmesi gerektiğinden, bu betiğe yapabileceğim başka şeyler var mı?

Yüklü olan libjpeg'yi kullanmayla ilgili önerileri okudum, ancak hangi işlevlerin etkinleştirildiğine veya Imagick'in onu özellikle kullanmasına zorlamanın bir yolu varsa hiçbir belge bulamıyorum. Imagick'in zaten kullanmadığından bile emin değilim.

Düzenleme: Çözüm

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

1079x1080 boyutundaki bir resim için 60 KB oldukça iyi görünüyor. Piksel boyutlarını düşürmeden veya kaliteyi ciddi şekilde düşürmeden çok daha küçük olabileceğini düşünmüyorum. – GolezTrol

+0

Sorun şu ki senaryomla bir yere yakınlaşmam. Şu anda yaklaşık 750KB, 60KB bir karşılaştırma (kraken.io aracının aynı görüntüde ne yapabildiğini). Tam bir hedef olarak 60 KB'ye bakmıyorum, ama 200 KB'ın altında olmak güzel olurdu. – MaKR

cevap

9

70 değerine setImageCompressionQuality ayarlayın ve peşine bu iki satırı ekleyin.

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

Bu, görüntülerin boyutunu önemli ölçüde azaltacaktır.

+1

Daha önce stripImage() kullanmıştım ve hiçbir etkisi yoktu. StripImage() olmadan setImageFormat ('jpg') eklemek, boyutu ~ 20KB daha fazla azalttı (exif/meta verilerini kaydetmeye çalışıyorduk, ancak performansa ikincil). Bu test görüntüsünün her ikisini birlikte kullanmanız, kalite ve sıkıştırmanın mükemmel birleşimiyle ilgili olan 178KB idi. Teşekkürler! – MaKR

+1

@MaKR tarafından tanımlanan garip davranışlara dair bir açıklama var mı? Dosya adı, .jpg ile bitiyorsa neden setImageFormat ('jpg') gerekli olmalıdır? Neden ilk olarak setImageCompression() gerekmelidir? Bütün bu Imagick saçmalığına bir açıklaması var mı? – matteo

+0

Mükemmel çözüm ... Bu ekstra yöntemlerle dosyaların çift haneli KB boyutlarına girmesiyle 5MB görüntüleri yalnızca 788KB'ye sıkıştırıyordum. –