Reputation: 154
consider the following simple PHP-Script:
<?php
print memory_get_usage()."<br />";
print ini_get("memory_limit")."<br />";
$file = imagecreatefromjpeg("image.jpg");
?>
The output is the following:
109848
120M
Fatal error: Out of memory (allocated 63700992) (tried to allocate 23040 bytes) in /homepages/13/d444038670/htdocs/bilderarchiv/test.php on line 4
The picture that I try to read is a large picture. However, the second line states that the memory_limit is 120 MB, but the script dies at an allocation of about 64 MB. How can this be? The script is running perfectly on another provider, although the memory_limit is 120M there as well.
Upvotes: 0
Views: 640
Reputation: 1910
You are running out of memory, but there is a solution.
Try running this on both your servers, to determine how much memory is needed per image pixel:
<?php
$mem0 = memory_get_usage(true);
$megapix = imagecreatetruecolor(1000,1000);
$mem1 = memory_get_usage(true);
$memdif = $mem1 - $mem0;
$perpixel = $memdif / (1000 * 1000);
echo "<pre>1 million pixel memory test
before imagecreate: $mem0
after imagecreate: $mem1
image memory used: $memdif
bytes per pixel: $perpixel";
?>
I got these results:
1 million pixel memory test (Linux)
before imagecreate: 524288
after imagecreate: 5505024
image memory used: 4980736
bytes per pixel: 4.980736
1 million pixel memory test (Windows)
before imagecreate: 262144
after imagecreate: 5505024
image memory used: 5242880
bytes per pixel: 5.24288
At 5 bytes per pixel, your 5760x3240 image will need 89MB.
To see if imagecreatefromjpeg needs a lot of temporary memory beyond the 89MB needed for the image, compare memory_get_usage
with memory_get_peak_usage
just after you load the image. In my testing, there wasn't a significant.
(Older versions of GD used 4 bytes I think.)
Next, find out how much memory you've really got:
<?php
echo 'memory_limit ??? ', ini_get('memory_limit'), '<br>';
$megs = Array();
for ( $i=0; $i < 1000; ++$i ) { // try up to 1000MB
$megs[] = str_repeat('*', 1048000);
$mb= round(memory_get_usage(true) / 1024/1024);
echo "$mb ";
flush();
ob_flush();
}
?>
If you get no output at all, there is probably buffering going on that you can't disable, so just try different upper limits in the for
loop until you find the largest one that still works.
One Solution
I gave up long ago on GD for scaling down large jpeg images, and use ImageMagick instead. If you execute it from within PHP, it is a separate process so the PHP memory limit no longer applies. Of course there is ultimately a memory limit, but you can tell ImageMagick the maximum memory to use.
(I also got better-quality images than with GD.)
Upvotes: 1