Page 1 of 2
[Solved] GD Library issues with file size.
Posted: Thu Feb 23, 2006 7:32 am
by determinedmoth
Hi
I've two idedentical scripts, running on two different servers.
Server I = PHP Version 5.0.4, GD 2.0.28 compatible, MAX UPLOAD = 100mb, max_execution_time 30
Server II =PHP Version 4.4.2, GD 2.0 or higher, MAX UPLOAD = 20mb, max_execution_time 50000
Upoading an small image, saving it, creating a thumbnail and saving that, works on both servers.
However, it will work for a 4mb+ file on Server I, while on Server II it will upload the file ok(all 4mb), but knock out and save a dreaded black thumbnail. I have excluded filename charaters as an issue, and permission problems because the script otherwise works fine on server II.
Code is derived from php.net examples, and some parts I found floating around here.
Is it just that Server II will not handle a large upload? Or can it be made to work?
Code: Select all
$currentDir = getcwd();
$filetype = $_FILES['userfile']['type'];
$filesize = $_FILES['userfile']['size'];
// Prepend the file with the md5 to make it unique
$unique_id = md5(uniqid(time()));
$file = $_FILES['userfile']['name'];
$filename = $unique_id.'_'.$file;
// Upload the File
$uploaddir = $currentDir."/images/highres/";
$uploadfile = $uploaddir . basename($filename);
// Check it's up
if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile)) {
$uploadCheck = 'Yes';
} else {
$uploadCheck = 'No';
}
chmod($uploadfile, 0666);
// Copy to thumbs folder
$oldfile = $currentDir."/images/highres/".$filename;
$newfile = $currentDir."/images/lowres/".substr($filename, -20);
$newfileToDB = substr($filename, -20);
if (!copy($oldfile, $newfile)) {
echo "failed to copy $file...\n";
}
// Resize
$width = 240;
$height = 180;
// Get new dimensions
list($width_orig, $height_orig) = getimagesize($newfile);
// Resample
$image_p = imagecreatetruecolor($width, $height);
$image = imagecreatefromjpeg($newfile);
imagecopyresampled($image_p, $image, 0, 0, 0, 0, $width, $height, $width_orig, $height_orig);
imagejpeg($image_p, $newfile, 100);
chmod($newfile, 0666);
//
Posted: Thu Feb 23, 2006 9:10 am
by ssand
I had a similar problem. Chances are you are hitting the memory limit in your php.ini.
This was posted on php.net and fixed the problem I was having. Basically adjusts the config of the Memory Limit for your script then (I think php will restore it back when done... I added the ini_restore just in case that's not true).
The one issue I see is that if your image is too large (resampling) it could set the memory limit too high.
If you want to test it first //comment the if statement and see what it says you need for Memory and compare it to your php info Memory Limit.
Insert it just above your resampled script (that's is the memory hog).
Code: Select all
$imageInfo = getimagesize($newfile);
$memoryNeeded = round(($imageInfo[0] * $imageInfo[1] * $imageInfo['bits'] * $imageInfo['channels'] / 8 + Pow(2, 16)) * 1.65);
echo "<br> Memory Needed: ".$memoryNeeded."<br>";
if ($memoryNeeded > 6000000) { ini_set( 'memory_limit' , ($memoryNeeded + 2000000)); }
/// after resizing is complete, put memory limit back.
ini_restore ( 'memory_limit' );
Also, the 6000000 is the 6MB memory limit set for my php. The 2000000 is an extra 2MB I added because once I resampled down my orignal to a "large" image, I then resampled that new image to my thumbnail.
edit: changed variable name to your match your file uploaded
Posted: Thu Feb 23, 2006 9:30 am
by determinedmoth
Thanks.
It still fails the same way. However:
Memory Needed: 35143680
This snippet is a little beyond me, should I change
Code: Select all
if ($memoryNeeded > 6000000) { ini_set( 'memory_limit' , ($memoryNeeded + 2000000)); }
too
Code: Select all
if ($memoryNeeded > 6000000) { ini_set( 'memory_limit' , ($memoryNeeded + 4000000)); }
?
I'm not even sure my host (1&1 - uk) would allow ini_set though.
Re: GD Library issues with file size.
Posted: Thu Feb 23, 2006 9:42 am
by ssand
did you put ini_restore ( 'memory_limit' ); below your resampling part?.. see below
determinedmoth wrote:Code: Select all
$currentDir = getcwd();
$filetype = $_FILES['userfile']['type'];
$filesize = $_FILES['userfile']['size'];
// Prepend the file with the md5 to make it unique
$unique_id = md5(uniqid(time()));
$file = $_FILES['userfile']['name'];
$filename = $unique_id.'_'.$file;
// Upload the File
$uploaddir = $currentDir."/images/highres/";
$uploadfile = $uploaddir . basename($filename);
// Check it's up
if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile)) {
$uploadCheck = 'Yes';
} else {
$uploadCheck = 'No';
}
chmod($uploadfile, 0666);
// Copy to thumbs folder
$oldfile = $currentDir."/images/highres/".$filename;
$newfile = $currentDir."/images/lowres/".substr($filename, -20);
$newfileToDB = substr($filename, -20);
if (!copy($oldfile, $newfile)) {
echo "failed to copy $file...\n";
}
// Resize
$width = 240;
$height = 180;
// Get new dimensions
list($width_orig, $height_orig) = getimagesize($newfile);
///////
$imageInfo = getimagesize($newfile);
$memoryNeeded = round(($imageInfo[0] * $imageInfo[1] * $imageInfo['bits'] * $imageInfo['channels'] / 8 + Pow(2, 16)) * 1.65);
echo "<br> Memory Needed: ".$memoryNeeded."<br>";
if ($memoryNeeded > 6000000) { ini_set( 'memory_limit' , ($memoryNeeded + 2000000)); }
// Resample
$image_p = imagecreatetruecolor($width, $height);
$image = imagecreatefromjpeg($newfile);
imagecopyresampled($image_p, $image, 0, 0, 0, 0, $width, $height, $width_orig, $height_orig);
imagejpeg($image_p, $newfile, 100);
chmod($newfile, 0666);
///////
/// after resizing is complete, put memory limit back.
ini_restore ( 'memory_limit' );
//
Posted: Thu Feb 23, 2006 9:45 am
by determinedmoth
Yes.
Code: Select all
//Fix Mem
$imageInfo = getimagesize($newfile);
$memoryNeeded = round(($imageInfo[0] * $imageInfo[1] * $imageInfo['bits'] * $imageInfo['channels'] / 8 + Pow(2, 16)) * 1.65);
echo "<br> Memory Needed: ".$memoryNeeded."<br>";
if ($memoryNeeded > 6000000) { ini_set( 'memory_limit' , ($memoryNeeded + 2000000)); }
// Resample
$image_p = imagecreatetruecolor($width, $height);
$image = imagecreatefromjpeg($newfile);
imagecopyresampled($image_p, $image, 0, 0, 0, 0, $width, $height, $width_orig, $height_orig);
imagejpeg($image_p, $newfile, 100);
chmod($newfile, 0666);
//
// put mem back
ini_restore ( 'memory_limit' );
Posted: Thu Feb 23, 2006 10:32 am
by ssand
I'm not sure of the total calculations it does for the Memory Limit (i thought it was from php.net under the imagecopyresampled, but I could locate it again). So, it might be calculating too low. I'm not sure if your 100 image quality plays apart in the memory or not.
You could adjust the +2000000 amount a bit (try the 4000000 if you haven't). Or try reducing your imagejpeg quality from 100 to 80.
But, I do know that your problem you are having is exactly what I was getting, just a black box for the image.
Posted: Thu Feb 23, 2006 10:43 am
by determinedmoth
ssand wrote:(i thought it was from php.net under the imagecopyresampled, but I could locate it again)
http://uk2.php.net/function.imagecreatefromjpeg
I think this is it.
Let me try these other options. I totally missed the image quality part.
Posted: Thu Feb 23, 2006 10:54 am
by determinedmoth
ssand wrote:
You could adjust the +2000000 amount a bit (try the 4000000 if you haven't). Or try reducing your imagejpeg quality from 100 to 80.
But, I do know that your problem you are having is exactly what I was getting, just a black box for the image.
Nope. It's not having any of it. The memory_limit is 40m in the php.ini, btw.
I even dropped the quality to 50.
I wonder, if once it's upload I terminate the script and call a second one to create the thumb.
Posted: Thu Feb 23, 2006 10:58 am
by ssand
what version of GD do you have?
imagecopyresampled appears to require GD 2.0.1 or later.
Posted: Thu Feb 23, 2006 11:02 am
by determinedmoth
"2.0 or higher" whatever that means...
But remember it works for smaller files!
Posted: Thu Feb 23, 2006 11:09 am
by ssand
did you see the updated post on php.net doesn't help that it's called tweakfactor..
so adjust the last value 1.65 to 1.8
Code: Select all
$memoryNeeded = round(($imageInfo[0] * $imageInfo[1] * $imageInfo['bits'] * $imageInfo['channels'] / 8 + Pow(2, 16)) * 1.65);
to
Code: Select all
$memoryNeeded = round(($imageInfo[0] * $imageInfo[1] * $imageInfo['bits'] * $imageInfo['channels'] / 8 + Pow(2, 16)) * 1.;
I'm not sure what that "tweakfactor" actually is? (image quality?).
But if it's just image quality it should have worked when you dropped to 50.
Posted: Thu Feb 23, 2006 11:16 am
by determinedmoth
ssand wrote:did you see the updated post on php.net doesn't help that it's called tweakfactor..
so adjust the last value 1.65 to 1.8
Code: Select all
$memoryNeeded = round(($imageInfo[0] * $imageInfo[1] * $imageInfo['bits'] * $imageInfo['channels'] / 8 + Pow(2, 16)) * 1.65);
to
Code: Select all
$memoryNeeded = round(($imageInfo[0] * $imageInfo[1] * $imageInfo['bits'] * $imageInfo['channels'] / 8 + Pow(2, 16)) * 1.;
I'm not sure what that "tweakfactor" actually is? (image quality?).
But if it's just image quality it should have worked when you dropped to 50.
I've tried that and tweaked it! Still no joy.
I'm googling to death and not found much.
Posted: Thu Feb 23, 2006 11:21 am
by determinedmoth
Ok this is interesting. I took an image that has been failing, and saved it as a severly compressed JPG - down to 89kb! This also failed! So the memory limit being the problem could just be a red herring. Maybe it's something to do with the image dimensions.
Posted: Thu Feb 23, 2006 11:31 am
by feyd
Maybe it's got "bad image" data in it, where GD has trouble understanding the data.

Posted: Thu Feb 23, 2006 11:57 am
by determinedmoth
I've got it.
It wont upload anything over 1686px in width.
1687px wont work.