這個 Image 類別封裝了 GD 庫的核心操作,提供等比縮放、水印疊加、多格式支援等功能,是 CMS、電商後台常見的圖片處理基礎設施。
<?php
class Image {
private $path = '';
public function __construct(string $path = '') {
$this->path = rtrim($path, '/') . '/';
}
// 公開 API
public function thumb(string $name, int $width, int $height, string $prefix = 'th_'): string|false
public function waterMark(string $bg, string $wm, int $pos = 0, string $prefix = 'wa_'): bool
// 內部核心方法
private function ImageInfo(string $img): array|false
private function Img_resource(string $name, array $info): GdImage|false
private function getNewSize(string $name, int $w, int $h, array $info): array
private function getImage(GdImage $src, array $size, array $info): GdImage
private function SaveNewImage(GdImage $img, string $name, array $info): string
private function getPos(array $bg, array $wm, int $pos): array|false
private function CopyImage(GdImage $bg, GdImage $wm, array $pos, array $wmInfo): GdImage
}
?>
thumb()支援指定目標寬高,自動計算最佳縮放比例,保持原圖比例不變形:
// 使用範例
$img = new Image('/var/www/uploads/');
$thumbName = $img->thumb('product.jpg', 300, 300); // 產生 th_product.jpg
// 內部演算法邏輯
private function getNewSize(...) {
$srcW = $info['width'];
$srcH = $info['height'];
// 計算縮放比例
$scale = min($width / $srcW, $height / $srcH);
if ($scale >= 1) return ['width' => $srcW, 'height' => $srcH];
return [
'width' => round($srcW * $scale),
'height' => round($srcH * $scale)
];
}
waterMark()支援 9 個預設位置 + 隨機位置,自動檢查水印尺寸不得超過背景圖:
| 參數值 | 位置 | 座標計算 |
|---|---|---|
| 1 | 左上 | (0, 0) |
| 2 | 上中 | ($bgW-$wmW)/2, 0 |
| 3 | 右上 | $bgW-$wmW, 0 |
| 4 | 左中 | 0, ($bgH-$wmH)/2 |
| 5 | 正中 | ($bgW-$wmW)/2, ($bgH-$wmH)/2 |
| 6 | 右中 | $bgW-$wmW, ($bgH-$wmH)/2 |
| 7 | 左下 | 0, $bgH-$wmH |
| 8 | 下中 | ($bgW-$wmW)/2, $bgH-$wmH |
| 9 | 右下 | $bgW-$wmW, $bgH-$wmH |
| 0 | 隨機 | rand(0, $bgW-$wmW), rand(0, $bgH-$wmH) |
private function getImage(GdImage $src, array $size, array $info): GdImage {
$dst = imagecreatetruecolor($size['width'], $size['height']);
// 關鍵:處理 GIF/PNG 透明背景
$transparent = imagecolortransparent($src);
if ($transparent >= 0) {
$rgb = imagecolorsforindex($src, $transparent);
$newTransparent = imagecolorallocate($dst, $rgb['red'], $rgb['green'], $rgb['blue']);
imagefill($dst, 0, 0, $newTransparent);
imagecolortransparent($dst, $newTransparent);
}
// 高品質重採樣
imagecopyresampled($dst, $src, 0, 0, 0, 0,
$size['width'], $size['height'],
$info['width'], $info['height']);
imagedestroy($src);
return $dst;
}
private function SaveNewImage(GdImage $img, string $name, array $info): string {
$path = $this->path . $name;
switch ($info['type']) {
case 'gif': imagegif($img, $path); break;
case 'jpg': imagejpeg($img, $path, 90); break; // 品質 90%
case 'png': imagepng($img, $path, 6); break; // 壓縮等級 6
}
imagedestroy($img);
return $name;
}
<?php
require_once 'Image.php';
$processor = new Image('/var/www/images/');
// 1. 商品圖自動生成多種尺寸
$sizes = [
['w' => 800, 'h' => 800, 'prefix' => 'lg_'],
['w' => 300, 'h' => 300, 'prefix' => 'md_'],
['w' => 150, 'h' => 150, 'prefix' => 'sm_'],
];
foreach ($sizes as $size) {
$processor->thumb('source.jpg', $size['w'], $size['h'], $size['prefix']);
}
// 2. 批次加浮水印
$watermarks = ['logo.png', 'copyright.png'];
foreach ($watermarks as $wm) {
$processor->waterMark('lg_source.jpg', $wm, 9, 'wm_'); // 右下角
}
// 3. 會員頭像處理流程
function processAvatar(string $tmpPath, string $saveDir): array {
$img = new Image($saveDir);
$filename = 'avatar_' . uniqid() . '.jpg';
// 移動暫存檔
move_uploaded_file($tmpPath, $saveDir . $filename);
// 生成正方形縮圖 (強制裁切需擴展)
$img->thumb($filename, 200, 200, 'sq_');
// 加上品牌水印
$img->waterMark('sq_' . $filename, 'brand_logo.png', 5);
return ['original' => $filename, 'square' => 'sq_' . $filename];
}
?>
ini_set('memory_limit', '256M')ImageProcessorInterface 便於切換 GD/Imagickimagewebp()、imageavif() 輸出現代格式| 現象 | 可能原因 | 解決方案 |
|---|---|---|
| 縮圖變黑/失真 | 未處理透明通道 | 確認 imagecolortransparent 邏輯 |
| 水印位置偏移 | 座標計算錯誤 | 檢查 getPos() 邊界條件 |
| PNG 體積過大 | 預設無壓縮 | 使用 imagepng($img, $path, 6) |
| JPG 品質差 | 品質參數過低 | 設定 imagejpeg($img, $path, 85-95) |
這個圖片處理類雖然基於 GD 庫實作,但架構清晰、功能完整,涵蓋了 Web 應用 80% 的圖片處理需求。理解其核心演算法(等比縮放、九宮格定位、透明度保持)對於進階圖片處理、遷移至 Imagick 或雲端圖片服務都有極大幫助。