【问题标题】:Resize/crop/pad a picture to a fixed size将图片调整大小/裁剪/填充到固定大小
【发布时间】:2010-10-19 07:50:23
【问题描述】:

我需要将图片调整为固定大小。但它必须保持宽度和高度之间的因素。

假设我想将图片大小从238 (w) X 182 (h) 调整为210 / 150

我现在要做的是:

Original width / target width = 1.333333
Original Height / target Height = 1.213333

现在我取最小的因素。

自从238 / 1.333333 = 210 以来,我的宽度总是正确的。 但是高度还是160

如何在不破坏图片的情况下将高度降至160

我需要裁剪吗?如果有怎么办?

【问题讨论】:

    标签: php resize crop


    【解决方案1】:

    你有Imagick吗?如果是这样,您可以使用它加载图像并执行thumbnailimage()

    之类的操作

    您可以在此处跳过任何一个参数(高度或宽度),它会正确调整大小。

    【讨论】:

    • 好吧,我更喜欢使用 gd,因为这就是我用于所有事情的方法。不知道我有没有 imagemagick
    • 这是 imagick php 中的一个示例:arturito.net/2011/01/08/…
    【解决方案2】:

    也许看看PHPThumb(它适用于 GD 和 ImageMagick)

    【讨论】:

      【解决方案3】:

      您必须从顶部和底部裁剪 5 px 才能达到您的目标尺寸,但这可能会破坏图片。

      确实你应该有一个目标宽度或高度,然后以相同的比例调整其他尺寸。

      【讨论】:

      • 是的,但是高度或宽度可能不符合其要求的值
      • 当您无法完全控制图像的来源时,使用特定的图像尺寸并不是一个好主意。您只能缩放它们以适应。
      【解决方案4】:

      这不会裁剪图片,但会在必要时在新图像周围留出空间,我认为在创建缩略图时这是一种更好的方法(比裁剪)。

      $w = 210;
      $h = 150;
      
      $orig_w = imagesx($original);
      $orig_h = imagesy($original);
      
      $w_ratio = $orig_w / $w;
      $h_ratio = $orig_h / $h;
      
      $ratio = $w_ratio > $h_ratio ? $w_ratio : $h_ratio;
      
      $dst_w = $orig_w / $ratio;
      $dst_h = $orig_h / $ratio;
      $dst_x = ($w - $dst_w) / 2;
      $dst_y = ($h - $dst_h) / 2;
      
      $thumbnail = imagecreatetruecolor($w, $h);
      
      imagecopyresampled($thumbnail, $original, $dst_x, $dst_y,
                         0, 0, $dst_w, $dst_h, $orig_w, $orig_h);
      

      【讨论】:

      • 你测试过吗,因为在我的例子中,高度仍然是 160 像素,而不是应该的 150
      • 高度为150,宽度为196。所以左右有7px的边距。
      • 身高 196?应该是 150!
      【解决方案5】:

      我宁愿调整大小以使图像包含在您的限制范围内,然后填写空白部分。因此,在上面的示例中,您将调整大小以使高度正常,然后用背景颜色向左右填充(我认为两端各 7 个像素)。

      【讨论】:

        【解决方案6】:

        在 PHP 源网页中调整图像大小可能会出现问题。较大的图像(磁盘上接近 2+MB)可能非常大,以至于它们需要超过 32MB 的内存来处理。

        出于这个原因,我倾向于使用基于 CLI 的脚本(最多可使用 128MB 内存)或标准命令行(它也可以根据需要使用)。

        # where to put the original file/image. It gets resized back 
        # it was originally found (current directory)
        SAFE=/home/website/PHOTOS/originals
        # no more than 640x640 when finished, and always proportional
        MAXSIZE=640
        # the larger image is in /home/website/PHOTOS/, moved to .../originals
        # and the resized image back to the parent dir.
        cd $SAFE/.. && mv "$1" "$SAFE/$1" && \
           convert "$SAFE/$1" -resize $MAXSIZE\x$MAXSIZE\> "$1"
        

        'convert' 是 ImageMagick 命令行工具的一部分。

        【讨论】:

          【解决方案7】:

          这些是缩略图吗?如果是这样,种植就不是一个大问题。我们一直这样做。我什至不回避将任意比例裁剪成残缺的二次缩略图,完全弄乱图像(是的,我是那个铁杆),如果它看起来不错的话。这是设计师对技术问题的回答,但仍然如此。不要害怕庄稼!

          【讨论】:

            【解决方案8】:

            我觉得有点混乱.. 如果只想调整大小,保持原来的比例,正确的操作是:

            $ratio = $originalWidth / $originalHeight;
            if(//you start from the width, and want to find the height){
             $newWidth = $x;
             $newHeight = $x / $ratio;
            }else if(//you start from the height, and want to find the width){
             $newHeight = $x;
             $newWidth = $x * $ratio;
            }
            

            否则,如果前缀 newWidth 和 newHeight 不能改变,并且拇指比例与原始比例不同,唯一的方法是对拇指进行裁剪或添加边框。

            如果你选择了这种方式,这个功能可以帮助你(我几年前在 5 分钟内写过,可能需要一些改进.. 它只适用于 jpg,例如;):

                function thumb_cut($nomeimage, $source_path, $destination_path, $new_width, $new_height){
                  list($width, $height, $type, $attr) = getimagesize($source_path.$nomeimage);
                  if($type == 2){
                    if($width > $new_width){
                      $new_width = $width;
                      $new_height = $height;
                    }
                    $compression = 100;
                    $destimg = imagecreatetruecolor($new_width,$new_height) or die("Problems creating the image");
                    $srcimg = ImageCreateFromJPEG($source_path.$nomeimage) or die("problem opening the image");
                    $w = ImageSX($srcimg);
                    $h = ImageSY($srcimg);
                    $ro = $new_width/$new_height;
                    $ri = $w/$h;
                    if($ro<$ri){
                      $par = "h";
                    }else{
                      $par = "w";
                    }
                    if($par == "h"){
                      $ih = $h;
                      $conv = $new_width/$new_height;
                      $iw = $conv*$ih;
                      $cw = ($w/2)-($iw/2);
                      $ch = ($h/2)-($ih/2);
                    }else if($par == "w"){
                      $iw = $w;
                      $conv = $new_height/$new_width;
                      $ih = $conv*$iw;
                      $cw = ($w/2)-($iw/2);
                      $ch = ($h/2)-($ih/2);
                    }
                    ImageCopyResampled($destimg,$srcimg,0,0,$cw,$ch,$new_width,$new_height,$iw,$ih) or die("problems with resize");
                    ImageJPEG($destimg,$destination_path.$nomeimage,$compression) or die("problems with storing new image");
                  }
                }
            

            【讨论】:

              【解决方案9】:

              这个解决方案与 Can Berk Güder 的解决方案基本相同,但在花了一些时间编写和评论之后,我想发帖。

              此函数会创建一个与您提供的大小完全相同的缩略图。 调整图像大小以最适合缩略图的大小。如果它不完全适合两个方向,则它在缩略图中居中。广泛的 cmets 解释了事情的经过。

              function thumbnail_box($img, $box_w, $box_h) {
                  //create the image, of the required size
                  $new = imagecreatetruecolor($box_w, $box_h);
                  if($new === false) {
                      //creation failed -- probably not enough memory
                      return null;
                  }
              
              
                  //Fill the image with a light grey color
                  //(this will be visible in the padding around the image,
                  //if the aspect ratios of the image and the thumbnail do not match)
                  //Replace this with any color you want, or comment it out for black.
                  //I used grey for testing =)
                  $fill = imagecolorallocate($new, 200, 200, 205);
                  imagefill($new, 0, 0, $fill);
              
                  //compute resize ratio
                  $hratio = $box_h / imagesy($img);
                  $wratio = $box_w / imagesx($img);
                  $ratio = min($hratio, $wratio);
              
                  //if the source is smaller than the thumbnail size, 
                  //don't resize -- add a margin instead
                  //(that is, dont magnify images)
                  if($ratio > 1.0)
                      $ratio = 1.0;
              
                  //compute sizes
                  $sy = floor(imagesy($img) * $ratio);
                  $sx = floor(imagesx($img) * $ratio);
              
                  //compute margins
                  //Using these margins centers the image in the thumbnail.
                  //If you always want the image to the top left, 
                  //set both of these to 0
                  $m_y = floor(($box_h - $sy) / 2);
                  $m_x = floor(($box_w - $sx) / 2);
              
                  //Copy the image data, and resample
                  //
                  //If you want a fast and ugly thumbnail,
                  //replace imagecopyresampled with imagecopyresized
                  if(!imagecopyresampled($new, $img,
                      $m_x, $m_y, //dest x, y (margins)
                      0, 0, //src x, y (0,0 means top left)
                      $sx, $sy,//dest w, h (resample to this size (computed above)
                      imagesx($img), imagesy($img)) //src w, h (the full size of the original)
                  ) {
                      //copy failed
                      imagedestroy($new);
                      return null;
                  }
                  //copy successful
                  return $new;
              }
              

              示例用法:

              $i = imagecreatefromjpeg("img.jpg");
              $thumb = thumbnail_box($i, 210, 150);
              imagedestroy($i);
              
              if(is_null($thumb)) {
                  /* image creation or copying failed */
                  header('HTTP/1.1 500 Internal Server Error');
                  exit();
              }
              header('Content-Type: image/jpeg');
              imagejpeg($thumb);
              

              【讨论】:

              • 实际上这个脚本不会调整原始图像的大小。这也可能吗?
              • 此脚本会复制原始图像。重新采样图像时,您必须制作副本。我的示例使用破坏了原始图像 (imagedestroy($i))。如果你想覆盖图像文件,那么只需将 $thumb 写入示例中的文件“img.jpg”即可。
              • 好的,谢谢。如果我想调整整张图片的大小而不是只做裁剪怎么办?
              • 这不是作物。裁剪是删除图像的一部分。此函数始终使用整个图像。
              • 在 if($new === false) { //创建失败后缺少一个 } -- 可能内存不足 return null;或者您必须删除 {
              【解决方案10】:

              从大图像快速生成高质量缩略图的提示:(from the php.net site)

              如果您分两个阶段生成缩略图:

              1. 使用快速调整大小从原始图像到最终尺寸两倍的中间图像
              2. 使用高质量重采样从中间图像到最终缩略图

              那么这可以更快;第 1 步中的调整大小质量相对较差,但具有足够的额外分辨率,在第 2 步中质量不错,并且中间图像足够小,可以进行高质量的重新采样(在 2:1 调整大小时效果很好)进展非常快。

              【讨论】:

              • 感谢您的加入。你有一些示例代码。这如何适合 gnut 的代码?
              【解决方案11】:

              技术是:

              1. 调整图像大小,使一个尺寸匹配,而另一个尺寸超过所需尺寸
              2. 从调整大小的图像中心取出所需大小的图像。

              最后,如果您对如何计算调整大小感到困惑,请记住,如果源图像和目标图像的比例相同,则此关系成立:

              SourceWidth / SourceHeight = DestinationWidth / DestinationHeight
              

              如果你知道三个参数,你可以很容易地计算出第四个参数。

              我为此写了一篇文章:
              Crop-To-Fit an Image Using ASP/PHP

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2011-10-08
                • 2011-11-11
                • 1970-01-01
                • 2013-03-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2010-10-03
                相关资源
                最近更新 更多