tags:

views:

57

answers:

3

BACKGROUND
I have a script to upload an image. One to keep the original image and one to resize the image. 1. If the image dimensions (width & height) are within max dimensions I use a simple "copy" direct to folder UserPics. 2. If the original dimensions are bigger than max dimensions I want to resize the width and height to be within max. Both of them are uploading the image to the folder, but in case 2, the image will not be resized.

QUESTION
Is there something wrong with the script?
Is there something wrong with the settings?

SETTINGS
Server: WAMP 2.0
PHP: 5.3.0
PHP.ini: GD2 enabled, Memory=128M (have tried 1000M)
Tried imagetypes uploaded: jpg, jpeg, gif, and png (same result for all of them)

SCRIPT

if (isset($_POST['adduserpic'])) {  
    // Check errors on file  
    if ($_FILES["file"]["error"] > 0) {  
        echo $_FILES["file"]["error"]." errors<br>";  
    } else {  
        $image =$_FILES["file"]["name"];  
        $uploadedfile = $_FILES["file"]["tmp_name"];  
    //Uploaded image  
    $filename = stripslashes($_FILES['file']['name']);  

    //Read filetype  
    $i = strrpos($filename,".");  
    if (!$i) { return ""; }  
    $l = strlen($filename) - $i;  
    $extension = substr($filename,$i+1,$l);  
    $extension = strtolower($extension);  

    //New picture name = maxid+1 (from database)  
    $query = mysql_query("SELECT MAX(PicId) AS number FROM userpictures");  
    $row = mysql_fetch_array($query);  
    $imagenumber = $row['number']+1;  

    //New name of image (including path)   
    $image_name=$imagenumber.'.'.$extension;    
    $newname = "UserPics/".$image_name;  

    //Check width and height of uploaded image  
    list($width,$height)=getimagesize($uploadedfile);  

    //Check memory to hold this image (added only as checkup)   
    $imageInfo = getimagesize($uploadedfile);   
    $requiredMemoryMB = ( $imageInfo[0] * $imageInfo[1] * ($imageInfo['bits'] / 8) * $imageInfo['channels'] * 2.5 ) / 1024;  
    echo $requiredMemoryMB."<br>";  

    //Max dimensions that can be uploaded  
    $maxwidth = 20;  
    $maxheight = 20;  

    // Check if dimensions shall be original  
    if ($width > $maxwidth || $height > $maxheight) {  
        //Make jpeg from uploaded image  
        if ($extension=="jpg" || $extension=="jpeg" || $extension=="pjpeg" ) {  
            $modifiedimage = imagecreatefromjpeg($uploadedfile);  
        } elseif ($extension=="png") {  
            $modifiedimage = imagecreatefrompng($uploadedfile);  
        } elseif ($extension=="gif") {  
            $modifiedimage = imagecreatefromgif($uploadedfile);  
        }   
        //Change dimensions  
        if ($width > $height) {  
            $newwidth = $maxwidth;  
            $newheight = ($height/$width)*$newwidth;  
        } else {  
            $newheight = $maxheight;  
            $newwidth = ($width/$height)*$newheight;  
        }  

        //Create new image with new dimensions  
        $newdim = imagecreatetruecolor($newwidth,$newheight);  
        imagecopyresized($newdim,$modifiedimage,0,0,0,0,$newwidth,$newheight,$width,$height);  
        imagejpeg($modifiedimage,$newname,60);  

        // Remove temp images  
        imagedestroy($modifiedimage);  
        imagedestroy($newdim);  
    } else {  
        // Just add picture to folder without resize (if org dim < max dim)  
        $newwidth = $width;  
        $newheight = $height;  
        $copied = copy($_FILES['file']['tmp_name'], $newname);  
    }

    //Add image information to the MySQL database  
    mysql_query("SET character_set_connection=utf8", $dbh);  
    mysql_query("INSERT INTO userpictures (PicId, Picext, UserId, Width, Height, Size) VALUES('$imagenumber', '$extension', '$_SESSION[userid]', '$newwidth', '$newheight', $size)") 
A: 

I can't see anything wrong with the script at first glance but this is awfully hard to solve without some test output and error reporting.

  1. Turn up error_reporting(E_ALL)

  2. See what $newname is set to

  3. See what the copy() command does

I bet you are getting something when you turn error reporting on. To find out the file's extension, by the way, I would use pathinfo.

Pekka
When error reporting on = No errors shownInformation about parameters:577.880859375 (required memory)300-20 ($width - $newwidth)263-17.533333333333 ($height - $newheight)UserPics/25.jpg ($newname)
Hans
Strange. @Hans what happens if you output the `imagejpeg` directly to the browser (adding a `content-type`header)? Do you get a resized image?
Pekka
A: 

Have you checked that the image resizing block is actually being used? Consider some debug output in there as well. I can't see anything obviously wrong

if ($width > $maxWidth || etc...) {
   echo "Hey, gotta shrink that there image";
   ... do the resizing ...
   $resizedImage = getimagesize($newname);
   var_dump($resizedImage); // see if the new image actually exists/what its stats are
   etc....
} else {
   echo "Woah, that's a small picture, I'll just make a straight copy instead";
}

You might also want to round off the $newheight/$newwidth to integer values - In almost all cases, you'll get some fractional result and images don't have fractional pixels.

As an aside, you've got a race condition with your ID number generator:

$query = mysql_query("SELECT MAX(PicId) AS number FROM userpictures");  
$row = mysql_fetch_array($query);  
$imagenumber = $row['number']+1; 

Consider the case of two uploads completing at almost the same time. They'll both get the same ID number (say, 25). And then whichever of the uploads takes longer to process will "win" and overwrite the faster one.

Consider rewriting the database portion to use a transaction, using the following logic:

 1. start transaction
 2. insert skeleton record into the db and get its ID
 3. do image processing, copying, saving, etc...
 4. update record with the new image's stats
 5. commit the transaction

This way, the transaction will "hide" the record as it's not committed yet, there's no way for two or more simultaneous uploads to get the same ID number, and if anything fails during image processing (insufficient ram, disk space, corrupt source image, etc...) you just roll back the transaction and clean up the mess.

I

Marc B
The vardump showed that the new image had not been resized. Thanks for the comment about the "race condition" as well!
Hans
A: 

1) Check permissions. make sure your UserPics directory can be written by the user running the web process (e.g., www-data on a debian system). I'm not familiar with system permissions on windows for this kind of thing, but that's what I would check if I were writing this myself (and I have, and I probably did).

2) Not related, per se, but check out http://sourceforge.net/projects/littleutils/

I run opt-gif and opt-jpg on all my uploaded images to save disk space, losslessly (my app doesn't need what's lost)

Matt