ImageMagick is an extremely powerful image manipulation alternative to GD. WordPress doesn’t currently support ImageMagick natively, but that isn’t going to stop me showing you how to add ImageMagick’s powerful functionality into WordPress.
Update: I have updated the code below to remove the comment that was shown if the function had been disabled due to an upgrade. It caused a error in WordPress’ RSS feed if left. This hack/mod continues to work in version 2.9.2 of WordPress too.
Ok you might be thinking that I’m obsessed with ImageMagick, and who knows, maybe you’re right. However it, in my opinion, is the best image manipulation package for use on servers. It has a lot of options can composite things I never even considered & most importantly has a excellent memory management system which is great for those on low resource or shared servers.
One thing that bugged me about WordPress is that dispite how complex & how brilliant it is, it still hasn’t included any support what-so-ever for ImageMagick. I mean even phpBB & Gallery2/3 have ImageMagick support and they are open source applications. I can’t really complain though as WordPress is still the best blogging software out there & I couldn’t live without it.
Anyway I have come up with a small fix hack that will make WordPress use ImageMagick. I would only advise doing this if you have a good knowledge of coding, and I will say this only once, back-up your database & your files just in case. Nothing should go wrong, if it does you can always just restore WordPress’ original source files, but have a back-up as it’s better to be safe than sorry.
Since the auto-updater was introduced modifying WP’s core files became dangerous as any changes are overwritten when you update. There are only two ways to get round this, one is not possible in PHP without the help of a PECL package such as ‘runkit’, the other is a little more complicated, but is the best thing available as PECL packages cannot always be installed on shared servers & the like. We are going to provide an alternate function for WordPress to use for resizing images, should the original it uses be missing. The easiest place to put this function, as it won’t be affected by auto updates, is the functions.php file of your theme. The function is this:
// Re-define image_resize() function to use ImageMagick. An evil, but necessary hack.
if(!function_exists('image_resize')) {
function image_resize( $file, $max_w, $max_h, $crop = false, $suffix = null, $dest_path = null, $jpeg_quality = 90 ) {
$magic = 'path/to/convert'; //place full or symbolized unix file path to ImageMagick here...
$size = @getimagesize( $file );
if ( !$size )
return new WP_Error('invalid_image', __('Could not read image size'), $file);
list($orig_w, $orig_h, $orig_type) = $size;
$dims = image_resize_dimensions($orig_w, $orig_h, $max_w, $max_h, $crop);
if ( !$dims )
return $dims;
list($dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h) = $dims;
// $suffix will be appended to the destination filename, just before the extension
if ( !$suffix )
$suffix = "{$dst_w}x{$dst_h}";
$info = pathinfo($file);
$dir = $info['dirname'];
$ext = $info['extension'];
$name = basename($file, ".{$ext}");
if ( !is_null($dest_path) and $_dest_path = realpath($dest_path) )
$dir = $_dest_path;
$destfilename = "{$dir}/{$name}-{$suffix}.{$ext}";
if ( IMAGETYPE_GIF == $orig_type ) {
$crop = ($crop) ? "^ -gravity center -extent {$dst_w}x{$dst_h}" : "";
exec($magic." -limit memory 50mb -limit map 128mb -size {$dst_w}x{$dst_h} '{$file}' -thumbnail {$dst_w}x{$dst_h}{$crop} '{$destfilename}'");
} elseif ( IMAGETYPE_PNG == $orig_type ) {
$crop = ($crop) ? "^ -gravity center -extent {$dst_w}x{$dst_h}" : "";
exec($magic." -limit memory 50mb -limit map 128mb -size {$dst_w}x{$dst_h} '{$file}' -thumbnail {$dst_w}x{$dst_h}{$crop} '{$destfilename}'");
} else {
// all other formats are converted to jpg
$destfilename = "{$dir}/{$name}-{$suffix}.jpg";
$crop = ($crop) ? "^ -gravity center -extent {$dst_w}x{$dst_h}" : "";
exec($magic." -limit memory 50mb -limit map 128mb -size {$dst_w}x{$dst_h} '{$file}' -thumbnail {$dst_w}x{$dst_h}{$crop} '{$destfilename}'");
}
// Set correct file permissions
$stat = stat( dirname( $destfilename ));
$perms = $stat['mode'] & 0000666; //same permissions as parent folder, strip off the executable bits
@ chmod( $destfilename, $perms );
return $destfilename;
}
}
?>
Again this is a dirty hack & I claim no resonsiblity for any problems it causes it is up to you whether or not you use it.
This is basically a copy of WordPress’ image resize function, but with all the GD image creation parts taken out and the final resize & save replaced with an exec with the equivalent ImageMagick code in. You may be wondering why I left the image type if in. This is because if the image’s do not match the two types shown the destination file name gets changed to convert all others to a jpg. Conversion will be handled by ImageMagick, but the if is there so that we don’t automatically convert all image types to jpg.
As far as I am aware it doesn’t create any security flaws as all info passed to image_resize() by WordPress is normally checked by WP first. All you have to do now is comment out the image_resize() function in the wp-includes/media.php. The problem of course is that you will have to comment it out again after an upgrade, but at least you don’t have to paste in a function again or even write it again. If there was a filter, or hook to use so you could change the image_resize() function it would be easier, but I haven’t been able to find one.
I hope that helps someone. Let me know should you find any errors or should anyone find any bug/flaws & I’ll try to fix them.

10 Responses
?? ????? ????? ?? ??????? ??????? ???? ???????????????? ???????? ??? ?? ???????????? ????, ??? ? ?? ?????????? ?????? ???????. ?? ????? ????? ????? ???????? ??????? ?? ????????????? ? ????? ???????.
Errrm… Okay! I’m not sure what’s going on here, but all I see is ‘?’s…
Hey Paul!
I’ve been trying out your modification tonight, but can’t seem to get it to work properly.
I have added your function to my theme’s functions.php at the very end, and commented out image_resize() in media.php. All checked and double-checked so far.
However, when I now upload an image in Wordpress, I get this error message after the crunching bit is done:
“Warning: Cannot modify header information – headers already sent by (output started at /home/xxx/xxx/wp-content/themes/dailynotes/functions.php:182) in /home/xxx/xxx/wp-admin/async-upload.php on line 26
Are you sure you want to do this?”
The full size image gets uploaded alright, but no resize versions are made.
Any ideas? I’d be happy to provide any other information.
I’m running Wordpress 2.9.1 and haven’t tinkered with any files besides these two.
Thanks a lot man, I appreciate your work!
L.
I’ll reply to myself here. I tried to simply comment out the image_resize function in media.php and insert your version below. This gives me another, and even more strange error message:
“Warning: getimagesize(/home/xxx/xxx/wp-content/uploads/2010/02/vfv-100×150.jpg) [function.getimagesize]: failed to open stream: No such file or directory in /home/xxx/xxx/wp-includes/media.php on line 484″
100×150? Where do it get those dimensions from? My thumbnail sizes are set at 150×150. Hmm, hmm.
I’ve got convert installed att /usr/local/bin/convert and it looks to be functioning on its own.
Strange, this.
Well I’ll assume you changed it but make sure you did change the
$magicvariable to the correct path for your ImageMagick install. Your error has nothing to do with that but thought I’d check anyway.I’m not sure what is going on with the second error, but the first one is a little strange. Can you tell me what code is on line 182 of your functions file. It appears to be trying to change the pages file header after it has loaded, which you cannot do. I’m not sure if that is stopping thumbnail generation, but it could be by causing PHP to stop.
Hi Paul, thanks for your reply. I figured out what was causing all my troubles. In the end it was my version of convert that didn’t like the “mb” after the specified memory amounts.
Changing “-limit memory 50mb -limit map 128mb” to “-limit memory 50 -limit map 128″ worked magic!
Thanks so much for sharing this piece of code!
L.
Ahh. Yeah some versions don’t like that, please make sure to check that your convert is actually reading those as Megabytes though now that you have removed the mb.
On recent installs of ImageMagick if you leave that off I believe the value is in bytes, so you may have just said
-limit memory 50bytes - limit map 128byteswhich would be bad.I can’t be certain though. If it starts to take an extrodinary amount of time to create thumbnails from larger images then it is probably in bytes. You could always take out the limit if you don’t need to worry about memory use. I’m on a shared server & so need to keep my memory usage in check.
Oh an forgot to say, no problems. I just have this ‘thing’ about not liking GD.
Ah, thanks for the heads-up, I’ll look into it.
When it comes to GD – I hear ya man. It totally screws up the color (profiles) on processed images. That’s why I wanted ImageMagick so I could get some more control. Haven’t figured out the profiles yet, but at least I managed to crank up the saturation by 20% on resized images, which means they look at least somewhat like their original sized counterparts.
Good stuff man, good stuff. Thanks again!
L.
No problem & nice idea. Never really thought about using Imagemagick like that.