title: PHP Imagick JPEG Optimization
body: <p>I'm using <code>PHP Imagick</code> to resize images at runtime.  The site has an image upload feature and we can't trust the user to use web-friendly <code>JPEGs</code>, as during the <code>mass-import</code> there are many <code>3</code> to <code>5MB</code> images, and even a few as large as <code>13MB</code>.  Each image gets turned into a thumbnail (<code>200x200</code>), and when going from list view into detailed view only one image is shown, so performance isn't a huge deal although we can't completely throw it by the wayside.  Here's what we're doing so far:</p>
  
  <pre><code>$iMagick = new Imagick($file);
  $iMagick-&gt;setImageResolution(72,72);
  $iMagick-&gt;resampleImage(72,72,imagick::FILTER_UNDEFINED,1);
  $geometry = $iMagick-&gt;getImageGeometry();
  if ($geometry['height'] &gt; 1920 || $geometry['width'] &gt; 1080) {
      $iMagick-&gt;scaleImage(1920, 0);
      if($geometry['height'] &gt; $resizeHeight) {
          $iMagick-&gt;scaleImage(0, 1080);
      }
  }
  $iMagick-&gt;setImageCompression(Imagick::COMPRESSION_JPEG);
  $iMagick-&gt;setImageCompressionQuality($compression);
  $iMagick-&gt;writeImage($file);
  $Imagick-&gt;clear();
  </code></pre>
  
  <p>Side note: I just realized the flaw in my conditional logic here about height/width, so ignore that for the time being.  I'll edit the question soon to reflect the correct condition comparisons.  For those who didn't catch it it's scaling all images to <code>1920</code> wide even if it's supposed to be scaling the height, then after the scale it's sizing it back down to <code>1080 height</code>.</p>
  
  <p>The image I've used to test starts as a <code>3MB 2398×2400</code> image.  Scaling it to <code>1079x1080</code> results in a <code>1.5MB</code> image, then adding <code>JPEG</code> compression at quality <code>70</code> brings it down to <code>750KB</code>.  Using kraken.io the image was able to be compressed to just under 60KB.  Are there any additional things I can do to this script since it needs to optimize the image at runtime?</p>
  
  <p>I've read suggestions to use libjpeg, which is installed, but I can't find any documentation on what functions it enables or if there's a way to force Imagick to use it specifically.  I'm not even sure that Imagick isn't using it already.</p>
  
  <p>Edit: Solution</p>
  
  <pre><code>function itm_optimizeImage($file, $compression = 70, $maxDimensions = ['width' =&gt; null, 'height' =&gt; null]) {
      $save = false;
      $fi = new finfo(FILEINFO_MIME);
      $mime = explode(';', $fi-&gt;file($file));
      switch ($mime[0]) {
          // possible to optimize other image types in the future
          case 'image/jpeg':
              try {
                  $iMagick = new Imagick($file);
                  if ($iMagick-&gt;getImageCompressionQuality() &gt; $compression) {
                      $file = !itm_compressJPEG($file, $compression, $maxDimensions, $iMagick);
                  }
              }
              catch (Exception $e) {
                  error_log(__FUNCTION__ . " $path/$file failed: " . $e-&gt;getMessage());
                  return false;
              }
              if ($file) {
                  $pathParts = pathinfo($file);
                  rename($file, $pathParts['dirname'] . '/' . $pathParts['filename'] . '.large.' . $pathParts['extension']);
                  $iMagick-&gt;writeImage($file);
              }
              $iMagick-&gt;clear();
              break;
      }
  
      return $file;
  }
  
  function itm_compressJPEG($file, $compression = 70, $maxDimensions = ['width' =&gt; null, 'height' =&gt; null], &amp;$iMagick = null) {
      try {
          $iMagickCreated = true;
          if ($iMagick) $iMagickCreated = false;
          else $iMagick = new Imagick($file);
  
          $iMagick-&gt;setImageResolution(72,72);
          $iMagick-&gt;resampleImage(72,72,imagick::FILTER_UNDEFINED,1);
          $geometry = $iMagick-&gt;getImageGeometry();
          if (($geometry['width'] / $maxDimensions['width']) &gt; ($geometry['height'] / $maxDimensions['height'])) {
              // scale by width
              $iMagick-&gt;scaleImage($maxDimensions['width'], 0);
          } else {
              // scale by height
              $iMagick-&gt;scaleImage(0, $maxDimensions['height']);
          }
          $iMagick-&gt;setImageCompression(Imagick::COMPRESSION_JPEG);
          $iMagick-&gt;setImageCompressionQuality($compression);
          $iMagick-&gt;setImageFormat('jpg');
          $iMagick-&gt;stripImage();
  
          if ($iMagickCreated) {
              $pathParts = pathinfo($file);
              rename($file, $pathParts['dirname'] . '/' . $pathParts['filename'] . '.large.' . $pathParts['extension']);
              $iMagick-&gt;writeImage($file);
              $Imagick-&gt;clear();
          }
          return $file;
      }
      catch (Exception $e) {
          error_log(__FUNCTION__ . " $path/$file failed: " . $e-&gt;getMessage());
          return false;
      }
  }
  </code></pre>