我正在尝试在上传时缩小用户上传的图片。
这没问题,但我现在想具体了解尺寸。
我正在寻找关于我正在努力生成的算法的一些建议,该算法将采用任何形状的图像 - 任何宽度/高度的正方形或矩形并缩小它的尺寸。
此图像需要缩小到目标框大小(这会更改但存储在变量中)..
因此需要缩小图像尺寸,使宽度和高度都大于目标的宽度和高度,保持纵横比。但只是……
目标大小将用于裁剪图像,因此边缘等周围没有空白。
我只是在寻找基于不同尺寸图像创建正确调整大小的算法 - 我可以处理裁剪,甚至在大多数情况下调整大小,但在少数情况下它会失败,所以我伸出手。
我并不是真的要求更伪的 PHP 代码。显然两者都可以。
谢谢。
当前代码..但我已经经历了很多次迭代,这可能不再有效了..:P
$image = $image_orig->clone();
$wRatio = $imageprops['width'] / $dimensions[0]; // imageprops = original image dimens.
$hRatio = $imageprops['height'] / $dimensions[1]; // $dimensions[0] = new width
$maxRatio = max($wRatio,$hRatio); // $dimensions[1] = new height
var_dump('thumb');
$ratio = ($imageprops['width'] - $dimensions[0]) > ($imageprops['height'] - $dimensions[1]);
$shape = ($imageprops['width'] > $imageprops['height']);
$error = ($imageprops['width'] / $imageprops['height']);
if( $error < 0.95 || $error > 1.05 ) { // its NOT a square
if($shape){ // longer width
$scale = $imageprops['height'] / $dimensions[0];
var_dump('1');
$height = $imageprops['height'] / $scale;
$image->scaleImage(0, $height);
} else {
$scale = $imageprops['width'] / $dimensions[1];
var_dump('2');
$width = $imageprops['width'] / $scale;
$image->scaleImage($width, 0);
}
} elseif($ratio) { // is square
$scale = $imageprops['height'] / $dimensions[1];
$newWidth = $imageprops['width'] / $scale;
$extra = 0;
$height = $dimensions[1]+$extra;
$image->scaleImage(0, $height);
} else {
$scale = $imageprops['width'] / $dimensions[0];
$newHeight = $imageprops['height'] / $scale;
$extra = 0;
$width = $dimensions[0]+$extra;
$image->scaleImage($width, 0);
}
$image_size = $image->getImageGeometry();
$image->cropImage($dimensions[0], $dimensions[1],($image_size['width']-$dimensions[0])/2,($image_size['height']-$dimensions[1])/2);
最佳答案
注意:我在原始发帖者编辑他的问题之前写了这个答案,以包含澄清要点的内容,这些内容已经改变了我认为原始问题的要求。
因此,您可以抛出一些概念和想法来尝试解决您打算实现的目标。 (重力裁剪、Content Aware Cropping、内容感知缩放等)
因为您总是在减小原始图像的大小,所以您实际上只是想“切掉”图像的一部分。非常像这样:
但是,问题是您经常希望确保选择图像的最佳区域,以免裁剪图像的不相关部分。这称为内容感知图像裁剪,只需使用“内容感知图像裁剪”进行搜索,您就可以找到大量信息。
无论如何,继续前进,具体取决于您的具体用例,您可能会发现实际上您不想从图像中切掉任何东西,而是想要“液体缩放和裁剪”图像,以便您做“内容感知调整大小”。内容感知调整大小的不同之处在于,调整大小会忽略图像的所有纵横比,而是查看相邻的边缘和颜色,以便以流畅的方式调整图像大小。
所以,幸运的是,Imagick
带有它自己的 [liquidRescaleImage][3]
函数。
你可以像这样使用它
$im->liquidRescaleImage(480, 260, 3, 18);
使用 Liquid Rescale 可以很好地重新缩放。下面是一个不完美的示例,但我有意创建了一个不完美的示例,因此您实际上可以看到 liquidRescale 改变了图像的构图,而不仅仅是调整纵横比。
原创
Content Aware Liquid Rescale (450x350)
但是,如果您只想缩放图像并保持纵横比,您可能想要像 Flickr 等网站那样做,它们使图像 longestLength 等于一个值。 (例如 Flickr 有 6 个左右不同的维度大小)
We resize your photos to more web-friendly dimensions. Each image has a 75x75 and 150x150 square thumbnail and 100-, 240-, 320-, 500-, 640- 800*-, 1024-, 1600*-, and 2048*-pixel versions (that's the length of the longest side), as well as your original file.
复制 Flickr 调整大小策略的基本类...
<?php
class Scale {
public function getImageScale($x, $y, $longestLength, $allowDistort = false) {
//Set the default NEW values to be the old, in case it doesn't even need scaling
list($nx, $ny) = array($x, $y);
if ($x > $y) {
if ($longestLength > $x && !$allowDistort) {
return array($x, $y);
}
$r = $x / $longestLength;
return array($longestLength, $y / $r);
} else {
if ($longestLength > $x && !$allowDistort) {
return array($x, $y);
}
$r = $y / $longestLength;
return array($x / $r, $longestLength);
}
return array($nx, $ny);
}
}
然后,如果您要像这样传递图像尺寸:
$originalImageX = 480;
$originalImageY = 260;
$scale = new Scale();
var_dump($scale->getImageScale($originalImageX,$originalImageY,120 ) );
/* Outputs
array(2) {
[0]=>
int(120)
[1]=>
int(65)
} */
另外,Git 上有这个 Content Aware Cropping 类,我之前已经调整了基类/结构以在我自己的项目中使用,所以我知道它工作得很好。我不确定此类的许可,但您显然可以看一下它并像我之前所做的那样切出适合您的内容。
https://gist.github.com/2468935#file_content_aware_image.php
(还有 PS。下次直接提供问题中的所有信息...)
关于PHP 调整图像大小并使用 imagemagick 裁剪,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13478032/