计算图片大小比例以进行调整大小

52

我有一个定义好的固定宽度和高度来重设图像大小。但是,由于图像可以具有任何类型的大小比例(它可以是垂直水平),因此会出现问题。在这种情况下,固定的宽度和高度会产生问题。我想要以更加智能的方式计算宽度和高度

例如,假设我已经定义了宽度1024px和高度768px,并且我想要调整一个垂直的图像(高度1100px和宽度200px)。在这种情况下,它将被调整为固定的大小(1024x768),因此宽度将从100px增加到768px,这看起来非常难看。同样,如果图像的高度小于768px,它将强制增加高度到768px

因此,我想根据原始图像大小比率计算新的图像大小。例如,如果上面的示例图像应缩放到最大高度为768px,但是宽度呢?它已经小于我的"最大宽度",即200px,所以宽度是否应保持不变?还是应该进一步减小宽度?

同样,如果图像的高度是200px,宽度为1100px。那么宽度应该缩小到1024px,但高度呢?

第三个问题是,假设高度和宽度都大于最大高度和最大宽度,比如宽度:1100px和高度:4000px。现在由于宽度和高度都大于最大宽度和最大高度,但图像是垂直的,它将使其变成水平的。那么在这种情况下,我如何检查是否应根据最大高度或最大宽度调整图像大小?

我非常感谢任何帮助。


可能是图像调整大小问题(PHP / GD)的重复。 - hakre
3
已经编写了一个扩展类,请查看:https://github.com/qaribhaider/php-image-resize - Qarib Haider
13个回答

83

这是我个人的图片调整代码库中的代码。首先,您需要的数据:

list($originalWidth, $originalHeight) = getimagesize($imageFile);
$ratio = $originalWidth / $originalHeight;

然后,该算法会尽量将图像调整到目标大小,保持原始纵横比,不会将图像拉伸大于原始尺寸:

$targetWidth = $targetHeight = min($size, max($originalWidth, $originalHeight));

if ($ratio < 1) {
    $targetWidth = $targetHeight * $ratio;
} else {
    $targetHeight = $targetWidth / $ratio;
}

$srcWidth = $originalWidth;
$srcHeight = $originalHeight;
$srcX = $srcY = 0;

这会将图像裁剪到完全填充目标尺寸,而不是拉伸它:

$targetWidth = $targetHeight = min($originalWidth, $originalHeight, $size);

if ($ratio < 1) {
    $srcX = 0;
    $srcY = ($originalHeight / 2) - ($originalWidth / 2);
    $srcWidth = $srcHeight = $originalWidth;
} else {
    $srcY = 0;
    $srcX = ($originalWidth / 2) - ($originalHeight / 2);
    $srcWidth = $srcHeight = $originalHeight;
}

以下执行实际调整大小的操作:

$targetImage = imagecreatetruecolor($targetWidth, $targetHeight);
imagecopyresampled($targetImage, $originalImage, 0, 0, $srcX, $srcY, $targetWidth, $targetHeight, $srcWidth, $srcHeight);
在这种情况下,$size 只是一个数字,用于指定宽度和高度(即正方形目标尺寸)。我相信你可以将其修改为使用非正方形的目标尺寸。这也应该会启发你,让你知道还有哪些其他的调整大小算法可以使用。

如果目标不是正方形,例如 $expectedWidth = 200;$expectedHeight = 150;,那么以下哪个是正确的方式: $targetWidth = $targetHeight = min(max($expectedWidth, $expectedHeight), max($originalWidth, $originalHeight)); 还是 $targetWidth = $targetHeight = min($expectedWidth, $expectedHeight, max($originalWidth, $originalHeight)); - Roopendra
1
@deceze请澄清这里$size可能的值是什么。 - Heemanshu Bhalla
如所述,这是“目标图像大小”。$size = 200 意味着结果将是最大为 200 x 200 像素的图像。 - deceze
@deceze 好的,谢谢。我之前也用过这个,让我再检查一遍。 - Heemanshu Bhalla
@deceze 我正在使用你提供的代码,但它无法正常工作,也无法生成图片。你可以在下面看到代码 -http://geeksprogrammings.blogspot.in/2016/05/crop-image-code-error.html - Heemanshu Bhalla
太棒了!谢谢! - Grufas

64
$ratio = $originalWidth / $originalHeight;

如果你想改变宽度:
$targetWidth = $targetHeight * $ratio;

如果你想改变高度:
$targetHeight = $targetWidth / $ratio;

18

您想要保持原始图像的纵横比。这是图像宽度和高度之间的比率。因此,您需要计算在垂直和水平方向上需要调整图像大小的因素,然后保留两者中较大的那个。伪代码如下:

target_height = 768
target_width = 1024
# 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 = target_height / im_height 
h_fact = 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
im_fact = min(v_fact, h_fact)
new_height = im_height * im_fact
new_width = im_width * im_fact
image.resize(new_width, new_height)

3
这很棒,下面是一个更短的PHP版本: list($width, $height, $type, $attr) = getimagesize($path); $ratio = min($maxHeight / $height, $maxWidth / $width); $newHeight = ceil($height * $ratio); $newWidth = ceil($width * $ratio); 注:该代码用于获取图片大小并按比例缩放图片至指定的最大高度和最大宽度。其中,$path是图片路径,$maxHeight和$maxWidth分别为所需的最大高度和最大宽度。最终,$newHeight和$newWidth存储了按比例缩放后的新图片高度和宽度。 - Kus

10

这很有效。

function calculateDimensions($width,$height,$maxwidth,$maxheight)
{

        if($width != $height)
        {
            if($width > $height)
            {
                $t_width = $maxwidth;
                $t_height = (($t_width * $height)/$width);
                //fix height
                if($t_height > $maxheight)
                {
                    $t_height = $maxheight;
                    $t_width = (($width * $t_height)/$height);
                }
            }
            else
            {
                $t_height = $maxheight;
                $t_width = (($width * $t_height)/$height);
                //fix width
                if($t_width > $maxwidth)
                {
                    $t_width = $maxwidth;
                    $t_height = (($t_width * $height)/$width);
                }
            }
        }
        else
            $t_width = $t_height = min($maxheight,$maxwidth);

        return array('height'=>(int)$t_height,'width'=>(int)$t_width);
    }

4
这个怎么样:
double ratio = imageWidth/imageHeight;
int newHeight = Math.min(displayHeight, displayWidth / ratio); 
int newWidth =  Math.min(displayWidth, displayHeight * ratio); 

1
请检查以下 PHP 代码:
$new_width  = 1024;
$new_height = 768;
$this_image = "images/my_image";

list($width, $height, $type, $attr) = getimagesize("$this_image");

if ($width > $height) {
  $image_height = floor(($height/$width)*$new_width);
  $image_width  = $new_width;
} else {
  $image_width  = floor(($width/$height)*$new_height);
  $image_height = $new_height;
}
echo "<img src='$this_image' height='$image_height' width='$image_width'>";

1
你需要做的是“保持”宽高比。原本你有一张尺寸为(宽x高)500x1000 的图片,这个宽高比是0.5。假设你将高度从1000更改为768,那么你的结果宽度将是0.5 * 768 = 384
另一个例子,1800 x 1200,你的“新”高度是200,那么你的“新”宽度是300,因为300/2001.5,而1800/1200也是1.5
祝你好运。

0

如果已经给定最大高度或宽度,或者没有给定,使用@(jilles de wit)的逻辑

注意:这些应该已经定义好了!

$mh = given height limit; //optional
$mw = given width limit; //optional

$height = $nh =[your original height];
$width = $nw =[your original width];

代码

if($mh || $mw){
if(is_numeric($mh)){$h_fact = $mh / $nh;}
if(is_numeric($mw)){$v_fact = $mw / $nw;}

if(is_numeric($v_fact) && is_numeric($h_fact)  ){$im_fact = min($v_fact, $h_fact);}else{$im_fact=is_numeric($v_fact)?$v_fact:$h_fact;}
$nw = $nw * $im_fact;
$nh = $nh * $im_fact;
}

重采样

$dst_img = imagecreatetruecolor($nw,$nh);
imagecopyresampled ($dst_img, $image, 0, 0, 0, 0, $nw, $nh, $width , $height);

0

你应该根据离最大值更远的属性来调整它的大小。然后,计算比率。

if(($w - $w_max) > ($h - $h_max)) {
    $w_new = $w_max;
    $h_new = (int) ($h * ($w_max / $w));
}
else {
    $h_new = $h_max;
    $w_new = (int) ($w * ($h_max / $h));
}

只有当目标大小是正方形($w_{max}$=$h_{max}$)时,此方法才能正确工作,否则根据输入图像和目标大小的相对大小关系,可能会得到新图像在宽度或高度上大于目标大小的结果。 - jilles de wit
例如:如果输入为 400x300,目标为 300x220,则您的代码会生成一个大小为 300x225 的图像,比目标更大。 - jilles de wit

0

获取最近的比率

$r=getRatio(820,460);//41:23
$r=getRatio(160,40);//4:1
$r=getRatio(1743,367);//1743:367


function getRatio($num1, $num2){

    if(abs($num1-$num2)<10 && $num1>100){
        $num1=$num2;
    }
    for($i = $num2; $i > 1; $i--) {
        if((($num1 % $i) == 0 && ($num2 % $i) == 0) ) {
            $num1 = $num1 / $i;
            $num2 = $num2 / $i;
        }
    }
    return round($num1,1).':'.round($num2,1);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接