简体   繁体   中英

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.

The logic regarding your thumbnail generation is incorrect, but your more pressing issue is saving the image file. You're trying to save in the root of the filesystem ( /users/$id/avatar.png ), likely without the permissions required to do so.

While you can save back to the upload path, it's not necessary. In imagepng , simply save the file to your destination (eg, /var/web/app/public/uploads/$id/avatar.png ). You can also use the magic constant __DIR__ to specify a path relative to the PHP file doing the execution.

As far as the cropping is concerned, considering using a prebuilt function or library for generating the thumbnails. I could copy some code here, but other people have beaten this problem to death many times over (and remedied other potential issues, like transparency). You can review the documentation (and user comments) on imagecopyresampled , or use a sophisticated library such as Imagine .

So, after reseaching 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 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. Thank you and Merry Christmass everybody.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM