旋转和裁剪

时间:2013-04-27 17:34:38

标签: php imagemagick crop image-resizing

我正在使用PHP旋转和裁剪图像,但我显示黑色边框,我知道您可以更改背景颜色,但我想旋转并裁剪图像以填充整个图像。基本上类似于CSS中的background-size: cover;(左)与background-size: contain;(右)。

见下图,右边是我现在得到的,左边是我想要达到的。旋转的度数是动态的,要生成的图像和源图像都是方形(200x200)。

Illustration of problem

编辑:这是我快速而又脏的代码:

$rotate = imagecreatefromjpeg($image);
// part of code created by www.thewebhelp.com, modified
$square_size = 200;
$original_width = imagesx($rotate); 
$original_height = imagesy($rotate);
if($original_width > $original_height){
    $new_height = $square_size;
    $new_width = $new_height*($original_width/$original_height);
}
if($original_height > $original_width){
    $new_width = $square_size;
    $new_height = $new_width*($original_height/$original_width);
}
if($original_height == $original_width){
    $new_width = $square_size;
    $new_height = $square_size;
}

$new_width = round($new_width);
$new_height = round($new_height);

$smaller_image = imagecreatetruecolor($new_width, $new_height);
$square_image = imagecreatetruecolor($square_size, $square_size);

imagecopyresampled($smaller_image, $rotate, 0, 0, 0, 0, $new_width, $new_height, $original_width, $original_height);

if($new_width>$new_height){
    $difference = $new_width-$new_height;
    $half_difference =  round($difference/2);
    imagecopyresampled($square_image, $smaller_image, 0-$half_difference+1, 0, 0, 0, $square_size+$difference, $square_size, $new_width, $new_height);
}
if($new_height>$new_width){
    $difference = $new_height-$new_width;
    $half_difference =  round($difference/2);
    imagecopyresampled($square_image, $smaller_image, 0, 0-$half_difference+1, 0, 0, $square_size, $square_size+$difference, $new_width, $new_height);
}
if($new_height == $new_width){
    imagecopyresampled($square_image, $smaller_image, 0, 0, 0, 0, $square_size, $square_size, $new_width, $new_height);
}

$degrees = rand(1,360);
$square_image = imagerotate($square_image, $degrees, 0);
imagejpeg($square_image,NULL,100);

1 个答案:

答案 0 :(得分:5)

在代码末尾替换这些行:

$degrees = rand(1,360);
$square_image = imagerotate($square_image, $degrees, 0);
imagejpeg($square_image,NULL,100);

有了这个:

$degrees = rand(1,360);
$square_image = imagerotate($square_image, $degrees, 0);

$rotated_size = imagesx($square_image);
$enlargement_coeff = ($rotated_size - $square_size) * 1.807;
$enlarged_size = round($rotated_size + $enlargement_coeff);
$enlarged_image = imagecreatetruecolor($enlarged_size, $enlarged_size);
$final_image = imagecreatetruecolor($square_size, $square_size);

imagecopyresampled($enlarged_image, $square_image, 0, 0, 0, 0, $enlarged_size, $enlarged_size, $rotated_size, $rotated_size);
imagecopyresampled($final_image, $enlarged_image, 0, 0, round($enlarged_size / 2) - ($square_size / 2), round($enlarged_size / 2) - ($square_size / 2), $square_size, $square_size, $square_size, $square_size);

imagejpeg($final_image,NULL,100);

这背后的逻辑是:

1)执行 imagerotate()后,我们的新图像已更改其尺寸,因为每次旋转通常会产生更大的图像。由于光源是方形图像,我们采用宽度或高度来确定旋转图像的尺寸。

2)当原始图像旋转时,即使是一点点,原始图像中可用像素数据的最大平方的尺寸将始终小于原始未旋转的方形图像。因此,为了生成与初始方形图像大小相同的新方形图像,但没有“黑色边框”神器,正如您所说,我们需要放大旋转图像,以便可用像素的最大方形来自旋转图像中原始图像的数据可以变得与初始方形图像一样大。

此处的关键值为 1.807 。此值基本上显示了为尺寸与原始未旋转图像的尺寸之间的差异的每个像素放大旋转图像所需的像素数。可能有一个更好的数学公式来检索这个值,不幸的是我在数学上很糟糕,所以这就是提出这个价值的难点。

  • 45 / 135/225 / 315度的旋转将始终产生具有最小可用像素数据平方的最大图像。
  • 了解这一点,您可以比较原始图像的尺寸和45度旋转的版本。在我们的例子中,原始图像是200x200,55度旋转版本是大约283x283
  • 在像Photoshop这样的程序中,您可以确定需要放大图像的45度旋转版本的次数,以便能够从中提取200x200的正方形而没有“黑色边框” - 在我们的如果需要将283x283图像放大到433x433图像,那么我们可以提取200x200平方
  • 433 - 283 = 150 - >意思是我们需要放大150像素的最大旋转图像,以便能够从中提取200x200的正方形。
  • 283 - 200 = 83 - > 83像素是最大可能旋转图像与原始未旋转图像之间的差异。
  • 变形的“较小” - 我们可以使用的“较大”的正方形区域 - 因此 - “较小”我们需要应用的放大量。由于45度旋转导致原始图像与需要150像素放大的变换图像之间的差异为83像素,我们可以这样做:
  • 150/83 = 1.807 - >意味着原始图像和旋转图像之间1像素的差异要求旋转的图像以1.807像素放大,这样我们就可以从中提取与原始图像具有相同尺寸的正方形

3)知道对于每1个像素差异,我们需要以1.807像素放大,我们检查旋转图像大小和原始图像大小之间的差异,并将其乘以该值,以查看放大图像应具有的尺寸:

$enlargement_coeff = ($rotated_size - $square_size) * 1.807;
$enlarged_size = round($rotated_size + $enlargement_coeff);

4)我们继续生成放大的旋转图像。

imagecopyresampled($enlarged_image, $square_image, 0, 0, 0, 0, $enlarged_size, $enlarged_size, $rotated_size, $rotated_size);

5)最后,我们从放大的旋转图像中提取200x200的正方形,使用其中心坐标作为参考

imagecopyresampled($final_image, $enlarged_image, 0, 0, round($enlarged_size / 2) - ($square_size / 2), round($enlarged_size / 2) - ($square_size / 2), $square_size, $square_size, $square_size, $square_size);

要打破它($square_size / 2),将返回放大的旋转图像中心点的X和Y坐标。 round($enlarged_size / 2)返回沿X轴从中心向左所需的像素数量,沿Y轴返回中心所需的像素数量,以获得200x200的正方形。


我希望你理解逻辑,虽然我理解我的解释可能听起来有些含糊不清,所以请随意提出更多问题!