January 17, 2014Charles Pourcel6 min read
I recently read an interesting article on the pros and cons of two of the most known PHP image manipulation libraries: GD and ImageMagick. As interesting as this reading was, it did not mention a very useful object oriented image manipulation library and its corresponding bundle to all those waiting for the simplest solution to edit, transform and store pictures on their Symfony2 web application: The Imagine library and the LiipImagineBundle. I will try to fill this gap by explaining how these two tools can greatly help you managing pictures easily.
This library is the perfect PHP 5.3+ object oriented tool to interact with your pictures in a simple way. It provides a common implementation for three of the most known image libraries (GD2, IMagick, Gmagick). So, pick your favorite one (using for example the aforementioned article), install Imagine using the official (well written) documentation and keep going! You still have a lot to discover...
Let's start with opening an existing picture using Imagine:
$imagine = new Imagine\Gd\Imagine(); //or $imagine = new Imagine\Imagick\Imagine();
$image = $imagine->open('/path/to/image.jpg');
Note: Depending on the name of the driver you are using, you will have to switch the namespace of the Imagine class to use: one of the rare drawbacks of Imagine. But let's not worry to much as this drawback can be overcome (check the Imagine Bundle main features below).
As you may have already noticed, Imagine follows some very simple and intuitive rules. For example, if you want to resize or crop an image (one of the most common and basic functionalities in Imagine) you will have to deal with "coordinates" and "dimensions". To crop you will need to specify the top left corner coordinates and the desired dimensions of the crop. You will therefore have to implement the PointInterface as follows:
//Indicates coordinates (x: 15, y: 30) $coordinates = new Imagine\Image\Point(15, 30);
Note: The coordinates always start from the top left corner and cannot have negative values.
And to specify dimensions implement the BoxInterface like this:
//Indicates dimensions (width: 400, height: 300) $dimensions = new Imagine\Image\Box(400, 300);
Since most of these code excerpts are actually extracted from the official Imagine documentation I will focus on the main interests of the library rather than duplicating code examples you could easily find on the corresponding page in the official documentation.
The Imagine library is already considered a reference when it comes to clean and decoupled image manipulation. I have briefly described its main features above but it contains more including some advanced "Filters" and a clean "Exception" management system. As you can see, it already covers most of the basic and even advanced use cases, and since it has been built to be easily extensible, you will not have too much trouble implementing any missing behaviour.
For those of you wanting to integrate it into a Symfony2 application, there is a Symfony2 bundle for that: the LiipImagineBundle. It uses the Imagine library and completes it with additional useful features.
The LiipImagineBundle wraps the Imagine library into a Symfony2 bundle and includes it into a larger (and yet simple) workflow. As the library itself, this bundle has been made highly extendable and therefore you can customize almost each part of the workflow's behaviour.
1. First, you will need to install and configure your bundle. Lucky for you, the Liip team thought about that and provides a quite understandable semantic configuration for the bundle.
2. Then use one of the Twig filters you defined in your configuration by calling it on a picture asset in one of your Twig templates.
3. If you now request the corresponding page (for example to display it in your browser) the ImagineBundle will detect if the filter has already been applied to this specific picture:
Using GD or Imagick to transform the pictures of your Symfony2 application (well even any web application) is good but using the Imagine library is better. It provides you with an object oriented and extensible code structure through a simple but powerful API. Using it allows you to easily switch from GD to Imagick for instance, if you started using GD and find a major drawback later. Still not convinced? Think about the next time a new developer will have to read and maintain the code you are currently so proud of.
And if you are in a Symfony2 application context you can get an even better solution depending on your needs: the LiipImagineBundle. Based on Imagine, it adds many useful features such as cache handling, template integration, many different strategies to store and retrieve your images, and all of this is highly customizable. Could you reasonably ask for more (except for coffee)?
Finally, if you want to know more on which driver you should use and see a basic but functional example of how Imagine can be used you can check this presentation I recently made. Its code focuses on the advantages of the "Transformation" approach over the more basic "Filter" one.
Web Developer at Theodo