| 函式 | 用途 | 透明度支援 |
|---|---|---|
imagecopy() | 直接複製像素區塊 | 不支援(PNG 需手動處理 Alpha) |
imagecopymerge() | 複製並依 pct 參數混合 | 支援 0-100 透明度 |
現代 PHP 版本中 imagecopy() 已能正確處理 PNG Alpha 通道(需配合 imagealphablending()、imagesavealpha()),imagecopymerge() 較適用於簡單不透明水印疊加。
; php.ini
extension=php_gd2.dll
; 移除前面分號並重啟 Apache/IIS
<?php
header('Content-Type: image/jpeg');
$dstFile = 'images/flower_1.jpg';
$srcFile = 'images/logo.gif'; // 水印圖
$alpha = 30; // 透明度 0-100
$dst = imagecreatefromjpeg($dstFile);
$src = imagecreatefromgif($srcFile);
$dstInfo = getimagesize($dstFile);
$srcInfo = getimagesize($srcFile);
// 右下角座標
$x = $dstInfo[0] - $srcInfo[0];
$y = $dstInfo[1] - $srcInfo[1];
imagecopymerge($dst, $src, $x, $y, 0, 0, $srcInfo[0], $srcInfo[1], $alpha);
imagejpeg($dst);
imagedestroy($dst);
imagedestroy($src);
?>
ImageTool<?php
class ImageTool {
/** 取得圖片資訊 */
public static function imageInfo(string $path): ?array {
if (!file_exists($path)) return null;
$info = getimagesize($path);
if (!$info) return null;
return [
'width' => $info[0],
'height' => $info[1],
'ext' => substr($info['mime'], strpos($info['mime'], '/') + 1), // jpeg, png, gif
];
}
/**
* 加水印
* @param string $dst 目標圖片
* @param string $water 水印圖片
* @param string|null $save 輸出路徑(null 覆寫原檔)
* @param int $pos 位置 0=左上 1=右上 2=右下(預設) 3=左下
* @param int $alpha 透明度 0-100
*/
public static function water(string $dst, string $water, ?string $save = null, int $pos = 2, int $alpha = 50): bool {
$dInfo = self::imageInfo($dst);
$wInfo = self::imageInfo($water);
if (!$dInfo || !$wInfo) return false;
if ($wInfo['width'] > $dInfo['width'] || $wInfo['height'] > $dInfo['height']) return false;
$dFunc = 'imagecreatefrom' . $dInfo['ext'];
$wFunc = 'imagecreatefrom' . $wInfo['ext'];
if (!function_exists($dFunc) || !function_exists($wFunc)) return false;
$dIm = $dFunc($dst);
$wIm = $wFunc($water);
// 計算座標
switch ($pos) {
case 0: $px = 0; $py = 0; break; // 左上
case 1: $px = $dInfo['width'] - $wInfo['width']; $py = 0; break; // 右上
case 3: $px = 0; $py = $dInfo['height'] - $wInfo['height']; break; // 左下
default: $px = $dInfo['width'] - $wInfo['width']; $py = $dInfo['height'] - $wInfo['height']; // 右下
}
imagecopymerge($dIm, $wIm, $px, $py, 0, 0, $wInfo['width'], $wInfo['height'], $alpha);
$save = $save ?? $dst;
if ($save === $dst) @unlink($dst);
$outFunc = 'image' . $dInfo['ext'];
$outFunc($dIm, $save);
imagedestroy($dIm);
imagedestroy($wIm);
return true;
}
/**
* 等比縮圖並白底置中
*/
public static function thumb(string $dst, ?string $save = null, int $width = 200, int $height = 200): bool {
$dInfo = self::imageInfo($dst);
if (!$dInfo) return false;
$scale = min($width / $dInfo['width'], $height / $dInfo['height']);
$dFunc = 'imagecreatefrom' . $dInfo['ext'];
$dIm = $dFunc($dst);
$tIm = imagecreatetruecolor($width, $height);
$white = imagecolorallocate($tIm, 255, 255, 255);
imagefill($tIm, 0, 0, $white);
$newW = (int)($dInfo['width'] * $scale);
$newH = (int)($dInfo['height'] * $scale);
$padX = (int)(($width - $newW) / 2);
$padY = (int)(($height - $newH) / 2);
imagecopyresampled($tIm, $dIm, $padX, $padY, 0, 0, $newW, $newH, $dInfo['width'], $dInfo['height']);
$save = $save ?? $dst;
if ($save === $dst) @unlink($dst);
$outFunc = 'image' . $dInfo['ext'];
$outFunc($tIm, $save);
imagedestroy($dIm);
imagedestroy($tIm);
return true;
}
}
// 使用範例
ImageTool::water('photo.jpg', 'logo.png', 'photo_wm.jpg', 2, 40);
ImageTool::thumb('photo_wm.jpg', 'photo_thumb.jpg', 300, 200);
?>
若水印為帶 Alpha 通道的 PNG,建議改用 imagecopy() 並開啟混色模式:
$dst = imagecreatefromjpeg('photo.jpg');
$wm = imagecreatefrompng('watermark.png');
imagealphablending($dst, true); // 開啟混色
imagesavealpha($dst, true); // 保留 Alpha
$x = imagesx($dst) - imagesx($wm);
$y = imagesy($dst) - imagesy($wm);
imagecopy($dst, $wm, $x, $y, 0, 0, imagesx($wm), imagesy($wm));
imagejpeg($dst, 'out.jpg', 90);
memory_limit,處理完立即 imagedestroy()。Intervention\Image 提供鏈式語法:Image::make($img)->insert($wm, 'bottom-right', 10, 10)->save($out)。