JPEG image file sizes too large? ImageMagick may be the cause.

Permalink
Building a site with retina images and noticed that all the JPEG images where way too large in file size. For example, a image that was 220k when resized via Photoshop was instead 1.4 megs when resized by concrete5. Zoinks!

I kept playing around with the following code inside config/site.php but it never had an effect.

define('AL_THUMBNAIL_JPEG_COMPRESSION', 50);

I only had this issue on our real server and not in our test environment. Turns out the real server was using ImageMagick while the test server was not.

Inside /concrete/core/helpers/image.php around line 152 is the following logic.

if(class_exists('Imagick')) {

The above is the branch of code that my server with the JPEG size issue was running.

Then further down around line 172 is the first problem with the following code.

if($image->getCompression() == imagick::COMPRESSION_JPEG) {

ImageMagick's getCompression() would never return a number 8 which is what COMPRESSION_JPEG equates to. In fact, it would never return any number but zero with various JPEG test files.

If you would like to see if your server has the same getCompression() === 0 issue please feel free to use the attached "get-compression.zip" to test with.

I also think the lowercase imagick should probably be Imagick but I didn't test that.

I proceeded to work on code changes and once I got past line 172 I ran into some other issues. Calling setCompressionQuality() had no effect but calling setImageCompressionQuality() did. More info on this tip in the comments ofhttp://php.net/manual/en/imagick.setcompressionquality.php...

I ended up making other changes including stripping color profiles and comments to make even smaller JPEG files. Here is my final code that is working as intended on my server.

if($imageRead) {
   $ext = strtolower(substr($originalPath, -4));
   if($ext === '.jpg' || $ext === 'jpeg') {
      $jpegCompression = $this->jpegCompression;
       if ($jpegCompression < 1) {
          $jpegCompression = 1;
        }
       $image->setImageCompression(Imagick::COMPRESSION_JPEG); 
            $image->setImageCompressionQuality($jpegCompression); // must be 1-100
       $image->stripImage(); // remove color profiles and comments
   }
   if($image->writeImage($newPath) === true) {
      $processed = true;
   }
}

So, I guess my best wish now is that if other people are having the same issue; the above code (or similar) could be tested and ultimately roll out in a future version of concrete5.

I don't have the bandwidth to test myself or submit a pull via GitHub so I'm hoping someone else can run with the above.

Questions more than welcome and thanks for reading. ^_^

1 Attachment