Exact image resizing in eZ Publish with custom image filters
eZ Publish comes with a useful set of image settings, and has a powerful framework within which you can define custom filters to be executed by the image handler. In this article, we'll show you how to make use of a custom ImageMagick filter to achieve exact image sizes.
For those who are familiar with eZ Publish, by now you know how simple it is to define custom image size aliases in an override of image.ini. This is actually best documented inline in the base image.ini. Most new image aliases involve a new entry in the AliasList array in the AliasSettings block...
... as well as the definition of the alias in its own block:
[square1] Filters Filters=geometry/scale=75;75
Exact image sizing
In most cases, you have one limiting dimension -- either the size or the width. Alias examples such as the one above work very well for this. However, it gets tricky when you want to resize images to fix exact width and height dimensions.
Suppose you want to resize images to fit a 75x75 square. One helpful filter is "crop":
[square1] Filters Filters=geometry/scale=75;75 Filters=geometry/crop=75;75;0;0
Here, you can resize the image, and then crop it. This gets you one step closer. However, unless your original image is already a perfect square, with the alias defined above, you will end up with images with dimensions such as 75x55 or 55x75. This is because the default ImageMagick "scale" filter does its resizing based on which dimension is bigger.
There are a couple of workarounds: one is to resize the image to dimensions that you know will be bigger than the square before cropping. However, this means that you are guaranteed to have to crop more of the image than necessary. Another workaround is to test which dimension is the bigger one before resizing, but this is quite an involved hack.
An efficient solution
In ImageMagick 6.3.8-2 (released in January 2008) or higher, there is a ^ flag that performs the resizing based on the smaller dimension. So you'll get a 103x75 or 75x103 image using the aspect ratio in the previous example, and that can then be cropped.
(If you have an older version of ImageMagick, you can compile it from the source here. Or, if you're on CentOS with the "remi" packages, you can install the package "ImageMagick2".)
Once you have a suitable version of ImageMagick, you can set up a custom image filter definition. To understand how to do that, let's look up the filter definition for "geometry/scale" in eZ Publish's base image.ini:
[ImageMagick] Filters=geometry/scale=-geometry %1x%2
If you compare this to how you use the filter in an image alias (geometry/scale=75;75), you can see how its usage maps to its definition. The actual ImageMagick call is to the operator "-geometry", and it uses the dimensions specified, split by a semi-colon. We can therefore define our own filter that is very similar to this, but that uses the ^ flag:
(Note that ImageMagick suggests using the "-resize" operator instead of the "-geometry" operator, but here we use "-geometry" for illustrative purposes.)
Here is a more complete image.ini.append.php example showing our new "geometry/scalemin" filter definition and 4 image aliases: 3 that use pre-defined filters and 1 that uses our new filter.
[ImageMagick] IsEnabled=true ExecutablePath=/usr/bin Executable=convert Filters=geometry/scalemin=-geometry %1x%2^ [AliasSettings] AliasList=square1 AliasList=square2 AliasList=square3 AliasList=square4 [square1] Filters Filters=geometry/scalewidth=75 Filters=geometry/crop=75;75;0;0 [square2] Filters Filters=geometry/scaleheight=75 Filters=geometry/crop=75;75;0;0 [square3] Filters Filters=geometry/scale=75;75 Filters=geometry/crop=75;75;0;0 [square4] Filters Filters=geometry/scalemin=75;75 Filters=geometry/crop=75;75;0;0
Here are some fun image examples showing an original-size image on top, and the 4 alias-sized images below it. Notice how only the last image alias gets us the desired end result in both cases.
The first example image is wider than it is tall; the image aliases that result in a perfect square are the one that scales only based on height and the alias that uses the new "geometry/scalemin" filter.
The second example image is taller than it is wide; the image aliases that result in a perfect square are the one that scales only based on width and the alias that uses the new "geometry/scalemin" filter.
Bonus filter example for resizing images to a bigger size, but not cropping the image; instead, center it and fill the remaining space with a black background:
Filters=geometry/galleryscale=-gravity center -background black -extent 900x600