![]()
![]()
I'm Maxim Chernyak aka Hakunin. Every day I deal with three technologies - Ruby on Rails, Drupal, and Zend Framework. I deal and I blag. Natalie is my fiancée and I love her.
| Sun | Mon | Tue | Wed | Thu | Fri | Sat |
|---|---|---|---|---|---|---|
| 28 | 29 | 30 | 1 | 2 | 3 | 4 |
| 5 | 6 | 7 | 8 | 9 | 10 | 11 |
| 12 | 13 | 14 | 15 | 16 | 17 | 18 |
| 19 | 20 | 21 | 22 | 23 | 24 | 25 |
| 26 | 27 | 28 | 29 | 30 | 31 | 1 |
Update: this function is now available at github.com/maxim/smart_resize_image.
Fork away!
Should be easy to find, right? All you want is a function that resizes an image to constraints (doesn't care if it should scale up or down), with possibility to select if you want to keep it proportional, and possibility to use either width or height as the constraint. Also, you want it to preserve transparency damn it! Surprisingly, I was unable to find a good function that does all that, so I decided to attempt writing it. This should do it.
Essentially, everything happens just as logically expected. Please, if you see anything wrong, and you know ways to enhance, or optimize it, let me know.
Update: Thank you Joanne for finding a bug with proportional resize, and providing a great, more concise and clear solution to proportional resize. (see comments)
Update: The image transparency code was updated to a more thorough solution. See comments for info.
Update: There is a new parameter "output" which can be set to either
Update: There is another new parameter "delete_original". Speaks for itself.
Please, excuse a few code misalignments. Bug with coloring filter.
function smart_resize_image( $file, $width = 0, $height = 0, $proportional = false, $output = 'file', $delete_original = true, $use_linux_commands = false ) { if ( $height <= 0 && $width <= 0 ) { return false; } $info = getimagesize($file); $image = ''; $final_width = 0; $final_height = 0; list($width_old, $height_old) = $info; if ($proportional) { if ($width == 0) $factor = $height/$height_old; elseif ($height == 0) $factor = $width/$width_old; else $factor = min ( $width / $width_old, $height / $height_old); $final_width = round ($width_old * $factor); $final_height = round ($height_old * $factor); } else { $final_width = ( $width <= 0 ) ? $width_old : $width; $final_height = ( $height <= 0 ) ? $height_old : $height; } switch ( $info[2] ) { case IMAGETYPE_GIF: $image = imagecreatefromgif($file); break; case IMAGETYPE_JPEG: $image = imagecreatefromjpeg($file); break; case IMAGETYPE_PNG: $image = imagecreatefrompng($file); break; default: return false; } $image_resized = imagecreatetruecolor( $final_width, $final_height ); if ( ($info[2] == IMAGETYPE_GIF) || ($info[2] == IMAGETYPE_PNG) ) { $trnprt_indx = imagecolortransparent($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($image, $trnprt_indx); // Allocate the same color in the new image resource $trnprt_indx = imagecolorallocate($image_resized, $trnprt_color['red'], $trnprt_color['green'], $trnprt_color['blue']); // Completely fill the background of the new image with allocated color. imagefill($image_resized, 0, 0, $trnprt_indx); // Set the background color for new image to transparent imagecolortransparent($image_resized, $trnprt_indx); } // Always make a transparent background color for PNGs that don't have one allocated already elseif ($info[2] == IMAGETYPE_PNG) { // Turn off transparency blending (temporarily) imagealphablending($image_resized, false); // Create a new transparent color for image $color = imagecolorallocatealpha($image_resized, 0, 0, 0, 127); // Completely fill the background of the new image with allocated color. imagefill($image_resized, 0, 0, $color); // Restore transparency blending imagesavealpha($image_resized, true); } } imagecopyresampled($image_resized, $image, 0, 0, 0, 0, $final_width, $final_height, $width_old, $height_old); if ( $delete_original ) { if ( $use_linux_commands ) exec('rm '.$file); else @unlink($file); } switch ( strtolower($output) ) { case 'browser': $mime = image_type_to_mime_type($info[2]); header("Content-type: $mime"); $output = NULL; break; case 'file': $output = $file; break; case 'return': return $image_resized; break; default: break; } switch ( $info[2] ) { case IMAGETYPE_GIF: imagegif($image_resized, $output); break; case IMAGETYPE_JPEG: imagejpeg($image_resized, $output); break; case IMAGETYPE_PNG: imagepng($image_resized, $output); break; default: return false; } return true; }
WOW
Thx guys alooooooooot for this finally something usefull about GD ;)
But does anyone have any idea how to gain more quality on watermarks? What files to use?
I have codes that are doing watermarks but result is so bad! Colors are really totaly disorted & fzzy.
Anyone have any clue..?
Thx & all the best guys :P
Great stuff
Thanks a lot for this excellent script!
brother, thanks soooo much! u
brother, thanks soooo much! u are so kind
Question!
Hey there!
First of all, amazing and helpful function. :) Thanks so much for putting it out there for the world to use.
Second, I have a slight problem. A customer with a web 2.0ish site has had all of their user-uploaded content saved into an SQL DB. This includes images.
As I am simply useless when it comes to these image mod in PHP stuff, do you have any suggestions as to how to move those images into the filesystem? I have the content type and the images themselves saved as a blob in the DB.
I was hoping, perhaps naively, to use your smart_image_resize function; but I guess this is a no-go!
Anyways, thanks so much for the function and even more if you can provide a tip for me. :)
This function only resizes.
This function only resizes. To grab images from database you need to use php's database APIs (like PDO), which differ depending on your db and php version. After you fetch images from db to filesystem you could perform any kind of processing such as this function.
Thanks!
If you have a "Donate to me for being awesome" fund, I'll gladly chip in something when I get paid for this project. :)
Thanks for the post, the code
Thanks for the post, the code is really useful. PHP GD functions are not very well documented in PHP, the sample code gives me a much better understanding as to how the GD functions work.
A Crop N Scale Function
here's a crop n scale function i think works really nicely
could easily integrate into here
<?php function crop_n_scale($src_img, $dimx, $dimy) { // functional scaling $srcH = imagesy($src_img); $srcW = imagesx($src_img); $ratio = $dimy/$srcH; $new_W = $srcW*$ratio; if ($new_W<$dimx) $ratio = $dimx/$srcW; //$img = scale_image($src_img, $srcW*$ratio, $srcH*$ratio); $img=imagecreatetruecolor($srcW*$ratio,$srcH*$ratio); imagecopyresampled($img,$src_img,0,0,0,0,$srcW*$ratio,$srcH*$ratio,$srcW,$srcH); // crop (if necessary) $img = crop_image($img, $dimx, $dimy); return $img; } ?>Better result
Thank you. This code is very usefull.
I obtained better results in transparent quality for gifs with this modification. If this param isn't added, transparent parts are dirty, with undesired pixels.
Observe "$trnprt_color['blue']" added as param at the end.
...
// Allocate the same color in the new image resource
$trnprt_indx = imagecolorallocate($image_resized, $trnprt_color['red'], $trnprt_color['green'], $trnprt_color['blue'], $trnprt_color['alpha']);
...
This alternative line also works
$trnprt_indx = imagecolorallocatealpha($image_resized, $trnprt_color['red'], $trnprt_color['green'], $trnprt_color['blue']);
!!! :D
thank you! :D this was helpful! :D i just used it for something I'm writing for a friend :D
thanks again! :)
Pingback
[...] ネットで調べたらsmart_image_resize関数ってやつを見つけました。 [...]
thought i'd add my code
I thought I'd post my code from the comment below... any input would be appreciated.
Fixed?
Hi again,
Sorry to be a pain in the ass. I found another script and tweaked it. The solution below is working for me. I thought I'd post it in case anyone else has trouble with the current code in the blog. I'm still unsure why the original code didn't work, but here is my current solution.
Thanks for a great resource.
elseif(($mime =="image/gif") || ($mime == "image/png")) { if($mime =="image/gif") { //get the image from the server $source = imagecreatefromgif($file); } else { //get the image from the server $source = imagecreatefrompng($file); } imagealphablending($adjusted_image, false); imagesavealpha($adjusted_image,true); $transparent = imagecolorallocatealpha($adjusted_image, 255, 255, 255, 127); imagefilledrectangle($adjusted_image, 0, 0, $new_width, $new_height, $transparent); imagecopyresampled($adjusted_image, $source, 0, 0, 0, 0, $new_width, $new_height, $width, $height); if($mime =="image/gif") { imagegif($adjusted_image, $file); } else { imagepng($adjusted_image, $file); }Hey, you aren't a pain - all
Hey, you aren't a pain - all the comments help. I'm just kinda not maintaining this function much lately, that's why I put it up on github - so others could easily fork it.
Color index error
Hi,
I thought that this script was working well, but I'm recieving an error on some transparent gifs:
Warning: imagecolorsforindex() [function.imagecolorsforindex]: Color index 63
out of range in /home/amarien/public_html/rocket/uploadprocessor.php on line 396
The image still uploads and looks fine. Why the error?
Any ideas about imagecolorsforindex()?
Thanks!
Watermark Option
Hey, great function.. I had four or five of these types of scripts I was using independently for different purposes and your function seems to bring all the elements together.
Wanted to add something to it in return.
How about a watermark option?
Just added the $apply_watermark argument to smart_resize():
Then added this if/else construct to replace the imagecopyresampled() function with code that combines the re-sized image with a watermark gif, (could be a png I suppose), if $apply_watermark is true.. Otherwise it functions like normal.
if ($apply_watermark) { $outputWidth = floor($rawWidth * $imageScaleTo); $outputHeight = floor($rawHeight * $imageScaleTo); $outputImage = Imagecreatetruecolor($final_width, $final_height); imagecopyresampled($image_resized, $image, 0, 0, 0, 0, $final_width, $final_height, $width_old, $height_old); // Turn on alpha blending imagealphablending($outputImage, true); // Create overlay image - Could be a png? $watermark = imagecreatefromgif("../images/watermark.gif"); // Get the offset centering for the overlay $offsetWidth = floor(($final_width - imagesx($watermark))/2); $offsetHeight = floor(($final_height - imagesy($watermark))/2); // Overlay watermark imagecopy($image_resized, $watermark, $offsetWidth, $offsetHeight, 0, 0, imagesx($watermark), imagesy($watermark)); } else { imagecopyresampled($image_resized, $image, 0, 0, 0, 0, $final_width, $final_height, $width_old, $height_old); }Hope this is useful to somebody.
Question though.. Is it possible to use imagecopyresampled() instead of imagecopy()? I just couldn't get it to work somehow.. I Dunno, it's like quarter to four in the morning and I'm getting bleary eyed.. :-)
Anyway..
Once again, thanks for posting this excellent function!
-TIM
Hey Tim, Thanks for
Hey Tim,
Thanks for additions. The best way to contribute this type of thing is to fork the project on GitHub (see message on top of the article). Then I might be able to pull changes if they make sense for original intention here. : )
Pingback
[...] while ago I wrote a php function for image resizing with preservation of transparency. It seems to have been quite popular, but until now there was no good way to fork the code, and/or [...]
Thank you!
Thank you for the part of the transparant crap!! Thankful to you forever ;)
Easy way to get more memory
To answer my own question about running out of memory...
Put this in the PHP script that calls smart_resize_image(...):
For more details about memory usage of the imagecreatefromjpeg function, see http://uk2.php.net/imagecreatefromjpeg
Memory allocation
Thanks for this script, it is great but I wanted to ask if anyone has run into problems when processing large images?
I have a image that is 2.9MB large and the smart_resize_image function gives a PHP error because more memory is needed than the limit I have set in my php.ini file (32M). Does anyone know why so much memory is needed (i.e. over 32MB for a 2.9MB file) and if there is a workaround other than increasing memory_limit in php.ini?
Specific details:
Great Script! Running on our Web App!
We have implemented a modified version of your code to our core web service! Works great on BuildaSearch.com!
Cheers!
Why so complex?
Why not just make the new image transparent before using imagecopyresampled?
$im = ImageCreateFromPNG($source);
$new_im = imagecreatetruecolor($new_size[0],$new_size[1]);
imagecolortransparent($new_im, imagecolorallocate($new_im, 0, 0, 0));
imagecopyresampled($new_im,$im,0,0,0,0,$new_size[0],$new_size[1],$size[0],$size[1]);
Don't know why it's missing,
Don't know why it's missing, but here's a simple solution for rotating the image:
if ($rotate > 0) {
$image_resized = imagerotate($image_resized, $rotate, 0);
}
You just add $rotate = 0 in the arguments.
How to call the function?
I was just wondering how you set the file you want, how you would call this function and display the image in a browser?
FIXED TO CHANGE QUALITY
To change the quality for JPEG simply modify the following lines.
function smart_resize_image( $file, $width = 0, $height = 0, $proportional = false, $output = 'file', $delete_original = true, $use_linux_commands = false )
function smart_resize_image( $file, $quality, $width = 0, $height = 0, $proportional = false, $output = 'file', $delete_original = true, $use_linux_commands = false )
And then:
imagejpeg($image_resized, $output);
imagejpeg($image_resized, $output, $quality);
Just thought I would share this in case anyone else was running into bad quality images (default 75) produced by this script.
Thanks,
David
And by bad....
And by "bad" I mean, lower quality images... This script has been a huge help!
imagecreate() vs imagecreatetruecolor()
I couldn't get transparency working in GIFs unless I used imagecreate() instead of imagecreatetruecolor(). I guess GIF is palette-based, so the color indexes get messed up. php.net actually says "This function will not work with GIF file formats," although I think they're lying since it just doesn't play nice with transparency.
GIF Transparency
Try my code from http://mediumexposure.com/techblog/smart-image-resizing-while-preserving... which works fine for me.
How do I use this script to
How do I use this script to output an image to the browser? Is there any example code?
+1 is there any example
+1 is there any example code?
Is there a way to make the
Is there a way to make the crop area to stand more 'up' than the current position (vertically) considerring that
i have pictures which containt valued information mainly on the uppper part of the image.
Last, but not least is to say that the function is great! Works excellent with no black lines, no matter what the source and destination is !
Well, I would say that
Well, I would say that cropping goes a little beyond this function's intended use. Instead, you should set the output to "return", this way you'll have the image object that you can manipulate with gd library any way you like.
resize tranparent gif
Hi Max;
you have nice script . i'm new to php and im trying to get a script that risizes tranparent gif and display the image in the screen. I spentlot of time playingwith your wornderfull script , but could not worked it. any help and scipt example would be appreciated
thanks
jeff
Let me know what kind of
Let me know what kind of problem occurs and I will be able to help. : )
This is very nice
This is very nice function
very very useful for me
Thanks a lot.
Hi, thanks for the great
Hi,
thanks for the great solution to preserving transparency. On Debian Etch I found that the transparency is not coming out correctly, and instead a grey background shows up (try for example this image: http://www.nba.com/media/bos_50px_080328.gif
Any others experiencing the same thing?
Output to web browser?
So...how would I use this function to output a resized image to the browser?
FANTASTIC :)
FANTASTIC :)
indeed!! thank you very much
indeed!! thank you very much programmer. you're fantastic, and your script too. thanks a bunch >:D<
Thanks!
Thanks, this is just what i was looking for, really made life easier for me!
Cheers!
R
P.S Please do something about your captcha... its one of the most irritating that i have ever come accross.
error message - php5 related?
I used this great script for a small Web project and it works fine on my local computer in an (OSX 10.4) PHP 4 environment. Recently I upgraded to OSX 10.5 that works with PHP5 and now I get this fatal error: 'call to undefined funtion imagecreatefromjpeg()' it's probably just a tiny thing but anyone here with the same problem and a suggestion how to fix it? thx a lot!
Sounds like you're missing
Sounds like you're missing GD Library in your PHP installation on the server. : )
GIF and 8 bit PNG do not show transparency
Thank you for writing this. It is exactly what I have been looking for all day, but there is one problem. GIF's and 8 bit PNG's do not show transparency correctly. GIF's just come out with white wherever it is supposed to be transparent and then 8 bit PNG's end up distorted-looking with random pixels transparent. 24-bit PNG's look great though.
Thanks
I'm seeing the same
I'm seeing the same thing...
8bit png's do not work
hi. thanks a lot for this
hi. thanks a lot for this code!
It's the best commented one and the best working one I have found!
when using proportional resizing, I wanted to have some changes.
if you set maxwidt=100px,maxheight=100px, the resultimage can be for example 100x75.
In my case I wanted that image to fixed to maxwidt and maxheight, and still have the picture propotional resized.
I have made it create a transparent frame that is fixed to maxwidth an maxheight, the propotional picture is then centered to that one.
look on the end of this page:(you should be able to see the code there without logging in)
http://www.experts-exchange.com/Web_Development/Web_Languages-Standards/...
multiple resizes
Help I can't figure out how to use this excellent function to make multiple resizes and upload them to separate directories (for larger, medium-sized, and thumbnail images). Here is my code:
Sorry I know I'm a newbie at this kind of thing. I've tried DELETE_ORIGINAL = false, I've tried renaming the image files. No relief from my frustration.
Figured it out
I figured it out. I should have been using copy() and not move_uploaded_file.
Thanks for the great function!!!
/* USE SMART_RESIZE FUNCTION TO MAKE 3 COPIES AND UPLOAD TO MEDIA DIR */ smart_resize_image( $_FILES['upload']['tmp_name'][$number], $width = 240, $height = 0, $proportional = true, $output = 'file', $delete_original = false, $use_linux_commands = false ); $success_display = copy($_FILES['upload']['tmp_name'][$number], DISPLAY_DIR.$file_name); smart_resize_image( $_FILES['upload']['tmp_name'][$number], $width = 400, $height = 0, $proportional = true, $output = 'file', $delete_original = false, $use_linux_commands = false ); $success_full = copy($_FILES['upload']['tmp_name'][$number], FULL_DIR.$file_name); smart_resize_image( $_FILES['upload']['tmp_name'][$number], $width = 120, $height = 0, $proportional = true, $output = 'file', $delete_original = true, $use_linux_commands = false ); $success_thumbs = move_uploaded_file($_FILES['upload']['tmp_name'][$number], THUMB_DIR.$file_name);You don't have to copy the
You don't have to copy the file yourself. You can use $output parameter -- it accepts any path where you want result image to appear. If you make $output to be "/path/to/directory" - it will copy file there for you. Just make sure delete_original = false for the first 2 conversions - and make delete_original = true for the last conversion, when you don't need to keep original file anymore.
Pingback
[...] Smart Image Resizing while preserving Transparency with PHP and the GD Library Sweet, I’ll definitely have to get back to this one! [...]
Post new comment