2013-04-27 123 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