無論是版權保護、品牌曝光或防盜圖,給圖片加水印都是剛需。本文彙整四種實作層次:從基礎文字水印、物件導向封裝、支援圖片/文字雙模式九宮格定位,到 TrueType 中文字體繪製,附完整參數說明與程式碼,可直接納入專案共用庫。
適用於單一腳本、固定位置、不需中文字體。
$src = '001.png';
$info = getimagesize($src);
$type = image_type_to_extension($info[2], false);
$fun = "imagecreatefrom{$type}";
$image = $fun($src);
$col = imagecolorallocatealpha($image, 255, 255, 255, 50);
imagestring($image, 5, 20, 30, 'helloworld', $col);
header('Content-type: ' . $info['mime']);
$func = "image{$type}";
$func($image);
imagedestroy($image);
封裝載入、繪製、輸出、銷毀,支援 RGBA 顏色陣列參數。
class Image_class {
private $image, $info;
public function __construct($src) {
$info = getimagesize($src);
$type = image_type_to_extension($info[2], false);
$this->info = $info;
$this->info['type'] = $type;
$this->image = ("imagecreatefrom{$type}")($src);
}
public function fontMark($fontsize, $x, $y, $color, $text) {
$col = imagecolorallocatealpha($this->image, $color[0], $color[1], $color[2], $color[3]);
imagestring($this->image, $fontsize, $x, $y, $text, $col);
}
public function show() {
header('content-type: ' . $this->info['mime']);
("image{$this->info['type']}")($this->image);
}
public function __destruct() { imagedestroy($this->image); }
}
// 使用
$obj = new Image_class('001.png');
$obj->fontMark(20, 20, 30, [255, 255, 255, 60], 'hello');
$obj->show();
setWater()(圖片/文字雙模式、九宮格定位)支援 GIF/PNG/JPG 來源圖,水印圖支援 PNG/GIF(保留透明通道),文字水印可指定字體檔、顏色、大小。九宮格位置碼 1-9 對應左上至右下,0 為隨機。
function setWater(
$imgSrc, // 目標圖片路徑
$markImg, // 水印圖片路徑(模式 img 時必填)
$markText, // 水印文字(模式 text 時必填)
$TextColor, // 文字顏色 "R,G,B"
$markPos, // 位置 0-9
$fontType, // TTF 字體路徑(文字模式)
$markType // 'img' 或 'text'
) {
$srcInfo = @getimagesize($imgSrc);
if (!$srcInfo) return;
$srcImg_w = $srcInfo[0]; $srcImg_h = $srcInfo[1];
// 載入來源圖
switch ($srcInfo[2]) {
case 1: $srcim = imagecreatefromgif($imgSrc); break;
case 2: $srcim = imagecreatefromjpeg($imgSrc); break;
case 3: $srcim = imagecreatefrompng($imgSrc); break;
default: die("不支援的圖片類型");
}
// 計算水印寬高
if ($markType == 'img') {
if (!file_exists($markImg)) return;
$markImgInfo = @getimagesize($markImg);
$logow = $markImgInfo[0]; $logoh = $markImgInfo[1];
if ($srcImg_w < $logow || $srcImg_h < $logoh) return;
switch ($markImgInfo[2]) {
case 1: $markim = imagecreatefromgif($markImg); break;
case 3: $markim = imagecreatefrompng($markImg); break;
default: die("水印圖需為 PNG/GIF");
}
} elseif ($markType == 'text') {
$fontSize = 16;
if (empty($markText) || !file_exists($fontType)) return;
$box = @imagettfbbox($fontSize, 0, $fontType, $markText);
$logow = max($box[2], $box[4]) - min($box[0], $box[6]);
$logoh = max($box[1], $box[3]) - min($box[5], $box[7]);
}
// 九宮格座標計算
if ($markPos == 0) $markPos = rand(1, 9);
switch ($markPos) {
case 1: $x = 5; $y = 5; break;
case 2: $x = ($srcImg_w - $logow) / 2; $y = 5; break;
case 3: $x = $srcImg_w - $logow - 5; $y = 5; break;
case 4: $x = 5; $y = ($srcImg_h - $logoh) / 2; break;
case 5: $x = ($srcImg_w - $logow) / 2; $y = ($srcImg_h - $logoh) / 2; break;
case 6: $x = $srcImg_w - $logow - 5; $y = ($srcImg_h - $logoh) / 2; break;
case 7: $x = 5; $y = $srcImg_h - $logoh - 5; break;
case 8: $x = ($srcImg_w - $logow) / 2; $y = $srcImg_h - $logoh - 5; break;
case 9: $x = $srcImg_w - $logow - 5; $y = $srcImg_h - $logoh - 5; break;
}
// 建立真彩畫布並複製來源圖
$dst_img = imagecreatetruecolor($srcImg_w, $srcImg_h);
imagecopy($dst_img, $srcim, 0, 0, 0, 0, $srcImg_w, $srcImg_h);
// 繪製水印
if ($markType == 'img') {
imagecopy($dst_img, $markim, $x, $y, 0, 0, $logow, $logoh);
imagedestroy($markim);
} elseif ($markType == 'text') {
$rgb = explode(',', $TextColor);
$color = imagecolorallocate($dst_img, $rgb[0], $rgb[1], $rgb[2]);
imagettftext($dst_img, $fontSize, 0, $x, $y, $color, $fontType, $markText);
}
// 輸出覆蓋原檔或另存
switch ($srcInfo[2]) {
case 1: imagegif($dst_img, $imgSrc); break;
case 2: imagejpeg($dst_img, $imgSrc); break;
case 3: imagepng($dst_img, $imgSrc); break;
}
imagedestroy($dst_img);
imagedestroy($srcim);
}
// 呼叫範例
setWater('photo.jpg', 'logo.png', '', '', 9, '', 'img'); // 右下角圖片水印
setWater('photo.jpg', '', '© MySite', '255,255,255', 5, 'msyh.ttf', 'text'); // 置中文字水印
使用 imagecreatefromstring() 配合 file_get_contents() 處理遠端圖片,搭配 imagefttext() 繪製中文。
$dst_path = 'https://example.com/photo.jpg';
$dst = imagecreatefromstring(file_get_contents($dst_path));
$font = './msyh.ttf'; // 微軟雅黑
$black = imagecolorallocate($dst, 0, 0, 0);
imagefttext($dst, 20, 0, 10, 30, $black, $font, '版權所有 © MySite');
list($w, $h, $type) = getimagesize($dst_path);
switch ($type) {
case 1: header("content-type:image/gif"); imagegif($dst); break;
case 2: header("content-type:image/jpeg"); imagejpeg($dst); break;
case 3: header("content-type:image/png"); imagepng($dst); break;
}
imagedestroy($dst);
imagescale()),降低記憶體峰值。imagedestroy() 及時釋放資源,避免 Allowed memory size exhausted。imagick),效能與格式支援優於 GD。將上述函式整理為 WatermarkHelper.php,配合 Composer 自動載入,即可在任何專案中一鍵呼叫 WatermarkHelper::add($img, $options)。保護圖片版權,從一行代碼開始。