【问题标题】:How to resize image keeping constraints php如何调整图像保持约束php
【发布时间】:2016-05-28 07:39:43
【问题描述】:

我制作了两个 GIF 来解释我想要做什么。灰色边框是我追求的尺寸(700 * 525)。他们在这个问题的底部。

我希望所有大于给定宽度和高度的图像都缩小到边界(从中心),然后裁剪掉边缘。这是我整理的一些代码来尝试这样做:

if ($heightofimage => 700 && $widthofimage => 525){
    if ($heightofimage > $widthofimage){
    
        $widthofimage = 525;
        $heightofimage = //scaled height.
        
        //crop height to 700.
    
    }
    
    if ($heightofimage < $widthofimage){
    
        $widthofimage = //scaled width.
        $heightofimage = 700;
        
        //crop width to 525.
    
    }
}else{
    echo "image too small";
}

这里有一些 GIF 可以直观地解释我想要实现的目标:

GIF 1:这里的图片比例在x方向上太多了

GIF 2:这里的图片比例在y方向上太大了


@timclutton 的图像质量比较

所以我使用了PHP (click here to do your own test with the php)的方法,然后将其与原始照片进行比较,您可以看到有很大的不同!:

你的PHP 方法:


(来源:tragicclothing.co.uk

实际文件:


(来源:mujjo.com


【问题讨论】:

标签: php html image


【解决方案1】:

我使用http://phpthumb.sourceforge.net 获得了一个漂亮的解决方案,还带有透明的弯曲边缘。

这是解决方案的另一种途径,可能只需少量配置即可满足某人的需求。

【讨论】:

    【解决方案2】:

    我已经使用 GD 库来完成调整大小。基本上我所做的是,我计算了图像尺寸,然后将图像尺寸调整为距离中心 700x525 的尺寸。

    <?php
    /*
     * PHP GD
     * resize an image using GD library
     */
    
    //the image has 700X525 px ie 4:3 ratio
    $src = 'demo_files/bobo.jpg';
    
    // Get new sizes
    list($width, $height) = getimagesize($src);
    
    $x = 0;
    $y = 0;
    if($width < $height){
        $newwidth = $width;
        $newheight = 3/4 * $width;
        $x = 0;
        $y = $height/2 - $newheight/2;
    }else{
        $newheight = $height;
        $newwidth = 4/3 * $height;
        $x=$width/2 - $newwidth/2;
        $y=0;
    
    }
    
    $targ_w = 700; //width of the image to be resized to
    $targ_h = 525; ////height of the image to be resized to
    $jpeg_quality = 90;
    
    $img_r = imagecreatefromjpeg($src);
    $dst_r = ImageCreateTrueColor( $targ_w, $targ_h );
    
    imagecopyresampled($dst_r,$img_r,0,0,$x,$y,$targ_w,$targ_h,$newwidth,$newheight);
    
    header('Content-type: image/jpeg');
    imagejpeg($dst_r,null,$jpeg_quality);
    
    exit;
    
    ?>
    

    【讨论】:

      【解决方案3】:

      使用Imagick

      define('PHOTO_WIDTH_THUMB', 700);
      define('PHOTO_HEIGHT_THUMB', 525);
      
      $image = new Imagick();
      $image->readImage($file_source);
      $width = $image->getImageWidth();
      $height = $image->getImageHeight();
      
      if($width > $height){
        $image->thumbnailImage(0, PHOTO_HEIGHT_THUMB);
      }else{
        $image->thumbnailImage(PHOTO_WIDTH_THUMB, 0);
      }
      
      $thumb_width = $image->getImageWidth();
      $thumb_height = $image->getImageHeight();
      $x = ($thumb_width - PHOTO_WIDTH_THUMB)/2;
      $y = ($thumb_height - PHOTO_HEIGHT_THUMB)/2;
      $image->cropImage(PHOTO_THUMB_WIDTH, PHOTO_THUMB_HEIGHT, $x, $y);
      $image->writeImage($thumb_destination);
      
      $image->clear();
      $image->destroy();
      unlink($file_source);
      

      【讨论】:

      • 我建议你删除最后一行 (unlink($file_source);),以免有人在没有仔细阅读的情况下使用它,最终丢失他们可能想要保留的文件。
      【解决方案4】:

      下面的代码应该做你想做的事。我没有对它进行广泛的测试,但它似乎适用于我制作的少数测试图像。脑海里有一个琐碎的疑问,我的数学在某个地方是错误的,但已经很晚了,我看不到任何明显的东西。

      编辑:很麻烦,我再次检查并发现了错误,即裁剪不在图像中间。代码替换为工作版本。

      简而言之:将此作为起点,而不是生产就绪代码!

      <?php
      
      // set image size constraints.
      $target_w = 525;
      $target_h = 700;
      
      // get image.
      $in = imagecreatefrompng('<path to your>.png');
      
      // get image dimensions.
      $w = imagesx($in);
      $h = imagesy($in);
      
      if ($w >= $target_w && $h >= $target_h) {
          // get scales.
          $x_scale = ($w / $target_w);
          $y_scale = ($h / $target_h);
      
          // create new image.
          $out = imagecreatetruecolor($target_w, $target_h);
      
          $new_w = $target_w;
          $new_h = $target_h;
          $src_x = 0;
          $src_y = 0;
      
          // compare scales to ensure we crop whichever is smaller: top/bottom or
          // left/right.
          if ($x_scale > $y_scale) {
              $new_w = $w / $y_scale;
      
              // see description of $src_y, below.
              $src_x = (($new_w - $target_w) / 2) * $y_scale;
          } else {
              $new_h = $h / $x_scale;
      
              // a bit tricky. crop is done by specifying coordinates to copy from in
              // source image. so calculate how much to remove from new image and
              // then scale that up to original. result is out by ~1px but good enough.
              $src_y = (($new_h - $target_h) / 2) * $x_scale;
          }
      
          // given the right inputs, this takes care of crop and resize and gives
          // back the new image. note that imagecopyresized() is possibly quicker, but
          // imagecopyresampled() gives better quality.
          imagecopyresampled($out, $in, 0, 0, $src_x, $src_y, $new_w, $new_h, $w, $h);
      
          // output to browser.
          header('Content-Type: image/png');
          imagepng($out);
          exit;
      
      } else {
          echo 'image too small';
      }
      
      ?>
      

      【讨论】:

      • 这对我有用,但如果图像不是 png,您可以使用:$ext = strtolower(substr(strrchr($file_name,'.'), 1));if($ext = = 'png')$in = imagecreatefrompng($source);否则 $in = imagecreatefromjpeg($source); if($ext == 'png') imagepng($out);否则 imagejpeg($out);
      • 这种方法大大降低了图像的质量!请参考我的问题中的更新...
      • 也许这只是我的老眼睛,但我看不出您发布的两张图片之间有很大差异(对于大多数互联网用户/设备来说,这当然不足以担心)。结果当然会有所不同,因为 PS 和 GD 使用不同的方法来执行此操作。如果质量是您最重要的目标,请使用 PS 方法。
      • @timclutton 请查看更新是否有其他方法可以创建更好质量的图像?谢谢
      • imagepng() 有一个压缩设置作为第三个参数,从 0(无)到 9。默认值(在我的代码中使用)是 6。您可以尝试更改它。另一种选择是尝试使用ImageMagick 而不是GD。但是您正在裁剪和调整源图像的大小; 会有质量损失。生成图像的用例是什么?同样,结果对我来说看起来很好,可以显示在网页上。如果质量是您最关心的问题,请不要裁剪和调整大小。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-11-29
      • 1970-01-01
      • 2020-05-12
      • 1970-01-01
      • 1970-01-01
      • 2019-08-15
      相关资源
      最近更新 更多