phpimageuploadresizephp-gd

PHP GD resize/crop image before uploading


I've been trying to fetch a file from an HTML form, then create a new one and use "imagecopyresampled" to get the central square from it, fitting either on X or Y, depending on which is smaller.

Unfortunately I got a bit confused about handling so many images and temporary names and I have been with trouble to copy the file to the user file on the system. The code is as follow:

if($_FILES){
    $valid = validate_image("avatar");

    if ($valid){
        list($width, $height, $type) = getimagesize($_FILES['avatar']['tmp_name']);

        $scale = $width/$height;
        $pixels = 150;
        $tmp_name = $_FILES['avatar']['tmp_name'];

        switch ($type) {
            case IMAGETYPE_GIF:
                $source = imagecreatefromgif($tmp_name);
                break;

            case IMAGETYPE_JPEG:
            case IMAGETYPE_JPG:
                $source = imagecreatefromjpeg($tmp_name);
                break;

            case IMAGETYPE_PNG:
                $source = imagecreatefrompng($tmp_name);
                break;
        }

        $upload = imagecreatetruecolor($pixels, $pixels);

        //sketchy image math: Get whichever coordinate is smaller and that will be 150 on the thumbnail from top to bottom (or left to right).
        //Then for the other one you know the size will be 150, but only for the part starting at (Coordinate/2)-SMALLERCOORD/2 to (coord/2)+SMALLERCOORD/2

        if ($width>$height){
            imagecopyresampled ($upload, $source, 0, 0, 0, ($width-$height/2), 150, 150, $height, $height);
        } else if ($width<=$height){
            imagecopyresampled ($upload, $source, 0, 0, 0, ($height-$width/2), 150, 150, $width, $width);
        }

        $name = "./users/$id/avatar.png";

        imagepng($upload, $tmp_name);

        if (!(move_uploaded_file($tmp_name, $name))) $fail .= "<h3>ERROR UPLOADING AVATAR. TRY AGAIN LATER OR CONTACT US.</h3><br>";
    }
}

First of all let me see if I understand how the code is working correctly: I get the file, check if it's valid with my function. Then I get the size and type of it. I check the type and create a image on the servers memory from it and another empty one on the size I want. Then I actually copy the resized and cropped image on the upload image I created. There if I wanted I could delete the temporary "source" image with imagedestroy, right? Next I try to make a png file from the "upload" image from the server memory. Here is where I think I got it wrong, I can't overwrite the temporary file, can I? And then I try to put the image temporary image where it should be uploaded but that doesn't work.

Am I getting this right? How can I fix this code? Thank you for your attention.


Solution

  • After researching online a lot I discovered that the biggest problem was on the User that was running apache (www-data).

    So I entered /etc/apache2/envvars and changed APACHE_RUN_USER to the owner of the folder. Then I had to do a chown on /etc/lib/php5 so that the sessions would stick/work with the new user.

    With that, I was able to now access the folder so that the server would be able to write and modify on it. Then I added to the code this part:

    $dir = "./users/$id/";
    $oldumask = mask(0); 
    mkdir ("$dir");
    chmod("$dir", 0750);
    umask($oldumask);
    

    This was added right before creating the png image. Then I removed the "move_uploaded_file" code and just used the imagepng function as Jacob Budin suggested:

    if(!imagepng($upload, $name)) $fail .= "<h3>ERROR!<h3><br>";
    

    This solved everything(but the fact that the cropping code was wrong, but that's not relevant). I'm still not 100% sure how GD/PHP handles the image very well, but this works.