2
\$\begingroup\$

I made this PHP class that loads any image you specify and resizes it to any size you want.

Features

If the size you specify is greater than the original, it will not stretch the image but use padding instead. Or if the size you requested is not the original aspect ratio, it will not distort the image but use padding to match the requested size.

You can specify what color you want the padding to be, default is white. It preserves transparency in .png files. You can specify what output you want to use (.jpeg/.gif/.png) but it defaults to the original file type.

Primary Purpose

The main reason I wanted to make this class was so that I could upload 1 large file and use it throughout the site. So I would not need to create several copies of the same image in different sizes (large, thumbnail, etc.)

In theory I wanted to be able to upload the largest version of the image I have, then still be able to load a page with 50 small thumbnails relatively fast because the large images are being shrunk before they are loaded.

Problem

It does work, however, when loading a very large image as a thumbnail, it still seems to take about the same amount of time as if it were not shrinking. Only instead of waiting for it to actually download you are waiting for the image to be processed and resampled before you can begin download. This delay only happens when processing large images. The one I used was 5MB.

Code

class ImageSrv
{
    private $image;
    private $original_width;
    private $original_height;
    private $original_type;

    // default colors for background and padding
    private $r = 255;
    private $g = 255;
    private $b = 255;

    function load($image_file) 
    {
        $this->image = $this->createImageFromFile($image_file);
    }

    function setBackground($r, $g, $b)
    {
        $this->r = (int) $r;
        $this->g = (int) $g;
        $this->b = (int) $b;
    }

    function createImageFromFile($image_file)
    {
        $image_info = getimagesize($image_file);

        $this->original_width = $image_info[0];
        $this->original_height = $image_info[1];
        $this->original_type = $image_info[2];

        if( $this->original_type == IMAGETYPE_JPEG ) 
        {
            return imagecreatefromjpeg($image_file);
        } 
        else if( $this->original_type == IMAGETYPE_GIF ) 
        {
            return imagecreatefromgif($image_file);
        } 
        else if( $this->original_type == IMAGETYPE_PNG ) 
        {
            /*
             * create image and preserve transpancy
             * this keeps png files from having a black backgroung
             * when you don't resize them.
             * pngs converted to jpgs still have a black background
             * not sure how to make it a different color
             */
            $im = imagecreatefrompng($image_file);
            imagealphablending($im, false);
            imagesavealpha($im, true);

            return $im;
        }   
    }

    function setSize($width = NULL,$height = NULL) 
    {
        if($width == NULL && $height == NULL)
        {
            return; 
        }

        $ratio = $this->original_width / $this->original_height;
        $new_ratio = $width / $height;

        if($width == NULL)
        {
            $width = $height*$ratio;
            if($width > $this->original_width)
            {
                $width = $this->original_width; 
            }
        }
        else if($height == NULL)
        {
            $height = $width/$ratio;
            if($height > $this->original_height)
            {
                $height = $this->original_height;   
            }
        }


        // if width is greater than original width 
        // set to original width and pad the difference
        if($width < $this->original_width)
        {
            $w = $width;
        }
        else
        {
            $w = $this->original_width;
        }
        // if height is greater than original height 
        // set to original height and pad the difference
        if($height < $this->original_height)
        {
            $h = $height;
        }
        else
        {
            $h = $this->original_height;
        }
        // check if new deminsions are same aspect ratio
        // if not, fix aspect ratio and pad the difference
        if( $w / $h != $ratio )
        {
            if($width > $w && $height > $h)
            {
                //no scaling    
            }
            else if($width > $w)
            {
                $w = $h*$ratio;
            }
            else if($height > $h)
            {
                $h = $w/$ratio;
            }
            else if($ratio < $new_ratio)
            {
                $w = $h*$ratio;
            }
            else
            {
                $h = $w/$ratio;
            }
        }

        // resize image with correct aspect ratio and use padding to meet required size
        $image = imagecreatetruecolor($width, $height);
        imagealphablending($image, false);
        imagesavealpha($image, true);
        $transparent = imagecolorallocatealpha($image, $this->r, $this->g, $this->b, 127);
        imagefill($image, 0, 0, $transparent);
        imagecopyresampled($image, $this->image, ($width - $w) / 2 , ($height - $h) / 2, 0, 0, $w, $h, $this->original_width, $this->original_height);

        $this->image = $image;

        // reset original width and height to the new width and height
        $this->original_width = $width;
        $this->original_height = $height;
    }

    function output($type=NULL) 
    {
        if($type == NULL)
        {
            $type = $this->original_type;   
        }

        if( $type == IMAGETYPE_JPEG ) 
        {
            header('Content-Type: image/jpeg');
            imagejpeg($this->image);
        } 
        else if( $type == IMAGETYPE_GIF ) 
        {
            header('Content-Type: image/gif');
            imagegif($this->image);         
        } 
        else if( $type == IMAGETYPE_PNG ) 
        {
            header('Content-Type: image/png');
            imagepng($this->image);
        }   
    }

}

Is there anything I can do to improve this performance?

\$\endgroup\$
2
\$\begingroup\$

Cache the generated images so they only need to be generated once.

\$\endgroup\$
1
\$\begingroup\$

I take it you are using GD for image manipulation. You could look at ImageMagick as an alternative, as its been shown to be faster at manipulating images. There is a related SO question here.

\$\endgroup\$
  • \$\begingroup\$ I know this is an old answer, but this doesn't fit the criteria for a good review on Code Review. We try to steer away from answers that say "use X because it is better" \$\endgroup\$ – Malachi Sep 12 '18 at 14:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.