Timthumb is an extremely popular thumbnail regeneration script, with built in caching. While it is an excellent script, it relies on GD which when combined with large images & a shared server is a disaster. Here is how to adapt timthumbs to work with ImageMagick.

Updated: 11/04/2011

After a lot of requests, I’ve updated the post to work with the new version of timthumb. It is fairly similar, but different enough for it to have caused problems. The only problem is that because this is a quick dirty hack (I believe the developer of timthumb should add full support for ImageMagick if he wishes) it disables all the filters & the ability to choose the crop location (center, left, etc).

Original Post – Updated For Version 1.26

Ok so recently I’ve been doing a lot of WordPress theme work & one of the popular ways to generate thumbnail sizes that are different from WordPress’, especially cropped ones, is to use the thumbnail generating script Timthumb. It’s a great script that generates thumbnails at the size you request, it also allows cropping & cache generation to stop the strain on the server. However on a shared or low memory server it can cause problems due to it’s use of GD. GD can be a huge memory hog, Imagemagick however can be told to use a specific amount of memory before dumping to swap or HDD. Great if you are on a shared server or a server with limited memory.

Anyway I altered Timthumb to use Imagemagick as there is no option built in to it. So I thought I’d share it for everyone who wants to use it. I can only share the code I used though & not the script just in case. Don’t want to run into any license problems. ;)

First we define a new constant, just to make it easy to alter our path the Imagemagick’s convert.

define ('CACHE_SIZE', 1000);				// number of files to store before clearing cache
define ('CACHE_CLEAR', 20);					// maximum number of files to delete on each cache clear
define ('CACHE_USE', TRUE);					// use the cache files? (mostly for testing)
define ('CACHE_MAX_AGE', 864000);			// time to cache in the browser
define ('VERSION', '1.26');					// version number (to force a cache refresh)
define ('DIRECTORY_CACHE', './cache');		// cache directory
define ('MAX_WIDTH', 1500);					// maximum image width
define ('MAX_HEIGHT', 1500);				// maximum image height
define ('ALLOW_EXTERNAL', FALSE);			// allow external website (override security precaution - not advised!)
define ('MEMORY_LIMIT', '30M');				// set PHP memory limit
define ('MAX_FILE_SIZE', 1500000);			// file size limit to prevent possible DOS attacks (roughly 1.5 megabytes)
define ('CURL_TIMEOUT', 10);				// timeout duration. Tweak as you require (lower = better)
define ('MAGIC_PATH', '~/local/bin/convert'); // path to imagemagick's convert

Now that we have an easy way to call our convert path we can continue. First though a quick note. Timthumb has support for filters, due to Imagemagick having different parameters I have not added support for them. Ok, now that’s out of the way we can get back to the code. I would comment out the bits of code no longer needed. It will not increase the size of the file as we aren’t actually adding that many lines of code to it.

Now is a tricky bit to explain. You need to find this line of code:

if (file_exists ($src)) {

and comment out everything after it (using /* */) until you reach this line:

show_image ($mime_type, $canvas);

Then you need to change that line of code to this:

show_image($src, $mime_type, $cache_dir, $new_width, $new_height, $zoom_crop);

Then comment out this line:

imagedestroy ($canvas);

Now find this function:

function show_image ($mime_type, $image_resized) {

    global $quality;

    $cache_file = get_cache_file ($mime_type);

	if (strpos ($mime_type, 'jpeg') > 1) {
		imagejpeg ($image_resized, $cache_file, $quality);
	} else {
		imagepng ($image_resized, $cache_file, floor ($quality * 0.09));
	}

	show_cache_file ($mime_type);

}

and change it to this:

function show_image($src, $mime_type, $cache_dir, $new_width, $new_height, $zoom_crop) {

    global $quality;

    $cache_file = get_cache_file ($mime_type);

	$new_width = is_numeric($new_width) ? $new_width : '100';
	$new_height = is_numeric($new_height) ? $new_height : '100';
	$crop = ($zoom_crop) ? "^ -gravity center -extent {$new_width}x{$new_height}" : "";

	if (strpos ($mime_type, 'jpeg') > 1) {
		exec(MAGIC_PATH." -limit memory 50mb -limit map 128mb -size {$new_width}x{$new_height} '{$src}' -thumbnail {$new_width}x{$new_height}{$crop} '{$cache_file}'");
	} else {
		exec(MAGIC_PATH." -limit memory 50mb -limit map 128mb -size {$new_width}x{$new_height} '{$src}' -thumbnail {$new_width}x{$new_height}{$crop} '{$cache_file}'");
	}

	show_cache_file ($mime_type);

}

That should be it. It seems to work fine on my server. I am not adding a demo as the amount of hits I may get on it might cause a problem even for imageMagick. However it really does work. If you have any problems please let me know. I’ll try and give support but as I’m not actually the developer who wrote timthumb my knowledge of it is limited. I’ll try and add in support for changing the crop location at some point, but for the minute I hope this helps those looking for ImageMagick support in the latest (as of now 1.26) version of timthumb.