createImageFromJPEG memory trouble

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

Post Reply
jollyjumper
Forum Contributor
Posts: 107
Joined: Sat Jan 25, 2003 11:03 am

createImageFromJPEG memory trouble

Post by jollyjumper »

Hi Everyone,

I've got a problem. My hosting provider's webserver is using php 4.3.3 with the --enable-memory-limit turned on.
It has been configured with a memory limit of 16 MB.

When I try to upload a file through a form, and open the file with createImageFromJPEG it gives me this error:
Fatal error: Allowed memory size of 16777216 bytes exhausted at (null):0 (tried to allocate 2048 bytes)
I'm absolutely sure that the code is executed once, as I suspected a loop, but this hasn't been the case.

Is this normal with a memory limit of 16 MB, so does it just need to be more, or am I doing something wrong?

Or maybe someone can tell me how I can free some memory?

Thanks in advance.

Greetz Jolly.
User avatar
volka
DevNet Evangelist
Posts: 8391
Joined: Tue May 07, 2002 9:48 am
Location: Berlin, ger

Post by volka »

what's the size of that image?
Maybe if you show us the code...
jollyjumper
Forum Contributor
Posts: 107
Joined: Sat Jan 25, 2003 11:03 am

Post by jollyjumper »

Hi Volka,

The file is 1.2 MB large.

The code is contained in two classes.

1. fileupload which handles the upload process, which inprinciple is this function(the dutch texts are just error messages):

Code: Select all

function Upload() {
    if (($this->upl_file != -1) && ($this->new_filename != -1) && ($this->copy_to != -1)) {
	  if (!($this->upl_file == "none" || $this->upl_file=="")) {
	    if (!file_exists($this->copy_to . "/" . $this->new_filename)) {
          $this->CorrectFilename();
		  if ($this->MustHaveType != "") {
  	        if ($this->MustHaveType !=$this->IsType) {$typeok = false;} else {$typeok = true;}
		  } else {
		    $typeok = true;
		  }
			if ($typeok == false) {
			  $this->error = "Het bestand is niet van het type " . $this->MustHaveType . " en is daarom niet opgeslagen.";
		    } else {
			  if (@copy($this->upl_file,$this->copy_to . "/" . $this->new_filename)) {
			    if (file_exists($this->copy_to . "/" . $this->new_filename)) {
			      return true;
			    } else {
			      $this->error = "Er is iets mis gegaan met het opslaan van het bestand.";
				  return false;
			    }
			  } else {
			    $this->error = "Het bestand is niet goed verstuurd en is daarom niet opgeslagen.";
			    return false;
			  }
			}
		  } else {
		    $this->error = "Het bestand dat u zojuist heeft verstuurd bestaat al en is daarom niet opgeslagen.";
		    return false;
		  }
	    } else {
	     return false;
	    }
     } else {
	   return false;
	 }
   }
2. The image resize:

Code: Select all

function Resize($NewImageWidth="",$NewImageWidthSmall="",$OnlyLarger=0) {
                copy($this->urlafbeelding,$this->tmpurlafbeelding);
                $size = GetImageSize ("$this->tmpurlafbeelding");
                $ImageWidth = $size[0];
                $ImageHeight = $size[1]; 
			 if ($OnlyLarger == 0) {
			   $resize_img = true;
			 } else {
			   if ($ImageWidth > $NewImageWidth) {
			    $resize_img = true;
			   } else {
			    $resize_img = false;
			   }
			 }
			 if ($resize_img) {
                $NewImageHeight = round(($NewImageWidth / $ImageWidth) * $ImageHeight);
              	$src_img = ImageCreateFromJPEG("$this->tmpurlafbeelding"); 
               if ($this->method != 0) {
               	$dst_img = imagecreatetruecolor($NewImageWidth,$NewImageHeight); 
               	imageCopyResampled($dst_img,$src_img,0,0,0,0,$NewImageWidth,$NewImageHeight,$ImageWidth,$ImageHeight); 
			   } else {
               	$dst_img = imagecreate($NewImageWidth,$NewImageHeight); 
               	imageCopyResized($dst_img,$src_img,0,0,0,0,$NewImageWidth,$NewImageHeight,$ImageWidth,$ImageHeight); 
			   }
               	ImageJPEG($dst_img,"$this->urlafbeelding",100); 
			 }

               if ($this->urlafbeelding_small != "") {
               	$NewImageHeight = round(($NewImageWidthSmall / $ImageWidth) * $ImageHeight);
               	$src_img = imagecreatefromjpeg("$this->tmpurlafbeelding"); 
               if ($this->method != 0) {
               	$dst_img = imagecreatetruecolor($NewImageWidthSmall,$NewImageHeight); 
               	imageCopyResampled($dst_img,$src_img,0,0,0,0,$NewImageWidthSmall,$NewImageHeight,$ImageWidth,$ImageHeight); 
			   } else {
               	$dst_img = imagecreate($NewImageWidthSmall,$NewImageHeight); 
               	imageCopyResized($dst_img,$src_img,0,0,0,0,$NewImageWidthSmall,$NewImageHeight,$ImageWidth,$ImageHeight); 
			   }
               	Imagejpeg($dst_img, $this->urlafbeelding_small,100); 				
               }

				unlink($this->tmpurlafbeelding);
  }
[mod_edit changed

Code: Select all

to

Code: Select all

][/size]

Hope this clarifies something.

Greetz Jolly.
User avatar
volka
DevNet Evangelist
Posts: 8391
Joined: Tue May 07, 2002 9:48 am
Location: Berlin, ger

Post by volka »

hm, can't tell you for certain but it might easily be that the image blows up your memory limit.
1.2MB jpeg get unpacked, gd isn't stingy with memory and you create a second image (for resizing) ...yes, it really might blow up...

Have you tested with a smaller image?
jollyjumper
Forum Contributor
Posts: 107
Joined: Sat Jan 25, 2003 11:03 am

Post by jollyjumper »

Hi Volka,

Yes I know the code in principle is correct because it works with smaller images, and it has always worked on our previous hosting provider's server, which didn't contain a memory limit.

But it sounds like it's a normal situation..then I don't worry anymore and just make sure I increase the memory limit before the resize starts. Do you know what a safe value is for resizing images, without screwing up the server?

Greetz Jolly.
User avatar
volka
DevNet Evangelist
Posts: 8391
Joined: Tue May 07, 2002 9:48 am
Location: Berlin, ger

Post by volka »

never have tested that. I wouldn't use the filesize but the image canvas size.
If you want to try use array getimagesize ( string filename [, array imageinfo]) and always echo the canvas size (and flush) before actually opening the image. Shouldn't take long to find the maximum size (probably almost linear growing with the product of width*height)

If your version of php is setup to provide this function you might also use int memory_get_usage ( void )
jollyjumper
Forum Contributor
Posts: 107
Joined: Sat Jan 25, 2003 11:03 am

Post by jollyjumper »

Hi Volka,

Thanks for the suggestion, I'm going to try this out, it sounds logical :-)

Greetz Jolly.
NED334
Forum Newbie
Posts: 4
Joined: Mon Feb 09, 2004 5:47 am
Location: The Netherlands

Post by NED334 »

Have you found a sollution about this memory problem? I am trying to make a thumbnail as well, and i allready get this message when i try to resize an image of +/_ 100kb.

Is there another way to make a thumbnail of an image(like 500kb)?


Please let me know, because i get sick :evil: of the irritating error massage, like this one:
Fatal error: Allowed memory size of 8388608 bytes exhausted (tried to allocate 4800 bytes)


Thanks for your replies!
jollyjumper
Forum Contributor
Posts: 107
Joined: Sat Jan 25, 2003 11:03 am

Post by jollyjumper »

Hi NED,

I've found a sollution, but your hosting provider needs to allow you to change this setting, so it also could not work for you.

Place this line before the piece of code that resizes you image:

Code: Select all

ini_set ("memory_limit", "100M");
You can adjust the 100M value to any of your liking, but 100M was enough for me.

Greetz Jolly.
NED334
Forum Newbie
Posts: 4
Joined: Mon Feb 09, 2004 5:47 am
Location: The Netherlands

Post by NED334 »

Thanks Jolly,

but i am not allowed to change the serversettings because i am running my site on a server that is not mine :(

I tried the line that you told me, but there was no result...

Is there no other option then using the imagecreatefromjpeg function, for creating a thumbnail or for resizeing an image, without changeing the serversettings?
jollyjumper
Forum Contributor
Posts: 107
Joined: Sat Jan 25, 2003 11:03 am

Post by jollyjumper »

Hi Ned,

I'm afraid not, at least no solution I've found. It's just that resizing a big jpeg costs more than 8 MB of memory.

You could ask the webmaster of your server if he/she would like to change the memory_limit to a higher value than 8 MB. I can't think of anything else that could help.

Maybe someone else who's reading this thread has another sollution?

Greetz Jolly.
woodse
Forum Newbie
Posts: 1
Joined: Tue Feb 17, 2004 8:35 am

Post by woodse »

As an alternative approach, check into the netpbm program as it ships with and is used in the Gallery program (http://gallery.menalto.com/).

The handy thing about this is that you shop out the processing work to another program, and this keep you from using up the memory space allocated to php. Also, netpbm produces better graphics. See the Gallery docs on why it was chosen over GD.
NED334
Forum Newbie
Posts: 4
Joined: Mon Feb 09, 2004 5:47 am
Location: The Netherlands

Post by NED334 »

Yeah i allready tried that as well, but i found out that my hosting provider doesn't support NETPBM. Thanks anyway...

But now i solved the memory problem. You get an error message like: Fatal error: Allowed memory size of 8388608 bytes exhausted (tried to allocate 4800 bytes) when you try to rescale an image(for example: 1200px to 105px). The filesize doen't matter. First of all i thought i recieved this message because of the filesize. I was testing with an image that was 1200px * 600px & 468kb. But then i tried an image that was 600px * 400px & 400kb it suddenly worked with no problem.
Now i made a script in Javascript that will not allow image files bigger then 900px wide/height, and the file size may not be bigger then 400kb, otherwise it will return a selfmade error message. 400kb and 900px width/height wil be big enough because otherwise the server space wil decrease very fast. When the Javascript detects that the pointed image is allowed, PHP takes it over, and FTP the image file to the server. After that imagecreatefromjpeg create 6 different image sizes, and store them on the server with some extra data in the database.

This solved the problem for me, with no changes on server level. I used this script for our own CMS system, and by the way: "You have to restrict your users, otherwise it will be a mess".

I hope this message helped some people with the memorylimit problem by using imagecreatefromjpeg in PHP, and saved a lot of time!


Greetz,

Dennis
jollyjumper
Forum Contributor
Posts: 107
Joined: Sat Jan 25, 2003 11:03 am

Post by jollyjumper »

Hi Dennis,

Could you post the javascript code you used here, as this might be handy for other users as well.

I'm certainly interested in how you did this..

Greetz Jolly.
NED334
Forum Newbie
Posts: 4
Joined: Mon Feb 09, 2004 5:47 am
Location: The Netherlands

Post by NED334 »

Hi Jolly,

below you have the javascript code to check the imagefile. Note that this script is made for Internet Explorer 5.0 and bigger, on windows. I don't know how it works on Mac's and others. Our CMS system is made for IE 5.5 and bigger so this was perfect.

This code checks:
* if the given file is an image(When it is not an image you can't click the submit button);
* if the given image is below 400kb(When the image is over 400kb you get a message, and you cannot click the submit button);
* if the given image is smaller then 900px in height or width(When the image is over 900px in height/width you'll recieve a message and you cannot click the submit button);

Please let me know what u think!


Here it is:

<script language="JavaScript">

function Check_IMG(img_size, fileName){
document.file_upload.Check_Submit.disabled = "TRUE";
var imgURL = "file:///" + fileName;
var img = new Image();
img.src = imgURL;
msg = "";
if(img.width > 900){
document.file_upload.Check_Submit.disabled = "TRUE";
msg += "- Your image is to wide!\n";
}
if(img.height > 900){
document.file_upload.Check_Submit.disabled = "TRUE";
msg += "- Your image is to high!\n";
}
if(img_size > 409600){
document.file_upload.Check_Submit.disabled = "TRUE";
size_in_kb = (1/(Math.pow(2,10))) * img_size;
msg += "- The image filesize is to big!\n\nThe file may not be bigger then 400kb";
}
if(msg){
document.file_upload.Check_Submit.disabled = "TRUE";
msg += "\nChoose another image.\nThe image is to high/wide.\n";
alert(msg);
}
else{
document.file_upload.Check_Submit.disabled = "";
}
}
</script>

<form name="file_upload" enctype="multipart/form-data" method="post" action="" onsubmit="JavaScript:this.Submit.disabled=true;">
<fieldset style="padding: 3;"><legend>Your Image: </legend>
<INPUT oncontextmenu="return false" onkeypress="return false" onkeydown="return false" type=file onchange="Check_Submit.disabled='true';img_preview.src=file.value;" name="file">
<IMG WIDTH=0 HEIGHT=0 alt="Image is loading" onerror="Check_Submit.disabled='true';" src="" onload="Check_IMG(img_preview.fileSize, file.value);" name="img_preview">
<input type="button" name="Check_Submit" value="Save image" onclick="document.file_upload.Check_Submit.disabled = 'TRUE';">
</fieldset>
</form>
Post Reply