Resize an Image (on the fly) & Keep its Aspect Ratio using PHP and GD
Posted on September 28, 2008, Filled under PHP,
Bookmark it
Thanks for visiting our website! We regularly publish posts like this one. If you are interested in receiving the latest updates as soon as they are posted, please consider subscribing to the RSS feed or to our e-mail newsletter.
This is a PHP Class useful if you need to resize images keeping their aspect ratio, using the GD Library. The new height is calculated proportionally to the new width’s size and reverse. For instance you have an image with the following dimensions: width – 1000, height – 800. Its thumbnail with a width of 250 will have the height of 200 (the ratio is kept).
Here’s the class (I will explain you how it works below):
resize.image.class.php
<?php
/*
---------------------------------------------------------------------
Credits: Bit Repository
Source URL: http://www.bitrepository.com/resize-an-image-keeping-its-aspect-ratio-using-php-and-gd.html
---------------------------------------------------------------------
*/
class Resize_Image {
var $image_to_resize;
var $new_width;
var $new_height;
var $ratio;
var $new_image_name;
var $save_folder;
function resize()
{
if(!file_exists($this->image_to_resize))
{
exit("File ".$this->image_to_resize." does not exist.");
}
$info = GetImageSize($this->image_to_resize);
if(empty($info))
{
exit("The file ".$this->image_to_resize." doesn't seem to be an image.");
}
$width = $info[0];
$height = $info[1];
$mime = $info['mime'];
/*
Keep Aspect Ratio?
Improved, thanks to Larry
*/
if($this->ratio)
{
// if preserving the ratio, only new width or new height
// is used in the computation. if both
// are set, use width
if (isset($this->new_width))
{
$factor = (float)$this->new_width / (float)$width;
$this->new_height = $factor * $height;
}
else if (isset($this->new_height))
{
$factor = (float)$this->new_height / (float)$height;
$this->new_width = $factor * $width;
}
else
exit(â€neither new height or new width has been setâ€);
}
// What sort of image?
$type = substr(strrchr($mime, '/'), 1);
switch ($type)
{
case 'jpeg':
$image_create_func = 'ImageCreateFromJPEG';
$image_save_func = 'ImageJPEG';
$new_image_ext = 'jpg';
break;
case 'png':
$image_create_func = 'ImageCreateFromPNG';
$image_save_func = 'ImagePNG';
$new_image_ext = 'png';
break;
case 'bmp':
$image_create_func = 'ImageCreateFromBMP';
$image_save_func = 'ImageBMP';
$new_image_ext = 'bmp';
break;
case 'gif':
$image_create_func = 'ImageCreateFromGIF';
$image_save_func = 'ImageGIF';
$new_image_ext = 'gif';
break;
case 'vnd.wap.wbmp':
$image_create_func = 'ImageCreateFromWBMP';
$image_save_func = 'ImageWBMP';
$new_image_ext = 'bmp';
break;
case 'xbm':
$image_create_func = 'ImageCreateFromXBM';
$image_save_func = 'ImageXBM';
$new_image_ext = 'xbm';
break;
default:
$image_create_func = 'ImageCreateFromJPEG';
$image_save_func = 'ImageJPEG';
$new_image_ext = 'jpg';
}
// New Image
$image_c = ImageCreateTrueColor($this->new_width, $this->new_height);
$new_image = $image_create_func($this->image_to_resize);
ImageCopyResampled($image_c, $new_image, 0, 0, 0, 0, $this->new_width, $this->new_height, $width, $height);
if($this->save_folder)
{
if($this->new_image_name)
{
$new_name = $this->new_image_name.'.'.$new_image_ext;
}
else
{
$new_name = $this->new_thumb_name( basename($this->image_to_resize) ).'_resized.'.$new_image_ext;
}
$save_path = $this->save_folder.$new_name;
}
else
{
/* Show the image without saving it to a folder */
header("Content-Type: ".$mime);
$image_save_func($image_c);
$save_path = '';
}
$process = $image_save_func($image_c, $save_path);
return array('result' => $process, 'new_file_path' => $save_path);
}
function new_thumb_name($filename)
{
$string = trim($filename);
$string = strtolower($string);
$string = trim(ereg_replace("[^ A-Za-z0-9_]", " ", $string));
$string = ereg_replace("[ tnr]+", "_", $string);
$string = str_replace(" ", '_', $string);
$string = ereg_replace("[ _]+", "_", $string);
return $string;
}
}
?>
Here’s an example of how you can use this class:
<?php
include 'resize.image.class.php';
$image = new Resize_Image;
$image->new_width = 200;
$image->new_height = 200;
$image->image_to_resize = "/home/mysite.com/public_html/images/sunset_wallpaper.jpg"; // Full Path to the file
$image->ratio = true; // Keep Aspect Ratio?
// Name of the new image (optional) - If it's not set a new will be added automatically
$image->new_image_name = 'sunset_wallpaper_thumbnail';
/* Path where the new image should be saved. If it's not set the script will output the image without saving it */
$image->save_folder = 'thumbs/';
$process = $image->resize();
if($process['result'] && $image->save_folder)
{
echo 'The new image ('.$process['new_file_path'].') has been saved.';
}
?>
How to invoke this class to generate thumbnails in a HTML page?
This class has an advantage: you can resize images ‘on the fly’ with it. This way you don’t have to necessarily save the resized image on the server. You can just output it. Here’s how you can call this class from a HTML page without using any PHP code in it:
demo.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html> <head> <title> Show Resized Image </title> <meta name="Author" content="Bit Repository"> <meta name="Keywords" content="src, image, resize, on the fly"> <meta name="Description" content="Display a resized image"> </head> <body> <img src="resize_image.php?image=sunset.jpg&new_width=200&new_height=200"> </body> </html>
As you can see, the resize_image.php script is called. Some info is needed to make the resize: original image (‘image’), a width (‘new_width’) and a height (‘new_height’). In many cases, if the ‘ratio aspect’ is enabled, you can specify only one measurement. The new dimensions will be calculated based on whether you choose: width or height. Here’s the resize_image.php script:
resize_image.php
<?php
set_time_limit(10000);
error_reporting(E_ALL ^ E_NOTICE);
include 'resize.image.class.php';
$resize_image = new Resize_Image;
// Folder where the (original) images are located with trailing slash at the end
$images_dir = 'images/';
// Image to resize
$image = $_GET['image'];
/* Some validation */
if(!@file_exists($images_dir.$image))
{
exit('The requested image does not exist.');
}
// Get the new with & height
$new_width = (int)$_GET['new_width'];
$new_height = (int)$_GET['new_height'];
$resize_image->new_width = $new_width;
$resize_image->new_height = $new_height;
$resize_image->image_to_resize = $images_dir.$image; // Full Path to the file
$resize_image->ratio = true; // Keep aspect ratio
$process = $resize_image->resize(); // Output image
?>
Do you wish to receive the latest updates as soon as they are posted? Get our RSS Feed or Subscribe to the Newsletter!
- September 28, 2008
- article by Gabriel C.
- 26 comments
Sponsors
Related Posts
-
PHP: Cropping a Rectangle Image to Square using GDat October 1, 2008 with 4 comments
-
PHP: How to Create Mirror Images using GDat January 19, 2009
-
PHP: How to Add Transparency to an Image using GDat October 13, 2008 with 5 comments
-
PHP: How to Download a Remote Image using GD or cURLat January 5, 2009 with 16 comments
-
PHP: How to center a text on an image using GDat September 9, 2008 with 4 comments



26 Replies to "Resize an Image (on the fly) & Keep its Aspect Ratio using PHP and GD"
October 1, 2008 at 3:47 AM
[...] The class checks if the image is already a square. If it is, it will output a message to the user. If it’s not it will calculate the necessary coordinates and crop it: to left, center or right (default is ‘center’). [...]
November 14, 2008 at 9:28 AM
[...] class we’re using to resize images (requires GD) doesn’t do a particularly good job of compressing the resulting images. Ideally [...]
January 2, 2009 at 8:31 AM
Hello,
Use this script to resize image to differect aspect ratio:
http://nashruddin.com/Resize_Image_to_Different_Aspect_Ratio_on_the_fly
Nash
February 21, 2009 at 7:27 PM
Nice work on this. But there is one problem I found. If you choose to keep the aspect ratio but select a width and height one of which is larger than orig and other smaller than orig the logic for keeping the ratio fails. Here’s a simplification that works. Note that the logic is the same whether the new image is going to be larger or smaller.
/* Keep Aspect Ratio? */
if($this->ratio)
{
// if preserving the ratio, only new width or new height
// is used in the computation. if both
// are set, use width
if (isset($this->new_width))
{
$factor = (float)$this->new_width / (float)$width;
$this->new_height = $factor * $height;
}
else if (isset($this->new_height))
{
$factor = (float)$this->new_height / (float)$height;
$this->new_width = $factor * $width;
}
else
exit(“neither new height or new width has been set”);
}
March 8, 2009 at 11:50 PM
Thanks, Larry! I’ve tested it and really works smoothly.
February 12, 2010 at 3:02 PM
i find that resizing based on the larger dimension suits my needs better:
if($this->ratio){
if (isset($this->new_width) and isset($this->new_height)){
// width and height set, find the largest and resize based on that
if($this->new_width > $this->new_height){
// width is larger
$factor = (float)$this->new_width / (float)$width;
$this->new_height = $factor * $height;
}else{
// height is larger
$factor = (float)$this->new_height / (float)$height;
$this->new_width = $factor * $width;
}
}else if (isset($this->new_width)){
// only width set
$factor = (float)$this->new_width / (float)$width;
$this->new_height = $factor * $height;
}else if (isset($this->new_height)){
// only height set
$factor = (float)$this->new_height / (float)$height;
$this->new_width = $factor * $width;
}else{
exit; //(“neither new height nor new width has been set”);
}
}
February 13, 2010 at 2:15 AM
oops! just realised it should be like this instead:
// width and height set, find the largest and resize based on that
if($width > $height){
// width is larger
March 13, 2009 at 7:47 PM
Exactly what I’ve been looking for.
March 21, 2009 at 8:04 PM
I have one question. Is it posible to create an function and point the source to it, instead of the approach in the example?
example:
to use:
<code><?php
print "<IMG SRC=\"".resize_image(sunset.jpg,200,200)."\"">";
?>
</code>
<code>
insead of:
<IMG SRC="resize_image.php?image=sunset.jpg&new_width=200&new_height=200">
</code>
p.s.: aaaaa, this stupid code. sorry for spaming. I ask moderator to delete above posts.
May 4, 2009 at 8:22 AM
[...] upload, on the fly resized by PHP5 in the [...]
May 25, 2009 at 10:02 AM
There is an another error or additional function:
I want to use this parameters:
$image->new_width = 128;
$image->new_height = 100;
And if i upload a picture (500*500), it produces a128*128 pixel thumbinalk, but I set 100px for maximal height, so i want a 100*100px image in this case.
Solution:
PART ONE:
function resize()
{
##########################
## Mattias’s extension
##########################
$eredeti_w = $this->new_width;
$eredeti_h = $this->new_height;
##########################
## Mattias’s extension END
##########################
.
.
.
PART TWO:
##########################
## Mattias’s extension
##########################
if($this->new_height > $eredeti_h)
{
$faktor = $eredeti_h / $this->new_height;
$this->new_height = $this->new_height * $faktor;
$this->new_width = $this->new_width * $faktor;
}
if($this->new_width > $eredeti_w)
{
$faktor = $eredeti_w / $this->new_width;
$this->new_height = $this->new_height * $faktor;
$this->new_width = $this->new_width * $faktor;
}
##########################
## Mattias’s extension END
##########################
// New Image
$image_c = ImageCreateTrueColor($this->new_width, $this->new_height);
.
.
.
Only need to insert code between the comment…
August 21, 2009 at 4:55 PM
What he is trying to say is true. If someone tries to re-size an image it should re-size it depending on which dimension is smaller.
The fix Mattias proposes is OK but involves to many checks. Instead, just switch the original statement of
if($this->ratio)
{
………..
}
with:
if($this->ratio)
{
// if preserving the ratio, only new width or new height
// is used in the computation. if both
// are set, use width
if (isset($this->new_width))
{
if (isset($this->new_height)&&($this->new_width > $this->new_height))
{
$factor = (float)$this->new_height / (float)$height;
$this->new_width = $factor * $width;
}else
{
$factor = (float)$this->new_width / (float)$width;
$this->new_height = $factor * $height;
}
}
else if (isset($this->new_height))
{
$factor = (float)$this->new_height / (float)$height;
$this->new_width = $factor * $width;
}
else
exit(‘neither new height or new width has been set’);
}
July 24, 2009 at 7:36 AM
Hi,
Perhaps my requirements are different to others, but I prefer that if I set a new_height & new_width then these numbers are essentially the maximum value I want for either dimension when maintaining aspect ratio. To achieve this I added an extra check before resizing:
...
if($this->ratio)
{
if (isset($this->new_width) && isset($this->new_height)){
if ($width > $height)
{
$factor = (float)$this->new_width / (float)$width;
$this->new_height = $factor * $height;
}
else
{
$factor = (float)$this->new_height / (float)$height;
$this->new_width = $factor * $width;
}
}
else if (isset($this->new_width))
{
...
October 30, 2009 at 9:41 PM
this is nice plugin i used it do we fixed the with and height.
November 3, 2009 at 9:36 PM
i get this error with large size image
Fatal error: Allowed memory size of 33554432 bytes exhausted (tried to allocate 3168 bytes)
February 5, 2010 at 8:21 AM
I get the same. Anyone know how to set the size limit?
November 6, 2009 at 9:12 AM
Would that be possibile to resize an image on a remote server using this script?
November 23, 2009 at 7:36 AM
Hi, thanks, that works fine, for local images.
What would I need to do to get images from my another domain?
I can do it with locally placed directories, e.g: ../ images but not with remote directories, e.g:
http://www.anotherdomain.xxx/image.jpg
Thank you,
James R
November 24, 2009 at 5:39 AM
Accidentally deleted your email response, please resend, thank you!
November 30, 2009 at 11:57 PM
hi having problem with transparency for PNG image. Anyone else?
Thanks
em
December 8, 2009 at 7:02 PM
I think I had a similar problem as Ashley. I check to see which source image dimension exceeds the target dimensions by the biggest scale factor and set it to that. It probably could use some cleanup but it seems to do the job. I didn’t check for issues if scaling up, I only need to scale down.
if($this->ratio) {
if (isset($this->new_width)) {
if (isset($this->new_height)) {
if (($this->new_height/$height) new_width/$width)) {
$factor = (float)$this->new_height / (float)$height;
$this->new_width = $factor * $width;
} else {
$factor = (float)$this->new_width / (float)$width;
$this->new_height = $factor * $height;
}
} else {
$factor = (float)$this->new_width / (float)$width;
$this->new_height = $factor * $height;
}
} else if (isset($this->new_height)) {
$factor = (float)$this->new_height / (float)$height;
$this->new_width = $factor * $width;
}
else
exit("neither new height or new width has been set");
}
December 9, 2009 at 12:19 PM
The code got messed up because of the less than angle bracket getting confused with a tag opening.
This is the corrected conditional:
if (($this->new_height/$height) < ($this->new_width/$width))
December 9, 2009 at 8:45 PM
BRAVOS and THANKS JD !
now work !!!!!
February 11, 2010 at 6:04 AM
Someone was asking about images with transparency not being preserved. I was using this with transparent GIFs and the transparency was turning black. I hacked the class file to support GIF transparency. You may be able to include PNGs by including that format in the if statement. Find the first line of this code in the existing class, and paste the rest in:
// New Image
$image_c = ImageCreateTrueColor($this->new_width, $this->new_height);
$new_image = $image_create_func($this->image_to_resize);
if ($new_image_ext == “gif”) {
$trnprt_indx = imagecolortransparent($new_image);
// If we have a specific transparent color
if ($trnprt_indx >= 0) {
// Get the original image’s transparent color’s RGB values
$trnprt_color = imagecolorsforindex($new_image, $trnprt_indx);
// Allocate the same color in the new image resource
$trnprt_indx = imagecolorallocate($image_c, $trnprt_color['red'], $trnprt_color['green'], $trnprt_color['blue']);
// Completely fill the background of the new image with allocated color.
imagefill($image_c, 0, 0, $trnprt_indx);
// Set the background color for new image to transparent
imagecolortransparent($image_c, $trnprt_indx);
}
}
February 13, 2010 at 2:41 AM
good work !
February 23, 2010 at 11:20 PM
good stuff!!,. like it very much,. especially combined with js