将图片调整大小/裁剪/填充到固定大小

时间:2021-04-15 21:21:35

I need to resize a picture to a fixed size. But it has to keep the factors between the width and height.

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

Say I want to resize a picture from 238 (w) X 182 (h) to 210 / 150

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

What I do now is:

我现在做的是:

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

Now I take the smallest factor.

现在我采取最小的因素。

Now I always have the right width since 238 / 1.333333 = 210. But the height is still 160.

现在我总是有正确的宽度,因为238 / 1.333333 = 210.但是高度仍然是160。

How do I get the height down to 160 without ruining the pic?

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

Do I need to crop? If so how?

我需要裁剪吗?如果是这样的话?

11 个解决方案

#1


This solution is basically the same as Can Berk Güder's, but after having spent some time writing and commenting, I felt like posting.

这个解决方案与CanBerkGüder的解决方案基本相同,但在花了一些时间写作和评论后,我觉得要张贴。

This function creates a thumbnail that is exactly as big as the size you give it. The image is resized to best fit the size of the thumbnail. If it does not fit exactly in both directions, it's centered in the thumnail. Extensive comments explain the goings-on.

此功能创建的缩略图与您提供的缩放尺寸完全一样大。调整图像大小以最适合缩略图的大小。如果它不能完全适合两个方向,那么它就会在thumnail中居中。广泛的评论解释了这些事情。

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

Example usage:

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

#2


This doesn't crop the picture, but leaves space around the new image if necessary, which I think is a better approach (than cropping) when creating thumbnails.

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

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

#3


Do you have Imagick? If so you can load the image with it and do something like thumbnailimage()

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

There you can skip either of the parameters (height or width) and it will resize correctly.

在那里,您可以跳过任一参数(高度或宽度),它将正确调整大小。

#4


Maybe take look at PHPThumb (it works with GD and ImageMagick)

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

#5


Just a tip for high-quality fast thumbnail generation from large images: (from the php.net site)

只是从大图像生成高质量快速缩略图的提示:(来自php.net网站)

If you do the thumbnail generation in two stages:

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

  1. From original to an intermediate image with twice the final dimensions, using a fast resize
  2. 从原始图像到具有两倍最终尺寸的中间图像,使用快速调整大小

  3. From the intermediate image to the final thumbnail using a high-quality resample
  4. 使用高质量的重采样从中间图像到最终缩略图

then this can be much faster; the resize in step 1 is relatively poor quality for its size but has enough extra resolution that in step 2 the quality is decent, and the intermediate image is small enough that the high-quality resample (which works nicely on a 2:1 resize) proceeds very fast.

然后这会快得多;步骤1中的调整大小是相对较差的质量,但具有足够的额外分辨率,在步骤2中质量是不错的,中间图像足够小,以至于高质量重采样(在2:1调整大小时效果很好)进展得非常快。

#6


I'd much rather resize so that the image is contained within your limit and then fill out the blank parts. So in the above example you would resize so that the height is OK, then fill up (7 pixels on each end I think) to the left and right with a background color.

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

#7


Resizing images from within a PHP-sourced webpage can be problematic. Larger images (approaching 2+MB on disk) can be so large that they need more than 32MB of memory to process.

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

For that reason, I tend to either do it from a CLI-based script, with up-to 128MB of memory available to it, or a standard command line, which also uses as much as it needs.

出于这个原因,我倾向于从基于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' is part of the ImageMagick command line tools.

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

#8


are these thumbnails? if they are, cropping is not a huge problem. we do it all the time. i don't even shy away from cropping arbitrary ratios into crippled quadratic thumbnails, completely messing up the image (yes, i'm that hardcore), if it just looks good. this is a designers answer to a technical question, but still. don't fear the crop!

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

#9


I think there is a little confusion.. If you only want to resize it, keeping the original ratio, the right operation is:

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

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

Else, if the prefixed newWidth and newHeight cant be changed, and the thumb ratio is different from the original ratio, the only way is to crop or add borders to the thumb.

否则,如果前缀newWidth和newHeight无法更改,并且拇指比率与原始比率不同,则唯一的方法是裁剪或向拇指添加边框。

If your'e on to take the cut way, this function can help you (i wrote years ago in 5 minutes, maybe need some improvement.. it works only with jpg, for example ;):

如果你采取切割的方式,这个功能可以帮助你(我在几年前写了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");
      }
    }

#10


The technique is to:

该技术是:

  1. resize the image so that one dimension matches while the other exceeds the desired dimensions
  2. 调整图像大小以使一个维度匹配而另一个维度超出所需维度

  3. take out the desired size image from the center of resized image.
  4. 从调整大小的图像的中心取出所需大小的图像。

Lastly if you are puzzled about how to do the resize math, remember that if proportions of source and destination images are same, this relation holds:

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

SourceWidth / SourceHeight = DestinationWidth / DestinationHeight

If you know three parameters, you can calculate the fourth one easily.

如果您知道三个参数,则可以轻松计算出第四个参数。

I wrote an article about this:
Crop-To-Fit an Image Using ASP/PHP

我写了一篇关于此的文章:使用ASP / PHP裁剪图像

#11


You'll have to crop 5 px off the top and bottom to get to your target size, however this could ruin the picture.

您将需要从顶部和底部裁剪5像素以达到目标尺寸,但这可能会破坏图片。

Really you should have a target width or height, then adjust the other dimension by the same proportion.

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

#1


This solution is basically the same as Can Berk Güder's, but after having spent some time writing and commenting, I felt like posting.

这个解决方案与CanBerkGüder的解决方案基本相同,但在花了一些时间写作和评论后,我觉得要张贴。

This function creates a thumbnail that is exactly as big as the size you give it. The image is resized to best fit the size of the thumbnail. If it does not fit exactly in both directions, it's centered in the thumnail. Extensive comments explain the goings-on.

此功能创建的缩略图与您提供的缩放尺寸完全一样大。调整图像大小以最适合缩略图的大小。如果它不能完全适合两个方向,那么它就会在thumnail中居中。广泛的评论解释了这些事情。

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

Example usage:

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

#2


This doesn't crop the picture, but leaves space around the new image if necessary, which I think is a better approach (than cropping) when creating thumbnails.

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

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

#3


Do you have Imagick? If so you can load the image with it and do something like thumbnailimage()

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

There you can skip either of the parameters (height or width) and it will resize correctly.

在那里,您可以跳过任一参数(高度或宽度),它将正确调整大小。

#4


Maybe take look at PHPThumb (it works with GD and ImageMagick)

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

#5


Just a tip for high-quality fast thumbnail generation from large images: (from the php.net site)

只是从大图像生成高质量快速缩略图的提示:(来自php.net网站)

If you do the thumbnail generation in two stages:

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

  1. From original to an intermediate image with twice the final dimensions, using a fast resize
  2. 从原始图像到具有两倍最终尺寸的中间图像,使用快速调整大小

  3. From the intermediate image to the final thumbnail using a high-quality resample
  4. 使用高质量的重采样从中间图像到最终缩略图

then this can be much faster; the resize in step 1 is relatively poor quality for its size but has enough extra resolution that in step 2 the quality is decent, and the intermediate image is small enough that the high-quality resample (which works nicely on a 2:1 resize) proceeds very fast.

然后这会快得多;步骤1中的调整大小是相对较差的质量,但具有足够的额外分辨率,在步骤2中质量是不错的,中间图像足够小,以至于高质量重采样(在2:1调整大小时效果很好)进展得非常快。

#6


I'd much rather resize so that the image is contained within your limit and then fill out the blank parts. So in the above example you would resize so that the height is OK, then fill up (7 pixels on each end I think) to the left and right with a background color.

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

#7


Resizing images from within a PHP-sourced webpage can be problematic. Larger images (approaching 2+MB on disk) can be so large that they need more than 32MB of memory to process.

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

For that reason, I tend to either do it from a CLI-based script, with up-to 128MB of memory available to it, or a standard command line, which also uses as much as it needs.

出于这个原因,我倾向于从基于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' is part of the ImageMagick command line tools.

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

#8


are these thumbnails? if they are, cropping is not a huge problem. we do it all the time. i don't even shy away from cropping arbitrary ratios into crippled quadratic thumbnails, completely messing up the image (yes, i'm that hardcore), if it just looks good. this is a designers answer to a technical question, but still. don't fear the crop!

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

#9


I think there is a little confusion.. If you only want to resize it, keeping the original ratio, the right operation is:

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

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

Else, if the prefixed newWidth and newHeight cant be changed, and the thumb ratio is different from the original ratio, the only way is to crop or add borders to the thumb.

否则,如果前缀newWidth和newHeight无法更改,并且拇指比率与原始比率不同,则唯一的方法是裁剪或向拇指添加边框。

If your'e on to take the cut way, this function can help you (i wrote years ago in 5 minutes, maybe need some improvement.. it works only with jpg, for example ;):

如果你采取切割的方式,这个功能可以帮助你(我在几年前写了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");
      }
    }

#10


The technique is to:

该技术是:

  1. resize the image so that one dimension matches while the other exceeds the desired dimensions
  2. 调整图像大小以使一个维度匹配而另一个维度超出所需维度

  3. take out the desired size image from the center of resized image.
  4. 从调整大小的图像的中心取出所需大小的图像。

Lastly if you are puzzled about how to do the resize math, remember that if proportions of source and destination images are same, this relation holds:

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

SourceWidth / SourceHeight = DestinationWidth / DestinationHeight

If you know three parameters, you can calculate the fourth one easily.

如果您知道三个参数,则可以轻松计算出第四个参数。

I wrote an article about this:
Crop-To-Fit an Image Using ASP/PHP

我写了一篇关于此的文章:使用ASP / PHP裁剪图像

#11


You'll have to crop 5 px off the top and bottom to get to your target size, however this could ruin the picture.

您将需要从顶部和底部裁剪5像素以达到目标尺寸,但这可能会破坏图片。

Really you should have a target width or height, then adjust the other dimension by the same proportion.

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