CSS sprites using Imagecache and ImageMagick Raw Action module

by Adrian 30th Nov, 2009 @ 15:04

A question in one of the Drupal IRC channels recently reminded me to write about my ImageMagick Raw Action module (im_raw) and its ability to generate CSS sprite style images from uploaded image files. This is not a recipe for a whole site CSS sprite containing all icons and backgrounds used, but a way to process a single uploaded image and append that processed version to the original.

ImageMagick raw action also opens up a wide array of potential visual effects driven by ImageMagick to be used in CSS hover effects in galleries or anywhere else you use imagecache presets.

You'll need to be comfortable with a command line, have ImageAPI, ImageCache and ImageMagick installed and working, and have installed ImageMagick raw action. This will work on both Drupal 5 and 6. It'll also help to have some knowledge of Drupal theming and CSS if you want to be able to do something useful with your sprite.

Raw power

Although it's possible to combine im_raw actions with other imagecache actions one of the advantages of im_raw is the ability to develop ImageMagick commands outside of drupal, working on the command line until you have the desired results.

So open up a terminal on a machine where you have ImageMagick installed, open up the ImageMagick usage site in your browser, grab an image for testing and lets get started.

Lets assume we're creating a thumbnail for an image gallery grid layout, we'll resize down to 200px square. Our basic ImageMagick command using a photo of runner beans (harvested from our garden last summer) is:

convert runnerbeans.jpg -resize 200x200 runnerbeans-out.jpg

resized image of runner beansOK, so that doesn't always give us square images, but at least if that works we know ImageMagick is installed and our input and output filenames work. Read around ImageMagick usage: thumbnails and framing and you'll find plenty of suggestions for generating good quality thumbnails

This will give us nice 200px square thumbnails:

convert runnerbeans.jpg -resize x400 -resize '400x<' -thumbnail 50% -gravity center -extent 200x200 runnerbeans-out.jpg

resized and cropped square image of runner beansNow we're square.

Let's add some effects, tinted red and retro dithered:

convert runnerbeans.jpg -resize x400 -resize '400x<' -thumbnail 50% -gravity center -extent 200x200 -modulate 110,0 -fill '#FF0022' -tint 100 -ordered-dither h2x4a runnerbeans-out.jpg

resized, filtered and cropped square image of runner beansLooks interesting.

Get spritely

"Well that's all very nice, but where's the sprite?" I hear you say. Fair enough. What we're going to do is use ImageMagick's clone and append options.

We'll clone our thumbnailed image, apply the effects and then append it to the original:

convert runnerbeans.jpg -resize x400 -resize '400x<' -thumbnail 50% -gravity center -extent 200x200 \( +clone -modulate 110,0 -fill '#FF0022' -tint 100 -ordered-dither h2x4a \) +append runnerbeans-out.jpg

sprite style image of runner beansGives us a sprite, as pictured to the left.

Lets look at this command in more detail. The resize options come first then the 'clone' creates a copy of our resized image, we apply our effects to that copy, then the +append glues our adulterated copy to the original. Note that we needed to escape the parentheses so as not to confuse the shell.

It should be clear to anyone with an inkling of what ImageMagick is capable of that this opens up an immense range of possibilities for image processing within Drupal. There are limits however, we can't use all the power of ImageMagick because calling convert, setting quality and dealing with file input/output are all dealt with by ImageAPI and Imagecache.

Feeding our command to ImageMagick raw action

This also means we have to trim our command before entering it into the im_raw text area. If you haven't already done so create a new imagecache preset and choose to add an im_raw action. In the text area im_raw provides you can paste in your command and trim to it's functional core. From our example above take off the call to convert, the input file name and the output file name. Leaving:

-resize x400 -resize '400x<' -thumbnail 50% -gravity center -extent 200x200 \( +clone -modulate 110,0 -fill '#FF0022' -tint 100 -ordered-dither h2x4a \) +append

The entire command that will actually be passed to convert by ImageAPI when using the above is:

convert inputfilename -resize x400 -resize '400x<;' -thumbnail 50% -gravity center -extent 200x200 \( +clone -modulate 110,0 -fill '#FF0022' -tint 100 -ordered-dither h2x4a \) +append -quality 92% outputfilename

The quality option is set site-wide for imageapi at admin/settings/imageapi/config and is thus something else we can't add in im_raw.

Theme and add CSS

If this were a fully rounded tutorial I'd now give examples of how to theme the sprite and CSS to make this sprite change on hover. However the examples would differ on Drupal 5 vs 6, there's so many different ways you can go from here I don't think it's good to provide a limited example and I'm sitting here doped up on Ibuprofen and Paracetemol fending off Swine Flu. So use your imagination and your skills and figure it out yourself.

Alternatively point Firebug at my portfolio and gallery index pages for some clues.

Finishing thoughts

This article barely scratches the surface of what's possible with ImageMagick and ImageMagick raw action. On a personal level I've also barely started to grasp what's possible. Anyone reading ImageMagick usage, can see there is a huge range of possibilities. And yet there are also limits imposed by reliance on ImageAPI and Imagecache (as well as great benefits, both are fantastic modules!). In particular iterative transformations which require the output file to be fed back in to a second command are tricky.

Good luck with your ImageMagick experiments!

No. 1 by BS Martin
5th Feb, 2011 @ 20:04

Do you know of any way to modify the outputfilename in order to change the file format (ex pdf -> jpg)?

Thanks.

No. 2 by Adrian
6th Feb, 2011 @ 1:41

This is an issue with imageapi in Drupal-6, it’s not possible to specify or indeed change the file extension. You can change the format, but then you end up with the wrong file extension for the format see: http://drupal.org/node/219261#comment-1881618

That issue 219261 is discussing how to fix this in the all new Imagemagick module for Drupal-7.

No. 3 by Anonymous
16th Aug, 2011 @ 18:55

Great tutorial! Exactly what I was looking for to get started.
Can you tell me what command I would have to use to convert a tif to a jpg based on the format you used above? Thanks.

No. 4 by Adrian
16th Aug, 2011 @ 19:29

As per comments 1 and 2 above, changing format is tricky because you can’t specify the destination file name. I’ve never done it myself. Perhaps you should take a look at http://www.imagemagick.org/Usage/files/#save and experiment.

FWIW there is some work to address the issue http://drupal.org/node/1206598 and a placeholder issue for supporting that in im_raw (full name is now ‘ImageMagick Raw Effect’ for the Drupal 7 version) at http://drupal.org/node/1227270

Can’t see myself having time to work on that for months yet though.

No. 5 by Anonymous
16th Aug, 2011 @ 20:40

Thanks for the resources. I’ll check them out.