Imagecreatefromjpeg has memory problem

Hi I have a site that allows admins to upload pictures. The issue I’m running into is that some of the images uploaded will fail with the following message. “Fatal error: Out of memory (allocated 46399488) (tried to allocate 3648 bytes) in /home/randon13/public_html/admin/fnc/createThumb.fnc.php on line 26” Line 26 relates to this piece of code

$im = imagecreatefromjpeg($tempFileLocation);

I have noticed that if the image is over a certain dimension it will fail 3648 X 2746. Smaller resolutions like 1600x1200 will upload just fine. This causes a problem because the admins need to have the script resize images straight from a digital camera.

I use Hostgator for the site and found out they have a 64M cap of the memory used. I know many people have ran into this but how do I get it work.

Here is my image create function.

<?php //Thumbnail creation function
  function createThumbnail($max_width, $max_height, $tempFileLocation, $original_file_name,
      $path_to_thumbs_directory,$fileType){

      //getimagesize used for dimensions of image and image type
      list($orig_width, $orig_height, $type, $attr) = getimagesize($tempFileLocation);

      //calculate scaling ratio
      if ($orig_width <= $max_width && $orig_height <= $max_height) {
          $ratio = 1;
      } elseif ($orig_width > $orig_height) {
          $ratio = $max_width / $orig_width;
      } else {
          $ratio = $max_height / $orig_height;
      }

      //check to see which type of image was uploaded
      //Then create image identifier with imagecreatefrom

      //Type 1 = gif
      if ($fileType == "gif") {
          $im = imagecreatefromgif($tempFileLocation);
          $extension = '.gif';
      //Type 2 = jpeg
      } else if($fileType == "jpeg" OR $fileType == "pjpeg" ) {
          [B]$im = imagecreatefromjpeg($tempFileLocation);[/B]
          $extension = '.jpeg';
      //Type 3 = png
      } elseif ($fileType == "png") {
          $im = imagecreatefrompng($tempFileLocation);
          $extension = '.png';
      }
      //calculate dimensions of image
      if (!isset($ratio)) {
          echo '<p>problem with ratio no image created!</p>';
      } else {
          $new_width = round($orig_width * $ratio);
          $new_height = round($orig_height * $ratio);
          //creates image place holder identifier of black image used in imagecopyresampled
          $nm = imagecreatetruecolor($new_width, $new_height);
		  //$nm = imagecreate($new_width, $new_height);

          //creates resized image thumbnail
          imagecopyresampled($nm, $im, 0, 0, 0, 0, $new_width, $new_height, $orig_width, $orig_height);


          //create image file base on type
          //to be displayed or moved to thumbnail file , set image quality
          switch ($type) {
              case 1:
                  imagegif($nm, $path_to_thumbs_directory . $original_file_name . $extension, 90);
                  break;
              case 2:
                  imagejpeg($nm, $path_to_thumbs_directory . $original_file_name . $extension, 90);
                  break;
              case 3:
                  imagepng($nm, $path_to_thumbs_directory . $original_file_name . $extension, 100);
                  break;
          }

          // frees image from memory
          imagedestroy($nm);
          /*
          $tn = '<p><img src="' . $path_to_thumbs_directory . $original_file_name . $extension .
              '" alt=' . $orginal_file_name . ' /></p>';
          $tn .= '<br />image resized<br />';
          echo $tn;
          */
      }
  }
  ?>

It fails here but only if image dimension is very large.

Basically you will have to rethink your upload plan. It might be ok if you upload the image and then do the resize but even then I think it might struggle.

An alternative would be to try ImageMagick if your host has it installed.
Look at http://www.rubblewebs.co.uk/imagemagick/ for some useful explanations, hints and tips as well as scripts

You can estimate how much memory will be needed, so that you can abort if it will be higher than your available memory, or try to increase the memory_limit if possible, to avoid the fatal error.

There’s quite a few posts in the manual pages for the various gd functions, which discuss memory estimation and issues. Here’s one of many.

http://www.php.net/manual/en/function.imagecreatefromjpeg.php#61709

Make sure to leave enough memory so you can do do other script processing until you destroy the image, which frees up the memory.

Hi thanks for the info. The issue is that I don’t think that HostGator will allow me to increase the memory needed. If I could how would I do it?

Also does my script look bad or something spikeZ that makes you say I need to rethink my upload plan?

Why does imagecreatefromjpeg function use so much memory?

Your function looks fine in the sense that there are is no unnecessary logic which may impact memory usage as far as I can see, you can manually increase the amount of PHP can use like so:-

ini_set('memory_limit', '64M');

The GD image functions have always been quite memory intensive, but to be fair to them, they need to load the entire image into memory in order to manipulate it.

As crmalibu has already suggested, take a wander over to the manual and read some of the comments about how to work out whether or not you have enough memory to load your image before starting.

:slight_smile:

Hi SilverBulletUK

thanks for the help. I have tried using the ini_set method but it still seems not to work. Although Hostgator is set at 64M already.

Alas I read over the information at php.net but I don’t totally understand how my knowing how much memory a given image needs to resize will help me.

I found this function within the comments on the manual, if return the amount of memory (in bytes) require to edit an image.

You could use this figure in your logic to decide how to proceed. I cannot attest to its reliability, but it’s a start. :slight_smile:

<?php
/**
 * @desc    Calculates the amount of memory required
 *             to manipulate an image with GD.
 * 
 *
 * @param    String    $sImagePath
 * @return     Integer Bytes required
 */
function getMemoryRequiredToEdit($sImagePath)
{
    $aImageInfo = getimagesize($sImagePath);
    return round((($aImageInfo[0] * $aImageInfo[1] * $aImageInfo['bits'] * $aImageInfo['channels'] / 8 + Pow(2, 16)) * 1.65));
}

echo getMemoryRequiredToEdit('/path/to/your/images/Sunset.jpg');

?>

Hmm okay the functions makes since. Although like I stated before how would I be able to make the function I have work if I know the amount of memory I need to create the image? My question is why will it not work even if my hosting server allows 64 megs of memory. When I developed this script it worked perfectly without a hinch and could upload any image. NOw when I moved it to my Hostgator it bombs if the resolution is very big.

If your host wont let you increase the memory limit, then you’re out of luck. Image manipulation can take a lot of memory. With gd, when you create an image resource, it doesn’t know what kind of manipulation you intend to do, and just stores it in a manipulation friendly format in memory, which happens to use a lot of memory. I’m sure it could be done in a much more memory frugal way if a resize is all that’s needed, but gd doesn’t have such facility.

The purpose of the function is to provide you a tool which you can use to help prevent your script from crashing with a fatal error.

You might try ImageMagick like suggested. It might decide to use a more memory friendly method if all you’re doing is a resize. It might also have a higher memory limit, or maybe you will have more success increasing its memory limit. It’s not php, it’s a standalone program often called from the command line.

okay I see that helps. So it seems what your saying it that GD is not a very good way to resize images. Why would they make such a library that would take up so much memory. HOw do some many other people upload images to different sites without issues like this?

So is there no way around this issue besides uploading smaller images?

It doesn’t sound like you’re reading the posts in this thread very carefully.

Hmmm really I do read them. I just don’t understand why GD functions like createimagefromjpeg takes up so much memory.

I have been traveling for work today, tomorrow I will have some time to work on this and see what happens. Thanks for the help I appreciate it.

Large shared hosts are not really meant to be used for resource intensive tasks such as resizing images. They provide the functionality for it to “work,” but it will never work very well.

Moving to a VPS where you can control the environment would resolve the issue.

hi bhanson. What do you mean by “larged shared hosts”? If there not meant for it then how do I get it work, dedicated servers seems what to crazy for me, if I only need more memory just for resizing images every couple of weeks.

A VPS seems like a very expensive solution to this problem. I guess it looks like I might to have to limit the size of photos a user can submit. :frowning:

Shared plans with companies like GoDaddy, HostGator, Dreamhost, iPower, Globat, JustHost, BlueHost, Hostmonster, Lunarpages or many others.

The plans are designed for small, unpopular websites that rarely get any traffic and don’t tax system resources. It’s kind of like buying a bus pass vs owning your own car. You can take (almost) anything with you just as you could with a car, but you’re limited in capacity and sometimes the bus will be full.

Those shared hosts charge about $10/month, and an entry level VPS is about $20/month. That’s less than a phone or internet bill.

Ok sounds interesting? Do you have a VPS you use to host your websites? What company is good to look at?

Slicehost and [URL=“http://linode.com”]Linode both have very good reputations.

I guess I should clarify a little bit more. Both of those companies provide unmanaged VPS. That means you’re in charge of all software on your server as well as updates and security. It’s not too difficult, but it would take some time to learn if you were interested in going that route.

ServInt is kind of like a mini [URL=“http://rackspace.com”]Rackspace. They provide top-tier managed VPS solutions (they manage the software for you). This means if you want something done you can simply open support ticket or give them a phone call and they will log in and do it for you.

Both of these companies provide a 24/7 phone number that rings directly to a real person, with real qualifications ready to provide support (which is why they’re a little bit more expensive).

If you’re not ready to manage your own server yet, then some of these solutions may be out of your budget, but there may be a host that’s kind of a hybrid.

MediaLayer also have a very stellar reputation. They provide a kind of premium shared hosting. You’ll get much better performance with them as they actually sell you reasonable allocations. They can provide better service and stick less customers on each server. I’m sure if you contacted them you could ask if your script would be allowed to run.

Another option might be MediaTemple. They provide a consumer cloud hosting solution. Beware that they have had issues in the past and don’t have quite the same reputation as the above listed companies. I’m sure if you contacted them they would also let you know if your script would run.

But if your website is very low traffic, or it would be reasonable to simply limit the file size of the uploaded images, then Hostgator may remain suitable for you. It all depends on your needs and expectations.

Wow thanks man for the options. I see your footer information it seems you specialize in VPS hosting. This reminds me of stuff like Amazon and their Cloud technologies like S3 and EC2. I had looked into it before but it seemed alitte to high for me to justify the cost of such a service.

I think for now I’m going to stick with Hostgator and just limit the resolution size of the image a person uploads. It seems that the actual file size doesn’t hurt the upload script nearly likely the resolution dimensions. It seems I have figured out that a image over 3376x2528 will make it fail.

I will simply just put some conditions that say if the image resolutions is less then 3376 X 2528 and is less than 4MB in size upload it. If not then reject it and tell the user why the image didn’t load it. I don’t totally like the limitation right now but alas I don’t want to speed the money for a full blow dedicated server at the time. The only time I need more memory is for this one upload process so I will leave with it for now. I will post the function I create once I have it completed that will limit the dimension size.

EC2 is comparatively expensive for small websites, but S3/SimpleDB/SQS/CloudFront have very low points of entry and are pretty cheap. Utilizing the latter services can greatly increase the scalability and speed of web applications. For a small website utilizing Amazon’s CDN it could cost just pennies a month (literally).

Cools thanks for the info.

Here is function I’m going to use to keep from having a fatal error. Keep in mind you will need to find out how much memory your hosting company allows. Then test the upload image and find where it give you a fatal error. Then in the follow function put the max dimensions that will not make the script fail with a fatal error. I would suggest you do this before you even get to manipulate the image so not to waste resources.


<?php
function imageSizeVerify($image, $maxWidth, $maxHeight){
	list($width, $height, $type, $attr) = getimagesize($image);
 	
	 //check width and height are not to large
	 if($width >= $maxWidth && $height >= $maxHeight){
	 	echo "<p><strong>Error:</strong> Image resolution is <strong>$width x $height</strong> is not allow.
		          Images $maxWidth x $maxHeight or smaller are allowed to upload. Resize your image and try again
			.</p>";
	 } else {
	 	echo "<p>$width x $height image can be uploaded</p>";
	 }
	
	
}

    $maxWidth = 3376;
	$maxHeight = 2528;
	
	$imageSize = '/your/web/path/here/someimage.JPG';
	
	imageSizeVerify($imageSize, $maxWidth, $maxHeight);


?>