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

PHP GD 圖片處理完全指南:從讀取、屬性獲取到水印與縮略圖生成

     編輯:PHP 相關知識

前言

GD 庫是 PHP 內建的圖形處理擴展,支援 JPEG、PNG、GIF、WBMP、XPM 等格式。本文系統梳理 GD 核心操作流程,涵蓋圖片讀取、屬性獲取、文字/圖片水印、縮略圖生成(含高質量重採樣),並針對常見坑點給出最佳實踐。

1. 讀取現有圖片

<?php
// 根據副檔名/MIME 動態選擇建立函數
function createImageFromFile(string $path): \GdImage|false
{
    $info = getimagesize($path);
    if (!$info) return false;

    return match ($info[2]) {
        IMAGETYPE_JPEG => imagecreatefromjpeg($path),
        IMAGETYPE_PNG  => imagecreatefrompng($path),
        IMAGETYPE_GIF  => imagecreatefromgif($path),
        IMAGETYPE_WBMP => imagecreatefromwbmp($path),
        default        => false,
    };
}

// 使用範例
$img = createImageFromFile('photo.jpg');
if (!$img) {
    die('不支援的圖片格式或檔案損壞');
}
// 輸出至瀏覽器
header('Content-Type: image/jpeg');
imagejpeg($img);
imagedestroy($img);

關鍵點:imagecreatefromjpeg() 等函數是根據檔案內容而非副檔名解碼。若將 .jpg 強改為 .png,imagecreatefrompng() 仍會失敗,因為檔案標頭仍是 JPEG。

2. 獲取圖片屬性

<?php
$img = imagecreatefromjpeg('photo.jpg');

// GD 內建函數
$width  = imagesx($img);   // 寬度
$height = imagesy($img);   // 高度
$type   = image_type_to_mime_type(IMAGETYPE_JPEG); // MIME

// 更豐富的資訊:getimagesize()
$info = getimagesize('photo.jpg');
/*
$info[0] = 寬度
$info[1] = 高度
$info[2] = 類型常數 (IMAGETYPE_JPEG=2, IMAGETYPE_PNG=3...)
$info[3] = width="xxx" height="yyy" 字串,可直接用於 <img> 標籤
$info['mime'] = MIME 類型
$info['channels'] = 通道數 (3=RGB, 4=RGBA)
$info['bits'] = 每通道位數
*/
echo "圖片尺寸:{$info[0]} x {$info[1]}";
echo "類型常數:{$info[2]}"; // 1=GIF, 2=JPG, 3=PNG, 4=SWF, 5=PSD, 6=BMP...

3. 文字水印實戰

<?php
/**
 * 給圖片添加文字水印
 * @param string $srcPath  源圖路徑
 * @param string $dstPath  輸出路徑(覆蓋源檔可傳同值)
 * @param string $text     水印文字
 * @param int    $pos      位置:0隨機 1左上 2置中 3右下
 * @param int    $size     字體大小
 * @param string $color    十六進位顏色 #RRGGBB
 * @param string $fontPath TTF 字體路徑
 */
function addTextWatermark(
    string $srcPath,
    string $dstPath,
    string $text,
    int $pos = 2,
    int $size = 20,
    string $color = '#FFFFFF',
    string $fontPath = 'C:/Windows/Fonts/simhei.ttf' // Linux 常用 /usr/share/fonts/truetype/dejavu/DejaVuSans.ttf
): bool
{
    if (!file_exists($srcPath)) return false;

    $info = getimagesize($srcPath);
    $srcImg = match ($info[2]) {
        IMAGETYPE_JPEG => imagecreatefromjpeg($srcPath),
        IMAGETYPE_PNG  => imagecreatefrompng($srcPath),
        IMAGETYPE_GIF  => imagecreatefromgif($srcPath),
        default        => false,
    };
    if (!$srcImg) return false;

    $imgW = imagesx($srcImg);
    $imgH = imagesy($srcImg);

    // 計算文字邊界框
    $box = imagettfbbox($size, 0, $fontPath, $text);
    $textW = $box[2] - $box[0];
    $textH = $box[3] - $box[7];

    if ($imgW < $textW || $imgH < $textH) {
        imagedestroy($srcImg);
        return false; // 圖片太小無法容納水印
    }

    // 位置計算
    switch ($pos) {
        case 0: $x = rand(0, $imgW - $textW); $y = rand(0, $imgH - $textH); break;
        case 1: $x = 10; $y = $textH + 10; break;
        case 2: $x = ($imgW - $textW) / 2; $y = ($imgH + $textH) / 2; break;
        case 3: $x = $imgW - $textW - 10; $y = $imgH - 10; break;
        default: $x = 10; $y = $textH + 10;
    }

    // 顏色解析
    $r = hexdec(substr($color, 1, 2));
    $g = hexdec(substr($color, 3, 2));
    $b = hexdec(substr($color, 5, 2));
    $textColor = imagecolorallocatealpha($srcImg, $r, $g, $b, 30); // 30% 透明度

    // 關鍵:啟用 Alpha 混合,否則透明度不生效
    imagealphablending($srcImg, true);
    imagesavealpha($srcImg, true);

    imagettftext($srcImg, $size, 0, $x, $y, $textColor, $fontPath, $text);

    // 按原格式儲存
    $saved = match ($info[2]) {
        IMAGETYPE_JPEG => imagejpeg($srcImg, $dstPath, 90),
        IMAGETYPE_PNG  => imagepng($srcImg, $dstPath, 6),
        IMAGETYPE_GIF  => imagegif($srcImg, $dstPath),
        default        => false,
    };

    imagedestroy($srcImg);
    return $saved;
}

4. 縮略圖生成:imagecopyresized vs imagecopyresampled

函數速度品質適用場景
imagecopyresized() 快 較差(鋸齒明顯) 即時預覽、低品質需求
imagecopyresampled() 稍慢 優秀(雙三次插值) 正式縮略圖、生產環境
<?php
/**
 * 高質量縮略圖(等比例縮放,支援最大寬高限制)
 */
function createThumbnail(
    string $srcPath,
    string $dstPath,
    int $maxW = 300,
    int $maxH = 300,
    int $quality = 85
): bool
{
    $info = getimagesize($srcPath);
    $srcImg = match ($info[2]) {
        IMAGETYPE_JPEG => imagecreatefromjpeg($srcPath),
        IMAGETYPE_PNG  => imagecreatefrompng($srcPath),
        IMAGETYPE_GIF  => imagecreatefromgif($srcPath),
        default        => false,
    };
    if (!$srcImg) return false;

    $srcW = imagesx($srcImg);
    $srcH = imagesy($srcImg);

    // 計算目標尺寸(等比例)
    $ratio = min($maxW / $srcW, $maxH / $srcH);
    if ($ratio >= 1) {
        // 原圖已小於限制,直接複製
        return copy($srcPath, $dstPath);
    }
    $dstW = (int)round($srcW * $ratio);
    $dstH = (int)round($srcH * $ratio);

    // 建立真彩色畫布(關鍵:imagecreatetruecolor 而非 imagecreate)
    $dstImg = imagecreatetruecolor($dstW, $dstH);

    // 保留透明通道(PNG/GIF)
    if ($info[2] === IMAGETYPE_PNG || $info[2] === IMAGETYPE_GIF) {
        imagealphablending($dstImg, false);
        imagesavealpha($dstImg, true);
        $transparent = imagecolorallocatealpha($dstImg, 255, 255, 255, 127);
        imagefill($dstImg, 0, 0, $transparent);
    }

    // 核心:重採樣縮放
    imagecopyresampled($dstImg, $srcImg, 0, 0, 0, 0, $dstW, $dstH, $srcW, $srcH);

    // 輸出
    $saved = match ($info[2]) {
        IMAGETYPE_JPEG => imagejpeg($dstImg, $dstPath, $quality),
        IMAGETYPE_PNG  => imagepng($dstImg, $dstPath, 6),
        IMAGETYPE_GIF  => imagegif($dstImg, $dstPath),
        default        => false,
    };

    imagedestroy($srcImg);
    imagedestroy($dstImg);
    return $saved;
}

5. 常見坑點總結

  1. 記憶體耗盡:處理大圖(如 4000×3000)需調大 memory_limit,或分塊處理。
  2. 透明背景變黑:PNG/GIF 縮放必須用 imagecreatetruecolor + imagesavealpha(true) + imagealphablending(false)。
  3. 字體找不到:imagettftext 需絕對路徑;Linux 下確認 php-gd 編譯支援 FreeType,且字體檔案可讀。
  4. 輸出前未發送 Header:直接輸出圖片二進位時,必須先 header('Content-Type: image/...'),且前後不能有任何空白字元。

結語

GD 雖非 ImageMagick 那般強大,但無需外部依賴、部署簡單,足以應對多數 Web 圖片處理需求。掌握「讀取→計算→繪製→輸出」四步流程,並善用 imagecopyresampled 與 Alpha 混合,即可產出專業級水印圖與縮略圖。

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