當前位置: 首頁> 最新文章列表> 為什麼imagefontwidth() 總是返回錯誤的寬度?

為什麼imagefontwidth() 總是返回錯誤的寬度?

M66 2025-06-04

在使用PHP 處理圖像時,我們常會用到imagefontwidth()函數來獲取特定字體大小的字符寬度,從而計算文本在圖像中的確切佔位。然而,很多開發者會遇到一個令人困擾的問題: imagefontwidth()返回的寬度總是與實際顯示效果不符,導致文本位置錯亂或者截斷。本文將深入分析該問題的原因,並提供可靠的解決方案。

imagefontwidth()是什麼?

imagefontwidth(int $font)是PHP GD 庫提供的函數之一,用於獲取指定字體大小中一個字符的像素寬度。它僅適用於GD 庫中內建的位圖字體,字體大小通常是整數值(1 到5)。

示例代碼:

 $width = imagefontwidth(5);
echo "字體寬度是:$width 像素";

常見誤區與錯誤表現

問題通常出現在以下幾個方面:

1. 字體類型誤解

imagefontwidth()只對內建的位圖字體有效,不適用於TrueType 字體(TTF)。很多開發者在使用imagettftext()渲染TTF 字體時,仍錯誤地用imagefontwidth()來計算寬度,這必然導致錯誤結果。

2. 忽略字符總寬度

即使使用內建字體,也要記住imagefontwidth()返回的是單個字符的寬度,如果你要渲染的是整段字符串,需要乘以字符串長度:

 $font = 5;
$text = "Hello";
$width = imagefontwidth($font) * strlen($text);

如果字符串中包含多字節字符(如中文),那麼strlen()返回的長度將不准確,需要改用mb_strlen()

 $width = imagefontwidth($font) * mb_strlen($text, 'UTF-8');

3. 字體未正確加載

雖然PHP 的位圖字體不需要手動加載,但若使用的是自定義字體路徑或系統字體,可能會混用不同的渲染函數,從而導致理解錯誤。

如何正確獲取字符串寬度?

情況一:使用GD 內建位圖字體

直接使用imagefontwidth() ,確保字體編號在1~5 範圍,並使用strlen()mb_strlen()

 $font = 3;
$text = "Welcome";
$width = imagefontwidth($font) * strlen($text);

情況二:使用TrueType 字體

對於TTF 字體, imagefontwidth()失效,必須使用imagettfbbox()獲取字符串在指定字體下的邊界框,然後根據坐標計算寬度:

 $fontFile = "/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf";
$fontSize = 14;
$text = "Welcome";

$bbox = imagettfbbox($fontSize, 0, $fontFile, $text);
$width = abs($bbox[2] - $bbox[0]);

在這個例子中, $bbox返回一個包含8 個元素的數組,表示文本邊框的四個角點。通過右上角和左上角的橫坐標差,即可計算寬度。

示例應用:動態繪製帶文本的圖片

$img = imagecreate(200, 50);
$bg = imagecolorallocate($img, 255, 255, 255);
$color = imagecolorallocate($img, 0, 0, 0);

$fontFile = "/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf";
$text = "Hello World";
$fontSize = 12;

$bbox = imagettfbbox($fontSize, 0, $fontFile, $text);
$textWidth = abs($bbox[2] - $bbox[0]);

$x = (200 - $textWidth) / 2;
$y = 30;

imagettftext($img, $fontSize, 0, $x, $y, $color, $fontFile, $text);

header("Content-Type: image/png");
imagepng($img);
imagedestroy($img);

通過這種方式,我們確保即使是TTF 字體也能獲得準確的寬度和居中位置。

小貼士

  • 別混用imagestring()imagettftext() :它們分別適用於位圖和TTF 字體。

  • imagefontwidth()返回的結果不受DPI 設置影響,但imagettfbbox()計算的是邏輯像素,會受字體文件影響。

  • 如果部署到其他服務器,務必確認字體文件路徑存在並可訪問。例如: https://m66.net/fonts/DejaVuSans.ttf

總結

imagefontwidth()返回錯誤的寬度時,大多數情況都是因為使用了不兼容的字體類型或者忽略了字符總數的乘積。了解該函數的適用範圍,並在處理TTF 字體時改用imagettfbbox()是解決問題的關鍵。正確選擇工具,才能在圖像處理時得到期望的精確佈局與效果。