tags:

views:

790

answers:

4

Is there a way to prevent the PHP GD image library from running out of memory? If too large an image is uploaded, GD tends to run out of memory, terminating the script. I'd like it to throw a catchable exception or something to that extend, but alas it doesn't.

Right now I'm using a cobbled-together script that first issues an ini_set('memory_limit', '128M'), if that works I'm usually all set. Depending on the server configuration though that may not be possible, so I'm falling back on an algorithm that tries to estimate the amount of memory needed (taking resolution, color depth, channels and a fudge factor into account), then compares it to memory_get_usage() if the function exists, otherwise does a rough estimate.

The whole thing works so far, but it's far from elegant and will fail in some edge cases, I'm sure. Is there any better way to do this, i.e. have GD fail gracefully if it has to, instead of grinding everything to a halt?

+3  A: 

Buy more memory! :-P

Seriously though, it is impossible to handle being out of memory because any action you take would require more memory.

Your best bet is to limit the size of image being uploaded based on the current memory settings.

Nick Presta
LOL, buy me a host with more memory. ;-) Well, I'd at least like GD to estimate its own memory usage, instead of me having to do the error-prone guesswork and then hold my breath. I can't just limit the image by file size. A small file with a highly-compressed, high-resolution JPG may take up more memory than a large file with a low-resolution PNG. That's why I have to fall back on my above mentioned calculation.
deceze
A: 

Your best bet is to stop trying to figure out how much ram it will need, and just max it out at the outset - if you have 4 GB available, tell the image script to use between 2 and 4 GB or so, and when the script ends, have it go back to normal, that will cover off all potentially fatal situations. That's the only "Fail-safe" way I can think of anyway ...

phalacee
That's what I'm trying to do, but that's rarely possible on shared hosts. For those cases I'm doing the best-guess calculations to prevent hang-ups.
deceze
+1  A: 

There is another way to do it, but it can be time consuming, as certain parts of the image editing process would be repeated a number of times, but you can set the memory limit to your estimated value, then try to process the image, if it fails catch the exception, increase the memory limit, then process the image again - repeating this until you succeed or reach a certain memory limit - at which point you'd throw an error message to the user explaining that their image is too big to be used.

Edit: To catch the out-of-memory error, you could use this solution: http://au2.php.net/set_error_handler#35622

phalacee
Read again, AFAIK there's nothing catchable being thrown. It's a one-shot works-or-it-doesn't operation. Unless you can tell me how to catch an out-of-memory error, which is what I'm asking for. :)
deceze
There is a way to catch these errors: http://au2.php.net/set_error_handler#35622
phalacee
I'll have to see if this actually helps, as noted by Nick, I'd have to use more memory to deal with the error after it occurred.
deceze
A: 

To catch PHP's fatal errors, like "Out of memory" or "PHP Fatal error: Allowed memory size of 8388608 bytes exhausted (tried to allocate … bytes) in", see here : http://php.net/manual/en/function.set-error-handler.php#88401

Once a PHP script is out of memory, it can't call the shutdown function because that would require the allocation of more memory.
scotts