旋转和裁剪 [英] Rotate and crop

查看:141
本文介绍了旋转和裁剪的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm rotating and cropping a image with PHP, but I get the black border showing, I know you can change the background color, but I want to rotate and crop the image to fill the whole image. Basically something similar to background-size: cover; (left) in CSS versus background-size: contain; (right).

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

See the image below, at right is what I got now, left is what I want to achieve. The number of degrees to rotate is dynamic and the image to be produced and the source-image are both square (200x200).

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

Here is my quick and dirty code:

$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);


推荐答案

在代码末尾替换这些行:

Replace these lines at around the end of your code:

$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()后,我们的新图像已更改其尺寸,因为每次旋转通常会产生更大的图像。由于源是方形图像,我们采用宽度或高度来确定旋转图像的尺寸。

1) After performing imagerotate() our new image has changed its dimensions, since every rotation generally results in a larger image. Since the source is a square image we take either the width or the height in order to determine the dimensions of the rotated image.

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

2) When the original image is rotated, even a little bit, the dimensions of the largest square of usable pixel data from the original image will always be smaller than the original unrotated square image. Therefore, in order to generate a new square image of the same size as the initial square image, but without the "black border" artifact, as you call it, we need to enlarge the rotated image, so that the largest square of usable pixel data from the original image in the rotated image can become as big as the initial square image.

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

The key value here is 1.807. This value basically shows how many pixels you need to enlarge a rotated image for each pixel of difference between its dimensions and the dimensions of the original unrotated image. There's probably a better Math formula to retrieve this value, unfortunately I suck at Math, so here's the hard way of coming up with that value.


  • 45 / 135/225 / 315度的旋转将始终产生具有最小可用像素数据平方的最大图像。

  • 了解这一点,您比较原始图像的尺寸及其45度旋转版本。在我们的例子中,原始图像为200x200,45度旋转版本约为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像素放大,这样我们就可以从中提取与原始图像具有相同尺寸的正方形

  • A rotation of 45 / 135 / 225 / 315 degrees will always produce the largest image with the smallest usable pixel data square.
  • Knowing this, you compare the dimensions of the original image and its 45-degrees-rotated version. In our case the original image is 200x200 and a 45-degrees-rotated version is about 283x283
  • In a program like Photoshop, you determine how many times you need to enlarge the 45-degrees-rotated version of the image in order to be able to extract a 200x200 square from it, without a "black border" - in our case the 283x283 image needed to be enlarged to a 433x433 image, so we could extract a 200x200 square
  • 433 - 283 = 150 -> meaning we need to enlarge the largest possible rotated image with 150 pixels in order to be able to extract a 200x200 square from it.
  • 283 - 200 = 83 -> 83 pixels is the difference between the largest possible rotated image and the original unrotated image.
  • The "smaller" the transformation - the "larger" the square area we can use and thus - the "smaller" the amount of enlargement we need to apply. And since a 45 degree rotation resulted in a difference of 83 pixels between the original image and the transformed image that required a 150 pixel enlargement, we can do:
  • 150 / 83 = 1.807 -> meaning a difference of 1 pixel between the original image and the rotated image requires that the rotated image is enlarged with 1.807 pixels, so that we can extract a square from it that has the same dimensions as the original image

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

3) Knowing that for each 1 pixel difference we need to enlarge with 1.807 pixels, we check what's the difference between our rotated image size and original image size and multiply it by that value, to see what dimensions should the enlarged image have:

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

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

4) We go ahead and generate the enlarged rotated image.

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

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

5) Finally, we extract a 200x200 square from our enlarged rotated image, using its center coordinates as reference

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($ enlarge_size / 2)返回沿X轴从中心向左,沿Y轴在中心上方留下的像素数量,以便获得200x200平方。

To break that down ($square_size / 2) returns the X and Y coordinates of the center point in the enlarged rotated image. round($enlarged_size / 2) returns the amount of pixels that you need left from the center along the X axis, and above the center along the Y axis, in order to get a 200x200 square.

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

I hope you understand the logic, although I'm understanding my explanation may sound a bit ambiguous, so please feel free to ask more!

这篇关于旋转和裁剪的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆