[Solved] GD Library issues with file size.

PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!

Moderator: General Moderators

determinedmoth
Forum Commoner
Posts: 33
Joined: Wed Jul 07, 2004 9:13 am

[Solved] GD Library issues with file size.

Post by determinedmoth »

Hi :D

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);
							//
Last edited by determinedmoth on Fri Feb 24, 2006 9:01 am, edited 1 time in total.
ssand
Forum Commoner
Posts: 72
Joined: Sat Jun 22, 2002 9:25 pm
Location: Iowa

Post 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
determinedmoth
Forum Commoner
Posts: 33
Joined: Wed Jul 07, 2004 9:13 am

Post 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.
ssand
Forum Commoner
Posts: 72
Joined: Sat Jun 22, 2002 9:25 pm
Location: Iowa

Re: GD Library issues with file size.

Post 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' ); 
							//
determinedmoth
Forum Commoner
Posts: 33
Joined: Wed Jul 07, 2004 9:13 am

Post 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' );
ssand
Forum Commoner
Posts: 72
Joined: Sat Jun 22, 2002 9:25 pm
Location: Iowa

Post 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.
determinedmoth
Forum Commoner
Posts: 33
Joined: Wed Jul 07, 2004 9:13 am

Post 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.
determinedmoth
Forum Commoner
Posts: 33
Joined: Wed Jul 07, 2004 9:13 am

Post 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.
ssand
Forum Commoner
Posts: 72
Joined: Sat Jun 22, 2002 9:25 pm
Location: Iowa

Post by ssand »

what version of GD do you have?

imagecopyresampled appears to require GD 2.0.1 or later.
determinedmoth
Forum Commoner
Posts: 33
Joined: Wed Jul 07, 2004 9:13 am

Post by determinedmoth »

"2.0 or higher" whatever that means...

But remember it works for smaller files!
ssand
Forum Commoner
Posts: 72
Joined: Sat Jun 22, 2002 9:25 pm
Location: Iowa

Post 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.
determinedmoth
Forum Commoner
Posts: 33
Joined: Wed Jul 07, 2004 9:13 am

Post 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.
determinedmoth
Forum Commoner
Posts: 33
Joined: Wed Jul 07, 2004 9:13 am

Post 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.
User avatar
feyd
Neighborhood Spidermoddy
Posts: 31559
Joined: Mon Mar 29, 2004 3:24 pm
Location: Bothell, Washington, USA

Post by feyd »

Maybe it's got "bad image" data in it, where GD has trouble understanding the data. :idea:
determinedmoth
Forum Commoner
Posts: 33
Joined: Wed Jul 07, 2004 9:13 am

Post by determinedmoth »

I've got it.

It wont upload anything over 1686px in width.

1687px wont work.
Post Reply