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

PHP 動態圖片生成完整指南:GD 與 FreeType 打造按鈕、廣告條與多行文字

     編輯:PHP 綜合知識

核心概念

PHP 不只能輸出 HTML,更能生成非 HTML 資料——動態圖片。應用場景:從資料庫產生廣告橫幅、圖形按鈕、驗證碼、圖表、個性化圖片等。關鍵在於正確設定 HTTP 標頭並輸出二進位圖片資料。

基礎版:單行文字按鈕生成器 (button.php)

<?php
// 關鍵:設定輸出內容類型為 GIF
header("Content-type: image/gif");

// 參數處理
$s = isset($_GET['s']) ? (int)$_GET['s'] : 11; // 字體大小
$text = $_GET['text'] ?? 'PHP is Cool';       // 顯示文字

// 計算文字邊界框 (需 FreeType 支援)
$fontPath = 'fonts/TIMES.TTF';
$bbox = imagettfbbox($s, 0, $fontPath, $text);
$dx = abs($bbox[2] - $bbox[0]); // 文字寬度
$dy = abs($bbox[5] - $bbox[3]); // 文字高度

$paddingX = 9;
$paddingY = 9;

// 建立調色盤圖像
$im = imagecreate($dx + $paddingX, $dy + $paddingY);

// 分配顏色
$blue = imagecolorallocate($im, 0x2c, 0x6D, 0xAF);
$black = imagecolorallocate($im, 0, 0, 0);
$white = imagecolorallocate($im, 255, 255, 255);

// 繪製雙層邊框產生 3D 效果
imagerectangle($im, 0, 0, $dx + $paddingX - 1, $dy + $paddingY - 1, $black);
imagerectangle($im, 0, 0, $dx + $paddingX, $dy + $paddingY, $white);

// 繪製文字陰影 (黑色,偏移 1px)
imagettftext($im, $s, 0, (int)($paddingX/2) + 1, $dy + (int)($paddingY/2), $black, $fontPath, $text);
// 繪製主文字 (白色)
imagettftext($im, $s, 0, (int)($paddingX/2), $dy + (int)($paddingY/2) - 1, $white, $fontPath, $text);

// 輸出並釋放
imagegif($im);
imagedestroy($im);
?>

關鍵注意事項

  • 純淨輸出: 檔案不得包含任何 HTML 標籤、PHP 標籤外的空白字元、BOM,否則圖片損毀。
  • 字體路徑: 將 TIMES.TTF 複製至網站目錄 fonts/ 下。中文字體需支援對應字符集 (如 msyh.ttc 微軟雅黑)。
  • 調用方式: <img src="button.php?s=36&text=PHP+is+Cool">

進階版:多行文字、自訂顏色、JPEG 輸出 (button.php 完整版)

<?php
header("Content-type: image/jpeg");

// 參數預設值
$bgRed   = $_GET['bgred']   ?? 0;
$bgGreen = $_GET['bggreen'] ?? 51;
$bgBlue  = $_GET['bgblue']  ?? 153;
$txtRed   = $_GET['chred']   ?? 255;
$txtGreen = $_GET['chgreen'] ?? 255;
$txtBlue  = $_GET['chblue']  ?? 255;
$shadow   = $_GET['shadow']  ?? 'yes';
$wrapPos  = $_GET['wrappos'] ?? 20;   // 換行字數
$crop     = $_GET['crop']    ?? 2.2;  // 行高倍數
$quality  = $_GET['jpegquality'] ?? 80;
$fontSize = $_GET['s']       ?? 11;
$fontName = $_GET['font']    ?? 'arialbd';

$text = $_GET['text'] ?? '';
$text = wordwrap($text, $wrapPos, "\n", true); // 自動換行

$fontPath = "/www/ttfonts/$fontName.ttf";

// 計算多行文字邊界
$bbox = imagettfbbox($fontSize, 0, $fontPath, $text);
$dx = abs($bbox[2] - $bbox[0]);
$dy = abs($bbox[5] - $bbox[3]);
$upper = abs($bbox[5]);
$under = $bbox[1];
$textHeight = $upper - $under;

$padX = 9;
$lineCount = substr_count($text, "\n") + 1;
$padY = ($lineCount * $crop * $fontSize) + $fontSize;

// 建立圖像
$im = imagecreate($dx + $padX, $textHeight + $padY);

// 顏色分配
$bgColor = imagecolorallocate($im, $bgRed, $bgGreen, $bgBlue);
$black = imagecolorallocate($im, 0, 0, 0);
$txtColor = imagecolorallocate($im, $txtRed, $txtGreen, $txtBlue);

// 雙層邊框
imagerectangle($im, 0, 0, $dx + $padX - 1, $textHeight + $padY - 1, $black);
imagerectangle($im, 0, 0, $dx + $padX, $textHeight + $padY, $white);

// 繪製陰影與主文字
if ($shadow === 'yes') {
    imagettftext($im, $fontSize, 0, (int)($padX/2) - 1, $textHeight + 2 + (int)($padY/2) - 3, $black, $fontPath, $text);
}
imagettftext($im, $fontSize, 0, (int)($padX/2) - 2, $textHeight + 2 + (int)($padY/2) - 4, $txtColor, $fontPath, $text);

// 輸出 JPEG
imagejpeg($im, null, $quality);
imagedestroy($im);
?>

測試表單 (test.php)

<form method="POST" action="button.php">
  文字: <input name="text" size="60"><br>
  大小: <input name="s" size="6" value="14"><br>
  換行位置: <input name="wrappos" size="3" value="20"><br>
  背景色 (R/G/B): <input name="bgred" value="0"> <input name="bggreen" value="51"> <input name="bgblue" value="153"><br>
  文字色 (R/G/B): <input name="chred" value="255"> <input name="chgreen" value="255"> <input name="chblue" value="255"><br>
  字型: <input name="font" value="arialbd"><br>
  陰影: <input type="radio" name="shadow" value="yes" checked>是 <input type="radio" name="shadow" value="no">否<br>
  <input type="submit" value="產生圖片">
</form>

環境需求與安裝

  • PHP 編譯時需啟用 --with-gd 並支援 FreeType (--with-freetype-dir)
  • Linux: apt-get install php-gd libfreetype6-dev 或編譯時指定路徑
  • Windows: PHP 內建 GD,確保 extension=gd 啟用,FreeType 通常已包含
  • 字體檔: 從 C:/Windows/Fonts 複製 arialbd.ttf、msyh.ttc 等至網站 fonts/ 目錄

常見問題與解決

問題原因解決
圖片顯示破損/無法載入PHP 檔案有 BOM、空白輸出、錯誤訊息混入純 PHP 檔案、關閉錯誤顯示 error_reporting(0)、確保 header() 在任何輸出前
中文顯示方框/亂碼字體不支援中文字符使用支援中文的 TTF 字體 (微軟雅黑、思源黑體、Noto Sans TC)
imagettfbbox/imagettftext 未定義GD 未啟用 FreeType 支援重新編譯 PHP 或安裝 php-gd 套件 (確認 php -m | grep gd)
字體檔找不到路徑錯誤、權限不足使用絕對路徑 __DIR__ . '/fonts/...'、確保 Web 使用者可讀取

現代化擴充應用

  1. 驗證碼生成: 隨機字串 + 干擾線/噪點 + Session 儲存驗證碼
  2. 動態圖表: 結合 pChart、SVG、Chart.js (前端渲染更佳)
  3. 個性化海報: 背景圖 + 用戶頭像 + 姓名 + QR Code (使用 imagecopyresampled、QRcode 庫)
  4. 水印添加: 批次處理上傳圖片加浮水印
  5. WebP/AVIF 輸出: imagewebp()、imageavif() (PHP 8.1+) 更優壓縮率

效能優化建議

  • 啟用 OPcache 加速 PHP 執行
  • 高頻圖片 (如按鈕) 產生後快取至檔案/Redis,避免重複計算
  • 大圖處理使用 imagecreatetruecolor() 真彩色模式,完成後 imagedestroy() 釋放記憶體
  • 考慮將圖片生成移至佇列 (Worker) 非同步處理,API 即時回傳任務 ID

總結

PHP GD + FreeType 提供強大的伺服端動態圖片生成能力。從簡單按鈕到複雜多行排版、自訂樣式,核心在於:正確設定 Content-Type、純淨二進位輸出、善用字體測量計算版面、妥善管理記憶體。現代開發中,簡單圖片 (按鈕、驗證碼) 仍適合伺服端生成;複雜圖表、高互動視覺化建議前端 (Canvas/SVG/WebGL) 渲染,伺服端只提供資料 API。

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