PHP 的 GD 库配合 FreeType 使用 ImageTTFText() 繪製文本時,僅支援 UTF-8 編碼。若直接傳入 GB2312(中文常用編碼)字符串,會導致中文顯示為亂碼或方塊。本文提供一個完整的 gb2utf8() 函數,實現 GB2312 到 UTF-8 的精確轉換,支援中英混排。
轉換分兩步:
gb2312.txt 映射表)。<?php
// gb2utf8.php
function gb2utf8($gb) {
if (!trim($gb)) return $gb;
// 載入 GB2312 -> Unicode 映射表(格式:GB碼十六進制=Unicode十六進制)
$table = [];
$lines = file("gb2312.txt");
foreach ($lines as $line) {
$gbCode = hexdec(substr($line, 0, 6));
$uniCode = hexdec(substr($line, 7, 6));
$table[$gbCode] = $uniCode;
}
$utf8 = "";
while (strlen($gb) > 0) {
$ord = ord($gb[0]);
if ($ord > 127) { // 雙字節中文字符
$char = substr($gb, 0, 2);
$gb = substr($gb, 2);
$gbCode = hexdec(bin2hex($char)) - 0x8080;
$uniCode = $table[$gbCode] ?? 0x3F; // 未找到用 '?'
$utf8 .= u2utf8($uniCode);
} else { // ASCII 單字節
$char = substr($gb, 0, 1);
$gb = substr($gb, 1);
$utf8 .= u2utf8(ord($char));
}
}
return $utf8;
}
// Unicode 碼點 -> UTF-8 字節序列
function u2utf8($c) {
$str = "";
if ($c < 0x80) {
$str .= chr($c);
} elseif ($c < 0x800) {
$str .= chr(0xC0 | ($c >> 6));
$str .= chr(0x80 | ($c & 0x3F));
} elseif ($c < 0x10000) {
$str .= chr(0xE0 | ($c >> 12));
$str .= chr(0x80 | (($c >> 6) & 0x3F));
$str .= chr(0x80 | ($c & 0x3F));
} elseif ($c < 0x200000) {
$str .= chr(0xF0 | ($c >> 18));
$str .= chr(0x80 | (($c >> 12) & 0x3F));
$str .= chr(0x80 | (($c >> 6) & 0x3F));
$str .= chr(0x80 | ($c & 0x3F));
}
return $str;
}
?>
<?php
header("Content-type: image/jpeg");
$im = imagecreate(800, 400);
$black = imagecolorallocate($im, 0, 0, 0);
$white = imagecolorallocate($im, 255, 255, 255);
include("gb2utf8.php");
$text = gb2utf8("aaa中過32434"); // 中英混排
// 注意:字體路徑需根據服務器實際情況調整
imagettftext($im, 90, 10, 110, 300, $white, "/usr/share/fonts/truetype/simsun.ttc", $text);
imagejpeg($im);
imagedestroy($im);
?>
gb2312.txt 必須與腳本同目錄,內容格式為每行 GB碼(6位十六進制)=Unicode碼(6位十六進制)。可從網上下載標準映射表。imagettftext 第 7 參數需指向真實存在的 TrueType 字體文件(如 simsun.ttc、msyh.ttc)。Windows 通常在 C:/Windows/Fonts/,Linux 在 /usr/share/fonts/。--with-freetype-dir 並確保 GD 支援 FreeType。static 變量或 APCu),避免每次調用都讀文件。PHP 5.6+ 可直接使用 mb_convert_encoding($str, 'UTF-8', 'GB2312') 或 iconv('GB2312', 'UTF-8//IGNORE', $str),無需手工映射表,效率更高且維護性更好。本文方案主要適用於早期 PHP 版本或無 mbstring/iconv 擴展的受限環境。