環境準備
# Windows php.ini
extension=php_gd2.dll
# Linux (Debian/Ubuntu)
sudo apt-get install php-gd
# CentOS/RHEL
sudo yum install php-gd
核心函式速查表
| 分類 | 函式 | 用途 |
| 建立資源 | imagecreatetruecolor(w,h) | 建立真彩色畫布 |
imagecreatefromjpeg/png/gif/webp/bmp($file) | 從檔案載入 |
imagecreatefromstring($data) | 從二進位字串載入 |
imagecreatefromwebp() | 支援 WebP (PHP 7.0+) |
| 輸出/儲存 | imagejpeg/png/gif/webp/bmp($im, $file?, $quality?) | 輸出至瀏覽器或檔案 |
imagedestroy($im) | 釋放記憶體 |
getimagesize($file) | 取得寬、高、MIME、HTML 屬性字串 |
| 幾何變換 | imagescale($im, $w, $h, $mode?) | 簡單等比縮放 (PHP 5.5+) |
imagecopyresampled() | 高品質重採樣縮放/裁切 |
imagerotate($im, $angle, $bgColor) | 旋轉(角度順時針) |
| 翻轉 | 無內建函式,需自行逐列/逐行複製 | 見下方範例 |
| 透明度 | imagealphablending($im, false) | 關閉混色,直接複製 Alpha |
imagesavealpha($im, true) | 儲存時保留 Alpha 通道 |
| 銳化 | 無內建,需自行卷積核運算 | 見下方範例 |
| 繪圖/文字 | imagettftext() | TrueType 字體繪文字(需 FreeType) |
imageline/rectangle/ellipse/arc() | 基本幾何圖形 |
實用片段集錦
1. 等比縮放並白底置中(通用函式)
function thumbFit(string $src, string $dst, int $maxW, int $maxH, string $bgColor = '#FFFFFF'): bool {
[$w, $h, $type] = getimagesize($src);
$create = ['image/jpeg'=>'imagecreatefromjpeg','image/png'=>'imagecreatefrompng','image/gif'=>'imagecreatefromgif'][$type ?? ''];
if (!$create) return false;
$im = $create($src);
$scale = min($maxW / $w, $maxH / $h);
$nW = (int)round($w * $scale);
$nH = (int)round($h * $scale);
$canvas = imagecreatetruecolor($maxW, $maxH);
$rgb = sscanf($bgColor, '#%02x%02x%02x');
$bg = imagecolorallocate($canvas, ...$rgb);
imagefill($canvas, 0, 0, $bg);
imagecopyresampled($canvas, $im, ($maxW-$nW)/2, ($maxH-$nH)/2, 0, 0, $nW, $nH, $w, $h);
$out = ['image/jpeg'=>'imagejpeg','image/png'=>'imagepng','image/gif'=>'imagegif'][$type];
$out($canvas, $dst, 90);
imagedestroy($im); imagedestroy($canvas);
return true;
}
2. 裁切指定區域
function crop(string $src, string $dst, int $x, int $y, int $w, int $h): bool {
$im = imagecreatefromjpeg($src); // 簡化:假設 JPEG
$cut = imagecreatetruecolor($w, $h);
imagecopyresampled($cut, $im, 0, 0, $x, $y, $w, $h, $w, $h);
imagejpeg($cut, $dst, 90);
imagedestroy($im); imagedestroy($cut);
return true;
}
3. 旋轉 45 度(背景白)
$im = imagecreatefromjpeg('photo.jpg');
$rotated = imagerotate($im, 45, imagecolorallocate($im, 255, 255, 255));
imagejpeg($rotated, 'rotated.jpg', 90);
imagedestroy($im); imagedestroy($rotated);
4. 水平/垂直翻轉
function flipHorizontal(string $src, string $dst): void {
$im = imagecreatefromjpeg($src);
$w = imagesx($im); $h = imagesy($im);
$out = imagecreatetruecolor($w, $h);
for ($x = 0; $x < $w; $x++) {
imagecopy($out, $im, $w - $x - 1, 0, $x, 0, 1, $h);
}
imagejpeg($out, $dst); imagedestroy($im); imagedestroy($out);
}
function flipVertical(string $src, string $dst): void {
$im = imagecreatefromjpeg($src);
$w = imagesx($im); $h = imagesy($im);
$out = imagecreatetruecolor($w, $h);
for ($y = 0; $y < $h; $y++) {
imagecopy($out, $im, 0, $h - $y - 1, 0, $y, $w, 1);
}
imagejpeg($out, $dst); imagedestroy($im); imagedestroy($out);
}
5. PNG 透明保留縮放
function resizePngKeepAlpha(string $src, string $dst, int $w, int $h): bool {
$im = imagecreatefrompng($src);
imagesavealpha($im, true);
$out = imagecreatetruecolor($w, $h);
imagealphablending($out, false);
imagesavealpha($out, true);
imagecopyresampled($out, $im, 0, 0, 0, 0, $w, $h, imagesx($im), imagesy($im));
imagepng($out, $dst);
imagedestroy($im); imagedestroy($out);
return true;
}
6. 簡易銳化(3x3 卷積核)
function sharpen(string $src, string $dst, float $amount = 1.0): bool {
$im = imagecreatefromjpeg($src);
$w = imagesx($im); $h = imagesy($im);
$out = imagecreatetruecolor($w, $h);
// 3x3 銳化核
$kernel = [
[0, -1, 0],
[-1, 5, -1],
[0, -1, 0]
];
$div = array_sum(array_map('array_sum', $kernel));
$offset = 0;
if (function_exists('imageconvolution')) {
imageconvolution($im, $kernel, $div, $offset);
imagejpeg($im, $dst, 90);
} else {
// 手動像素級實作(略,效能極差)
}
imagedestroy($im); imagedestroy($out);
return true;
}
7. 文字水印(中文支援)
function textWatermark(string $src, string $dst, string $text, string $font, int $size, array $rgb, int $x, int $y): bool {
$im = imagecreatefromjpeg($src);
$color = imagecolorallocate($im, ...$rgb);
imagettftext($im, $size, 0, $x, $y, $color, $font, $text);
imagejpeg($im, $dst, 90);
imagedestroy($im);
return true;
}
8. 圖片水印(支援 PNG 透明)
function imageWatermark(string $src, string $dst, string $wm, int $pos = 2, int $alpha = 100): bool {
$dstIm = imagecreatefromjpeg($src);
$wmIm = imagecreatefrompng($wm);
imagealphablending($dstIm, true);
imagesavealpha($dstIm, true);
$dw = imagesx($dstIm); $dh = imagesy($dstIm);
$ww = imagesx($wmIm); $wh = imagesy($wmIm);
$positions = [
0 => [0, 0],
1 => [$dw-$ww, 0],
2 => [$dw-$ww, $dh-$wh],
3 => [0, $dh-$wh],
];
[$px, $py] = $positions[$pos] ?? $positions[2];
if ($alpha >= 100) {
imagecopy($dstIm, $wmIm, $px, $py, 0, 0, $ww, $wh);
} else {
imagecopymerge($dstIm, $wmIm, $px, $py, 0, 0, $ww, $wh, $alpha);
}
imagejpeg($dstIm, $dst, 90);
imagedestroy($dstIm); imagedestroy($wmIm);
return true;
}
最佳實務建議
- 記憶體管理:大圖處理前
ini_set('memory_limit', '512M'),用完立即 imagedestroy()。
- 錯誤處理:每個 GD 函式回傳值檢查,拋出異常或記錄日誌。
- 安全性:上傳檔案請用
getimagesize() 驗證真實類型,禁止直接執行上傳目錄腳本。
- 現代化:新專案請直接
composer require intervention/image,享受鏈式 API、單元測試、Laravel/Symfony 整合。