Manipulating Images with PHP and GraphicsMagick

September 28, 2009

Tutorials

The Right Image

One of the things I like best about PHP is its support for a diverse array of tools and technologies. Take, for instance, image manipulation. Like most developers, I’ve known for a while that PHP comes with GD support for basic image generation and processing tasks, and I’ve even used it on occasion to dynamically create images from a base template. However, I recently needed to write some code involving cropping, resizing and otherwise torturing images and while researching the topic, I came across another PHP extension for image manipulation: the GraphicsMagick extension.

Based on the robust, multi-threaded GraphicsMagick library, aka the “Swiss Army knife of image processing”, PHP’s GraphicsMagick extension allows developers to add street cred to their image (sorry, I couldn’t resist!) with some fairly powerful API methods. This article discusses the extension in detail, introducing you to its key functions and showing you how to rotate, resample, transform, crop, carve, and otherwise mangle your images until they roll over and beg for mercy. So come on in, and bring your evil laughter with you!

Lights! Camera! Magic!

GraphicsMagick support in PHP comes through PECL’s ext/gmagick extension, which is maintained by Vito Chin and Mikko Koppanen, and provides an object-oriented API for image manipulation. Although this extension is currently in beta, it still allows you to do some fairly interesting things, including cropping, resizing and applying effects to images using PHP.

To get started with ext/gmagick, you’ll need to first make sure that you’re running PHP v5.1.3 or better, as the extension will not work on any earlier version. If you’ve got this, download the GraphicsMagick libraries (v1.2.6 or better) and compile them for your system. Assuming you’re on a *NIX system, here’s how:

shell> tar -xzvf GraphicsMagick-1.3.7.tar.gz
shell> cd GraphicsMagick-1.3.7
shell> ./configure --without-perl --enable-shared --disable-openmp
shell> make
shell> make install

Once this is done, you can proceed to install the GraphicsMagick extension using the pecl command, as shown below:

shell> pecl install gmagick-beta

In case you don’t have access to the pecl command, you can also manually download the source code archive (v1.0.1-beta at this time) and compile it into a loadable PHP module with phpize:

shell> cd gmagick-1.0.1b1
shell> phpize
shell> ./configure
shell> make
shell> make install

Regardless of which procedure you choose, you should end up with a loadable PHP module named gmagick.so in your PHP extension directory. You should now enable the extension in the php.ini configuration file, restart your Web server, and check that the extension is enabled with a quick call to phpinfo():

This article uses GraphicsMagick v1.3.7 and ext/gmagick v1.0.1-beta.

Picture This

Once you have all the pieces loaded, let’s take ext/gmagick out for a quick spin. Here’s a simple example, which reads a photo and displays various photo properties:

<?php
try {
  // initialize object
  $image = new Gmagick();

  // read image file
  $file = 'gallery/IMG_0001.JPG';
  $image->readImage($file);
  echo '<img src="' . $file . '" width="200" height="150" /> <br/>';

  // get image height and width
  echo 'Image dimensions: ' . $image->getImageWidth() . ' x ' . $image->getImageHeight() . '<br/>';

  // get image format
  echo 'Image format: ' . $image->getImageFormat() . '<br/>';

  // get image depth
  echo 'Image depth: ' . $image->getImageDepth() . '<br/>';

  // get number of unique image colors
  echo 'Image colors: ' . $image->getImageColors() . '<br/>';

  // get image resolution
  $r = $image->getImageResolution();
  echo 'Image resolution: ' . $r['x'] . 'x' . $r['y'] . '<br/>';

  // free resource handle
  $image->destroy();
} catch (Exception $e) {
  die ($e->getMessage());
}
?>

Your primary access point to GraphicsMagick in PHP is through the Gmagick object, which is initialized in the first line of the script above. This object exposes a number of methods for image manipulation, but the one you’re going to be on first-name terms with very soon is the readImage() method, which accepts a file path as argument and reads the corresponding image into memory. Detailed information on the image, such as its dimensions, resolution, color depth and format, can now be obtained via a range of conveniently-named get*() methods, as illustrated above.

Here’s what the output looks like:

Scaling Up

If you need to dynamically resize images so they fit into a particular template, the GraphicsMagick extension has you covered: simply call the resizeImage() method with the new height and width. You can then send the new image to the output device, or write it to a file.

Consider the next example, which demonstrates by resizing an image to 150% of its original dimensions:

<?php
try {
  // initialize object 
  $image = new Gmagick();

  // read image file
  $image->readImage('gallery/original.jpg');

  // set height and width as 150% of original
  $height = $image->getImageHeight() * 1.5;
  $width = $image->getImageWidth() * 1.5;

  // resize image
  $image->resizeImage($width, $height, null, 1);

  // write new image file
  $image->writeImage('gallery/new.jpg');

  // free resource handle
  $image->destroy();
} catch (Exception $e) {
  die ($e->getMessage());
}
?>

Here’s what the output looks like:

You can resample an image with the resampleImage() method, which accepts the dimensions of the new resolution, the image filter and the blur factor as arguments. Here’s an example of it in action:

<?php
try {
  // initialize object
  $image = new Gmagick();

  // read image file
  $image->readImage('gallery/original.jpg');

  // resample image
  $image->resampleImage(160, 120, null, 1);

  // write new image file
  $image->writeImage('gallery/new.jpg');

  // free resource handle
  $image->destroy();
} catch (Exception $e) {
  die ($e->getMessage());
}
?>

And here’s some example output:

If what you’re really trying to do is create a thumbnail gallery, there’s a simpler way: the extension has a thumbnailImage() method, which accepts height and width numbers and generates a thumbnail version of the original image corresponding those dimensions. Here’s an example, which iterates over a directory, locates all the JPEGs in it and builds a thumbnail gallery of 150×150 images:

<?php
try {
  // get all the JPEG files in a directory
  $fileList = glob('gallery/*.JPG');
  foreach ($fileList as $file) {
    // initialize object
    $image = new Gmagick();

    // for each file
    // generate thumbnail
    // write thumbnail to disk
    $image->readImage($file);
    $image->thumbnailImage(150, 150);
    $thumbFile = dirname($file) . '/' . basename($file, '.JPG') . '.thumb.jpg';
    $image->writeImage($thumbFile);

    // free resource handle
    $image->destroy();
  }

} catch (Exception $e) {
  die ($e->getMessage());
}
?>

:
Here’s what the output looks like:

In the Frame

The GraphicsMagick extension also includes methods for rotating, flipping and cropping images. Here’s an example:

<?php
try {
  // initialize object
  $image = new Gmagick();

  // read image file
  $image->readImage('gallery/original.jpg');

  // rotate image
  $image->rotateImage('red', -45);

  // write new image file
  $image->writeImage('gallery/new.jpg');

  // free resource handle
  $image->destroy();
} catch (Exception $e) {
  die ($e->getMessage());
}
?>

The rotateImage() method needs two arguments: the number of degrees by which to rotate the original image (second) and the fill color to use for any resultant empty space (first). Here’s what the script above generates:

You can create a vertical or horizontal mirror image with the flipImage() and flopImage() methods, respectively. Here’s an example:

<?php
try {
  // initialize object
  $image = new Gmagick();

  // read image file
  $image->readImage('gallery/original.jpg');

  // flip image vertically
  $image->flipImage();

  // write new image file
  $image->writeImage('gallery/new_1.jpg');

  // revert
  $image->flipImage();

  // flip image horizontally
  $image->flopImage();

  // write new image file
  $image->writeImage('gallery/new_2.jpg');

  // free resource handle
  $image->destroy();
} catch (Exception $e) {
  die ($e->getMessage());
}
?>

And here’s an example of the resulting output:

You can crop a portion of the image with the cropImage() method, which accepts four arguments: the width and height of the area to crop, in pixels, and the X and Y coordinates of the pixel at the top left corner of the crop area. Here’s an example:

<?php
try {
  // initialize object
  $image = new Gmagick();

  // read image file
  $image->readImage('gallery/original.jpg');

  // crop image
  $image->cropImage(122, 70, 76, 138);

  // write new image file
  $image->writeImage('gallery/new.jpg');

  // free resource handle
  $image->destroy();
} catch (Exception $e) {
  die ($e->getMessage());
}
?>

And here’s the resulting output:

Finally, you can magnify an image to twice its original size, or scale it down to half, with the magnifyImage() and minifyImage() methods, as below:

<?php
try {
  // initialize object
  $image = new Gmagick();

  // read image file
  $image->readImage('gallery/original.jpg');

  // magnify image 2x
  $image->magnifyImage();

  // write new image file
  $image->writeImage('gallery/new_1.jpg');

  // revert
  $image->minifyImage();

  // scale image to half
  $image->minifyImage();

  // write new image file
  $image->writeImage('gallery/new_2.jpg');

  // free resource handle
  $image->destroy();
} catch (Exception $e) {
  die ($e->getMessage());
}
?>

Take a look at what this produces:

Not My Type

Living up to its billing as the “Swiss Army knife of image processing”, the GraphicsMagick extension eats formats for breakfast. It can read and convert between most common image formats, including JPEG, GIF, PNG and TIFF, making it perfect for on-the-fly image conversion of uploaded photos or drawings. To convert an image, simply read it into memory with readImage(), use the setImageFormat() method to set the target format, and then write it back out with writeImage(). Simple, logical and oh so easy!

Here’s an example:

<?php
try {
  // initialize object
  $image = new Gmagick();

  // read image file
  $image->readImage('gallery/original.jpg');

  // switch to GIF format
  $image->setImageFormat('GIF');

  // write new image file
  $image->writeImage('gallery/new.gif');

  // free resource handle
  $image->destroy();
} catch (Exception $e) {
  die ($e->getMessage());
}
?>

Incidentally, you can get a list of all the formats supported by your build with the queryFormats() method.

Border Incursion

You can add a 2D border to your image with the borderImage() method, which accepts three arguments: the border color, the border width and the border height. Here’s an example of it in action, generating a blue border that’s 4 pixels wide and 15 pixels high:

<?php
try {
  // initialize object
  $image = new Gmagick();

  // read image file
  $image->readImage('gallery/original.jpg');

  // add border to image
  $image->borderImage('blue', 4, 15);

  // write new image file
  $image->writeImage('gallery/new.jpg');

  // free resource handle
  $image->destroy();
} catch (Exception $e) {
  die ($e->getMessage());
}
?>

Here’s what the output looks like:

If you prefer 3D, the frameImage() method lets you apply a 3D border to your image. Here’s how it works:

<?php
try {
  // initialize object
  $image = new Gmagick();

  // read image file
  $image->readImage('gallery/original.jpg');

  // add 3D border to image
  $image->frameImage('silver', 20, 20, 5, 5);

  // write new image file
  $image->writeImage('gallery/new.jpg');

  // free resource handle
  $image->destroy();
} catch (Exception $e) {
  die ($e->getMessage());
}
?>

And here’s an example of what the output looks like:

You can blur or sharpen an image with the blurImage() and sharpenImage() methods, both of which accept a blur/sharpen radius value and a standard deviation. Here’s an example:

<?php
try {
  // initialize object
  $image = new Gmagick();

  // read image file
  $image->readImage('gallery/original.jpg');

  // blur image
  $image->blurImage(8, 3);

  // write new image file
  $image->writeImage('gallery/new.jpg');

  // free resource handle
  $image->destroy();
} catch (Exception $e) {
  die ($e->getMessage());
}
?>

And here’s the output:

Swirl Cycle

I’ve left the most impressive bits for last. The GraphicsMagick extension comes with a bunch of methods that allow you to apply special effects to your images. For example, the swirlImage() method adds a swirling effect to the center of your image:

<?php
try {
  // initialize object
  $image = new Gmagick();

  // read image file
  $image->readImage('gallery/original.jpg');

  // add swirl effect
  $image->swirlImage(180);

  // write new image file
  $image->writeImage('gallery/new.jpg');

  // free resource handle
  $image->destroy();
} catch (Exception $e) {
  die ($e->getMessage());
}
?>

Here’s an example of the resulting output:

The charcoalImage() method lets you re-render an image in the style of a charcoal drawing:

<?php
try {
  // initialize object
  $image = new Gmagick();

  // read image file
  $image->readImage('gallery/original.jpg');

  // add charcoal drawing effect
  $image->charcoalImage(5, 0.2);

  // write new image file
  $image->writeImage('gallery/new.jpg');

  // free resource handle
  $image->destroy();
} catch (Exception $e) {
  die ($e->getMessage());
}
?>

Here’s an example of the resulting output:

The oilPaintImage() method lets you render an image in the style of an oil painting:

<?php
try {
  // initialize object
  $image = new Gmagick();

  // read image file
  $image->readImage('gallery/original.jpg');

  // add oil paint effect
  $image->oilPaintImage(2.5);

  // write new image file
  $image->writeImage('gallery/new.jpg');

  // free resource handle
  $image->destroy();
} catch (Exception $e) {
  die ($e->getMessage());
}
?>

Here’s an example of the resulting output:

The cycleColorMapImage() method lets you shift the colors of the image. As the manual suggests, if you do this a few times, it produces a psychedelic effect. Here’s an example:

<?php
try {
  // initialize object
  $image = new Gmagick();

  // read image file
  $image->readImage('gallery/original.jpg');

  // displace image colors
  $image->cycleColorMapImage(100);
  $image->cycleColorMapImage(100);
  $image->cycleColorMapImage(100);
  $image->cycleColorMapImage(100);

  // write new image file
  $image->writeImage('gallery/new.jpg');

  // free resource handle
  $image->destroy();
} catch (Exception $e) {
  die ($e->getMessage());
}
?>

And here’s an example of the resulting output:

The solarizeImage() method lets you apply a darkroom effect to your image:

<?php
try {
  // initialize object
  $image = new Gmagick();

  // read image file
  $image->readImage('gallery/original.jpg');

  // solarize image
  $image->solarizeImage(100);

  // write new image file
  $image->writeImage('gallery/new.jpg');

  // free resource handle
  $image->destroy();
} catch (Exception $e) {
  die ($e->getMessage());
}
?>

The shearImage() method lets you move part of the image to create a “parallelogram effect”:

<?php
try {
  // initialize object
  $image = new Gmagick();

  // read image file
  $image->readImage('gallery/original.jpg');

  // displace image colors
  $image->shearImage('white', 5, 70);

  // write new image file
  $image->writeImage('gallery/new.jpg');

  // free resource handle
  $image->destroy();
} catch (Exception $e) {
  die ($e->getMessage());
}
?>

Here’s the output:

As the examples above illustrate, you no longer need a Photoshop expert to hold your hand when it comes to working with images, because PHP’s GraphicsMagick extension offers a full-fledged alternative for dynamic image manipulation. This article has only scratched the tip of the iceberg – the PHP manual documents more than 130 methods for this extension. In other words, there’s no shortage of things to play with – so why not try it out and see what you think!

Copyright Melonfire, 2009. All rights reserved.

7 Responses to “Manipulating Images with PHP and GraphicsMagick”

  1. tgs_raja Says:

    Is anyone have manipulated the image for the opacity? If yes, please let me know the name of the method in Gmagick.

    Thanks,
    Sabari

  2. thinsoldier Says:

    Is it just me or do your thumbnail gallery example images look squashed?

    How do you maintain the original proportions when making thumbnails?

    How would you handle resizing a batch of landscape & portrait images to all fit without the boundaries of a particular width & height?

  3. barry853 Says:

    I’ve followed the installation instruction step by step without problems. Nevertheless when I’m trying to do sth like this

    $image = new Gmagick();
    $image->readImage($path_to_source);

    I get : "No decode delegate for this image format"
    my source img format is .jpeg. Does anyone have an idea about the reason of that?

  4. b0romir Says:

    Hi,

    I’m trying to install it on windows but http://pecl4win.php.net/ is temporarily unavailable. Do you know ehre I could find dll file of that library for windows.

  5. Jonathanz Says:

    It’s really helpful article.
    step by step

  6. truethermo Says:

    I’ve tested GraphicsMagick because GD was too slow and memory hungry and it turned out GM is much more memory efficient and faster than GD, especially for large images.

  7. sgoranov Says:

    Nice article !
    I’ve got two questions. The first one is about the performance. Have you made any tests, specially on image scaling, because this is the most used feature I think ?
    Secondly, do you have any idea when Graphics Magic extension will be included into the php itself (now it’s in pecl) ?

    Regards,
    S.G.