Resizing Images using Object Oriented PHP and ImageMagick

Category: Software and Systems Engineering
Author: Sean O'Donnell
Thu, Dec. 22nd, 2011 @ 15:25:32 (MST)

Using ImageMagick via PHP (and PERL) is a common practice for developing High-Quality Photo Manipulation capabilities for web and command-line applications.

I do use the GD Library with PHP for some things... such as generating dynamic images on-the-fly, or for interfacing with the TTF/TrueType Library, but I try not to use it for HQ photo manipulation, as ImageMagick seems to have better proven results. Although the GD Library is still sufficient quality, why settle for less? The only time that I would use GD for tasks that ImageMagick can do, is if ImageMagick is not installed on the server, such case being in certain shared-hosting environments.

The example below is a simple 'ImageMagick' wrapper object written using OO PHP4. The class contains a few basic methods (aka functions) that I commonly use within my web applications and command-line applications.

The most common task that I encounter, is photo resizing.

Various issues come in to play when doing image resizing (in general), so I'll try to address the basics reasons why I prefer to use ImageMagick for this task, rather than using GD.

1) Generally, increasing Photo Sizes degrades image quality, resulting in pixelation. Resampling helps a bit, but it's still pixelated. (Note: Pixelation and Pixelate are (made-up) words that I use to describe the effect, I don't know the actual term for it, unfortunately. Perhaps, decimation or simply degradation?)

2) GD Library requires you to calculate the dimensions (manually) beforehand, and does not perform constrained resize procedures based on just the height or just the width (it requires both). ImageMagick (convert --geometry) doesn't require this extra (manual calculation) step, as it does provide either just the height or just the width (or both) to resize the image in a constrained fashion.

3) ImageMagick doesn't degrade the quality of the image, whereas the GD Library does. You can achieve an almost loss-less conversion via GD. but it requires far more (method execution) steps than it does to use ImageMagick.

<?php
/**
 * @file ImageMagick.php
 * 
 * The ImageMagick class is intended to provide a 
 * front-end PHP Object Oriented Interface to using 
 * the ImageMagick photo manipulation tools.
 *
 * I personally prefer using the ImageMagick Library 
 * over the PHP/GD Library, as the quality of the GD Library
 * is (proven to be) slightly less than that of ImageMagick.
 *
 * @requires PHP >= 4 (w/ safe_mode=off), ImageMagick
 *
 * @copyleft 2004 Sean O'Donnell <sean@seanodonnell.com>
 *
 * $Id: $
 *
 */
class ImageMagick 
{
    
/**
     * define the path to the ImageMagick convert utility
     * (using a constant instead of a variable)
     */
    
    
var $convert '/usr/bin/convert';
    
    function 
ImageMagick()
    {
        return;
    }

    function 
constrain($file_path,$int_max_width,$int_max_height
    {
        if (
file_exists($file_path))
        {
            
$int_imgsize getimagesize($file_path);
    
            if (
$int_imgsize[0] > $int_max_width || $int_imgsize[1] > $int_max_height
            {
                
/**
                 * resize photo to fit interface restrictions, 
                 * constrained by width and/or height
                 */
                
exec($this->convert ." -geometry "$int_max_width ."x"$int_max_height ." "$file_path ." "$file_path);
            } 
        }
        else
        {
            die(
$file_path ." does not exist");
        }
        return;
    }

    function 
constrain_by_width($file_path,$int_max_width
    {
        if (
file_exists($file_path))
        {
            
$int_imgsize getimagesize($file_path);
    
            if (
$int_imgsize[0] > $int_max_width
            {
                
/**
                 * resize photo to fit interface restrictions, 
                 * constrained by width
                 */
                
exec($this->convert ." -geometry "$int_max_width ." "$file_path ." "$file_path);
            } 
        }
        else
        {
            die(
$file_path ." does not exist");
        }
        return;
    }

    function 
constrain_by_height($file_path,$int_max_height
    {
        if (
file_exists($file_path))
        {
            
$int_imgsize getimagesize($file_path);
    
            if (
$int_imgsize[0] > $int_max_width
            {
                
/**
                 * resize photo to fit interface restrictions, 
                 * constrained by height
                 */
                
exec($this->convert ." -geometry x"$int_max_height ." "$file_path ." "$file_path);
            } 
        }
        else
        {
            die(
$file_path ." does not exist");
        }
        return;
    }
}
?>

The Object above allows me to interact with ImageMagick to execute any of the following common procedures:

ImageMagick::constrain(); - constrain the image according to the max height/width
ImageMagick::constrain_by_width(); - constrain the image according to the max width
ImageMagick::constrain_by_height(); - constrain the image according to the max height

The beauty of using a simple Object via PHP, is that I can now re-use these methods in both command-line and web applications.

Example

Below is an example PHP script that uses the ImageMagick object (above) to resize an image in a constrained fashion.

<?php
/** 
 * @file example.php
 */
@require 'ImageMagick.php';

$im = new ImageMagick;

/**
* set the physical path to the file (example)
*/
$file_uri 'images/example.gif';
$file_fs "/home/seanod/www/"$file_uri;

/**
* set the Maximum Width
*/
$width 640;
$height 480;

/**
* execute the function
*/
$im->constrain($file_fs,$width,$height);

print 
"<p><img src=\""$file_uri ."\" /></p>\n";
?>

The example above will resize the Image ($file_fs) to a width of 640, if the image's original width is not smaller.

If the image height is greater than the width, then the image will be resized according to the maximum height (480), instead of the maximum width.

Copyleft (<) 1998-2019 www.seanodonnell.com