Chinese (Traditional) (中文(繁體)) translation by Fuhuan (you can also view the original English article)
想要一個用PHP調解圖像大小的簡單方法嗎? 將學習如何構建我們的PHP,並進行擴展。 調整大小應該很容易。 有多麼容易? 就三個步驟!
介紹
為了讓你快速了解我們想要達成的目標,應該是:
- 使用方便
- 格式獨立。 能使用IE打開,調整大小,並保存一些不同的圖像格式。
- 矢量圖像
注意:這不是關於如何創建類和對象的教程,雖然這個技能會有幫助,但為了遵循本教程,這不是必需的。
有很多內容需要討論 - 讓我們開始吧。
步驟1
我們將從頭開始。 在你的工作目錄中創建兩個文件:一個叫做index.php文件,另一個叫做調整,class.php


第2步調用對象
為了讓你了解我們想要實現的目標,我們將開始編寫用於調整圖像大小的代碼。 打開你的index.php的文件並添加下面的代碼。
正如你所看到的,我們正在做的事情有一個很好的目標。 我們打開圖像文件,設置要調整圖像大小的尺寸以及調整大小的類型。
然後我們保存圖像,選擇我們想要的圖像格式和圖像質量。 保存並關閉你的的的index.php文件。
1 |
|
2 |
// *** Include the class
|
3 |
include("resize-class.php"); |
4 |
|
5 |
// *** 1) Initialize / load image
|
6 |
$resizeObj = new resize('sample.jpg'); |
7 |
|
8 |
// *** 2) Resize image (options: exact, portrait, landscape, auto, crop)
|
9 |
$resizeObj -> resizeImage(150, 100, 'crop'); |
10 |
|
11 |
// *** 3) Save image
|
12 |
$resizeObj -> saveImage('sample-resized.gif', 100); |
保存並關閉你的的的index.php文件。 請記住,這完全是關於靈活性。
請記住,這完全是關於靈活性。
它是面向對象的編程(OOP),使得這種輕鬆的感覺成為可能。 想想像一個模式的類; 你可以封裝數據 - 另一個術語,這實際上意味著隱藏數據。 然後,我們可以重複使用這個類,而不需要重寫任何調整大小的代碼 - 你只需要調用適當的方法,就像我們在第二步中所做的那樣。 一旦我們的模式被創建,我們創建這個模式的實例,稱為對象。
“構造函數被稱為構造函數,它是一種特殊的類方法,當你創建一個新的對象時,該方法被類調用。”
讓我們開始創建我們的resize類。 打開resize-class.php文件。 下面是一個非常基本的類骨架結構,我將其命名為“resize”。 請注意類變量註釋行; 這是我們稍後將開始添加我們重要的類變量。
構造函數,稱為構造函數,是一種特殊的類方法(術語“方法”與函數相同,但是在討論類和對象時,常常使用術語方法),在你創建時由類調用一個新的對象。 這使得它適合我們做一些初始化 - 我們將在下一步中完成。
1 |
|
2 |
Class resize |
3 |
{
|
4 |
// *** Class variables
|
5 |
|
6 |
public function __construct() |
7 |
{
|
8 |
|
9 |
}
|
10 |
}
|
請注意,這是構造方法的雙下劃線。
第4步構造函數
我們將修改上面的構造函數方法。 首先,我們將傳入要調整大小的圖像的文件名(和路徑)。 我們將調用這個變量$ fileName。
我們需要打開通過PHP(更具體地說PHP GD庫)傳入的文件,以便PHP可以讀取圖像。 我們正在用自定義方法“openImage'來做這件事。 我會去看看這個方法
在一瞬間工作,但現在,我們需要將結果保存為類變量。 一個類變量只是一個變量 - 但它是特定於該類的。 還記得我之前提到的類變量註釋嗎? 通過輸入'private $ image;'將'image'添加為私有變量。 通過將該變量設置為“私人”,你可以設置該變量的範圍,因此只能由該類訪問。 從現在開始,我們可以調用我們打開的圖像,稱為資源,稍後我們將在調整大小時進行調用。
當我們處理它時,讓我們存儲圖像的高度和寬度。 有一種感覺,這些將在稍後有用。
你現在應該有以下。
1 |
|
2 |
Class resize |
3 |
{
|
4 |
// *** Class variables
|
5 |
private $image; |
6 |
private $width; |
7 |
private $height; |
8 |
|
9 |
function __construct($fileName) |
10 |
{
|
11 |
// *** Open up the file
|
12 |
$this->image = $this->openImage($fileName); |
13 |
|
14 |
// *** Get width and height
|
15 |
$this->width = imagesx($this->image); |
16 |
$this->height = imagesy($this->image); |
17 |
}
|
18 |
}
|
方法imagesx和imagesy構建在GD庫的一部分函數中。 它們分別檢索圖像的寬度和高度。
步驟5打開圖像
在上一步中,我們將自定義方法稱為openImage。 在這一步中,我們將創建該方法。 我們希望腳本為我們做思考,因此根據傳入的文件類型,腳本應該確定調用哪個GD庫函數來打開圖像。 這可以通過將文件擴展名與切換語句進行比較來輕鬆實現。
我們傳遞我們想要調整大小的文件並返回該文件資源。
1 |
|
2 |
private function openImage($file) |
3 |
{
|
4 |
// *** Get extension
|
5 |
$extension = strtolower(strrchr($file, '.')); |
6 |
|
7 |
switch($extension) |
8 |
{
|
9 |
case '.jpg': |
10 |
case '.jpeg': |
11 |
$img = @imagecreatefromjpeg($file); |
12 |
break; |
13 |
case '.gif': |
14 |
$img = @imagecreatefromgif($file); |
15 |
break; |
16 |
case '.png': |
17 |
$img = @imagecreatefrompng($file); |
18 |
break; |
19 |
default: |
20 |
$img = false; |
21 |
break; |
22 |
}
|
23 |
return $img; |
24 |
}
|
步驟6如何調整大小
這是愛發生的地方。 這一步實際上只是解釋我們要做什麼 - 所以這裡沒有作業。 在下一步中,我們將創建一個公共方法,我們將調用它來執行調整大小; 因此傳遞寬度和高度以及有關如何調整圖像大小的信息是有意義的。 我們來談談這個片刻。 將會出現你希望將圖像大小調整為確切大小的場景。 太好了,讓我們包括這個。 但也有時候,你不得不調整數百個圖像的大小,並且每個圖像都有不同的縱橫比 - 考慮縱向圖像。 將這些尺寸調整到一個確切的大小會導致嚴重的失真如果我們看看我們的選項以防止失真,我們可以:
- 盡可能調整圖像的大小以適應新的圖像尺寸,同時保持縱橫比。
- 調整圖像的大小,盡可能接近我們的新圖像尺寸並裁剪剩餘部分。
這兩個選項都是可行的,取決於你的需求。
是的 我們將嘗試處理以上所有內容。 總而言之,我們將提供以下選項:
- 總而言之,我們將提供以下選項: (精確)
- 按寬度調整大小 - 將設置精確寬度,根據高寬比調整高度。 (景觀)
- 按高度調整大小 - 例如按寬度調整大小,但高度將被設置並動態調整寬度。 (肖像)
- 自動確定選項2和3。 如果你正在循環顯示具有不同尺寸照片的文件夾,請讓腳本確定如何處理此問題。 (汽車)
- 調整大小,然後裁剪。 這是我最喜歡的。 確切的大小,沒有失真。 作物)
步驟7調整大小 我們開始做吧!
調整大小方法有兩部分。 首先是通過創建一些自定義方法來獲得我們新圖像的最佳寬度和高度 - 當然,如上所述傳遞調整大小'選項'。 寬度和高度以數組形式返回並設置為各自的變量。 隨意'作為參考傳遞' - 但我不是那個巨大的粉絲。
第二部分是執行實際調整大小的內容。 為了保持這個教程的大小,我讓你閱讀下面的GD函數:
- imagecreatetruecolor
- imagecopyresampled。
我們還將imagecreatetruecolor方法(新的真彩色圖像)的輸出保存為類變量。 添加'private $ imageResized;' 與你的其他類變量。
調整大小由一個稱為GD Library的PHP模塊執行。 我們使用的許多方法都是由這個庫提供的。
1 |
|
2 |
// *** Add to class variables
|
3 |
private $imageResized; |
1 |
|
2 |
public function resizeImage($newWidth, $newHeight, $option="auto") |
3 |
{
|
4 |
|
5 |
// *** Get optimal width and height - based on $option
|
6 |
$optionArray = $this->getDimensions($newWidth, $newHeight, strtolower($option)); |
7 |
|
8 |
$optimalWidth = $optionArray['optimalWidth']; |
9 |
$optimalHeight = $optionArray['optimalHeight']; |
10 |
|
11 |
// *** Resample - create image canvas of x, y size
|
12 |
$this->imageResized = imagecreatetruecolor($optimalWidth, $optimalHeight); |
13 |
imagecopyresampled($this->imageResized, $this->image, 0, 0, 0, 0, $optimalWidth, $optimalHeight, $this->width, $this->height); |
14 |
|
15 |
// *** if option is 'crop', then crop too
|
16 |
if ($option == 'crop') { |
17 |
$this->crop($optimalWidth, $optimalHeight, $newWidth, $newHeight); |
18 |
}
|
19 |
}
|
步驟8決策樹
此方法選擇要採取的路線,目標是根據你的調整大小選項獲取最佳調整大小寬度和高度。 此方法選擇要採取的路線,目標是根據你的調整大小選項獲取最佳調整大小寬度和高度。 它會調用適當的方法,我們將在下一步中創建該方法。
1 |
|
2 |
private function getDimensions($newWidth, $newHeight, $option) |
3 |
{
|
4 |
|
5 |
switch ($option) |
6 |
{
|
7 |
case 'exact': |
8 |
$optimalWidth = $newWidth; |
9 |
$optimalHeight= $newHeight; |
10 |
break; |
11 |
case 'portrait': |
12 |
$optimalWidth = $this->getSizeByFixedHeight($newHeight); |
13 |
$optimalHeight= $newHeight; |
14 |
break; |
15 |
case 'landscape': |
16 |
$optimalWidth = $newWidth; |
17 |
$optimalHeight= $this->getSizeByFixedWidth($newWidth); |
18 |
break; |
19 |
case 'auto': |
20 |
$optionArray = $this->getSizeByAuto($newWidth, $newHeight); |
21 |
$optimalWidth = $optionArray['optimalWidth']; |
22 |
$optimalHeight = $optionArray['optimalHeight']; |
23 |
break; |
24 |
case 'crop': |
25 |
$optionArray = $this->getOptimalCrop($newWidth, $newHeight); |
26 |
$optimalWidth = $optionArray['optimalWidth']; |
27 |
$optimalHeight = $optionArray['optimalHeight']; |
28 |
break; |
29 |
}
|
30 |
return array('optimalWidth' => $optimalWidth, 'optimalHeight' => $optimalHeight); |
31 |
}
|
第9步最佳尺寸
我們已經討論了這四種方法的作用。 他們只是基本的數學,真的,這是計算我們最合適的。
1 |
|
2 |
private function getSizeByFixedHeight($newHeight) |
3 |
{
|
4 |
$ratio = $this->width / $this->height; |
5 |
$newWidth = $newHeight * $ratio; |
6 |
return $newWidth; |
7 |
}
|
8 |
|
9 |
private function getSizeByFixedWidth($newWidth) |
10 |
{
|
11 |
$ratio = $this->height / $this->width; |
12 |
$newHeight = $newWidth * $ratio; |
13 |
return $newHeight; |
14 |
}
|
15 |
|
16 |
private function getSizeByAuto($newWidth, $newHeight) |
17 |
{
|
18 |
if ($this->height < $this->width) |
19 |
// *** Image to be resized is wider (landscape)
|
20 |
{
|
21 |
$optimalWidth = $newWidth; |
22 |
$optimalHeight= $this->getSizeByFixedWidth($newWidth); |
23 |
}
|
24 |
elseif ($this->height > $this->width) |
25 |
// *** Image to be resized is taller (portrait)
|
26 |
{
|
27 |
$optimalWidth = $this->getSizeByFixedHeight($newHeight); |
28 |
$optimalHeight= $newHeight; |
29 |
}
|
30 |
else
|
31 |
// *** Image to be resizerd is a square
|
32 |
{
|
33 |
if ($newHeight < $newWidth) { |
34 |
$optimalWidth = $newWidth; |
35 |
$optimalHeight= $this->getSizeByFixedWidth($newWidth); |
36 |
} else if ($newHeight > $newWidth) { |
37 |
$optimalWidth = $this->getSizeByFixedHeight($newHeight); |
38 |
$optimalHeight= $newHeight; |
39 |
} else { |
40 |
// *** Sqaure being resized to a square
|
41 |
$optimalWidth = $newWidth; |
42 |
$optimalHeight= $newHeight; |
43 |
}
|
44 |
}
|
45 |
|
46 |
return array('optimalWidth' => $optimalWidth, 'optimalHeight' => $optimalHeight); |
47 |
}
|
48 |
|
49 |
private function getOptimalCrop($newWidth, $newHeight) |
50 |
{
|
51 |
|
52 |
$heightRatio = $this->height / $newHeight; |
53 |
$widthRatio = $this->width / $newWidth; |
54 |
|
55 |
if ($heightRatio < $widthRatio) { |
56 |
$optimalRatio = $heightRatio; |
57 |
} else { |
58 |
$optimalRatio = $widthRatio; |
59 |
}
|
60 |
|
61 |
$optimalHeight = $this->height / $optimalRatio; |
62 |
$optimalWidth = $this->width / $optimalRatio; |
63 |
|
64 |
return array('optimalWidth' => $optimalWidth, 'optimalHeight' => $optimalHeight); |
65 |
}
|
第10步裁剪
如果你選擇了作物 - 也就是說,你已經使用了作物選項,那麼你還有一小步。 我們將裁剪圖像
中央。 裁剪是一個非常類似的調整大小的過程,但是會傳入更多的尺寸參數。
1 |
|
2 |
private function crop($optimalWidth, $optimalHeight, $newWidth, $newHeight) |
3 |
{
|
4 |
// *** Find center - this will be used for the crop
|
5 |
$cropStartX = ( $optimalWidth / 2) - ( $newWidth /2 ); |
6 |
$cropStartY = ( $optimalHeight/ 2) - ( $newHeight/2 ); |
7 |
|
8 |
$crop = $this->imageResized; |
9 |
//imagedestroy($this->imageResized);
|
10 |
|
11 |
// *** Now crop from center to exact requested size
|
12 |
$this->imageResized = imagecreatetruecolor($newWidth , $newHeight); |
13 |
imagecopyresampled($this->imageResized, $crop , 0, 0, $cropStartX, $cropStartY, $newWidth, $newHeight , $newWidth, $newHeight); |
14 |
}
|
第11步保存圖像
我們到了那裡; 幾乎完成。 現在是時候保存圖像了。 我們通過路徑,我們想要的圖像質量從0到100,100是最好的,並且調用適當的方法。 關於圖像質量需要注意幾點:JPG使用0-100的比例,100是最好的。 GIF圖像沒有圖像質量設置. PNG的確如此,但他們使用0-9的比例,0是最好的。 這是不好的,因為我們不希望我們每次想要保存圖像時都會記住這一點。 我們做了一些魔術來標準化一切。
1 |
|
2 |
public function saveImage($savePath, $imageQuality="100") |
3 |
{
|
4 |
// *** Get extension
|
5 |
$extension = strrchr($savePath, '.'); |
6 |
$extension = strtolower($extension); |
7 |
|
8 |
switch($extension) |
9 |
{
|
10 |
case '.jpg': |
11 |
case '.jpeg': |
12 |
if (imagetypes() & IMG_JPG) { |
13 |
imagejpeg($this->imageResized, $savePath, $imageQuality); |
14 |
}
|
15 |
break; |
16 |
|
17 |
case '.gif': |
18 |
if (imagetypes() & IMG_GIF) { |
19 |
imagegif($this->imageResized, $savePath); |
20 |
}
|
21 |
break; |
22 |
|
23 |
case '.png': |
24 |
// *** Scale quality from 0-100 to 0-9
|
25 |
$scaleQuality = round(($imageQuality/100) * 9); |
26 |
|
27 |
// *** Invert quality setting as 0 is best, not 9
|
28 |
$invertScaleQuality = 9 - $scaleQuality; |
29 |
|
30 |
if (imagetypes() & IMG_PNG) { |
31 |
imagepng($this->imageResized, $savePath, $invertScaleQuality); |
32 |
}
|
33 |
break; |
34 |
|
35 |
// ... etc
|
36 |
|
37 |
default: |
38 |
// *** No extension - No save.
|
39 |
break; |
40 |
}
|
41 |
|
42 |
imagedestroy($this->imageResized); |
43 |
}
|
現在也是摧毀我們的圖像資源釋放一些內存的好時機。 如果你要在製作中使用此功能,則最好捕獲並返回保存圖像的結果。
結論
好吧,伙計們。 感謝你參閱本教程,我希望你覺得它有用。 我會通過下面的評論感謝你的反饋。



