Reputation: 3637
I almost always have a PHP resize script (using GD) in websites for my clients. No matter how many times I tell them to resize their huge 7MP images from their digital camera before uploading them, they still never do it. The result is an "Out Of Memory" error from the server, and the image doesn't get resized, because the original image was too large resolution-wise.
Is there a better way to resize really large images? Is there a service that offers an API that I could tap into through my script to resize these large images?
Upvotes: 6
Views: 8562
Reputation: 2676
I got stuck for days (and nights) with this problem.
Moreover, providers memory limit differs from one to another.
And change the memory_limit
in PHP does not work on shared servers, providers usually limit the ram even if phpinfo()
says that you got 128Mo (1and1 limits RAM to 60Mo per process for example).
But I finally found something quite efficient here : http://www.imagemagick.org/Usage/files/#massive
It needs imagemagick
, but I discovered that most of the providers natively provides this on their servers, even shared ones.
exec('env MAGICK_TMPDIR=<tmp_dir> nice -5 convert -limit memory 32 -limit map 32 -resize 800x600 huge.jpg reasonable.jpg');
As it's said :
env MAGICK_TMPDIR=<tmp_dir>
set up a temp directory for imagemagick
to simulate ram (kind of)
nice -5
is also a unix command to change the priority of a process
(http://en.wikipedia.org/wiki/Nice_(Unix))
convert ...
is the imagemagick command line
The real deal is about -limit memory 32
and -limit map 32
. This is the way you limit the memory used by the binary (here : 32Mo). You will probably need to fit the values to match the values of your server (Generally PHP tells you the maximum allocated memory when it gives you the Fatal Error. I suggest you to divide this value by 2 or 4 to be confortable).
I also needed to put some other lines in my PHP to avoid some collateral issues :
ignore_user_abort(true); // ignore user abort : let the script finish resizing even if user aborts
set_time_limit(0); // ignore server timeout
putenv('MAGICK_THREAD_LIMIT=1'); // limit the number of thread for the binary. Very important in my case
Hope all that will help ...
To know if convert
is available on your server, you can try this (in PHP) :
$out = array();
exec('which convert 2>&1', $out);
print_r($out);
That will gives you the path of the binary, if exists.
Upvotes: 2
Reputation: 25774
I had spent some time trying to debug PHP code that used GD directly, but failed on large images and on a subset of images that seemed to have minor errors that choked GD.
But then I found phpThumb (http://phpthumb.sourceforge.net/), and I'm never going back. After adding two PHP files to my web directory (phpthumb.class.php
and phpthumb.functions.php
) I was able to use the following code to generate my thumbnails:
include("phpthumb.class.php");
// Load data into phpThumb object and set parameters
$phpThumb = new phpThumb();
$phpThumb->setSourceData(file_get_contents($_GET['filename']));
$phpThumb->setParameter('w', $width); // Set width
$phpThumb->setParameter('h', $height); // Set height
$phpThumb->setParameter('zc', 1); // Specify zoom-crop (instead of stretch)
$phpThumb->setParameter('q', 100); // Specify quality
// Generate & output thumbnail
$phpThumb->GenerateThumbnail(); // Generate the thumbnail
$phpThumb->OutputThumbnail(); // Output it to browser
$phpThumb->RenderToFile("$thumbname"); // Output it to file
$phpThumb->purgeTempFiles(); // Clean up
Boom, works like a charm, is pretty fast and has no problems with large files. Also, it can use either GD or ImageMagick, depending on what's available on the server, so it's relatively portable.
Upvotes: 1
Reputation: 136
If you have available ImageMagick api in your PHP configuration - use it! ImageMagick doesn't get counted in PHPs memory_limit
and therefore can work with bigger files.
If you realy have no control over the server, the quick and very bad workaround is - after getting the image file from $_POST, first check the dimensions with:
<?php
$image_size = getimagesize("yourfile.jpg")
$mem_usage = $image_size[0] * $image_size[1] * 4 //4 bytes per pixel (RGBA)
if ($mem_usage > $mem_aviable) {
die ('Please upload smaller pic. I tell you that all the time. '.
'Resize yout huge 7MP images from your digital camera '.
'before uploading them.'); //Better put something more polite here.
}
Upvotes: 3
Reputation: 3606
how about uploading them then queuing the resize job, a command line php script can then pick up and process (faster and can have a separate memory limit and execution time)
Upvotes: 1
Reputation: 321698
You could shell out to an external programme, for example using convert.
Upvotes: 1
Reputation: 831
You can call Imagemagick to resize the picture from your php page, but there's a security matter then if you allow system calls
Any API will use a lot of Memory, you can change your php memory_limit aswell.
Upvotes: 3