On the fly image resizing in Lithium

Recently I’ve been playing around with the very promising PHP framework Lithium. In fact we decided to use it at work for some project as well. Documentation is a bit scarce and disorganized, and there aren’t a whole lot of content on the web about it, so I figured i might as well share some of my discoveries.

This is not a full tutorial, I am building on the source for Lithiums creator Nate Abeles photoblog exampleand just exending it to handle on the fly resizing.
Note: ImageMagick is required!

The reason ImageMagick is used and not GD is because of several reasons:

  • GD requires you to unpack and read the entire image into memory in the PHP process. For big images this will be a memory hog. (can be several gigabytes for 10-20M jpgs)
  • GD has an awkward format where ImageMagick is a more straight forward readable one liner
  • ImageMagick scales better in terms of file type support. (Supports more than 100 major image formats)

The only reason to use GD in my view is if you are on shared hosting and absolutely can not get ImageMagick available.

To the code

Open app/config/routes.php and you find this route handling the image requests and find this code somewhere in it:

We will change this so we achieve the following effect:

  • Map images to /image/{id}.{type}
  • Cache images to files even original is in MongoDB
  • The previous means copying /image/4cc9953fb6ada15424050000.jpg to webroot/image/4cc9953fb6ada15424050000.jpg
  • Allow resizing by url mapping /image/{id}_{width}x{height}.{type} which will create the file on the file system and serve it

First we will modify the route quite a bit, follow the inline comments in this gist:

Now you have some code that matches image urls and fires up a closure that tries to get a version of the image from the Photo model. But we don’t have that method yet, so lets create it!

With that code hooked into your model you should be up and running. Try uploading an image and accessing it using the correct pattern. Simply build an image tag like this in your views: <img src=”/image/4cc9953fb6ada15424050000_300x300.jpg” alt=”My image” />

Now this code is not perfect, it lacks quite a lot of error detection and file type support, but combined with the photo blog setup its a robust start to an image handling system. Also, there are other strategies for solving this, and the first that came to mind was to filter access to image file endings registered in the Media class and handle it on the fly at render time. The reason i chose this method instead of that is that while on the fly resizing is great, there are many situations where you know all the way that you need a set of fixed sizes. In such scenarios its probably better to be able to call the version() method from other places.

Find more blog posts