Forum Moderators: coopster
It wasn't the size of the image (mb or kb) but rather the dimensions of the picture. For example, an image which was 300kb and 2500 x 2500 pixel dimensions PHP or GD cannot rescale without bytes exhausted error, but a 2mb 1200 x 1200 pixel dimension resized no problem.
How can I fix this issue? Is this a GD limitation or PHP 5.2?
GD INFO:
GD Version - bundled (2.0.28 compatible)
FreeType Support - enabled
FreeType Linkage - with freetype
FreeType Version - 2.1.9
GIF Read Support - enabled
GIF Create Support - enabled
JPG Support - enabled
PNG Support - enabled
WBMP Support - enabled
XBM Support - enabled
Two things, First, I know I can up the limits in the script itself. Is their any danger in doing this? Slow down the site, all other scripts become paused, etc.?
Secondly, been trying some test jpegs, a 2500x3300 jpeg will cause the error, but 2500x2500, no problems. Going to try a few other and see if I can pin it down to an exact size...
Added more memory to the server and increased the php memory limits for this one script to parse the large files. This solved the problem but I still have one nagging question.
The image that was causing the limit error was 240kb and 3000 x 3000 pixels in dimensions. An image with smaller dimensions 2400 x 1200 and 1.6mb runs fine (on the old memory limits).
This concludes to me that image dimensions matter more than image size. Given the fact that more and more people are taking larger and larger pictures (picture dimensions), what are the alternatives to GD? Can PHP pass an uploaded file to an alternative image processor to compress a large photo, say through exec()?
My current limits sit at 50mb, with 2gb of system memory this could be eaten up fairly quickly if 20 users decide to upload large files bringing the system to a screeching slow down....
<?php
$filename = 'imagejpeg.jpg';
$im = imagecreatefromjpeg($filename) or die ("Cannot Initialize new GD image stream");
header ("Content-type: image/jpg");
imagejpeg($im);
imagedestroy($im);
?>
This concludes to me that image dimensions matter more than image size.
Exactly correct. Although the source image you feed to imagecreatefrom(type) may be compressed, GD is creating an uncompressed version in memory for processing. GD will compress the image again when it is exported using image(type).
what are the alternatives to GD?
ImageMagick [imagemagick.org] is a popular alternative and can either be executed through system calls or by installing the ImageMagick extension [us3.php.net].
You can test it by making two JPEGs which are of equal pixel dimensions but dramatically different file sizes then run each through this script.
<?php
ini_set('memory_limit', -1);
echo 'Start: '.memory_get_usage().' <br />';
$filename = $_SERVER['DOCUMENT_ROOT'].'/play/gd-memory/3500x3500-72.jpg';
$im = imagecreatefromjpeg($filename) or die ("Cannot Initialize new GD image stream");
echo 'ImageCreate: '.memory_get_usage().' <br />';
imagedestroy($im);
echo 'ImageDestroy: '.memory_get_usage().' <br />';
?>
I ran a 72 KB 3500x3500 JPEG and a 904 KB 3500x3500 image and both used up just under 62 MB of memory (61,392,088 bytes to be exact).
Added: I'm knee deep in a six month long image generation project so I've been tearing through books on ImageMagick, graphics programming with Perl, etc. to learn all the fundamentals. I used to spend a lot of time compressing my source images that would be processed by GD until I learned that the quantity of pixels exclusively determines memory usage. I was pretty surprised when I read that.
I'm still not sure why ImageMagick is slower, btw. It's supposed to be faster. But, even called from the command line directly (no PHP) the operations are slower. :/
I allocate 128M as default and the largest image buffer it generates is around 1,000 x 1,000 pixels (but I'll have multiple image buffers in memory at any given time). Final image sizes are around 500 x 500 pixels. I'll cache images to disk and use imagedestroy to clear those from memory so I don't bump into my memory limit.
I'm knee deep in a six month long image generation project so I've been tearing through books on ImageMagick, graphics programming with Perl, etc. to learn all the fundamentals.
I've never delved into graphics that intently (haven't had a need yet) but bought a book back in 2003 about PHP Graphics anyway. 99.99% of the graphics work here is performed using special software (read: not by me), but I have automated some things to make life easier. Therefore, you have my attention here and am eager to learn from you.
I have a jpeg of 188 KB @ 3500 x 3500 and ran it through your script there to have another look at memory usage to be certain I am not missing something.
Start: 17848
ImageCreate: 61317304
ImageDestroy: 17992
Start: 17896
ImageCreate: 76552
ImageDestroy: 18040
I used to spend a lot of time compressing my source images that would be processed by GD until I learned that the quantity of pixels exclusively determines memory usage. I was pretty surprised when I read that.
Where did you read that? I don't know enough about image processing but wouldn't mind picking your brain here if you don't mind sharing ;)
Time is money however so I'll understand if you can't share your entire 6 month learning curve!
If I may add a concern from a PHP APPLICATION point of view. Cameras continue to take larger pictures while at the same time camera owners are becoming less familiar with the ability to scale the image resolution...
They all tend to have a first chapter that covers fundamentals of image processing. All image processing does is push around individual pixels and the only way to do that is to have all those pixels in memory. I'm pretty sure that technically the formula is
((pixel width * pixel height) * color depth)(plus some storage overhead for the data).
The only reference online to this fact I could find is the GD FAQ [boutell.com] titled "Why does gd cause my PHP script to run out of memory?" (way at the bottom of the page)
Of course, opening truly huge images can cause real memory problems, if several are open at once. 8,000 pixels times 8,000 pixels times four bytes for truecolor equals a walloping 256 megabytes.
If you are wondering how programs can manipulate images which are larger than the computers memory (a task Photoshop deals with regularly), they only process one "chunk" of the image at a time, caching the results to disk as it goes. The image you see on screen is a composited scaled down version, hence why it takes a few seconds to redraw every time you zoom in (you may also be able to see the square "chunks" redrawing separately. GD has that capability as well. See imagegd2 [php.net], imagecreatefromgd2part [php.net].
Cameras continue to take larger pictures ... camera owners are becoming less familiar with the ability to scale the image resolution
Totally agree. Cheap consumer digital cameras are already bumping the 7-10 megapixel range and most users will cheerfully upload those huge files. Anyone serious about offering web services that include user image uploads should figure that any upload will initially need to be drastically resized and choose servers with enough memory to handle that operation.
I'll understand if you can't share your entire 6 month learning curve
I'll share as much as I can (and the parts I understand well enough to express). :)
By the way, I just realized this last week and was going to post but forgot ... the GD Library has moved [webmasterworld.com]!