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

PHP 給圖片添加文字/圖片水印完整實現:過程式、物件導向、綜合函數三種風格

     編輯:PHP 綜合知識

圖片水印是內容保護、品牌曝光的常用手段。PHP GD 擴展提供豐富的圖像處理函數,本文展示三種代碼風格實現文字/圖片水印:過程式 (適合簡單腳本)、物件導向 (適合複用擴展)、綜合函數 (支援多種位置、格式、類型),並解析關鍵函數用法、透明度控制、記憶體管理。

核心 GD 函數速查

函數用途
getimagesize()獲取圖片寬高、MIME、類型常數
image_type_to_extension()類型常數 → 副檔名 (如 IMAGETYPE_JPEG → '.jpg')
imagecreatefromjpeg/png/gif/webp()從檔案/字串建立圖像資源
imagecreatetruecolor()建立真彩色畫布 (支援透明度)
imagecolorallocatealpha()分配帶 Alpha 通道顏色 (0 不透明 ~ 127 完全透明)
imagestring()繪製固定字體字串 (字體 1-5)
imagettftext()繪製 TrueType 字體文字 (支援中文、旋轉、大小)
imagecopy()複製圖像區塊 (水印圖片疊加)
imagecopymerge()帶透明度合併複製
imagejpeg/png/gif/webp()輸出圖像到瀏覽器或檔案
imagedestroy()釋放圖像資源記憶體

風格一:過程式函數 (單一腳本、直觀直接)


優缺點

  • ✅ 代碼緊湊、無類開銷、適合一次性腳本
  • ❌ 難以複用、參數硬編碼、錯誤處理分散

風格二:物件導向封裝 (可複用、可擴展、狀態管理)

type}";
        $this->image = $loadFunc($src);
    }

    // 文字水印
    public function addTextWatermark(int $fontSize, int $x, int $y, array $rgba, string $text): self {
        $color = imagecolorallocatealpha($this->image, $rgba[0], $rgba[1], $rgba[2], $rgba[3]);
        imagestring($this->image, $fontSize, $x, $y, $text, $color);
        return $this;  // 鏈式調用
    }

    // TTF 文字水印 (支援中文、旋轉)
    public function addTTFWatermark(string $fontFile, int $size, float $angle, int $x, int $y, array $rgba, string $text): self {
        $color = imagecolorallocatealpha($this->image, $rgba[0], $rgba[1], $rgba[2], $rgba[3]);
        imagettftext($this->image, $size, $angle, $x, $y, $color, $fontFile, $text);
        return $this;
    }

    // 圖片水印
    public function addImageWatermark(string $markSrc, int $x, int $y, int $opacity = 100): self {
        $markInfo = getimagesize($markSrc);
        $markType = image_type_to_extension($markInfo[2], false);
        $loadFunc = "imagecreatefrom{$markType}";
        $mark = $loadFunc($markSrc);
        
        // 處理透明度
        if ($opacity < 100) {
            imagefilter($mark, IMG_FILTER_COLORIZE, 0, 0, 0, (100 - $opacity) * 1.27);
        }
        imagecopy($this->image, $mark, $x, $y, 0, 0, $markInfo[0], $markInfo[1]);
        imagedestroy($mark);
        return $this;
    }

    // 輸出到瀏覽器
    public function output(): void {
        header('Content-Type: ' . $this->info['mime']);
        $outputFunc = "image{$this->type}";
        $outputFunc($this->image);
    }

    // 儲存到檔案
    public function save(string $dest): bool {
        $saveFunc = "image{$this->type}";
        return $saveFunc($this->image, $dest);
    }

    // 解構釋放
    public function __destruct() {
        if (is_resource($this->image)) imagedestroy($this->image);
    }
}

// 使用範例
$wm = new ImageWatermarker('photo.jpg');
$wm->addTextWatermark(20, 20, 30, [255,255,255,60], 'Copyright 2024')
   ->addImageWatermark('logo.png', 100, 100, 50)
   ->output();

進階擴展點

  • 支援 imagefilter() 陰影、浮雕、灰階等效果
  • 加入 rotate()、resize() 等前置處理
  • 實現 WatermarkPosition 策略類 (左上、右下、平鋪、對角線等)

風格三:綜合功能函數 (參數化、支援九宮格位置、雙模式)

 [5, 5],                                    // 左上
        2 => [($srcW - $markW) / 2, 5],                 // 上中
        3 => [$srcW - $markW - 5, 5],                   // 右上
        4 => [5, ($srcH - $markH) / 2],                 // 左中
        5 => [($srcW - $markW) / 2, ($srcH - $markH) / 2], // 中心
        6 => [$srcW - $markW - 5, ($srcH - $markH) / 2], // 右中
        7 => [5, $srcH - $markH - 5],                   // 左下
        8 => [($srcW - $markW) / 2, $srcH - $markH - 5], // 下中
        9 => [$srcW - $markW - 5, $srcH - $markH - 5],  // 右下
    ];
    [$x, $y] = $positions[$markPos];

    // 4. 建立真彩色畫布並複製源圖 (保持透明度)
    $dst = imagecreatetruecolor($srcW, $srcH);
    imagealphablending($dst, true);
    imagesavealpha($dst, true);
    imagecopy($dst, $srcIm, 0, 0, 0, 0, $srcW, $srcH);

    // 5. 疊加水印
    if ($markType === 'img') {
        imagecopy($dst, $markIm, $x, $y, 0, 0, $markW, $markH);
        imagedestroy($markIm);
    } elseif ($markType === 'text') {
        $rgb = explode(',', $textColor);
        $color = imagecolorallocate($dst, $rgb[0], $rgb[1], $rgb[2]);
        imagettftext($dst, 16, 0, $x, $y, $color, $fontFile, $markText);
    }

    // 6. 覆蓋輸出 (保持原格式)
    $saveFunc = "image" . image_type_to_extension($srcInfo[2], false);
    $saveFunc($dst, $imgSrc);

    // 7. 清理
    imagedestroy($dst);
    imagedestroy($srcIm);
}

// 使用範例
setWaterMark('photo.jpg', '', '© MySite', '255,0,0', 9, 'msyh.ttf', 'text');  // 右下紅字
setWaterMark('photo.jpg', 'logo.png', '', '', 5, '', 'img');                    // 中心圖片水印

關鍵技術細節深度解析

1. 透明度保持 (Alpha Channel)

// 方法一:imagecopymerge (簡單但不支援 Alpha 通道疊加)
imagecopymerge($dst, $mark, $x, $y, 0, 0, $w, $h, $opacity);

// 方法二:預處理水印圖片 Alpha (推薦)
$markAlpha = imagecreatetruecolor($w, $h);
imagealphablending($markAlpha, false);
imagesavealpha($markAlpha, true);
$transparent = imagecolorallocatealpha($markAlpha, 0, 0, 0, 127);
imagefill($markAlpha, 0, 0, $transparent);
imagecopy($markAlpha, $mark, 0, 0, 0, 0, $w, $h);
// 然後 imagecopy($dst, $markAlpha, ...)

4. 記憶體管理

  • 每個 imagecreate* 佔用 ~ 寬×高×4 位元組 (真彩色)
  • 大圖 (如 4000×3000) 佔用 ~48MB,及時 imagedestroy()
  • 批量處理時在循環內銷毀,避免記憶體洩漏觸發 memory_limit

生產環境建議

  1. 異步處理:上傳後推入隊列,Worker 進程處理水印,回寫結果
  2. CDN 邊緣處理:Cloudflare Workers、阿里云 CDN 圖片處理參數、七牛云數據處理,無需源站運算
  3. 原圖保留:水印版另存為 _wm.jpg,保留無水印原圖備用
  4. 格式優化:輸出 WebP (imagewebp() PHP 5.5+),體積減少 30%+
  5. 安全驗證:驗證上傳檔案 MIME、魔術位元組、尺寸限制,防止惡意圖片攻擊 GD

從簡單腳本到企業級服務,水印功能的演進核心在於「職責分離、資源隔離、異步解耦」。選擇適合當前階段的實現風格,預留擴展接口,才能應對業務增長帶來的複雜度。

  1. 上一篇文章:
  2. 下一篇文章: