phpfile-uploadimage-resizingimage-quality

Can't upload image with 100% quality


I'm trying to upload image via PHP, but I'm unable to upload an image with 100% quality.

The code I'm actually using

class imaging
{

    // Variables
    private $img_input;
    private $img_output;
    private $img_src;
    private $format;
    private $quality = 100;
    private $x_input;
    private $y_input;
    private $x_output;
    private $y_output;
    private $resize;

    // Set image
    public function upload($orig, $name, $path)
    {
        move_uploaded_file($orig, __DIR__ . "/../uploads/" . $path . 'orig_' . $name);
    }

    public function set_img($img)
    {
        //$img = __DIR__ . '/../uploads/' . $img;

        $img = '../uploads/' . $img;

        // Find format
        $ext = strtoupper(pathinfo($img, PATHINFO_EXTENSION));

        // JPEG image
        if(is_file($img) && ($ext == "JPG" OR $ext == "JPEG"))
        {
            $this->format = $ext;
            $this->img_input = ImageCreateFromJPEG($img);
            $this->img_src = $img;

        }

        // PNG image
        elseif(is_file($img) && $ext == "PNG")
        {

            $this->format = $ext;
            $this->img_input = ImageCreateFromPNG($img);
            $this->img_src = $img;

        }

        // GIF image
        elseif(is_file($img) && $ext == "GIF")
        {

            $this->format = $ext;
            $this->img_input = ImageCreateFromGIF($img);
            $this->img_src = $img;

        }

        // Get dimensions
        $this->x_input = imagesx($this->img_input);
        $this->y_input = imagesy($this->img_input);
    }

    // Set maximum image size (pixels)
    public function set_size($size = 100)
    {
        // Wide
        if($this->x_input >= $this->y_input && $this->x_input > $size)
        {
            $this->x_output = $size;
            $this->y_output = ($this->x_output / $this->x_input) * $this->y_input;

            $this->resize = TRUE;
        }

        // Tall
        elseif($this->y_input > $this->x_input && $this->y_input > $size)
        {
            $this->y_output = $size;
            $this->x_output = ($this->y_output / $this->y_input) * $this->x_input;

            $this->resize = TRUE;
        }

        // Don't resize
        else { $this->resize = FALSE; }

    }

    // Set image quality (JPEG only)
    public function set_quality($quality)
    {

        if(is_int($quality))
        {

            $this->quality = $quality;

        }

    }

    // Save image
    public function save_img($path)
    {

        // Resize
        if($this->resize)
        {

            $this->img_output = ImageCreateTrueColor($this->x_output, $this->y_output);
            ImageCopyResampled($this->img_output, $this->img_input, 0, 0, 0, 0, $this->x_output, $this->y_output, $this->x_input, $this->y_input);

        }

        // Save JPEG
        if($this->format == "JPG" OR $this->format == "JPEG")
        {

            if($this->resize) { imageJPEG($this->img_output, __DIR__ . "/../uploads/" . $path, $this->quality); }
            else { copy($this->img_src, __DIR__ . "/../uploads/" . $path); }

        }

        // Save PNG
        elseif($this->format == "PNG")
        {

            if($this->resize) { imagePNG($this->img_output, __DIR__ . "/../uploads/" . $path, 9); }
            else { copy($this->img_src, __DIR__ . "/../uploads/" . $path); }

        }

        // Save GIF
        elseif($this->format == "GIF")
        {

            if($this->resize) { imageGIF($this->img_output, __DIR__ . "/../uploads/" . $path); }
            else { copy($this->img_src, __DIR__ . "/../uploads/" . $path); }

        }

    }

    // Get width
    public function get_width()
    {

        return $this->x_input;

    }

    // Get height
    public function get_height()
    {

        return $this->y_input;

    }

    // Clear image cache
    public function clear_cache()
    {

        @ImageDestroy($this->img_input);
        @ImageDestroy($this->img_output);

    }

}

And calling upload

$img = new imaging;
$img->upload($src['tmp_name'], $name, $dir);
$img->set_img($dir . 'orig_' . $name); // upload original file
$img->set_quality(100);

// Small thumbnail
$img->set_size(700);                   // upload thumbnail
$img->save_img($dir . $name);

// Finalize
$img->clear_cache();

Result isn't very good, instead of setting quality=100. Original file (width cca 1100px) is uploaded correctly (no resize on server), when I open it in Photoshop, resize to 700px width and compare with 700px thumb resized in PHP, there is very big difference in quality.

See both images, original resized in Photoshop (top) and resize image via PHP (bottom) - texts, images, etc. are blurred, colors aren't bright.

Orig size
enter image description here



200% zoom in Photoshop
enter image description here


Any ideas? Thanks for your replies :-)


Solution

  • I'm gonna answer here because I don't have enough reputation to make a comment.

    To resize the image, i think it's better to use the command imagescale. It's better that use ImageCreateTrueColor + ImageCopyResampled.

    So I'd do it

            // Resize
            if($this->resize)
            {
                $this->img_output = imagescale($this->img_input, $this->x_output, $this->y_output);
    
            }
    

    But there are some other things that you also may change:

    Also, I've tried to not repeat any code and optimising the resources.

    EDIT: Also you can clear the cache and the end of the process.

    class imaging
    {
    
        // Variables
        private $img_input;
        private $img_output;
        private $img_src;
        private $format;
        private $quality = 100;
        private $x_input;
        private $y_input;
        private $x_output;
        private $y_output;
        private $resize;
    
        // Set image
        public function upload($orig, $name, $path)
        {
            move_uploaded_file($orig, __DIR__ . "/../uploads/" . $path . 'orig_' . $name);
        }
    
            // Set image quality (JPEG only)
        public function set_quality($quality)
        {
    
            if(is_int($quality))
            {
    
                $this->quality = $quality;
    
            }
    
        }
    
        // Set maximum image size (pixels)
        private function resize($size = 100)
        {   
            $resize = FALSE; 
            // Wide
            if($this->x_input >= $this->y_input && $this->x_input > $size)
            {
                $this->x_output = $size;
                $this->y_output = ($this->x_output / $this->x_input) * $this->y_input;
    
                $resize = TRUE;
            }
    
            // Tall
            elseif($this->y_input > $this->x_input && $this->y_input > $size)
            {
                $this->y_output = $size;
                $this->x_output = ($this->y_output / $this->y_input) * $this->x_input;
    
                $resize = TRUE;
            }
    
            if($resize){
    
                switch ($this->format) {
                    case 'JPEG':
                    case 'JPG':
                        $this->img_input = ImageCreateFromJPEG($img);
                        break;
                    case 'PNG':
                        $this->img_input = ImageCreateFromPNG($img);
                        break;
                    case 'GIF':
                        $this->img_input = ImageCreateFromGIF($img);
                        break;
                    
                    default:
                        throw new Exception("This extension " . $ext . " it's not compatible.");
                        
                        break;
                }
    
            }
    
        }
    
        // Save image
        public function save_img($path)
        {
            // We have resized the image
            if($this->img_input){
                switch ($this->format) {
                    case 'JPEG':
                    case 'JPG':
                        imageJPEG($this->img_output, __DIR__ . "/../uploads/" . $path, $this->quality);
                        break;
                    case 'PNG':
                        imagePNG( $this->img_output, __DIR__ . "/../uploads/" . $path, 9);
                        break;
                    case 'GIF':
                        imageGIF( $this->img_output, __DIR__ . "/../uploads/" . $path);
                        break;
                    
                    default:
                        throw new Exception("This extension " . $ext . " it's not compatible.");
                        
                        break;
                }
            }else{
                copy($this->img_src, __DIR__ . "/../uploads/" . $path);
            }
    
        }
    
        public function create_thumbnail($imgSrc, $savePath, $size = 100)
        {
            $this->img_src = '../uploads/' . $img;
    
            if(file_exists($this->img_src)){
                list($this->x_input, $this->y_input) = getimagesize($imageSrc);
                $this->format = strtoupper(pathinfo($img, PATHINFO_EXTENSION));
                $this->resize($size);
                $this->save_img($savePath);
                $this->clear_cache();
            }else{
                throw new Exception("Image not found in " . $imdSrc);
            }
    
        }
    
        // Get width
        public function get_width()
        {
    
            return $this->x_input;
    
        }
    
        // Get height
        public function get_height()
        {
    
            return $this->y_input;
    
        }
    
        // Clear image cache
        public function clear_cache()
        {
    
            @ImageDestroy($this->img_input);
            @ImageDestroy($this->img_output);
    
        }
    
    }