Scale Image Using PHP and Maintaining Aspect Ratio

前端 未结 10 1911
孤独总比滥情好
孤独总比滥情好 2020-11-30 07:38

Basically I want to upload an image (which i\'ve sorted) and scale it down to certain constraints such as max width and height but maintain the aspect ratio of the original

相关标签:
10条回答
  • 2020-11-30 08:26

    I was thinking about how to achieve this and i came with a pretty nice solution that works in any case... Lets say you want to resize heavy images that users upload to your site but you need it to maintain the ratio. So i came up with this :

    <?php
    // File 
    $filename = 'test.jpg';
    
    
    
    // Get sizes
    list($width, $height) = getimagesize($filename);
    //obtain ratio
    $imageratio = $width/$height;
    
    if($imageratio >= 1){
        $newwidth = 600;
        $newheight = 600 / $imageratio; 
    }
    else{
         $newidth = 400;
         $newheight = 400 / $imageratio;
    };
    
    
    
    
    // Load
    $thumb = imagecreatetruecolor($newwidth, $newheight);
    $source = imagecreatefromjpeg($filename);
    
    // Resize
    imagecopyresized($thumb, $source, 0, 0, 0, 0, $newwidth, $newheight, $width, 
    $height);
    
    // Output
    imagejpeg($thumb, "img/test.jpg");
    imagedestroy();
    ?>
    

    In this case if width is bigger than height, i wanted the width to be 600px and if the height was bigger than the width, i wanted the width to be 400px

    0 讨论(0)
  • 2020-11-30 08:27

    I had written a peice of code like this for another project I've done. I've copied it below, might need a bit of tinkering! (It does required the GD library)

    These are the parameters it needs:

    $image_name - Name of the image which is uploaded
    $new_width - Width of the resized photo (maximum)
    $new_height - Height of the resized photo (maximum)
    $uploadDir - Directory of the original image
    $moveToDir - Directory to save the resized image
    

    It will scale down or up an image to the maximum width or height

    function createThumbnail($image_name,$new_width,$new_height,$uploadDir,$moveToDir)
    {
        $path = $uploadDir . '/' . $image_name;
    
        $mime = getimagesize($path);
    
        if($mime['mime']=='image/png') { 
            $src_img = imagecreatefrompng($path);
        }
        if($mime['mime']=='image/jpg' || $mime['mime']=='image/jpeg' || $mime['mime']=='image/pjpeg') {
            $src_img = imagecreatefromjpeg($path);
        }   
    
        $old_x          =   imageSX($src_img);
        $old_y          =   imageSY($src_img);
    
        if($old_x > $old_y) 
        {
            $thumb_w    =   $new_width;
            $thumb_h    =   $old_y*($new_height/$old_x);
        }
    
        if($old_x < $old_y) 
        {
            $thumb_w    =   $old_x*($new_width/$old_y);
            $thumb_h    =   $new_height;
        }
    
        if($old_x == $old_y) 
        {
            $thumb_w    =   $new_width;
            $thumb_h    =   $new_height;
        }
    
        $dst_img        =   ImageCreateTrueColor($thumb_w,$thumb_h);
    
        imagecopyresampled($dst_img,$src_img,0,0,0,0,$thumb_w,$thumb_h,$old_x,$old_y); 
    
    
        // New save location
        $new_thumb_loc = $moveToDir . $image_name;
    
        if($mime['mime']=='image/png') {
            $result = imagepng($dst_img,$new_thumb_loc,8);
        }
        if($mime['mime']=='image/jpg' || $mime['mime']=='image/jpeg' || $mime['mime']=='image/pjpeg') {
            $result = imagejpeg($dst_img,$new_thumb_loc,80);
        }
    
        imagedestroy($dst_img); 
        imagedestroy($src_img);
    
        return $result;
    }
    
    0 讨论(0)
  • 2020-11-30 08:28
    <?php
    Class ResizedImage
    {
        public $imgfile;
        public $string      = '';
        public $new_width   = 0;
        public $new_height  = 0;
        public $angle       = 0;
        public $max_font_size = 1000;
        public $cropped = false;//whether crop the original image if h or w > new h or w
        public $font = 'fonts/arialbd.ttf';
    
        private $img;
        private $trans_colour;
        private $orange;
        private $white; 
        private $whitetr;
        private $blacktr;
    
        public function PrintAsBase64()
        {
            $this->SetImage();
            ob_start();
            imagepng($this->img);
            $b64img = ob_get_contents();
            ob_clean();
            imagedestroy($this->img);
            $b64img = base64_encode($b64img);
            echo($b64img);
        }
        public function PrintAsImage()
        {
            $this->SetImage();
    
            header('Content-type: image/png');
    
            imagepng($this->img);
            imagedestroy($this->img);
        }
    
        private function SetImage()
        {
            if ($this->imgfile == '') {$this->imgfile='NoImageAvailable.jpg';}
            $this->img          = imagecreatefromstring(file_get_contents($this->imgfile));
            $this->trans_colour = imagecolorallocatealpha($this->img, 0, 0, 0, 127);
            $this->orange       = imagecolorallocate($this->img, 220, 210, 60);
            $this->white        = imagecolorallocate($this->img, 255,255, 255);
            $this->whitetr      = imagecolorallocatealpha($this->img, 255,255, 255, 95);
            $this->blacktr      = imagecolorallocatealpha($this->img, 0, 0, 0, 95);
    
            if ((!$this->cropped) && ($this->string !=''))
            {$this->watermarkimage();}
    
            if (($this->new_height > 0) && ($this->new_width > 0)) {$this->ResizeImage();};
    
            if (($this->cropped) && ($this->string !=''))
            {$this->watermarkimage();}
    
            imageAlphaBlending($this->img, true);
            imageSaveAlpha($this->img, true);
        }
        ////
        private function ResizeImage()
        {
            # v_fact and h_fact are the factor by which the original vertical / horizontal
            # image sizes should be multiplied to get the image to your target size.
            $v_fact = $this->new_height / imagesy($this->img);//target_height / im_height; 
            $h_fact = $this->new_width / imagesx($this->img);//target_width / im_width;
            # you want to resize the image by the same factor in both vertical 
            # and horizontal direction, so you need to pick the correct factor from
            # v_fact / h_fact so that the largest (relative to target) of the new height/width
            # equals the target height/width and the smallest is lower than the target.
            # this is the lowest of the two factors
            if($this->cropped) 
            {   $im_fact = max($v_fact, $h_fact);   }
            else
            {   $im_fact = min($v_fact, $h_fact);   }
    
            $new_height = round(imagesy($this->img) * $im_fact);
            $new_width  = round(imagesx($this->img) * $im_fact);
    
            $img2 = $this->img;     
            $this->img = imagecreatetruecolor($new_width, $new_height);     
            imagecopyresampled($this->img, $img2, 0, 0, 0, 0, $new_width, $new_height, imagesx($img2), imagesy($img2));
    
            $img2 = $this->img;     
            $this->img = imagecreatetruecolor($this->new_width, $this->new_height);
            imagefill($this->img, 0, 0, $this->trans_colour);
    
            $dstx = 0;
            $dsty = 0;
            if ($this->cropped)
            {
                if (imagesx($this->img) < imagesx($img2))
                {   $dstx = round((imagesx($this->img)-imagesx($img2))/2); }
    
                if (imagesy($this->img) < imagesy($img2))
                {   $dsty = round((imagesy($this->img)-imagesy($img2))/2); }
            }
            else
            {
                if (imagesx($this->img) > imagesx($img2))
                {   $dstx = round((imagesx($this->img)-imagesx($img2))/2); }
    
                if (imagesy($this->img) > imagesy($img2))
                {   $dsty = round((imagesy($this->img)-imagesy($img2))/2); }
            }
    
            imagecopy ( $this->img, $img2, $dstx, $dsty, 0, 0, imagesx($img2) , imagesy($img2));
            imagedestroy($img2);        
        }   
    
        ////
    
        private function calculateTextBox($text,$fontFile,$fontSize,$fontAngle) 
        { 
            /************ 
            simple function that calculates the *exact* bounding box (single pixel precision). 
            The function returns an associative array with these keys: 
            left, top:  coordinates you will pass to imagettftext 
            width, height: dimension of the image you have to create 
            *************/ 
            $rect = imagettfbbox($fontSize,$fontAngle,$fontFile,$text); 
            $minX = min(array($rect[0],$rect[2],$rect[4],$rect[6])); 
            $maxX = max(array($rect[0],$rect[2],$rect[4],$rect[6])); 
            $minY = min(array($rect[1],$rect[3],$rect[5],$rect[7])); 
            $maxY = max(array($rect[1],$rect[3],$rect[5],$rect[7])); 
    
            return array( 
            "left"   => abs($minX) - 1, 
            "top"    => abs($minY) - 1, 
            "width"  => $maxX - $minX, 
            "height" => $maxY - $minY,
            "box"    => $rect ); 
        }
    
        private function watermarkimage($font_size=0)
        {
            if ($this->string == '')
            {die('Watermark function call width empty string!');}
    
            $box = $this->calculateTextBox($this->string, $this->font, $font_size, $this->angle);
            while ( ($box['width'] < imagesx($this->img)) && ($box['height'] < imagesy($this->img)) && ($font_size <= $this->max_font_size) )
            {
                $font_size++;
                $box = $this->calculateTextBox($this->string, $this->font, $font_size, $this->angle);   
            }
    
            $font_size--;
            $box = $this->calculateTextBox($this->string, $this->font, $font_size, $this->angle);
    
            $vcenter = round((imagesy($this->img) / 2) + ($box['height'] / 2));  
            $hcenter = round((imagesx($this->img) - $box['width']) / 2 );
    
            imagettftext($this->img, $font_size, $this->angle, $hcenter, $vcenter, $this->blacktr, $this->font, $this->string);     
            imagettftext($this->img, $font_size, $this->angle, $hcenter+1, $vcenter-2, $this->whitetr, $this->font, $this->string);
        }
    }
    ?>
    

    Also I have been using the accepted answer but it does not keep the ratio in some cases. I have found some good answers on the forum and have put them in together and finally created a Class which resizes an image. As extra function u can put a watermark text.

    u can see what happens when choose to crop or not, if not a transparent area will be added to the new resized image.

    This example is more than asked, but I think it is a good example.

    0 讨论(0)
  • 2020-11-30 08:29

    works perfecly for me

        static function getThumpnail($file){
    
        $THUMBNAIL_IMAGE_MAX_WIDTH  = 150; # exmpl.
        $THUMBNAIL_IMAGE_MAX_HEIGHT = 150;
    
        $src_size = filesize($file);
        $filename = basename($file);
    
        list($src_width, $src_height, $src_type) = getimagesize($file);
        $src_im = false;
        switch ($src_type) {
            case IMAGETYPE_GIF  : $src_im = imageCreateFromGif($file);  break;
            case IMAGETYPE_JPEG : $src_im = imageCreateFromJpeg($file); break;
            case IMAGETYPE_PNG  : $src_im = imageCreateFromPng($file);  break;
            case IMAGETYPE_WBMP  : $src_im = imagecreatefromwbmp($file);  break;
        }   
        if ($src_im === false) { return false; }
    
        $src_aspect_ratio = $src_width / $src_height;
        $thu_aspect_ratio = $THUMBNAIL_IMAGE_MAX_WIDTH / $THUMBNAIL_IMAGE_MAX_HEIGHT;
    
        if ($src_width <= $THUMBNAIL_IMAGE_MAX_WIDTH && $src_height <= $THUMBNAIL_IMAGE_MAX_HEIGHT) {
            $thu_width  = $src_width;
            $thu_height = $src_height;
        } elseif ($thu_aspect_ratio > $src_aspect_ratio) {
            $thu_width  = (int) ($THUMBNAIL_IMAGE_MAX_HEIGHT * $src_aspect_ratio);
            $thu_height = $THUMBNAIL_IMAGE_MAX_HEIGHT;
        } else {
            $thu_width = $THUMBNAIL_IMAGE_MAX_WIDTH;
            $thu_height = (int) ($THUMBNAIL_IMAGE_MAX_WIDTH / $src_aspect_ratio);
        }
    
        $thu_im = imagecreatetruecolor($thu_width, $thu_height);
        imagecopyresampled($thu_im, $src_im, 0, 0, 0, 0, $thu_width, $thu_height, $src_width, $src_height);
    
        $dst_im    = imagecreatetruecolor($THUMBNAIL_IMAGE_MAX_WIDTH,$THUMBNAIL_IMAGE_MAX_WIDTH);
        $backcolor = imagecolorallocate($dst_im,192,192,192);
        imagefill($dst_im,0,0,$backcolor);
        imagecopy($dst_im, $thu_im, (imagesx($dst_im)/2)-(imagesx($thu_im)/2), (imagesy($dst_im)/2)-(imagesy($thu_im)/2), 0, 0, imagesx($thu_im), imagesy($thu_im));
        imagedestroy($src_im);
        imagedestroy($thu_im);
        }
    
    0 讨论(0)
提交回复
热议问题