1

I am building a reviews site and having issues with my image uploads processing. I have set up my php.ini to allow for a max_file_uploadsize of 10M and a post_max_size of 60M but I am limiting my file upload size to 6MB. I am using the smart_resize_image function to resize my images. I am allowing a max of 5 images to be uploaded and looping through the $_FILES array with a foreach loop. Here is my image processing code:

        $allowed = array('image/pjpeg', 'image/jpeg', 'image/jpg', 'image/JPG', 'image/PNG', 'image/png');
        $i = 1;
        foreach($_FILES as $image) {
            if  (file_exists($image['tmp_name'])) {
                if (in_array($image['type'], $allowed)) {
                    if($image['size'] < 6291456) {  
                        include_once('/inc/smart_resize_image.function.php');
                        $movedL = '/public_html/ureview/images/restaurants/'.$pid.'/'.$sid.'-'.$i.'.jpg';
                        smart_resize_image($image['tmp_name'], null, 800, 500, true,$movedL, true,false,100);
                        $i++;
                    }else{
                        echo'Image #'.$i.' file size limit of 5MB!';
                        exit();
                    }
                }else{
                    echo'Image #'.$i.' file type not allowed!';
                    exit();
                }
            }
        }    

The error I am getting is:

 Allowed memory size of 33554432 bytes exhausted (tried to allocate 12288 bytes) in /inc/smart_resize_image.function.php

I think what the issue is that the smart_resize_image function is unlinking after processing but not freeing up memory. I know there are multiple sites that process image uploads so it is possible but I can not figure out what I need to change in my code.

EDIT: I am looking to see if there are inefficiencies in my code above that would cause the error to happen.

Action Coding
  • 780
  • 4
  • 13
  • 1
    Possible duplicate of [Allowed memory size of 33554432 bytes exhausted (tried to allocate 43148176 bytes) in php](http://stackoverflow.com/questions/415801/allowed-memory-size-of-33554432-bytes-exhausted-tried-to-allocate-43148176-byte) – Alon Eitan Feb 10 '17 at 19:24
  • I would never set memory_limit to -1 as the question above suggests. My question is asking if there is inefficiencies in my code above that would cause the error to happen – Action Coding Feb 10 '17 at 19:49
  • Well, you can read about [imagedestroy](http://php.net/manual/en/function.imagedestroy.php) and try to implement it in your code – Alon Eitan Feb 10 '17 at 19:54
  • Tried that, couldnt find how to convert $image['tmp_name'] into a resource. Tried using fopen but it said that was not a valid image resource. – Action Coding Feb 10 '17 at 19:58
  • I use `session_destroy()` in the situations where I encounter this error. – carla Feb 10 '17 at 20:01
  • 1
    `smart_resize_image` is not very smart when it comes to memory management: it doesn't explicitly call `imagedestroy` in the default mode. Do as @AlonEitan suggested, or call `gc_collect_cycles()` to synchronize the reference counts and clean up the values still hanging around in memory. – bishop Feb 10 '17 at 20:39

1 Answers1

1

I see that the $output parameter of smart_resize_image described as

@param $output - name of the new file (include path if needed)

But I also see on line 110 that you can pass 'return' and it will make the function to return the image resource:

$res = smart_resize_image($image['tmp_name'], null, 800, 500, true,'return', true,false,100);

Now you have the recourse that you can destroy, but before destroying it, you need to save it as file (lines 218-226 of the smart_resize_image() function that you now need to implement yourself). So this is how you do it:

// smart_resize_image($image['tmp_name'], null, 800, 500, true,$movedL, true,false,100); /* OLD */

$quality = 100;
$info  = getimagesize($image['tmp_name']);

$res = smart_resize_image($image['tmp_name'], null, 800, 500, true,'return', true,false,100);

switch ( $info[2] ) {
  case IMAGETYPE_GIF:   imagegif($res, $movedL);    break;
  case IMAGETYPE_JPEG:  imagejpeg($res, $movedL, $quality);   break;
  case IMAGETYPE_PNG:
    $quality = 9 - (int)((0.9*$quality)/10.0);
    imagepng($res, $movedL, $quality);
    break;
  default: break;
}
imagedestroy ( $res ); // Now you should be able to destroy the resource (returned from the 'smart_resize_image' function)

The above code now use the imagedestroy() which frees any memory associated with image resource, and hopefully will stop you from getting the memory exhausted error

Alon Eitan
  • 11,798
  • 8
  • 44
  • 56
  • The only thing I had to change was the first "true" after return in the smart_resize_image function had to be set to false so the function didnt unlink the original image. – Action Coding Feb 11 '17 at 05:51
  • @ActionCoding Thanks for letting me know. I switched the order and called `$info = getimagesize($image['tmp_name']);` before calling the `smart_resize_image` function, so now you don't need to unlink the image yourself – Alon Eitan Feb 11 '17 at 07:35