The need to resize and crop images in order to create thumbs, is a very common scenario for most websites. For example a blog like this one uses images in the content of the posts, images which at some point are used to create a thumb for the homepage. In most cases, the thumb’s dimensions are not dynamic but are static throughout the website in order to better fit the template. This however creates a major problem when we try to automatically resize and crop our images in the desired dimensions.
Cropping Using Traditional Techniques
Let’s assume that we want to use this photo of a man holding a camera in our website. (image courtesy of littlevisuals.co)
Now let’s also assume that our website uses 230×270 thumbs. The image currently is 800×533 so some resizing and cropping is in order.
Most libraries in order to avoid stretching, utilize what is known as smart cropping. This means that the code will resize the image and when one dimension is equal to the desired one, the code will check if the other dimension is also correct. If not, the code will crop starting from the center in order to reach the final dimensions. Using this technique the generated thumb is similar to this.
This result however is less than ideal. The more “interesting” part of the photo is obviously the right one, the man actually holding the camera, and part of it got cut off. By calculating the image’s entropy, we can determine which part of the photo has more energy and keep that one instead.
What is Image Entropy?
According to astro.cornell.edu
Image entropy is a quantity which is used to describe the `business’ of an image, i.e. the amount of information which must be coded for by a compression algorithm. Low entropy images, such as those containing a lot of black sky, have very little contrast and large runs of pixels with the same or similar DN values. An image that is perfectly flat will have an entropy of zero. Consequently, they can be compressed to a relatively small size. On the other hand, high entropy images such as an image of heavily cratered areas on the moon have a great deal of contrast from one pixel to the next and consequently cannot be compressed as much as low entropy images.
So by calculating the entropy of various slices of our photo, we can determine which part of the image is busier and try to keep that slice in the final thumb. By doing so we are not just cropping from the center in hope that the actual subject of the photo is at the center, but instead we figure out the start and end coordinates of the crop, much like how a human would actually do.
In order to make all that happen we can use this crop library by stojg
This php library needs the Imagick extension to be installed, so first thing first we should install and enable this library. This however is a little trickier than it sounds.
I am using WAMP 64bit with PHP 5.4 compiled with VC9. This information is important because depending on your configuration you need to find the appropriate versions of Imagick and mod_imagick.dll. For more information on installing Imagick you can visit elxsy but if you have the same setup as me you need to download and install:
- ImageMagick-6.8.7-8-Q16-x64-dll.exe from here
- php_imagick-svn20120508-5.4-VC9-x64 from here
Once you download those two
- Install Imagick 6.8.7, preferably at C:/imagick
- Place the mod_imagick.dll file in wamp/bin/php/php5.4.12/ext
- Edit your php.ini file and insert extension=php_imagick.dll
- Edit your apache httpd.conf file and insert SetEnv MAGICK_HOME C:/imagick
- Restart your system. IMPORTANT you need to restart Windows not just WAMP
So if everything worked as it should, we should be able to use the stojg/crop library.
So let’s fire our favorite code editor and write
use stojg/crop; require_once 'src/stojg/crop/Crop.php'; require_once 'src/stojg/crop/CropBalanced.php'; require_once 'src/stojg/crop/CropCenter.php'; require_once 'src/stojg/crop/CropEntropy.php'; $cropperEntropy = new stojg\crop\CropEntropy(__DIR__."/a.jpg"); $croppedImage = $cropperEntropy->resizeAndCrop(230, 270); $croppedImage->writeimage(__DIR__."/crop-entropy.jpg");
Our generated thumb using entropy to calculate the cropping coordinates should look like this:
Which is obviously better than the initial thumb. Here is a side by side comparison of the two
Cropping from center
The library has a few other classes that you can use to test the various techniques and an additional class called CropFace. This class also calculates entropy to crop the image, but additionally tries to detect faces and keeps them from being cut off. In order to use this class you must have the PHP Facedetect Extension which uses OpenCV.
The library generally produces far from perfect results and to be honest the photo used in this scenario is actually one that was more likely to produce a good result. However the general idea is very interesting and in many cases this technique will save you a lot of time.
Tim Reynolds wrote a follow up article in which he explains how the calculations are being done behind the scenes far better than me and has actually made alterations to the original library to make it work better. You can download his modified library from his github repo.