Code

Resize an Image on the Fly with PHP

I have created three different functions that use PHP's GD Image Functions to resize images on the fly. The first crops images to fit to the new size so that the aspect ratio is maintained. The second allows you to set a maximum width or height and then shrinks the image to fit those specifications. And, the third forces the image into a specific size, even if that means that the aspect ratio is changed. Additionally, I've constructed a function that loads and saves the images (in JPEG, GIF, PNG, or BMP format) and provides detailed error reporting in case something goes wrong. We'll start with the examples first and then explain how everything works.

Examples

PenguinThey say a picture is worth a thousand words. Well, here's a few pictures... you can decide how many words they're worth. The penguin to the left is the image we'll start with. He's 111 x 193 pixels. In all three examples, we use the resize_image helper function to load up and save the actual image files.


Penguinresize_image('crop','penguin.jpg','penguin_crop.jpg',100,100);

As you can see, this poor penguin was cropped into a smaller image, 100 x 100 pixels, using the resize_image_crop function.


Penguinresize_image('max','penguin.jpg','penguin_max.jpg',100,100);

With the resize_image_max function, we specified that this penguin would have a max height or width of 100 pixels. Since the original is taller than it is wide, the new penguin is 100 pixels tall, but only 57 pixels wide.


Penguinresize_image('force','penguin.jpg','penguin_force.jpg',100,100);

Finally, we created this squished penguin using the resize_image_force function. He is 100 x 100 pixels, but because no cropping occured, the original aspect ratio was abandoned.


resize_image_crop($image,$width,$height)

This function generates a new image in the dimensions you specify, maintaining the aspect ratio by cropping when necessary.

<?php

function resize_image_crop($image,$width,$height) {
    $w = @imagesx($image); //current width
    $h = @imagesy($image); //current height
    if ((!$w) || (!$h)) { $GLOBALS['errors'][] = 'Image couldn\'t be resized because it wasn\'t a valid image.'; return false; }
    if (($w == $width) && ($h == $height)) { return $image; } //no resizing needed
    
    //try max width first...
    $ratio = $width / $w;
    $new_w = $width;
    $new_h = $h * $ratio;
    
    //if that created an image smaller than what we wanted, try the other way
    if ($new_h < $height) {
        $ratio = $height / $h;
        $new_h = $height;
        $new_w = $w * $ratio;
    }
    
    $image2 = imagecreatetruecolor ($new_w, $new_h);
    imagecopyresampled($image2,$image, 0, 0, 0, 0, $new_w, $new_h, $w, $h);

    //check to see if cropping needs to happen
    if (($new_h != $height) || ($new_w != $width)) {
        $image3 = imagecreatetruecolor ($width, $height);
        if ($new_h > $height) { //crop vertically
            $extra = $new_h - $height;
            $x = 0; //source x
            $y = round($extra / 2); //source y
            imagecopyresampled($image3,$image2, 0, 0, $x, $y, $width, $height, $width, $height);
        } else {
            $extra = $new_w - $width;
            $x = round($extra / 2); //source x
            $y = 0; //source y
            imagecopyresampled($image3,$image2, 0, 0, $x, $y, $width, $height, $width, $height);
        }
        imagedestroy($image2);
        return $image3;
    } else {
        return $image2;
    }
}

?>

resize_image_max($image,$max_width,$max_height)

This function checks to see if your image exceeds either the max width or the max height specified and, if so, resizes the image while maintaining the aspect ratio.

<?php

function resize_image_max($image,$max_width,$max_height) {
    $w = imagesx($image); //current width
    $h = imagesy($image); //current height
    if ((!$w) || (!$h)) { $GLOBALS['errors'][] = 'Image couldn\'t be resized because it wasn\'t a valid image.'; return false; }

    if (($w <= $max_width) && ($h <= $max_height)) { return $image; } //no resizing needed
    
    //try max width first...
    $ratio = $max_width / $w;
    $new_w = $max_width;
    $new_h = $h * $ratio;
    
    //if that didn't work
    if ($new_h > $max_height) {
        $ratio = $max_height / $h;
        $new_h = $max_height;
        $new_w = $w * $ratio;
    }
    
    $new_image = imagecreatetruecolor ($new_w, $new_h);
    imagecopyresampled($new_image,$image, 0, 0, 0, 0, $new_w, $new_h, $w, $h);
    return $new_image;
}

?>

resize_image_force($image,$width,$height)

This function generates a new image in the dimensions you specify without cropping, so the aspect ratio may be altered.

<?php

function resize_image_force($image,$width,$height) {
    $w = @imagesx($image); //current width
    $h = @imagesy($image); //current height
    if ((!$w) || (!$h)) { $GLOBALS['errors'][] = 'Image couldn\'t be resized because it wasn\'t a valid image.'; return false; }
    if (($w == $width) && ($h == $height)) { return $image; } //no resizing needed

    $image2 = imagecreatetruecolor ($width, $height);
    imagecopyresampled($image2,$image, 0, 0, 0, 0, $width, $height, $w, $h);

    return $image2;
}

?>

resize_image($method,$image_loc,$new_loc,$width,$height)

Those functions all start with an image that has already been opened by the GD Image functions. This next function goes farther and opens up an image file, resizes it according to the method you choose, and then saves it for you. It also displays any errors that are generated in an easy-to-understand way.

<?php

function resize_image($method,$image_loc,$new_loc,$width,$height) {
    if (!is_array(@$GLOBALS['errors'])) { $GLOBALS['errors'] = array(); }
    
    if (!in_array($method,array('force','max','crop'))) { $GLOBALS['errors'][] = 'Invalid method selected.'; }
    
    if (!$image_loc) { $GLOBALS['errors'][] = 'No source image location specified.'; }
    else {
        if ((substr(strtolower($image_loc),0,7) == 'http://') || (substr(strtolower($image_loc),0,7) == 'https://')) { /*don't check to see if file exists since it's not local*/ }
        elseif (!file_exists($image_loc)) { $GLOBALS['errors'][] = 'Image source file does not exist.'; }
        $extension = strtolower(substr($image_loc,strrpos($image_loc,'.')));
        if (!in_array($extension,array('.jpg','.jpeg','.png','.gif','.bmp'))) { $GLOBALS['errors'][] = 'Invalid source file extension!'; }
    }
    
    if (!$new_loc) { $GLOBALS['errors'][] = 'No destination image location specified.'; }
    else {
        $new_extension = strtolower(substr($new_loc,strrpos($new_loc,'.')));
        if (!in_array($new_extension,array('.jpg','.jpeg','.png','.gif','.bmp'))) { $GLOBALS['errors'][] = 'Invalid destination file extension!'; }
    }

    $width = abs(intval($width));
    if (!$width) { $GLOBALS['errors'][] = 'No width specified!'; }
    
    $height = abs(intval($height));
    if (!$height) { $GLOBALS['errors'][] = 'No height specified!'; }
    
    if (count($GLOBALS['errors']) > 0) { echo_errors(); return false; }
    
    if (in_array($extension,array('.jpg','.jpeg'))) { $image = @imagecreatefromjpeg($image_loc); }
    elseif ($extension == '.png') { $image = @imagecreatefrompng($image_loc); }
    elseif ($extension == '.gif') { $image = @imagecreatefromgif($image_loc); }
    elseif ($extension == '.bmp') { $image = @imagecreatefromwbmp($image_loc); }
    
    if (!$image) { $GLOBALS['errors'][] = 'Image could not be generated!'; }
    else {
        $current_width = imagesx($image);
        $current_height = imagesy($image);
        if ((!$current_width) || (!$current_height)) { $GLOBALS['errors'][] = 'Generated image has invalid dimensions!'; }
    }
    if (count($GLOBALS['errors']) > 0) { @imagedestroy($image); echo_errors(); return false; }

    if ($method == 'force') { $new_image = resize_image_force($image,$width,$height); }
    elseif ($method == 'max') { $new_image = resize_image_max($image,$width,$height); }
    elseif ($method == 'crop') { $new_image = resize_image_crop($image,$width,$height); }
    
    if ((!$new_image) && (count($GLOBALS['errors'] == 0))) { $GLOBALS['errors'][] = 'New image could not be generated!'; }
    if (count($GLOBALS['errors']) > 0) { @imagedestroy($image); echo_errors(); return false; }
    
    $save_error = false;
    if (in_array($extension,array('.jpg','.jpeg'))) { imagejpeg($new_image,$new_loc) or ($save_error = true); }
    elseif ($extension == '.png') { imagepng($new_image,$new_loc) or ($save_error = true); }
    elseif ($extension == '.gif') { imagegif($new_image,$new_loc) or ($save_error = true); }
    elseif ($extension == '.bmp') { imagewbmp($new_image,$new_loc) or ($save_error = true); }
    if ($save_error) { $GLOBALS['errors'][] = 'New image could not be saved!'; }
    if (count($GLOBALS['errors']) > 0) { @imagedestroy($image); @imagedestroy($new_image); echo_errors(); return false; }

    imagedestroy($image);
    imagedestroy($new_image);
    
    return true;
}

function echo_errors() {
    if (!is_array(@$GLOBALS['errors'])) { $GLOBALS['errors'] = array('Unknown error!'); }
    foreach ($GLOBALS['errors'] as $error) { echo '<p style="color:red;font-weight:bold;">Error: '.$error.'</p>'; }
}



?>


15 Comments

July 31, 2012, 9:11 am
This is a great script. At first I didn't follow the directions completely and had a few problems. I didn't realize I needed the resize_image function AND the resize_image_crop function to get what I wanted. Once I understood the function it worked like a charm. Best thing to do is just copy and paste all 4 functions. Great work.
September 7, 2012, 2:29 pm
Really useful, I appreciate your snip of code. Thanks a lot.
kalveh
September 13, 2012, 12:20 pm
Thanks for this code :) really appreciated.
September 21, 2012, 5:02 pm
Thanks! This is awesome, I'm going to try and integrate it into my site. Is there a way to use this to make images a "minimum" size? I have a slideshow that the photos need to fill out but the edges need to be cropped, so I was thinking I'd get it to the minimum-width and crop the height or to the minimum height and crop the width. Any advice?
mike
October 26, 2012, 6:53 pm
whats the pages name? can u please name the pages?
Juan
December 4, 2012, 9:30 am
how can i show the generated img?
fadhil
December 11, 2012, 5:56 am
very nice but what if I want to dislpay cropped image on the fly? the script only saves the cropped image
Marcus
December 17, 2012, 2:07 pm
Wow! Fantastic! Works like a charm..

Thank you!
Vilda
January 31, 2013, 2:42 pm
Great script, but in function resize image is bug:
wrong:
if ((substr(strtolower($image_loc),0,7) == 'http://') || (substr(strtolower($image_loc),0,7) == 'https://'))
correct:
if ((substr(strtolower($image_loc),0,7) == 'http://') || (substr(strtolower($image_loc),0,8) == 'https://'))
Anup
February 14, 2013, 7:36 am
This Post is very well explained and indeed a very useful post. Thanks Guys for this Awesome Post. I really like it!!!!
May 7, 2013, 11:53 am
I have GD installed and enabled, but I am getting a Fatal error: Call to undefined function resize_image_crop()
What am I missing?
Jeff
August 22, 2013, 10:01 am
very usefull tips, thank you very much for sharing.
Dennis Munding
February 11, 2014, 9:21 am
@Deanna: Basic computer programming skills...??

Copy and pasting other people's source code is _not_ programming...

Must be easy to call yourself a "webdeveloper" and actually charge money using a template and add some copied functions...

Makes me sick!

Nothing personally - your kind is all over the world...

And I should be happy - 'cause it makes me busy cleaning up the mess. you're spreading all over the internet...
March 1, 2014, 3:56 am
I was greatly helped by this, I say thank you very much ^ _ ^
April 3, 2014, 7:09 am
I was sett
resize_image('max','a.png','files_produk/cache/b.png',100,100);
Error: Image could not be generated!

thanks

Leave a Comment

Name
Email
Website
Comment
Name and email are required. Your email will not be published.

This post was published on August 4th, 2011 by Robert James Reese in the following categories: Images, PHP.

Before using any of the code or other content in this post, you must read and agree to our Terms & Conditions.

Copyright © 2014, Ink Plant. All rights reserved.