首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 圖片水印大全:文字、圖片、九宮格定位、TrueType 字體完整實作

     編輯:PHP 相關知識

一份涵蓋所有場景的水印函式庫

無論是版權保護、品牌曝光或防盜圖,給圖片加水印都是剛需。本文彙整四種實作層次:從基礎文字水印、物件導向封裝、支援圖片/文字雙模式九宮格定位,到 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'); // 置中文字水印

層次四:TrueType 中文水印(支援遠端圖片 URL)

使用 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。
  • 生產環境建議安裝 ImageMagick 擴展(imagick),效能與格式支援優於 GD。
  • 水印圖建議預先處理為適當尺寸的 PNG-24,避免執行期縮放失真。

將上述函式整理為 WatermarkHelper.php,配合 Composer 自動載入,即可在任何專案中一鍵呼叫 WatermarkHelper::add($img, $options)。保護圖片版權,從一行代碼開始。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved