View Full Version : how to allocate more memory for gd image resize
jonas-e
10-22-2007, 03:58 PM
Hi
I am designing a cms for my site. The user will be taking photos with a digital SLR camera and these photos need to be resized and uploaded to the webserver, see php script below. Although the photos are not very large - only 6megapixel and mostly around 1.6mb, the server easily runs low on
memory. So I get this error message on the remote server:
Fatal error: Allowed memory size of 16,777,216 bytes exhausted (tried to allocate 4000 bytes)
My localhost server seems to have a higher limit at 33,554,432 bytes.
Is there a way to allocate more memory in a script for this purpose?
Or any suggestions for a work-around?
// Get file names
$orig_name = $_FILES['upl_file']['name'];
$temp_path = $_FILES['upl_file']['tmp_name'];
// Temp vars for file naming - shall come from form later
$avl_id = 3; $img_id = 99;
// Using date and time incl seconds for unique file name
$now = date(Y.m.d.'_'.G.i.s);
// Get the file extension, lower case
$ext = strtolower(end(explode(".", $orig_name)));
// New unique file name
$new_name = 'avlid'.$avl_id.'_'.$now.'_'.rand(10,99).'_imgid'.$img_id.'.'.$ext;
// Setting path for full size file and web image file
$path_fullsize = 'E:\data\avl_img_orig\\'.$new_name;
$path_web = 'avls/img/'.$new_name;
// Copy original to local drive outside site folder
copy($temp_path, $path_fullsize);
// RESIZING START:
// Load image with home-made function
$image = open_image($temp_path);
// Get original width and height and set new
$width = imagesx($image);
$height = imagesy($image);
$new_width = 800;
$new_height = $height * ($new_width/$width);
// Resample
$image_resized = imagecreatetruecolor($new_width, $new_height);
imagecopyresampled($image_resized, $image, 0, 0, 0, 0, $new_width, $new_height, $width, $height);
// Save resized image
imagejpeg($image_resized, $path_web);
djr33
10-22-2007, 06:33 PM
Although the photos are not very large - only 6megapixel and mostly around 1.6mb, the server easily runs low on
memory.First, that IS a large image, compared to most work, though perhaps not most digital photography. Secondly, that's a huge image for the GD library. A 300x300 image can take forever to process, depending on the actions involved.
ini_set(”memory_limit”,”16M”);
That will allow you to change the limits.
Or you can change them directly in the php.ini config file.
HOWEVER!!!
If you do this and it is not allowed on your host, you may have your account suspended or you may end up with another consequence, such as being charged for excessive server use.
I was/am working on a graphics project using the GD library and without too much processing, we were able to completely overload the server, stretching it to about 80%, and this was on a shared server, so the account was suspended. Anyway, moral is... keep an eye on such scripts. If you get a couple people on that at the same time with large images, you will end up overworking the server and the loading times will be slow as well.
One way to work around this is to add sleep() in the script, so it pauses and gives the server a slight break, but in doing so, you make the processing take even longer.
The PHP GD library is not meant for what you are doing, really; if you can get it to work, that's great and quite convenient. However, it may just not be practical. I wish it was not so sluggish.
The main processing intensive work in your script is the resampling in the resize. As it changes, it compares all of the pixels and interpolates for the best representation. This ends up with a nicer image. It does also take more power, though. Instead of imagecopyresampled(), you could just use imagecopy(), which would end up less smooth, something like a gif, perhaps. If the images are large enough, it might actually be faster to try using imagecopy() to get it down to a reasonable size, then use imagecopyresampled() from there.
jonas-e
10-22-2007, 06:57 PM
Thanks a lot for your elaborate answer!
I tried it, and it doesnt seem to work on the remote host (www.one.com) - but I don't get any error message either.
Anyway - it works on my localhost - I suppose I will rely on this part of the cms to run locally (which is where I will store the original photos anyway).
Am I supposed to clear that memory again after using it in another command?
I don't understand the sleep() function - where should I put - and do you put a number of e.g. seconds in the brackets to indicate how long it should sleep?
Cheers,
Jonas
djr33
10-22-2007, 09:33 PM
Hmm.... if it works locally, then the code is likely correct, and your host blocks it because you don't have permission to use more memory (on a share account); it's also probably a sign that it would be against the TOS. You could contact the host and ask permission, though. They may allow it as you have a legitimate reason for using so much power. In most cases, that much power would only be used by spammers sending out many emails, or some other strange activity, so they block it by default. Certainly no guarantee they'd allow you to do that, though.
Also, if you have access to php.ini, you can change that, and if you don't, it may be a sign that you don't have permission to change it at all.
As for changing it back, I'm not actually sure on that. Ah... here:
Sets the value of the given configuration option. The configuration option will keep this new value during the script's execution, and will be restored at the script's ending.So, no, you would just leave it as is.
Sleep can be used anywhere in the function, probably within a loop, though in the case of a single function that takes so much power, it might not be possible to use sleep to help; you could try to rewrite the resampling function, do it in a grid and put the pieces back together, or you could see if the source code is available and add the sleep in there. May not apply well in this case.
jonas-e
10-23-2007, 04:41 PM
Well, as my host has hundreds of thousands of customers world-wide and very low rates (~1.5USD/month for 1GB web hotel), they usually do not make any custom changes whatsoever. But this is working good anyway - it is supposed to run locally, storing the original photos on a local drive. Thanks!
The sleep function is a bit odd:
echo date();
sleep(10);
echo date();
I was hoping it to print the first statement on the screen, wait 10 seconds, then print the next. Instead the page remains blank for 10 seconds, then prints them both at the same time - and as expected with 10 seconds difference.
djr33
10-23-2007, 06:14 PM
I can't comment on the host, though I'm not at all surprised.
As for sleep, that makes sense. It executes the code, pauses execution at the sleep, then continues execution after the sleep. Output is just sent out after all of this, I think. (I'm not entirely sure how execution vs. output works in php. I would be inclined to think it works in a linear fashion, so that would output then pause for 10 seconds, but I'm not surprised to see variation on that. It may also depend on the server configuration or the type/function of output.)
To test this, you can do it with time, as you did, showing the execution is delayed, though not the output.
BLiZZaRD
10-23-2007, 08:16 PM
image magik is faster than GD, and just as good.....
jonas-e
10-23-2007, 08:58 PM
what's image magik?
part of php?
i don't think my webhost has that - but I could ask..
djr33
10-23-2007, 09:21 PM
I think GD is more likely to be included, but image magik may be as well.
http://www.imagemagick.org/script/index.php
It will still take a significant amount of processing power, though likely less.
I don't know how to use image magik, though, so I won't be able to help. But good luck (and maybe teach me a bit ;)).
Powered by vBulletin® Version 4.2.2 Copyright © 2021 vBulletin Solutions, Inc. All rights reserved.