php 调整图像大小而不失真保持纵横比,然后使用 WideImage 裁剪多余的图像

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6355954/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 00:07:53  来源:igfitidea点击:

Resize image without distortion keeping aspect ratio then crop excess using WideImage

phpimage-resizing

提问by lethalMango

I have an area on a site that I am working on that will display a users profile image that is pulled from an external source (therefore no control on its original size).

我在我正在处理的网站上有一个区域,该区域将显示从外部来源提取的用户个人资料图像(因此无法控制其原始大小)。

What I am looking to do is take an image (in this example 1000px x 800pxand resize it to 200px x 150px. Obviously with this there is an aspect ratio difference.

我想要做的是拍摄一张图像(在本例中1000px x 800px并将其调整为200px x 150px. 显然这存在纵横比差异。

What I want to do is resize the original image without distortion, which in this case would produce a 200px x 160pximage. What I then want to do is crop any excess from the edges to produce the correct image size. So in this case crop 5pxoff the top and bottom of the image finally producing a 200px x 150px.

我想要做的是在不失真的情况下调整原始图像的大小,在这种情况下会产生200px x 160px图像。然后我想要做的是从边缘裁剪任何多余的部分以产生正确的图像大小。所以在这种情况下,裁剪5px掉图像的顶部和底部,最终生成一个200px x 150px.

I have the WideImagelibrary currently and would like to use that. I have seen several similar questions on SO but nothing that I can say exactly does as I am trying to achieve.

我目前有WideImage库并想使用它。我在 SO 上看到了几个类似的问题,但我不能说完全符合我想要实现的目标。

回答by binaryLV

You might try:

你可以试试:

$img->resize(200, 150, 'outside')->crop('center', 'middle', 200, 150);


Some users post their versions of calculations... Here's also my version:

一些用户发布了他们的计算版本......这也是我的版本:

$sourceWidth = 1000;
$sourceHeight = 250;

$targetWidth = 200;
$targetHeight = 150;

$sourceRatio = $sourceWidth / $sourceHeight;
$targetRatio = $targetWidth / $targetHeight;

if ( $sourceRatio < $targetRatio ) {
    $scale = $sourceWidth / $targetWidth;
} else {
    $scale = $sourceHeight / $targetHeight;
}

$resizeWidth = (int)($sourceWidth / $scale);
$resizeHeight = (int)($sourceHeight / $scale);

$cropLeft = (int)(($resizeWidth - $targetWidth) / 2);
$cropTop = (int)(($resizeHeight - $targetHeight) / 2);

var_dump($resizeWidth, $resizeHeight, $cropLeft, $cropTop);

回答by Chad A

I tried all of your solutions and came up with strange numbers every time. So, this is my way of doing the calculations.

我尝试了你所有的解决方案,每次都想出了奇怪的数字。所以,这是我进行计算的方式。

Basic proportional formula: a/b=x/y -> ay = bx then solve for the unknown value. So, let's put this into code.

基本比例公式:a/b=x/y -> ay = bx 然后求解未知值。所以,让我们把它写成代码。

This function assumes you've opened the image into a variable. If you pass the path you'll have to open the image in the function, do the math, kill it, return the values and then open the image again when you resize it, that's inefficient...

此函数假定您已将图像打开为变量。如果传递路径,则必须在函数中打开图像,进行数学运算,杀死它,返回值,然后在调整大小时再次打开图像,这是低效的...

function resize_values($image){
    #for the purpose of this example, we'll set this here
    #to make this function more powerful, i'd pass these 
    #to the function on the fly
    $maxWidth = 200; 
    $maxHeight = 200;

    #get the size of the image you're resizing.
    $origHeight = imagesy($image);
    $origWidth = imagesx($image);

    #check for longest side, we'll be seeing that to the max value above
    if($origHeight > $origWidth){ #if height is more than width
         $newWidth = ($maxHeight * $origWidth) / $origHeight;

         $retval = array(width => $newWidth, height => $maxHeight);
    }else{
         $newHeight= ($maxWidth * $origHeight) / $origWidth;

         $retval = array(width => $maxWidth, height => $newHeight);
    }
return $retval;
}

Above function returns an array, obviously. You can work the formula into whatever script you're working on. This has proven to be the right formula for the job. So... up to you whether or not you use it. LATER!

显然,上面的函数返回一个数组。您可以将公式应用到您正在处理的任何脚本中。这已被证明是适合这项工作的正确公式。所以......取决于你是否使用它。之后!

回答by Salman A

Answer #1 (edited)

答案 #1(已编辑)

After having a look at thisand this, you probably need to do something like this:

在查看了thisthis 之后,您可能需要执行以下操作:

$img->resize(200, 150, 'outside')->crop("center", "center", 200, 150);

While resizing it will resize the image so that it either fits exactly within the box (box = 200x150) or one of the dimension fits while the other exceeds the box. While cropping, the portion of the image that bleedsoutside the box will be trimmed. Specifying the centersmart coordinate means the top+bottom or left+right portion will be removed.

在调整大小时,它会调整图像大小,使其完全适合框(框 = 200x150)或其中一个尺寸适合而另一个超出框。裁剪时,会修剪框外的图像部分。指定center智能坐标意味着顶部+底部或左侧+右侧部分将被删除。

Answer #2

答案#2

If you are having problems in calculatingwhat to crop, try this:

如果您在计算要裁剪的内容时遇到问题,请尝试以下操作:

<?php
$target_wide = 200;
$target_tall = 150;

$test_case = array(
    array(1000, 800),
    array(800, 1000),
    array(1000, 750), // perfect fit
    array(750, 1000)
);

foreach($test_case as $test) {
    list(
        $source_wide,
        $source_tall
    ) = $test;
    $source_aspect_ratio = $source_wide / $source_tall;
    $target_aspect_ratio = $target_wide / $target_tall;
    if ($source_aspect_ratio > $target_aspect_ratio)
    {
        $output_tall = $target_tall;
        $output_wide = (int) ($target_tall * $source_aspect_ratio);
    }
    else
    {
        $output_wide = $target_wide;
        $output_tall = (int) ($target_wide / $source_aspect_ratio);
    }
    $output_crop_hori = (int) (($output_wide - $target_wide) / 2);
    $output_crop_vert = (int) (($output_tall - $target_tall) / 2);
    var_dump($source_wide, $source_tall, $output_wide, $output_tall, $output_crop_hori, $output_crop_vert);
    echo PHP_EOL;
}

Output:

输出:

int(1000)
int(800)
int(200)
int(160)
int(0)
int(5)

int(800)
int(1000)
int(200)
int(250)
int(0)
int(50)

int(1000)
int(750)
int(200)
int(150)
int(0)
int(0)

int(750)
int(1000)
int(200)
int(266)
int(0)
int(58)

回答by Jiten Mhatre

//Following code for keeping aspect ratio

$srcWidth=1000;
$srcHeight=800;

$targetWidth=200;
$targetHeight=150;

$diff=0;
//get difference

if( $srcWidth > $srcHeight ) // 1000 > 800
{
    $diff = $srcWidth - $srcHeight; // 1000 - 800 = 200
    $diff = ($diff / $srcWidth) * 100; // ( 200 / 1000 ) * 100 = 20
}
else
{
    $diff = $srcHeight - $srcWidth;
    $diff = ($diff / $srcHeight)*100;
}

if( $targetWidth > $targetHeight)
{
    $targetHeight = (( $targetHeight * $diff ) / 100) - $targetWidth; // (( 200 * 20 ) /  100) - 200 = 160
}
else
{
    $targetWidth = (( $targetWidth * $diff ) / 100) - $targetHeight;
}

回答by OZ_

That's how you can calculate size of crop:

这就是您可以计算作物大小的方法:

$src_width = 1000;
$src_height = 500;
$src_ratio = $src_width/$src_height;

$width = 200;
$height = 150;
$ratio = $width/$height;

$crop_height = 0;
$crop_width = 0;

if ($src_height > $src_width)
{
    $new_height = $width/$src_ratio;
    $crop_height = $new_height-$height;
}
else
{
    $new_width = $height*$src_ratio;
    $crop_width = $new_width-$width;
}

print 'Crop height: '.$crop_height.PHP_EOL
      .'Crop width: '.$crop_width;