【问题标题】:Scale Image Using PHP and Maintaining Aspect Ratio使用 PHP 缩放图像并保持纵横比
【发布时间】:2010-11-25 07:08:00
【问题描述】:

基本上我想上传一张图片(我已经排序)并将其缩小到某些限制,例如最大宽度和高度,但保持原始图片的纵横比。

我没有在服务器上安装 Imagick - 否则这很容易。

一如既往地感谢任何帮助。 谢谢。

编辑:我不需要整个代码或任何东西,只要朝着正确的方向推进就很棒了。

【问题讨论】:

    标签: php image scale


    【解决方案1】:

    这是我使用 X、Y 或两个轴保存纵横比来缩放图像的功能。

    它还会将图像缩放到其大小的百分比。

    兼容 PHP 5.4

    /** Use X axis to scale image. */
    define('IMAGES_SCALE_AXIS_X', 1);
    /** Use Y axis to scale image. */
    define('IMAGES_SCALE_AXIS_Y', 2);
    /** Use both X and Y axes to calc image scale. */
    define('IMAGES_SCALE_AXIS_BOTH', IMAGES_SCALE_AXIS_X ^ IMAGES_SCALE_AXIS_Y);
    /** Compression rate for JPEG image format. */
    define('JPEG_COMPRESSION_QUALITY', 90);
    /** Compression rate for PNG image format. */
    define('PNG_COMPRESSION_QUALITY', 9);
    
    /**
     * Scales an image with save aspect ration for X, Y or both axes.
     *
     * @param string $sourceFile Absolute path to source image.
     * @param string $destinationFile Absolute path to scaled image.
     * @param int|null $toWidth Maximum `width` of scaled image.
     * @param int|null $toHeight Maximum `height` of scaled image.
     * @param int|null $percent Percent of scale of the source image's size.
     * @param int $scaleAxis Determines how of axis will be used to scale image.
     *
     * May take a value of {@link IMAGES_SCALE_AXIS_X}, {@link IMAGES_SCALE_AXIS_Y} or {@link IMAGES_SCALE_AXIS_BOTH}.
     * @return bool True on success or False on failure.
     */
    function scaleImage($sourceFile, $destinationFile, $toWidth = null, $toHeight = null, $percent = null, $scaleAxis = IMAGES_SCALE_AXIS_BOTH) {
        $toWidth = (int)$toWidth;
        $toHeight = (int)$toHeight;
        $percent = (int)$percent;
        $result = false;
    
        if (($toWidth | $toHeight | $percent)
            && file_exists($sourceFile)
            && (file_exists(dirname($destinationFile)) || mkdir(dirname($destinationFile), 0777, true))) {
    
            $mime = getimagesize($sourceFile);
    
            if (in_array($mime['mime'], ['image/jpg', 'image/jpeg', 'image/pjpeg'])) {
                $src_img = imagecreatefromjpeg($sourceFile);
            } elseif ($mime['mime'] == 'image/png') {
                $src_img = imagecreatefrompng($sourceFile);
            }
    
            $original_width = imagesx($src_img);
            $original_height = imagesy($src_img);
    
            if ($scaleAxis == IMAGES_SCALE_AXIS_BOTH) {
                if (!($toWidth | $percent)) {
                    $scaleAxis = IMAGES_SCALE_AXIS_Y;
                } elseif (!($toHeight | $percent)) {
                    $scaleAxis = IMAGES_SCALE_AXIS_X;
                }
            }
    
            if ($scaleAxis == IMAGES_SCALE_AXIS_X && $toWidth) {
                $scale_ratio = $original_width / $toWidth;
            } elseif ($scaleAxis == IMAGES_SCALE_AXIS_Y && $toHeight) {
                $scale_ratio = $original_height / $toHeight;
            } elseif ($percent) {
                $scale_ratio = 100 / $percent;
            } else {
                $scale_ratio_width = $original_width / $toWidth;
                $scale_ratio_height = $original_height / $toHeight;
    
                if ($original_width / $scale_ratio_width < $toWidth && $original_height / $scale_ratio_height < $toHeight) {
                    $scale_ratio = min($scale_ratio_width, $scale_ratio_height);
                } else {
                    $scale_ratio = max($scale_ratio_width, $scale_ratio_height);
                }
            }
    
            $scale_width = $original_width / $scale_ratio;
            $scale_height = $original_height / $scale_ratio;
    
            $dst_img = imagecreatetruecolor($scale_width, $scale_height);
    
            imagecopyresampled($dst_img, $src_img, 0, 0, 0, 0, $scale_width, $scale_height, $original_width, $original_height);
    
            if (in_array($mime['mime'], ['image/jpg', 'image/jpeg', 'image/pjpeg'])) {
                $result = imagejpeg($dst_img, $destinationFile, JPEG_COMPRESSION_QUALITY);
            } elseif ($mime['mime'] == 'image/png') {
                $result = imagepng($dst_img, $destinationFile, PNG_COMPRESSION_QUALITY);
            }
    
            imagedestroy($dst_img);
            imagedestroy($src_img);
        }
    
        return $result;
    }
    

    测试:

    $sourceFile = '/source/file.jpg'; // Original size: 672x100
    $destinationPath = '/destination/path/';
    
    scaleImage($sourceFile, $destinationPath . 'file_original_size.jpg', 672, 100);
    // Result: Image 672x100
    scaleImage($sourceFile, $destinationPath . 'file_scaled_75_PERCENT.jpg', null, null, 75);
    // Result: Image 504x75
    scaleImage($sourceFile, $destinationPath . 'file_scaled_336_X.jpg', 336, null, null, IMAGES_SCALE_AXIS_X);
    // Result: Image 336x50
    scaleImage($sourceFile, $destinationPath . 'file_scaled_50_Y.jpg', null, 50, null, IMAGES_SCALE_AXIS_Y);
    // Result: Image 336x50
    scaleImage($sourceFile, $destinationPath . 'file_scaled_500x70_BOTH.jpg', 500, 70, null, IMAGES_SCALE_AXIS_BOTH);
    // Result: Image 470x70
    scaleImage($sourceFile, $destinationPath . 'file_scaled_450x70_BOTH.jpg', 450, 70, null, IMAGES_SCALE_AXIS_BOTH);
    // Result: Image 450x66
    scaleImage($sourceFile, $destinationPath . 'file_scaled_500x70_40_PERCENT_BOTH.jpg', 500, 70, 40, IMAGES_SCALE_AXIS_BOTH);
    // Result: Image 268x40
    

    【讨论】:

    【解决方案2】:

    非常适合我

        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);
        }
    

    【讨论】:

      【解决方案3】:

      我正在考虑如何实现这一点,我提出了一个非常好的解决方案,在任何情况下都可以使用...... 假设您想调整用户上传到您网站的重图像的大小,但您需要它来保持比例。所以我想出了这个:

      <?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();
      ?>
      

      在这种情况下,如果宽度大于高度,我希望宽度为 600px,如果高度大于宽度,我希望宽度为 400px

      【讨论】:

        【解决方案4】:

        我找到了完成这项工作的数学方法

        Github 存储库 - https://github.com/gayanSandamal/easy-php-image-resizer

        现场示例 - https://plugins.nayague.com/easy-php-image-resizer/

        <?php
        //path for the image
        $source_url = '2018-04-01-1522613288.PNG';
        
        //separate the file name and the extention
        $source_url_parts = pathinfo($source_url);
        $filename = $source_url_parts['filename'];
        $extension = $source_url_parts['extension'];
        
        //define the quality from 1 to 100
        $quality = 10;
        
        //detect the width and the height of original image
        list($width, $height) = getimagesize($source_url);
        $width;
        $height;
        
        //define any width that you want as the output. mine is 200px.
        $after_width = 200;
        
        //resize only when the original image is larger than expected with.
        //this helps you to avoid from unwanted resizing.
        if ($width > $after_width) {
        
            //get the reduced width
            $reduced_width = ($width - $after_width);
            //now convert the reduced width to a percentage and round it to 2 decimal places
            $reduced_radio = round(($reduced_width / $width) * 100, 2);
        
            //ALL GOOD! let's reduce the same percentage from the height and round it to 2 decimal places
            $reduced_height = round(($height / 100) * $reduced_radio, 2);
            //reduce the calculated height from the original height
            $after_height = $height - $reduced_height;
        
            //Now detect the file extension
            //if the file extension is 'jpg', 'jpeg', 'JPG' or 'JPEG'
            if ($extension == 'jpg' || $extension == 'jpeg' || $extension == 'JPG' || $extension == 'JPEG') {
                //then return the image as a jpeg image for the next step
                $img = imagecreatefromjpeg($source_url);
            } elseif ($extension == 'png' || $extension == 'PNG') {
                //then return the image as a png image for the next step
                $img = imagecreatefrompng($source_url);
            } else {
                //show an error message if the file extension is not available
                echo 'image extension is not supporting';
            }
        
            //HERE YOU GO :)
            //Let's do the resize thing
            //imagescale([returned image], [width of the resized image], [height of the resized image], [quality of the resized image]);
            $imgResized = imagescale($img, $after_width, $after_height, $quality);
        
            //now save the resized image with a suffix called "-resized" and with its extension. 
            imagejpeg($imgResized, $filename . '-resized.'.$extension);
        
            //Finally frees any memory associated with image
            //**NOTE THAT THIS WONT DELETE THE IMAGE
            imagedestroy($img);
            imagedestroy($imgResized);
        }
        ?>
        

        【讨论】:

          【解决方案5】:

          我已经为我完成的另一个项目编写了一段这样的代码。我在下面复制了它,可能需要一些修补! (它确实需要 GD 库)

          这些是它需要的参数:

          $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
          

          它将图像缩小或放大到最大宽度或高度

          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;
          }
          

          【讨论】:

          • 很好 - 非常感谢,这将很有用。我正在与主机交谈以尝试对 Imagick 进行排序...目前遇到一个致命错误,它说它没有找到该类...
          • 如果您使用&lt;?php phpinfo(); ?&gt; 并搜索GD,如果启用,即使没有imagick,上述功能也应该可以工作:),但是,如果您遇到任何错误,请随时让我知道。
          • 不知道为什么这会引起投票,我几年前写的,最近在尝试(再次)解决相同问题时偶然发现它,但它没有保持纵横比!
          • 当源图像不是正方形时,您肯定是指$thumb_h = $old_y*($new_width/$old_x);$thumb_w = $old_x*($new_height/$old_y);,这将始终调整为最大可能的缩略图,$new_height 作为最大高度,$new width 作为最大宽度
          • 它几乎可以工作,但第二部分应该改为 if($old_x
          【解决方案6】:

          我知道您正在寻找可以按比例调整图像大小的除数。检查这个demo

          如何在数学上得到除数

          假设我们的原始图像具有宽度 x 和高度 y; x=300 和 y = 700

          最大高度和最大宽度为200;

          首先,我们将检查图像的哪个维度大于另一个。 我们的高度(y)大于宽度(x)

          其次,我们检查我们的高度是否大于我们的最大高度。 对于我们的例子,我们的高度大于最大高度。在小于最大高度的情况下,我们将新高度设置为原始高度。

          最后,我们寻找我们的除数,如下所示

          if y is set to maximum height 200 and max-y=200;
          y=max-y, that is 
          if y=max-y
          what about 
          x=?
          that is, 
          if 700 is resized to 200
          what about 300?
          700=200
          300=?
          new width = (200 (new height) * 300(width)) / 700 (height)
          so our divisor is
          divisor= new height (300) / height(700) 
          new width = divisor * width or width / (1/divisor)
          

          如果宽度大于高度,反之亦然

          if ($width > $height) {
              if($width < $max_width)
                  $newwidth = $width;
          
              else
          
              $newwidth = $max_width; 
          
          
              $divisor = $width / $newwidth;
              $newheight = floor( $height / $divisor);
          }
          else {
          
               if($height < $max_height)
                   $newheight = $height;
               else
                   $newheight =  $max_height;
          
              $divisor = $height / $newheight;
              $newwidth = floor( $width / $divisor );
          }
          

          查看完整示例并使用working demo 进行尝试。

          【讨论】:

          • 我使用你的代码它可以工作,,,但是由于纵横比,这不提供 100*100 的图像,,这提供 100*50 的图像。如何添加背景颜色等图像的填充(25 up 和 25 btm)?
          【解决方案7】:

          这是一个综合性的应用程序,我努力开发它,包括最常见的操作,如放大和缩小、缩略图、保留纵横比、转换文件类型、更改质量/文件大小等等......

          <?php
          //##// Resize (and convert) image (Scale up & scale down, thumbnail, preserve aspect ratio) //##//
          ///////////////////////////////////////////////
          ///////////////// Begin.Setup /////////////////
          // Source File:
          $src_file = "/your/server/path/to/file.png";// png or jpg files only
          
          // Resize Dimensions:
          // leave blank for no size change (convert only)
          // if you specify one dimension, the other dimension will be calculated according to the aspect ratio
          // if you specify both dimensions system will take care of it depending on the actual image size 
          // $newWidth = 2000;
          // $newHeight = 1500;
          
          // Destination Path: (optional, if none: download image)
          $dst_path = "/your/server/path/new/";
          
          // Destination File Name: (Leave blank for same file name)
          // $dst_name = 'image_name_only_no_extension';
          
          // Destination File Type: (Leave blank for same file extension)
          // $dst_type = 'png';
          $dst_type = 'jpg';
          
          // Reduce to 8bit - 256 colors (Very low quality but very small file & transparent PNG. Only for thumbnails!)
          // $palette_8bit = true;
          
          ///////////////// End.Setup /////////////////
          ///////////////////////////////////////////////
          if (!$dst_name){$dst_name = strtolower(pathinfo($src_file, PATHINFO_FILENAME));}
          if (!$dst_type){$dst_type = strtolower(pathinfo($src_file, PATHINFO_EXTENSION));}
          if ($palette_8bit){$dst_type = 'png';}
          if ($dst_path){$dst_file = $dst_path . $dst_name . '.' . $dst_type;}
          
          $mime = getimagesize($src_file);// Get image dimensions and type
          
          // Destination File Parameters:
          if ($dst_type == 'png'){
              $dst_content = 'image/png';
              $quality = 9;// All same quality! 0 too big file // 0(no comp.)-9 (php default: 6)
          } elseif ($dst_type == 'jpg'){
              $dst_content = 'image/jpg';
              $quality = 85;// 30 Min. 60 Mid. 85 Cool. 90 Max. (100 Full) // 0-100 (php default: 75)
          } else {
              exit('Unknown Destination File Type');
          }
          
          // Source File Parameters:
          if ($mime['mime']=='image/png'){$src_img = imagecreatefrompng($src_file);}
          elseif ($mime['mime']=='image/jpg'){$src_img = imagecreatefromjpeg($src_file);}
          elseif ($mime['mime']=='image/jpeg'){$src_img = imagecreatefromjpeg($src_file);}
          elseif ($mime['mime']=='image/pjpeg'){$src_img = imagecreatefromjpeg($src_file);}
          else {exit('Unknown Source File Type');}
          
          // Define Dimensions:
          $old_x = imageSX($src_img);
          $old_y = imageSY($src_img);
          
          if ($newWidth AND $newHeight){
              if($old_x > $old_y){
                  $new_x    =   $newWidth;
                  $new_y    =   $old_y / $old_x * $newWidth;
              } elseif($old_x < $old_y){
                  $new_y    =   $newHeight;
                  $new_x    =   $old_x / $old_y * $newHeight;
              } elseif($old_x == $old_y){
                  $new_x    =   $newWidth;
                  $new_y    =   $newHeight;
              }
          } elseif ($newWidth){
              $new_x    =   $newWidth;
              $new_y    =   $old_y / $old_x * $newWidth;
          } elseif ($newHeight){
              $new_y    =   $newHeight;
              $new_x    =   $old_x / $old_y * $newHeight;
          } else {
              $new_x    =   $old_x;
              $new_y    =   $old_y;
          }
          
          $dst_img = ImageCreateTrueColor($new_x, $new_y);
          
          if ($palette_8bit){//////// Reduce to 8bit - 256 colors ////////
              $transparent = imagecolorallocatealpha($dst_img, 255, 255, 255, 127); 
              imagecolortransparent($dst_img, $transparent);
              imagefill($dst_img, 0, 0, $transparent);
              imagecopyresampled($dst_img,$src_img,0,0,0,0,$new_x,$new_y,$old_x,$old_y);// Great quality resize.
              imagetruecolortopalette($dst_img, false, 255);
              imagesavealpha($dst_img, true);
          } else {
              // Check image and set transparent for png or white background for jpg
              if ($dst_type == 'png'){
                  imagealphablending($dst_img, false);
                  imagesavealpha($dst_img, true);
                  $transparent = imagecolorallocatealpha($dst_img, 255, 255, 255, 127);
                  imagefilledrectangle($dst_img, 0, 0, $new_x, $new_y, $transparent);
              } elseif ($dst_type == 'jpg'){
                  $white = imagecolorallocate($dst_img, 255, 255, 255);
                  imagefilledrectangle($dst_img, 0, 0, $new_x, $new_y, $white);
              }
          
              imagecopyresampled($dst_img,$src_img,0,0,0,0,$new_x,$new_y,$old_x,$old_y);// Great quality resize.
          }
          
          // Skip the save to parameter using NULL, then set the quality; imagejpeg($dst_img);=> Default quality
          if ($dst_file){
              if ($dst_type == 'png'){
                  imagepng($dst_img, $dst_file, $quality);
              } elseif ($dst_type == 'jpg'){
                  imagejpeg($dst_img, $dst_file, $quality);
              }
          } else {
              header('Content-Disposition: Attachment;filename=' . $dst_name . '.' . $dst_type);// comment this line to show image in browser instead of download
              header('Content-type: ' . $dst_content);
              if ($dst_type == 'png'){
                  imagepng($dst_img, NULL, $quality);
              } elseif ($dst_type == 'jpg'){
                  imagejpeg($dst_img, NULL, $quality);
              }
          }
          imagedestroy($src_img);
          imagedestroy($dst_img);
          //##// END : Resize image (Scale Up & Down) (thumbnail, bigger image, preserve aspect ratio) END //##//
          

          【讨论】:

          • 这是一个非常高级的脚本,我努力涵盖最多并完善它。我注意到一个downvote,你真的尝试过吗?让我知道它是否有问题......
          • 几年后,我用你的公式来保持纵横比和它的工作,赞成。关于整个 sn-p,我看不出有人投反对票的原因。谢谢。
          【解决方案8】:
          <?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);
              }
          }
          ?>
          

          我也一直在使用公认的答案,但在某些情况下它并没有保持这个比例。我在论坛上找到了一些很好的答案并将它们放在一起,最后创建了一个调整图像大小的类。作为额外功能,您可以添加水印文本。

          你可以看到选择是否裁剪时会发生什么,如果没有,透明区域将添加到新调整大小的图像中。

          这个例子比问的多,但我认为这是一个很好的例子。

          【讨论】:

          • 这似乎是一个很好的功能并且可以按预期工作,但是如果我想总是裁剪怎么办..例如我的目标图像是 500 400 那么://W400 H300 = stretchW |拉伸H //W400 H500 = 首先拉伸W+H 然后裁剪H //W500 H300 = 首先拉伸W+H 然后裁剪W //W500 H500 = cropW |作物H
          • 我没有清楚地理解您的意思,但是该功能有效。你可以选择裁剪或不裁剪。当您在页面上使用该功能时,将默认值设置为“true”。如果您可以通过一些更改使其更好地工作,欢迎您。顺便说一句,我不是 php/web master,只是一个业余爱好者。
          【解决方案9】:

          实际上被接受的解决方案不是正确的解决方案。原因很简单:会出现源图像和目标图像的比例不同的情况。任何计算都应反映这种差异。

          请注意 PHP.net 网站上给出的示例中的相关行:

          $ratio_orig = $width_orig/$height_orig;
          
          if ($width/$height > $ratio_orig) {
             $width = $height*$ratio_orig;
          } else {
             $height = $width/$ratio_orig;
          }
          

          完整的例子可以在这里找到: http://php.net/manual/en/function.imagecopyresampled.php

          在 stackoverflow 上还有其他答案(带有示例),用于解决相同问题的类似问题(以不同方式表述的相同问题)。

          例子:

          假设我们有一个 1630 x 2400 像素的图像,我们希望自动调整其大小,同时保持纵横比为 160 x 240。让我们用公认的解决方案做一些数学运算:

          if($old_x < $old_y) 
              {
                  $thumb_w    =   $old_x*($new_width/$old_y);
                  $thumb_h    =   $new_height;
              }
          

          身高 = 240 宽度 = 1630 * ( 160/2400 ) = 1630 * 0.0666666666666667 = 108.6666666666667 108.6 x 240 这不是正确的解决方案。

          提出的下一个解决方案如下:

          if($old_x < $old_y)
              {
                  $thumb_w    =   $old_x/$old_y*$newHeight;
                  $thumb_h    =   $newHeight;
              }
          

          高度 = 240; 宽度 = 1630 / 2400 * 240 = 163 它更好(因为它保持纵横比),但它超过了可接受的最大宽度。

          都失败了。

          我们根据 PHP.net 提出的解决方案进行数学计算: 宽度 = 160 高度 = 160/(1630 / 2400) = 160/0.6791666666666667 = 235.5828220858896(else 子句)。 160 x 236(四舍五入)是正确答案。

          【讨论】:

            【解决方案10】:

            公式在保持纵横比方面是错误的。 应该是:原始高度/原始宽度x新宽度=新高度

            function createThumbnail($imageName,$newWidth,$newHeight,$uploadDir,$moveToDir)
            {
                $path = $uploadDir . '/' . $imageName;
            
                $mime = getimagesize($path);
            
                if($mime['mime']=='image/png'){ $src_img = imagecreatefrompng($path); }
                if($mime['mime']=='image/jpg'){ $src_img = imagecreatefromjpeg($path); }
                if($mime['mime']=='image/jpeg'){ $src_img = imagecreatefromjpeg($path); }
                if($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    =   $newWidth;
                    $thumb_h    =   $old_y/$old_x*$newWidth;
                }
            
                if($old_x < $old_y)
                {
                    $thumb_w    =   $old_x/$old_y*$newHeight;
                    $thumb_h    =   $newHeight;
                }
            
                if($old_x == $old_y)
                {
                    $thumb_w    =   $newWidth;
                    $thumb_h    =   $newHeight;
                }
            
                $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 . $imageName;
            
                if($mime['mime']=='image/png'){ $result = imagepng($dst_img,$new_thumb_loc,8); }
                if($mime['mime']=='image/jpg'){ $result = imagejpeg($dst_img,$new_thumb_loc,80); }
                if($mime['mime']=='image/jpeg'){ $result = imagejpeg($dst_img,$new_thumb_loc,80); }
                if($mime['mime']=='image/pjpeg'){ $result = imagejpeg($dst_img,$new_thumb_loc,80); }
            
                imagedestroy($dst_img);
                imagedestroy($src_img);
                return $result;
            }
            

            【讨论】:

            • 只是,它不保持纵横比。如果我想将 300x300 的图像调整为 500x200,它将创建一个 500x200。
            猜你喜欢
            • 1970-01-01
            • 2015-07-31
            • 2013-03-04
            • 2011-08-24
            • 2014-06-02
            • 2014-01-04
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多