4

I've done some searching for this and I understand that it is not possible to recover from an exhausted memory fatal error. I have a script that runs imagecreatefromjpeg. I tried catching the exception, I tried running the function with @ and then checking the return value for null or false, I tried running it with 'die()'. Nothing works. So I can't 'recover' from it.

So is it possible to anticipate it before I get to it? Is it possible to check the uncompressed size of a jpeg and then die gracefully? I want to sent a message to my users along the lines of "The image $image is too large to process. You will need to create a thumbnail manually".

My shared host won't allow me to increase memory size beyond 64mb so that's not an option. My code is as follows...

function createthumb($section,$filename,$constrain=100)
{
    $dir = "$section/thumbs_$constrain";
    if(file_exists($workingdir."$section/thumbs_$constrain/$filename")) return 1; 
    if(!file_exists($dir)) mkdir($dir);

    $src = imagecreatefromjpeg($workingdir."$section/$filename");
...
MrVimes
  • 3,212
  • 10
  • 39
  • 57

4 Answers4

8

As a rule of thumb, you might use the size in pixels returned by getimagesize() :

list ($width, $height) = getimagesize($file);
$memory = $width * $height * 4; // 4 bytes per pixel

If this number is greater than a predefined limit (to be determined empirically, start with something like 32*1024*1024), then don't load it with imagecreatefromjpeg().

BenMorel
  • 34,448
  • 50
  • 182
  • 322
  • 1
    Thanks. I'll do this for now. I'll look into imagemagic for a long term solution. Is the 32*1024*1024 figure close to that which will trigger the memory overrun on a 64mb limit? – MrVimes May 25 '11 at 17:30
  • I've done some testing and it *seems* that the formula to use is like this: take the value of `ini_get('memory_limit')` *in bytes* and multiply it by 0.19. Then compare that with the total number of pixels in the uploaded image (width x height). If the total number of pixels in the uploaded image is greater than the first number, reject it. I've tried this on two servers using 0.19 and 0.20 as the multiplying number and the 0.19 one works. – Nick Apr 07 '12 at 00:02
  • Yes, using 4 bytes per pixel, 0.20 means roughly 80% of the available memory for GD, that looks normal! That's not an exact science though. – BenMorel Apr 08 '12 at 14:09
1

Have you thought about using ImageMagic instead of GD? ImageMagic is able to resize jpegs during load, so it doesn't consume copious amounts of PHP's memory. See this StackOverflow answer for details.

Community
  • 1
  • 1
Sander Marechal
  • 22,978
  • 13
  • 65
  • 96
  • I'll look into imagemagic. thanks. It may require some faffing about though so for now I'm using the answer suggested by Benjamin Morel. – MrVimes May 25 '11 at 17:28
0

I think only error handler can help you as exception handling may not work on memory exhausted

http://php.net/manual/en/function.set-error-handler.php

zod
  • 12,092
  • 24
  • 70
  • 106
0

You can verify string source size before imagegreatefromjpeg.

Adrian B
  • 1,490
  • 1
  • 19
  • 31