旋转和裁剪

aNe*_*847 5 php crop imagemagick image-resizing

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

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

问题的例证

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

$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);
Run Code Online (Sandbox Code Playgroud)

mar*_*gtr 5

在代码末尾替换这些行:

$degrees = rand(1,360);
$square_image = imagerotate($square_image, $degrees, 0);
imagejpeg($square_image,NULL,100);
Run Code Online (Sandbox Code Playgroud)

有了这个:

$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);
Run Code Online (Sandbox Code Playgroud)

这是背后的逻辑:

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);
Run Code Online (Sandbox Code Playgroud)

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

imagecopyresampled($enlarged_image, $square_image, 0, 0, 0, 0, $enlarged_size, $enlarged_size, $rotated_size, $rotated_size);
Run Code Online (Sandbox Code Playgroud)

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);
Run Code Online (Sandbox Code Playgroud)

为了打破它,($square_size / 2)返回放大的旋转图像中的中心点的X和Y坐标.round($enlarged_size / 2)返回沿X轴从中心向左,以及沿Y轴在中心上方留下的像素数量,以获得200x200的正方形.


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