2013-04-27 151 views
5

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

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

Illustration of problem

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

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

有了这个:

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

显示您的代码。 – sachleen 2013-04-27 17:45:31

+0

我认为你的“背景大小”比喻不符合你的要求。 – Ejaz 2013-04-27 17:57:20

+0

http://stackoverflow.com/a/22511805/2106820 – 2014-03-19 16:12:04

回答

5

在围绕你的代码的末尾替换这些行

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

这里是背后的逻辑:在执行imagerotate后

1)()我们的新形象已经改变了它的尺寸,因为每转通常会导致较大的图像。由于源是一个正方形图像,我们可以采用宽度或高度来确定旋转图像的尺寸。 2)当原始图像旋转时,即使一点点,来自原始图像的可用像素数据的最大平方的尺寸将总是小于原始未旋转正方形图像的尺寸。因此,为了生成与初始方形图像大小相同但没有“黑色边框”伪影的新方形图像,我们需要放大旋转后的图像,以便可用像素的最大平方来自旋转图像中原始图像的数据可以变成与初始方形图像一样大。

这里的关键值是1.807。此值主要显示您需要为每个像素的尺寸和原始未旋转图像的尺寸放大旋转图像所需的像素数。有可能有一个更好的数学公式来检索这个值,不幸的是我吸取了数学,所以这是提出这个价值的艰难方法。

  • 45度/ 135度/ 225度/ 315度的旋转将始终以最小的可用像素数据平方产生最大的图像。
  • 知道这一点之后,您会比较原始图像和其45度旋转版本的尺寸。在我们的例子中,原始图像是200x200,而45度旋转版本是大约283x283
  • 在像Photoshop这样的程序中,您可以确定需要放大多少次才能放大图像的45度旋转版本,以便能够从中提取一个200x200的正方形,没有“黑色边框” - 在我们的情况下,需要将283x283图像放大为433x433图像,因此我们可以提取200x200平方米的图像,这意味着我们可以提取2003平方米我们需要放大150像素的最大可能旋转图像,以便能够从中提取200x200平方。
  • 283 - 200 = 83 - > 83像素是最大可能的旋转图像和原始未旋转图像之间的差异。
  • “变小”的变换 - 我们可以使用的“更大”的方形区域,因此 - 我们需要应用的“更小”的放大量。由于45度旋转导致原始图像与需要150像素放大的变换图像之间的83个像素的差异,所以我们可以这样做:
  • 150/83 = 1.807->表示在原始图像和经旋转的图像需要旋转的图像被放大以1.807个像素,这样我们就可以从中提取的正方形,其具有相同的尺寸知道,对于每个1个像素差原始图像

3)我们需要放大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平方。


我希望你明白的逻辑,虽然我理解我的解释听起来可能有点暧昧,所以请随意问更多!

+0

哇!感谢您的详细解释。你的解决方案有效,但由于调整大小会导致很多质量损失,你能解决吗? – aNewStart847 2013-04-28 08:31:03