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

PHP GD 動態產生文字 PNG 圖片完整實作

     編輯:PHP 綜合知識

應用場景

驗證碼、水印、動態簽名檔、圖表標籤、社群分享圖 (OG Image) 等需求,伺服器端即時繪製文字輸出 PNG。

完整類別實作

<?php
/**
 * 文字轉 PNG 圖片類別
 * 用法:
 */
class TextPNG
{
    // 預設屬性
    private $font      = __DIR__ . '/fonts/DejaVuSans.ttf'; // 必須存在 TTF 檔
    private $text      = 'Sample';
    private $size      = 24;
    private $angle     = 0;       // 旋轉角度 (度)
    private $padding   = 10;      // 邊距
    private $transparent = true;  // 背景透明
    private $color     = [0, 0, 0];       // RGB 文字色
    private $bgColor   = [255, 255, 255]; // RGB 背景色

    // 設定器 (鏈式呼叫)
    public function setFont($font) { $this->font = $font; return $this; }
    public function setText($text) { $this->text = $text; return $this; }
    public function setSize($size) { $this->size = (int)$size; return $this; }
    public function setAngle($angle) { $this->angle = (int)$angle; return $this; }
    public function setPadding($padding) { $this->padding = (int)$padding; return $this; }
    public function setTransparent($bool) { $this->transparent = (bool)$bool; return $this; }
    public function setColor(array $rgb) { $this->color = $rgb; return $this; }
    public function setBgColor(array $rgb) { $this->bgColor = $rgb; return $this; }

    // 解析 GET 參數 (方便直接 )
    public function parseRequest()
    {
        $map = [
            'font' => 'setFont',
            'msg'  => 'setText',
            'size' => 'setSize',
            'rot'  => 'setAngle',
            'pad'  => 'setPadding',
            'tr'   => 'setTransparent',
            'r'    => fn($v) => $this->setColor([(int)$v, $this->color[1], $this->color[2]]),
            'g'    => fn($v) => $this->setColor([$this->color[0], (int)$v, $this->color[2]]),
            'b'    => fn($v) => $this->setColor([$this->color[0], $this->color[1], (int)$v]),
            'br'   => fn($v) => $this->setBgColor([(int)$v, $this->bgColor[1], $this->bgColor[2]]),
            'bg'   => fn($v) => $this->setBgColor([$this->bgColor[0], (int)$v, $this->bgColor[2]]),
            'bb'   => fn($v) => $this->setBgColor([$this->bgColor[0], $this->bgColor[1], (int)$v]),
        ];
        foreach ($_GET as $k => $v) {
            if (isset($map[$k])) {
                $map[$k]($v);
            }
        }
    }

    // 核心繪圖
    public function render()
    {
        // 1. 計算邊界
        $box = imagettfbbox($this->size, $this->angle, $this->font, $this->text);
        if (!$box) throw new RuntimeException("字型載入失敗: {$this->font}");

        // 文字實際寬高
        $textWidth  = max($box[2], $box[4]) - min($box[0], $box[6]);
        $textHeight = max($box[1], $box[3]) - min($box[5], $box[7]);

        // 旋轉後畫布尺寸計算 (簡化:以外接矩形)
        $width  = $textWidth  + $this->padding * 2;
        $height = $textHeight + $this->padding * 2;

        // 2. 建立畫布
        $img = imagecreatetruecolor($width, $height);
        $bg = imagecolorallocate($img, ...$this->bgColor);
        $fg = imagecolorallocate($img, ...$this->color);

        if ($this->transparent) {
            imagecolortransparent($img, $bg);
        } else {
            imagefill($img, 0, 0, $bg);
        }

        // 3. 繪製文字 (基準點 左下角)
        $x = $this->padding - min($box[0], $box[6]);
        $y = $this->padding + $textHeight - min($box[1], $box[3]); // 基線校正
        imagettftext($img, $this->size, $this->angle, $x, $y, $fg, $this->font, $this->text);

        // 4. 輸出
        header('Content-Type: image/png');
        header('Cache-Control: public, max-age=31536000'); // 1 年快取
        imagepng($img);
        imagedestroy($img);
    }
}

// ===== 入口腳本 =====
$png = new TextPNG();
$png->parseRequest()->render();
?>

字型檔案準備

  1. 下載開源字型:DejaVu Sans (支援中文需 Noto Sans CJK)。
  2. 放置於專案 fonts/ 目錄,確保 PHP 讀取權限。
  3. 類別預設路徑 __DIR__ . '/fonts/DejaVuSans.ttf',可透過 ?font=fonts/YourFont.ttf 覆蓋。

URL 參數完整表

參數說明範例
msg文字內容 (URL encode)msg=Hello%20World
size字體大小 (pt)size=32
rot旋轉角度 (度)rot=15
pad邊距 (px)pad=20
tr透明背景 (0/1)tr=0
r,g,b文字 RGB (0-255)r=255&g=0&b=0 (紅色)
br,bg,bb背景 RGBbr=0&bg=0&bb=0 (黑底)
font字型相對路徑font=fonts/NotoSansCJKtc-Regular.otf

HTML 使用範例

<img src="text_png.php?msg=PHP%20GD%20%E5%8B%95%E6%85%8B%E5%9C%96%E7%89%87&size=28&r=ffffff&br=000000&pad=15" alt="動態圖片">

<!-- 驗證碼範例 -->
<img id="captcha" src="captcha.php" onclick="this.src='captcha.php?'+Date.now()">
<script>
// captcha.php 內部 Session 儲存驗證碼,文字透過 $png->setText($_SESSION['captcha'])
</script>

進階擴充建議

  • 多行文字:自行分行、計算行高、迴圈 imagettftext。
  • 陰影/描邊:先繪製偏移 1-2px 的同樣文字 (陰影色),再繪製主文字。
  • 抗鋸齒/品質:imagefttext (FreeType2) 參數控制,或縮放高解析度再 imagecopyresampled 縮小。
  • 效能優化:固定文字 (如水印) 產生一次快存檔案/Redis,避免重複繪製。
  • 安全性:限制 msg 長度、過濾控制字元、設定 Content-Security-Policy。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved