0

Am using the very handy SimpleImage PHP class for resizing images, and have run into the following problem:

While test uploading various images, certain pictures were being uploaded but not resized. Upon investigation, it appears that the actual dimensions of the image were the cause of the problem (not the file size). A 5M image would upload and resize, whereas a 1.9M image would not. The difference was the latter was 4000 X 3000 - larger dimensions than the other. I resized the succeful image to be sure, and the same failure occured.

This is a silent failure, no error messages are being generated.

I am using the exact SimpleImage class as shown here

I am using it in conjunction with Uploadify, as shown below. At the moment, I'm just trying to get a flat conversion to a 200px high image. Any help in solving this would be greatly appreciated - do I need to incrementally resize, or what is the best course to follow?

<?php
session_id($_REQUEST['sID']);
session_start();
require_once '../config.php';

$target_dir = $_SERVER['DOCUMENT_ROOT'].GAL_DIR.$_POST['target_dir'];

if (!empty($_FILES)) {

    require_once 'SimpleImage.php';
    $file_parts = pathinfo($_FILES['Filedata']['name']);    

    $name = preg_replace("/[^A-ZÀ-ÿ0-9._-]/i", " ",$file_parts['filename']);

            /* Just some record keeping...
    $text = "txtrec.txt";
    $att = $target_dir."txtrec.txt";
    $record= "TIME: ".date('Y-m-d H:i:s')."\n";
    $record.= "IP: ".$_SERVER['REMOTE_ADDR']."\n";
    $record.= "DATA ARRAY: ". implode(",",$_FILES['Filedata'])."\n";
    $record.= "NAME: ".$_FILES["Filedata"]["name"]."\n"; //file-name.ext
    $record.= "TYPE: ".$_FILES["Filedata"]["type"]."\n"; //application/octet
    $record.= "SIZE: ".$_FILES["Filedata"]["size"]."\n"; //bit size
    $record.= "TMP_NAME: ".$_FILES["Filedata"]["tmp_name"]."\n"; //tmp storage name
    $record.= "BASENAME: ".$file_parts['basename'] ."\n"; //file-name.ext
    $record.= "EXTENSION: ".$file_parts['extension'] ."\n"; //ext (no dot)
    $record.= "FILENAME: ".$file_parts['filename'] ."\n"; //file-name (no dot/ext)
    $record.= "DOCUMENT_ROOT: ".$_SERVER['DOCUMENT_ROOT']."\n";
    $record.= "TARGET_DIR: ".$target_dir ."\n"; //path to gallery dir (with closing slash)
    $record.= "TMP_DIR: ".$target_dir.'tmp/'."\r\r\n";
    $fh = fopen($text, 'a') or die("can't open file");
        fwrite($fh, $record);
    fclose($fh);
    $fh = fopen($att, 'a') or die("can't open att file");
        fwrite($fh, $record);
    fclose($fh);
            */

    // Validate the file type
    $ok = FALSE;
    $ok_types = array('jpg','jpeg','gif','png');
    $file_ext = strtolower($file_parts['extension']);
    if (in_array($file_ext,$ok_types)) {
        $ok = TRUE;
    }

    if($ok) {
        $fileName = $name.'.'.$file_parts['extension'];
        array_push($_SESSION['files'],$fileName);
        $tmp_file=$target_dir.'tmp/'.$name.'.'.$file_parts['extension'];
        $target_file=$target_dir.$name.'.'.$file_parts['extension'];
        move_uploaded_file($_FILES["Filedata"]["tmp_name"],$tmp_file);

        list($width, $height, $type, $attr) = getimagesize($tmp_file);
        $dimensions = $width.' '.$height.' '.$type.' '.$attr;
        $fh = fopen($text, 'a') or die("can't open file");
            fwrite($fh, $dimensions);
        fclose($fh);

        $image = new SimpleImage();
        $image->load($tmp_file);
        $image->resizeToHeight(200);
        $image->save($target_file);

        unlink($tmp_file);

            echo '1';
    } 
    else {
        echo 'Invalid file type.';
    }
}
?>
Eamonn
  • 1,338
  • 2
  • 21
  • 53
  • Here is one thing you could check: the SimpleImage library uses the GD function imagecreatefromjpeg (or the corresponding format equivalent), which fails silently with a false return. Check what a direct imagecreatefromjpeg on your image returns. – Asad Saeeduddin Oct 16 '12 at 18:36
  • This may be the problem, as alluded to by Jack below. Running this function on its own returns the error `Allowed Memory size exhausted...` Pumping the memory limit at the top of the script is not working however, seemingly not changing the default (still returning `tried to allocate 16000 bytes`). Any ideas? – Eamonn Oct 16 '12 at 20:25
  • The other [SO question](http://stackoverflow.com/questions/6991602/fatal-error-allowed-memory-size) I read on this said the problem was occurring because he was not destroying the image objects afterwards to free up memory (they have an imagedestroy function). You aren't using a loop are you? – Asad Saeeduddin Oct 16 '12 at 20:31
  • check out what [this guy](http://www.php.net/manual/en/function.imagedestroy.php#54095) has to say about imagedestroy being imperative. – Asad Saeeduddin Oct 16 '12 at 20:34
  • The original upload (ie. the big file) is unlinked immediately afterward, so should be destroyed, yes. I'm wondering if the ini_set is working at all? Is it deprecated? – Eamonn Oct 16 '12 at 20:35
  • 1
    I believe the image object is distinct from the file you are saving it to. According to several people at the link I posted above, the resource itself remains in the working memory. I just checked the class, and there is no unset or deconstructor being used after the image is saved. – Asad Saeeduddin Oct 16 '12 at 20:39
  • Was just reading the same thing - have now added `imagedestroy($new_image);` to the end of the resize function (that calls `imagecreatetruecolor`). Still no luck :( – Eamonn Oct 16 '12 at 20:45
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/18131/discussion-between-asad-and-eamonn) – Asad Saeeduddin Oct 16 '12 at 20:56

1 Answers1

4

If it fails on really large images, your PHP script is probably running out of memory or time to run. Try putting this at the top of your script:

ini_set('memory_limit','32M'); // Or However Big the Image is in MB
ini_set('max_execution_time', '60'); // Extend execution time to a minute
Dan Hanly
  • 7,829
  • 13
  • 73
  • 134
Jack
  • 1,386
  • 1
  • 8
  • 17
  • Thanks for that - the memory limiter was already in place, but i did extend the execution time (to 120) as you suggested. Still no joy however. – Eamonn Oct 16 '12 at 19:08
  • One more - ini_set("upload_max_filesize", "10M"); – Jack Oct 16 '12 at 19:12
  • Need to make sure that the source image isn't being cut off mid-upload. – Jack Oct 16 '12 at 19:12
  • If it is being uploaded via post, make sure you also do ini_set("post_max_size", "10M"); as well – Jack Oct 16 '12 at 19:13
  • Also, make sure the memory limit is well over 32M if you are going over 4000x3000px since 4000 * 3000 * 3 (or 4 if there is alpha channel, like png) = 36,000,000 – Jack Oct 16 '12 at 19:16
  • Ok, I'm trying a few here - with all the changes suggested - still no luck. I can't figure why though... Fails with a 2M image and a 6M image, both jpgs @ 4000 X 3000. Memory limit is now set to 48M. – Eamonn Oct 16 '12 at 19:37
  • To clarify, the `ini_set` params are now declared both at the beginning of the SimpleImage class AND at the beginning of the above Uploadify script – Eamonn Oct 16 '12 at 19:42