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

PHP GD imagecopy 實現圖片合成與水印添加完整教學

     編輯:PHP 綜合知識

前言

在 PHP 圖形處理中,將一張圖片 (Logo、水印、縮圖、二維碼) 合成到另一張背景圖上,是極高頻的剛需場景。GD 庫的核心函數 imagecopy() 及其進階版本 imagecopyresampled()、imagecopymerge() 為此提供了強大支撐。本文將從基礎複製到縮放合成、透明度控制、水印實戰,全方位講解圖片合成技術。

核心函數對比

函數用途關鍵特性
imagecopy()**等比複製**源圖像素 1:1 複製到目標,不縮放,速度最快
imagecopyresized()**縮放複製** (低質量)支援縮放,但無插值算法,縮放後鋸齒明顯
imagecopyresampled()**高質量縮放複製**雙三次插值,**生產環境首選**,畫質平滑
imagecopymerge()**帶透明度合成**支援 pct 參數 (0-100) 控制源圖不透明度,適用水印
imagecopymergegray()灰度合成轉灰度後合成,較少用

基礎實戰:Logo 水印添加 (等比複製)

<?php
// 1. 載入背景圖 (畫布)
$background = imagecreatefromjpeg('photo.jpg');
if (!$background) die('背景圖載入失敗');

// 2. 載入水印圖 (源圖)
$watermark = imagecreatefrompng('logo.png'); // PNG 支援透明通道
if (!$watermark) die('水印圖載入失敗');

// 3. 獲取水印尺寸
$wmarkWidth = imagesx($watermark);
$wmarkHeight = imagesy($watermark);

// 4. 計算放置位置:右下角 (留 10px 邊距)
$destX = imagesx($background) - $wmarkWidth - 10;
$destY = imagesy($background) - $wmarkHeight - 10;

// 5. 【核心】複製合成
// imagecopy($dst, $src, $dst_x, $dst_y, $src_x, $src_y, $src_w, $src_h)
imagecopy($background, $watermark, $destX, $destY, 0, 0, $wmarkWidth, $wmarkHeight);

// 6. 輸出
header('Content-Type: image/jpeg');
imagejpeg($background, null, 90); // 品質 90%

// 7. 釋放資源
imagedestroy($background);
imagedestroy($watermark);
?>

進階實戰:縮放合成 (縮小 Logo 置中)

當水印圖過大,需按比例縮放後再合成,必須使用 imagecopyresampled()。

<?php
$bg = imagecreatefromjpeg('bg.jpg');
$logo = imagecreatefrompng('big_logo.png');

$bgW = imagesx($bg);
$bgH = imagesy($bg);
$logoW = imagesx($logo);
$logoH = imagesy($logo);

// 目標:Logo 寬度佔背景 20%,高度等比縮放
$targetW = $bgW * 0.2;
$targetH = $logoH * ($targetW / $logoW);

// 計算置中座標
$destX = ($bgW - $targetW) / 2;
$destY = ($bgH - $targetH) / 2;

// 高質量縮放複製
// imagecopyresampled($dst, $src, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h)
imagecopyresampled($bg, $logo, $destX, $destY, 0, 0, $targetW, $targetH, $logoW, $logoH);

header('Content-Type: image/jpeg');
imagejpeg($bg);
imagedestroy($bg);
imagedestroy($logo);
?>

專業水印實作:半透明 PNG + 文字水印雙重防護

<?php
function addWatermark($srcPath, $savePath, $wmText = 'Copyright © 2024') {
    // 1. 載入源圖 (自動檢測類型)
    $info = getimagesize($srcPath);
    $mime = $info['mime'];
    $createFunc = 'imagecreatefrom' . (($mime === 'image/jpeg') ? 'jpeg' : (($mime === 'image/png') ? 'png' : 'gif'));
    $image = $createFunc($srcPath);
    
    // 2. 啟用 Alpha 混合 (關鍵:讓 PNG 透明通道正常工作)
    imagealphablending($image, true);
    imagesavealpha($image, true);

    // --- A. 圖片水印 (半透明 Logo) ---
    $logo = imagecreatefrompng('watermark_logo.png');
    $logoW = imagesx($logo); $logoH = imagesy($logo);
    $margin = 20;
    $dstX = imagesx($image) - $logoW - $margin;
    $dstY = imagesy($image) - $logoH - $margin;
    
    // 使用 imagecopymerge 控制不透明度 (50%)
    imagecopymerge($image, $logo, $dstX, $dstY, 0, 0, $logoW, $logoH, 50);
    imagedestroy($logo);

    // --- B. 文字水印 (對角線平鋪) ---
    $font = __DIR__ . '/fonts/SourceHanSansTC-Regular.otf';
    $textColor = imagecolorallocatealpha($image, 255, 255, 255, 80); // 白色,透明度 80/127
    $fontSize = 20;
    $angle = -30; // 傾斜角度
    
    $bbox = imagettfbbox($fontSize, $angle, $font, $wmText);
    $textW = $bbox[2] - $bbox[0];
    $textH = $bbox[1] - $bbox[7];
    
    // 平鋪繪製
    for ($x = -$textW; $x < imagesx($image); $x += $textW + 50) {
        for ($y = -$textH; $y < imagesy($image); $y += $textH + 50) {
            imagettftext($image, $fontSize, $angle, $x, $y, $textColor, $font, $wmText);
        }
    }

    // 3. 保存
    imagejpeg($image, $savePath, 90);
    imagedestroy($image);
    return true;
}

// 使用
addWatermark('original.jpg', 'watermarked.jpg');
?>

關鍵技術點深度解析

1. Alpha 混合與透明通道保存

// 處理 PNG 透明背景時,必須開啟:
imagealphablending($canvas, true);  // 開啟混合模式
imagesavealpha($canvas, true);      // 保存完整 Alpha 通道 (而非單色透明)

若不開啟 `imagesavealpha(true)`,輸出的 PNG 透明區域會變黑或變白。

2. 座標系統與裁剪邏輯

  • 源圖座標 (`src_x`, `src_y`):從源圖哪裡開始讀取 (0,0 為左上角)。可實現**圖片裁剪** (只複製源圖一部分)。
  • 目標座標 (`dst_x`, `dst_y`):貼上到目標圖的位置。
  • 尺寸參數:`src_w`, `src_h` 為源圖讀取區域寬高;`dst_w`, `dst_h` (僅 resampled) 為目標繪製區域寬高。

3. 記憶體管理與效能

  • 大圖處理 (如 4000x3000) 會消耗大量記憶體 (單張 ~48MB)。
  • 調整 `memory_limit` (如 `ini_set('memory_limit', '256M')`)。
  • 處理完成**立即** `imagedestroy()` 釋放資源。
  • 極大圖片建議分塊處理或使用 ImageMagick (Imagick 擴展),其記憶體管理更優、支援磁盤快取。

常見問題排查

現象原因解決
水印背景有白邊/黑邊PNG 非真透明,或 Alpha 混合未開啟確保水印為真 Alpha 透明 PNG;開啟 `imagealphablending` + `imagesavealpha`
合成後圖片變模糊使用 `imagecopyresized` 而非 `resampled`改用 `imagecopyresampled()`
透明度不生效用 `imagecopy` 複製帶透明度的 PNG用 `imagecopymerge($dst, $src, ..., pct)` 或確保 Alpha 混合開啟
座標錯位混淆 src/dst 參數順序記住順序:`$dst, $src, $dst_x, $dst_y, $src_x, $src_y...`

總結

imagecopy 系列函數是 PHP GD 圖片合成的基石。掌握 四大核心變體 的適用場景:

  1. 等比複製 → `imagecopy()`
  2. 高質量縮放 → `imagecopyresampled()`
  3. 透明度控制 → `imagecopymerge()`
  4. Alpha 通道完整保留 → `imagealphablending` + `imagesavealpha` + `imagecopy/resampled`

結合座標計算、記憶體管理、錯誤處理,即可構建穩健的圖片水印、海報生成、縮圖裁剪服務。對於高併發、超大圖、複雜濾鏡場景,建議遷移至 ImageMagick (Imagick) 或 Go/Rust 圖像微服務。

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