PHP Conference Japan 2024

imagettftext

(PHP 4, PHP 5, PHP 7, PHP 8)

imagettftext使用 TrueType 字型將文字寫入影像

說明

imagettftext(
    GdImage $image,
    float $size,
    float $angle,
    int $x,
    int $y,
    int $color,
    string $font_filename,
    string $text,
    array $options = []
): array|false

使用 TrueType 字型將給定的 text 寫入影像。

注意:

在 PHP 8.0.0 之前,imagefttext()imagettftext() 的擴充變體,它額外支援 extrainfo。從 PHP 8.0.0 開始,imagettftext()imagefttext() 的別名。

參數

image

一個 GdImage 物件,由其中一個影像建立函式傳回,例如 imagecreatetruecolor()

size

字型大小(以點為單位)。

angle

角度(以度為單位),0 度表示文字從左至右讀取。較高的值表示逆時針旋轉。例如,值 90 會導致文字從下至上讀取。

x

xy 給定的座標將定義第一個字元的基準點(大約是字元的左下角)。這與 imagestring() 不同,其中 xy 定義第一個字元的左上角。例如,「左上」是 0, 0。

y

y 座標。這會設定字型基準線的位置,而不是字元的底部。

color

顏色索引。使用顏色索引的負值會關閉反鋸齒。請參閱 imagecolorallocate()

fontfile

您想要使用的 TrueType 字型的路徑。

根據 PHP 使用的 GD 函式庫版本,fontfile 開頭不是 / 時,會將 .ttf 附加到檔名,並且該函式庫會嘗試沿著函式庫定義的字型路徑搜尋該檔名。

當使用低於 2.0.18 的 GD 函式庫版本時,會使用 空格字元,而不是分號,作為不同字型檔案的「路徑分隔符」。意外使用此功能會導致警告訊息:Warning: Could not find/open font。對於這些受影響的版本,唯一的解決方案是將字型移至不包含空格的路徑。

在許多情況下,當字型與使用它的腳本位於同一目錄時,以下技巧將減輕任何包含問題。

<?php
// 設定 GD 的環境變數
putenv('GDFONTPATH=' . realpath('.'));

// 命名要使用的字型(請注意缺少 .ttf 副檔名)
$font = 'SomeFont';
?>

注意:

請注意,open_basedir 不適用於 fontfile

text

UTF-8 編碼的文字字串。

可以包含十進位數值字元參照(形式為:&#8364;)來存取字型中位置 127 以外的字元。支援十六進位格式(如 &#xA9;)。可以直接傳遞 UTF-8 編碼的字串。

不支援具名實體,例如 &copy;。請考慮使用 html_entity_decode() 將這些具名實體解碼為 UTF-8 字串。

如果在字串中使用字型不支援的字元,將會以空心矩形取代該字元。

傳回值

傳回一個包含 8 個元素的陣列,代表文字邊界框的四個點。點的順序是左下、右下、右上、左上。這些點相對於文字,與角度無關,因此當您水平查看文字時,「左上」表示左上角。如果發生錯誤,則傳回 false

更新日誌

版本 說明
8.0.0 已新增 options

範例

範例 #1 imagettftext() 範例

這個範例腳本將產生一個 400x30 像素的白色 PNG,其中包含黑色文字「Testing...」(帶有灰色陰影),字型為 Arial。

<?php
// 設定內容類型
header('Content-Type: image/png');

// 建立圖片
$im = imagecreatetruecolor(400, 30);

// 建立一些顏色
$white = imagecolorallocate($im, 255, 255, 255);
$grey = imagecolorallocate($im, 128, 128, 128);
$black = imagecolorallocate($im, 0, 0, 0);
imagefilledrectangle($im, 0, 0, 399, 29, $white);

// 要繪製的文字
$text = 'Testing...';
// 將路徑替換為您自己的字型路徑
$font = 'arial.ttf';

// 為文字加入陰影效果
imagettftext($im, 20, 0, 11, 21, $grey, $font, $text);

// 加入文字
imagettftext($im, 20, 0, 10, 20, $black, $font, $text);

// 使用 imagepng() 比使用 imagejpeg() 可以產生更清晰的文字
imagepng($im);
imagedestroy($im);
?>

上面的範例會輸出類似以下的結果

Output of example : imagettftext()

注意事項

注意: 此函式僅在 PHP 編譯時啟用 FreeType 支援時可用 (--with-freetype-dir=DIR)

參見

新增註解

使用者貢獻註解 40 則註解

Valentijn de Pagter
16 年前
如果您正在尋找簡單的文字對齊方式,您需要使用 imagettfbbox() 命令。當提供正確的參數時,它會在一個陣列中返回您要建立的文字欄位的邊界,這將允許您計算用於置中或對齊文字所需的 x 和 y 座標。

水平置中範例

<?php

$tb
= imagettfbbox(17, 0, 'airlock.ttf', 'Hello world!');

?>

$tb 會包含

陣列
(
[0] => 0 // 左下角 X 座標
[1] => -1 // 左下角 Y 座標
[2] => 198 // 右下角 X 座標
[3] => -1 // 右下角 Y 座標
[4] => 198 // 右上角 X 座標
[5] => -20 // 右上角 Y 座標
[6] => 0 // 左上角 X 座標
[7] => -20 // 左上角 Y 座標
)

對於水平對齊,我們需要從影像的寬度減去「文字框」的寬度 { $tb[2] 或 $tb[4] },然後除以二。

假設您有一個 200 像素寬的影像,您可以這樣做

<?php

$x
= ceil((200 - $tb[2]) / 2); // 文字的左下角 X 座標
imagettftext($im, 17, 0, $x, $y, $tc, 'airlock.ttf', 'Hello world!'); // 將文字寫入影像

?>

這將為您的文字提供完美的水平置中對齊,誤差約為 1 像素。祝您玩得愉快!
suyog at suyogdixit dot com
11 年前
為了您的普遍教化:以下嵌入式函式會將一塊完全對齊的文字放置到 GD 影像上。它有點耗費 CPU,所以我建議快取輸出,而不是即時進行。

引數

$image - 目標畫布的 GD 控制代碼
$size - 文字大小
$angle - 文字傾斜度(效果不是很好),水平文字請保持為 0
$left - 從左邊開始區塊的像素數
$top - 從頂部開始區塊的像素數
$color - 顏色的控制代碼 (imagecolorallocate 結果)
$font - .ttf 字型的路徑
$text - 要換行和對齊的文字
$max_width - 文字區塊的寬度,文字應該在其中換行並完全對齊
$minspacing - 單字之間的最小像素數
$linespacing - 行高的倍數(1 表示正常間距;1.5 表示 1.5 行間距等)

例如。
$image = ImageCreateFromJPEG( "sample.jpg" );
$cor = imagecolorallocate($image, 0, 0, 0);
$font = 'arial.ttf';
$a = imagettftextjustified($image, 20, 0, 50, 50, $color, $font, "Shree", 500, $minspacing=3,$linespacing=1);
header('Content-type: image/jpeg');
imagejpeg($image,NULL,100);

function imagettftextjustified(&$image, $size, $angle, $left, $top, $color, $font, $text, $max_width, $minspacing=3,$linespacing=1)
{
$wordwidth = array();
$linewidth = array();
$linewordcount = array();
$largest_line_height = 0;
$lineno=0;
$words=explode(" ",$text);
$wln=0;
$linewidth[$lineno]=0;
$linewordcount[$lineno]=0;
foreach ($words as $word)
{
$dimensions = imagettfbbox($size, $angle, $font, $word);
$line_width = $dimensions[2] - $dimensions[0];
$line_height = $dimensions[1] - $dimensions[7];
if ($line_height>$largest_line_height) $largest_line_height=$line_height;
if (($linewidth[$lineno]+$line_width+$minspacing)>$max_width)
{
$lineno++;
$linewidth[$lineno]=0;
$linewordcount[$lineno]=0;
$wln=0;
}
$linewidth[$lineno]+=$line_width+$minspacing;
$wordwidth[$lineno][$wln]=$line_width;
$wordtext[$lineno][$wln]=$word;
$linewordcount[$lineno]++;
$wln++;
}
for ($ln=0;$ln<=$lineno;$ln++)
{
$slack=$max_width-$linewidth[$ln];
if (($linewordcount[$ln]>1)&&($ln!=$lineno)) $spacing=($slack/($linewordcount[$ln]-1));
else $spacing=$minspacing;
$x=0;
for ($w=0;$w<$linewordcount[$ln];$w++)
{
imagettftext($image, $size, $angle, $left + intval($x), $top + $largest_line_height + ($largest_line_height * $ln * $linespacing), $color, $font, $wordtext[$ln][$w]);
$x+=$wordwidth[$ln][$w]+$spacing+$minspacing;
}
}
return true;
}
gav-alex at bk dot ru
19 年前
大家好!
當我的主機更新其 php 函式庫時,我在最初幾分鐘遇到了與你們一些人相同的問題。
Php 無法找到 TrueType 字型的路徑。
在我的案例中,解決方案是讓路徑看起來像這樣
<?php
imagettftext
($im, 20, 0, 620, 260, $secondary_color, "./tahoma.ttf" , "NEWS");
?>
所以,如您所見,我只是新增了 "./"

我想要在這裡新增的另一個提示是如何使用 imagettftext 在影像上以俄文寫作
您只需像這樣更改函式引數即可
<?php
imagettftext
($im, 15, 0, 575, 300, $secondary_color, "./tahoma.ttf" , win2uni("some word in russian"));
?>
其中 win2uni 是一個將 win1251 編碼轉換為 Unicode 的函式。以下是它的程式碼:
<?php

// Windows 1251 -> Unicode
function win2uni($s)
{
$s = convert_cyr_string($s,'w','i'); // win1251 -> iso8859-5
// iso8859-5 -> unicode:
for ($result='', $i=0; $i<strlen($s); $i++) {
$charcode = ord($s[$i]);
$result .= ($charcode>175)?"&#".(1040+($charcode-176)).";":$s[$i];
}
return
$result;
}
?>

今天就到這裡!謝謝您的關注!
Alex
mitch at electricpulp dot com
17 年前
如果您在字型使用上遇到問題...(找不到/無法開啟字型),請檢查資料夾/字型檔案的權限,並確保它們的權限為 775,尤其是當您剛從 Windows 電腦中提取它們時。希望這對您有所幫助!
s.pynenburg _at_ gm ail dotcom
16 年前
我有一個圖片產生器,使用者可以設定文字的起始位置 - 然而它總是超出圖片邊緣。所以我寫了這個基本函式:它會測量輸入的文字和 x 座標是否會導致文字超出邊緣,如果會,它會盡可能在一行中顯示文字,然後換到下一行。
限制:
-它只會執行一次(也就是說,它不會分成三行)
-我非常確定它不適用於有角度的文字。

<?PHP

function imagettftextwrap($im, $size, $angle, $x_pos, $y_pos, $color, $font, $instr)
{
$box = @imagettfbbox($size, 0, $font, $instr);
$width = abs($box[4] - $box[0]);
$height = abs($box[3] - $box[5]);
$overlap = (($x_pos + $width) - imagesx($im));
if(
$overlap > 0) //如果文字不符合圖片大小
{
$chars = str_split($instr);
$str = "";
$pstr = "";
for(
$m=0; $m < sizeof($chars); $m++)
{
$bo = imagettfbbox($fsize1, 0, $font1, $str);
$wid = abs($bo[4] - $bo[0]);
if((
$x_pos + $wid) < imagesx($im)) //只要不超出範圍,就從字串中新增一個字元
{
$pstr .= $chars[$m];
$bo2 = imagettfbbox($fsize1, 0, $font1, $pstr);
$wid2 = abs($bo2[4] - $bo2[0]);
if((
$x_pos + $wid2) < imagesx($im))
{
$str .= $chars[$m];
}
else
{
break;
}
}
else
{
break;
}
}
$restof = "";
for(
$l=$m; $l < sizeof($chars); $l++)
{
$restof .= $chars[$l]; //將剩餘的字串新增到新的一行
}
imagettftext($im, $size, $angle, $x_pos, $y_pos, $color, $font, $str); //印出較短的那一行
imagettftext($im, $size, $angle, 0, $y_pos + $height, $color, $font, $restof); //以及剩下的部分
}
else
{
imagettftext($im, $size, $angle, $x_pos, $y_pos, $color, $font, $instr); //否則照常輸出
}

}

?>
pillepop2003 at nospam dot yahoo dot de
19 年前
嗨,大家好,

如果您想讓文字繞著中心旋轉,而不是繞著它的「左下」旋轉點,請檢查這個函式:

<?php
// 將中心旋轉的 ttf 文字放入圖片中
// 與 imagettftext() 相同的簽名;
function imagettftext_cr(&$im, $size, $angle, $x, $y, $color, $fontfile, $text)
{
// 取得邊界框
$bbox = imagettfbbox($size, $angle, $fontfile, $text);

// 計算偏差值
$dx = ($bbox[2]-$bbox[0])/2.0 - ($bbox[2]-$bbox[4])/2.0; // 左右偏差
$dy = ($bbox[3]-$bbox[1])/2.0 + ($bbox[7]-$bbox[1])/2.0; // 上下偏差

// 新的旋轉點
$px = $x-$dx;
$py = $y-$dy;

return
imagettftext($im, $size, $angle, $px, $py, $color, $fontfile, $text);
}

?>

好棒
Phil
JohnB
14 年前
只是以防你像我一樣不知道,在 Windows 中,ttf 字型不一定在所有字體大小都會進行反鋸齒。Arial 似乎在所有大小都有效,但例如 Calibri 僅在 8 點大小進行反鋸齒,然後在所有 16 點及以上的尺寸進行反鋸齒。不僅如此,在像 10 和 12 這樣的字體大小中,字元不會以預期的角度列印:字元都以傾斜的基準線直立列印。
philip at webdesco dot com
15 年前
嗨,
對於像我這樣的菜鳥來說,如果您在包含字型檔案時遇到問題,請在檔案名稱前面加上 ./

在我的開發伺服器上,以下方法運作良好
$myfont = "coolfont.ttf";

在我的主機伺服器上,我唯一能讓字型運作的方式如下
$myfont = "./coolfont.ttf";

希望這對某人有幫助!
web at evanreeves dot com
15 年前
我在嘗試使用像素字型呈現非反鋸齒文字時遇到問題。關於為顏色設定負值的提示是有效的,但我仍然對我嘗試呈現的黑色文字感到困擾。我發現如果我將 imagecolorallocate() 函式從

$color = imagecolorallocate($base, 0, 0, 0);

改為

$color = imagecolorallocate($base, 1, 1, 1); (接近黑色)

然後在 imagettftext() 中使用顏色的負值,它就可以正常工作。不同之處在於,我的第一個實作設定了 $color = 0。顯然,你不能有 $color = -0,它沒有任何區別。當我切換到 (1,1,1) 時,它變成了 $color = 1,我可以取它的負值。
John Conde
14 年前
如果你想要建立段落,你需要將你的文字分成幾行,然後將每一行單獨放置在下一行。

以下是如何執行此操作的基本範例

<?php
// 基本字型設定
$font ='./times.ttf';
$font_size = 15;
$font_color = 0x000000

// 要放置為段落的文字
$text = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer non nunc lectus. Curabitur hendrerit bibendum enim dignissim tempus. Suspendisse non ipsum auctor metus consectetur eleifend. Fusce cursus ullamcorper sem nec ultricies. Aliquam erat volutpat. Vivamus massa justo, pharetra et sodales quis, rhoncus in ligula. Integer dolor velit, ultrices in iaculis nec, viverra ut nunc.';

// 將其分成 125 個字元的片段
$lines = explode('|', wordwrap($text, 115, '|'));

// 起始 Y 位置
$y = 513;

// 迴圈瀏覽各行並將它們放置在圖片上
foreach ($lines as $line)
{
imagettftext($image, $font_size, 0, 50, $y, $font_color, $font, $line);

// 遞增 Y,使下一行位於前一行下方
$y += 23;
}

?>
badrou14 at yahoo dot fr
3 年前
對於 windows,您可以藉助 Ohmycode 使用此程式碼
他的解決方案的連結:https://ohmycode.wordpress.com/2008/09/20/imagettftext-gdfontpath-et-ttf-sous-windows/
<?php

$font
= realpath(".")."\\arial.ttf";


$black = imagecolorallocate($im, 0, 0, 0);


$im = imagecreatetruecolor(400, 30);


imagettftext($im, 20, 0, 10, 20, $black, $font, "coucou");
?>
ben at spooty dot net
15 年前
這是一個簡單的函式,用於包裝要放入圖像中的文字。它將包裝成所需的行數,但 $angle 必須為零。$width 參數是影像的寬度。

<?php
function wrap($fontSize, $angle, $fontFace, $string, $width){

$ret = "";

$arr = explode(' ', $string);

foreach (
$arr as $word ){

$teststring = $ret.' '.$word;
$testbox = imagettfbbox($fontSize, $angle, $fontFace, $teststring);
if (
$testbox[2] > $width ){
$ret.=($ret==""?"":"\n").$word;
} else {
$ret.=($ret==""?"":' ').$word;
}
}

return
$ret;
}
?>
matt at mmkennedy dot net
16 年前
對於任何嘗試列印黑色條碼,並嘗試關閉反鋸齒的人,請記住 -1 * [0,0,0] 是 0,而不是 -0。
dotpointer
16 年前
對於那些嘗試停用字型平滑或字型 ClearType 的人,請查看此函式的顏色參數。您正在尋找的正確詞是反鋸齒。
lassial at gmail dot com
17 年前
Roy van Arem 提出了一個簡潔的程式碼,用於列出機器上的 TTF 字型。然而,它有一些問題(例如檔案副檔名的大小寫區分以及有缺陷的字型),我在以下腳本中已修正這些問題,該腳本可以實作為單一 PHP 腳本(名稱隨您喜好)

<?php //請確保上方沒有空白行

$ffolder="/usr/local/bin/fonts"; //您的字型所在的目錄

if (empty($_GET['f']))
{
$folder=dir($ffolder); //開啟目錄
echo "<HTML><BODY>\n";

while(
$font=$folder->read())
if(
stristr($font,'.ttf')) //僅限 ttf 字型
$fonts[]=$font;

$folder->close();

if (!empty(
$fonts))
{
echo
"<table><tr><th colspan='2'>$ffolder目錄中的可用字型</th></tr>"
."\n<tr><th>名稱</th><th>外觀</th>";
sort($fonts);
foreach (
$fonts as $font)
echo
"<tr><td>$font</td><td> <IMG src='".$_SERVER['SCRIPT_NAME']
.
"?f=$font'></td></tr>\n";
}
else echo
"在 $ffolder 中找不到字型";
echo
"\n</HTML></BODY>";
}

else
{
$im=@imagecreatetruecolor(200,30)
or die(
"無法初始化新的 GD 影像串流");

$black=imagecolorallocate($im,0,0,0);
$white=imagecolorallocate($im,255,255,255);

imagefill($im,0,0,$white);
imagettftext($im,14,0,5,25,$black, "$ffolder/".$_GET['f'] , $_GET['f']);

header("Content-type: image/png");
header('Content-Length: ' . strlen($im));

imagepng($im);
imagedestroy($im);
}
?>
ultraniblet at gmail dot com
17 年前
我發現 GD 的字距調整(字母之間的間距)相當差勁 - 它達不到一般設計師的標準。以下是一些改進的方法
- 使用字母的邊界框逐個放置字母,而不是使用一個字串
- 使用 $kerning 值進行調整
- 對於小字體,從較大的尺寸縮小取樣,以調整小於 1 像素的增量

例如

<?PHP

$STRING
= "NOTRE PHILOSOPHIE";

// ---- 預設值
$FONT = "CantoriaMTStd-SemiBold.otf";
$FONT_SIZE = 10.5;
$WIDTH = 200;
$HEIGHT = 16;
$KERNING = 0;
$BASELINE = 12;
$BG_COLOR = array(
"R"=>5,
"G"=>45,
"B"=>53
);
$TXT_COLOR = array(
"R"=>188,
"G"=>189,
"B"=>0
);

// ---- 建立畫布 + 調色盤
$canvas = imageCreateTrueColor($WIDTH*4,$HEIGHT*4);

$bg_color = imageColorAllocate($canvas, $BG_COLOR["R"], $BG_COLOR["G"], $BG_COLOR["B"]);

$txt_color = imageColorAllocate($canvas, $TXT_COLOR["R"], $TXT_COLOR["G"], $TXT_COLOR["B"]);

imagefill ( $canvas, 0, 0, $bg_color );

// ---- 繪圖

$array = str_split($STRING);
$hpos = 0;

for(
$i=0; $i<count($array); $i++)
{
$bbox = imagettftext( $canvas, $FONT_SIZE*4, 0, $hpos, $BASELINE*4, $txt_color, $FONT, $array[$i] );

$hpos = $bbox[2]+$KERNING;
}

// ---- 縮小取樣 & 輸出
$final = imageCreateTrueColor($WIDTH,$HEIGHT);

imageCopyResampled( $final, $canvas, 0,0,0,0, $WIDTH, $HEIGHT, $WIDTH*4, $HEIGHT*4 );

header('Content-type: image/png');

imagePNG($final);

imageDestroy($canvas);
imageDestroy($final);

?>
Tom Pike
18 年前
參考:Craig at frostycoolslug dot com

「使用顏色索引的負值可以關閉反鋸齒功能。」

這是真的,但前提是影像必須使用 imagecreate() 建立(而不是 imagecreatetruecolor())
Craig at frostycoolslug dot com
18 年前
這一個有點讓我困惑,所以為了幫助其他人...。

「使用顏色索引的負值可以關閉反鋸齒功能。」

簡而言之

<?php

$textColour
= ImageColorAllocate($image, 255, 255, 255);
ImageTTFText($image, 8, 0, 0, 0, -$textColour, $font, $text);

?>

請注意在 ImageTTFText 中,$textColor 前面的 - (減號),這會建立負色彩索引,並關閉文字的反鋸齒功能。
Mer`Zikain
18 年前
我一直在尋找為文字加入字距微調的方法,最後就寫了這個函式來做到。當然,如果你是根據文字產生圖片大小,你必須找出新的尺寸來容納新的文字寬度,但我相信你可以搞定的。

for($i=0;$i<strlen($text);$i++){
// 取得單一字元
$value=substr($text,$i,1);
if($pval){ // 檢查是否存在前一個字元
list($lx,$ly,$rx,$ry) = imagettfbbox($fontsize,0,$font,$pval);
$nxpos+=$rx+3;
}else{
$nxpos=0;
}
// 將字母加入圖片
imagettftext($im, $fontsize, 0, $nxpos, $ypos, $fontcolor, $font, $value);
$pval=$value; // 儲存目前的字元以便下次迴圈使用
}
mats dot engstrom at gmail dot com
18 年前
我同意 --colobri-- 的筆記。

僅在 ./configure 上加入 --with-ttf 和 --with-freetype-dir=/usr/lib/ 然後執行 "make; make install" 是不夠的。

我必須執行 "make clean" 然後再執行 "make install" 才能啟用 FreeType 支援。

以下是我的相關 ./configure 程式碼行
--with-gd \
--enable-gd-native-ttf \
--with-ttf \
--with-freetype-dir=/usr/lib/ \
--with-jpeg-dir=/usr/lib/libjpeg.so.62 \
--enable-exif \
alexey at NOSPAMPLS dot ozerov dot de
19 年前
請注意,如果 php.ini 中啟用了 open_basedir 限制,則 TrueType 字型的路徑必須包含在 open_basedir 清單中。
denis at reddodo dot com
16 年前
waage 所撰寫的函式 ttfWordWrappedText 中有一個小但非常危險的錯誤,只要試著執行 ttfWordWrappedText("aaaaa\naa",4) 你的腳本就會進入無窮迴圈。
你可以用以下程式碼修正這個問題
<?php
function ttfWordWrappedText_fixed($text, $strlen = 8) {
$text = urldecode($text);
$text = explode("\n", $text);
$i = 0;
foreach(
$text as $text)
{
while(
strlen($text) > $strlen && strstr($text, ' ') !== FALSE) {
$startPoint = strpos($text, ' ');
$line[$i][] =substr($text,0,$startPoint);
$text = trim(strstr($text, ' '));
}
$line[$i][] = trim($text);
}
$line[$i][] = trim($text);
$i++;
}

return
$line;
}
?>
更好的解決方案是檢查輸入文字是否有長度超過所需換行點的行。
denis at reddodo dot com
16 年前
waage 所撰寫的函式 ttfWordWrappedText 中有一個小但非常危險的錯誤,只要試著執行 ttfWordWrappedText("aaaaa\naa",4) 你的腳本就會進入無窮迴圈。
你可以用以下程式碼修正這個問題
<?php
function ttfWordWrappedText_fixed($text, $strlen = 8) {
$text = urldecode($text);
$text = explode("\n", $text);

$i = 0;
foreach(
$text as $text)
{
while(
strlen($text) > $strlen && stristr($text, ' ') !== FALSE) {
$startPoint = $strlen - 1;
while(
substr($text, $startPoint, 1) != " ") {
$startPoint--;
}
$line[$i][] = trim(substr($text, 0, $startPoint));
$text = substr($text, $startPoint);
}
$line[$i][] = trim($text);
$i++;
}

return
$line;
}
?>
更好的解決方案是檢查輸入文字是否有長度超過所需換行點的行。
waage
17 年前
我在嘗試同時取得文字換行和換行偵測時遇到一些問題,但在以下註解的幫助下,我成功了。(感謝 jwe 提供這裡的主要程式碼)

<?php
function ttfWordWrappedText($text, $strlen = 38) {
$text = urldecode($text);
$text = explode("\n", $text);

$i = 0;
foreach(
$text as $text)
{
while(
strlen($text) > $strlen) {
$startPoint = $strlen - 1;
while(
substr($text, $startPoint, 1) != " ") {
$startPoint--;
}
$line[$i][] = trim(substr($text, 0, $startPoint));
$text = substr($text, $startPoint);
}
$line[$i][] = trim($text);
$i++;
}

return
$line;
}
?>

這會為每個輸入的換行符號傳回一個陣列,並為每個換行的文字傳回一個子陣列。

例如:

陣列
(
[0] => 陣列
(
[0] => 這是第一行長文字
[1] => 我輸入的。
)

[1] => 陣列
(
[0] => 而這是之後的新行。
)
)
admin at sgssweb dot com
18 年前
另一種方法如下。在建立 GMIPluggableSet 類別的子類別之後,應該覆寫兩個方法:getExpression() 和 getVariables(),然後將其傳遞給 FontImageGenerator 類別的實例。
例如,程式碼如下

<?php

require_once 'package.fig.php';

class
SampleFontImagePluggableSet
extends GMIPluggableSet
{
var
$defaultVariables = array(
"text" => null,
"size" => null,
"font" => null,
"color" => "0x000000",
"alpha" => "100",
"padding" => 0,
"width" => null,
"height" => null,
"align" => "left",
"valign" => "middle",
"bgcolor" => "0xffffff",
"antialias" => 4
);

function
SampleFontImagePluggableSet() {
parent::GMIPluggableSet();
}

function
getExpression() {
return
"size {width}, {height};".
"autoresize none;".
"type gif, 256, {color: {bgcolor}};".
"padding {padding};".
"color {color: {bgcolor}};".
"fill;".
"color {color: {color}, {alpha}};".
"antialias {antialias};".
"font {font}, {size};".
"string {text}, 0, 0, {width}, {height}, {align}, {valign};";
}

function
getVariables() {
return
array_merge($this->defaultVariables, $_GET);
}
}

$pluggableSet = new SampleFontImagePluggableSet();
$fig = new FontImageGenerator();
$fig->setPluggableSet($pluggableSet);
$fig->execute();

?>

這段程式碼會輸出一張圖片,圖片上的文字內容由 $_GET['text'] 定義,字型由 $_GET['font'] 定義,文字顏色由 $_GET['color'] 定義,背景顏色由 $_GET['bgcolor'] 定義,依此類推。

此腳本檔案位於:http://sgssweb.com/experiments/?file=PHPFontImageGenerator
admin at phpru dot com
18 年前
我的設定:php5.1.2+apache 1.33
iconv() 函數在處理所有西里爾編碼時運作良好,因此你不需要像 win2uni 那樣編寫你的函數。
jwe
18 年前
給任何接收類似此頁面範例文字(例如:透過 $_GET['text'] 或類似方式)並需要將文字格式化為多行的人一個小提示。訣竅在於找出空格...

<?php
$text
= $_GET['text'];
// 每行最多 38 個字元...
while(strlen($text) > 38) {
$startPoint = 37;
// 尋找空格以便在此處斷行
while(substr($text, $startPoint, 1) != " ") {
$startPoint--;
}
$line[] = trim(substr($text, 0, $startPoint));
$text = substr($text, $startPoint);
}
$line[] = trim($text);
?>

結果會是一個名為 $line 的陣列,其中包含你需要依序輸出的所有文字行。

剩下的工作就是根據你想要使用的字型大小來決定圖片的正確高度。別忘了在行之間為標點符號和下行字母(逗號、g、q、p、y 等)保留一些間距空間。

當你需要使用非標準字型建立標題圖片時,imagettftext 非常有用。太棒了。非常感謝開發人員。

--Julian
plusplus7 at hotmail dot com
20 年前
如果你得到的不是文字而是全部都是矩形,那很可能表示你的 ttf 字型不是 OpenType,特別是如果它是較舊的免費軟體字型。這個要求在較舊的版本中並不存在,所以你可能會發現你的字型在升級後停止運作。要解決此問題,請嘗試下載免費的 MS Volt 工具。從那裡,開啟你的字型檔案,然後點擊「編譯」,並重新儲存。
Anonymous
17 年前
只是想評論一下 Sohel Taslim 的優秀函數...
如果有人需要為這種函數添加背景透明度(幾乎每個人都已經需要),請添加

$bg_color = imagecolorat($im,1,1);
imagecolortransparent($im, $bg_color);

在 "if($L_R_C == 0){ //Justify Left" 這一行之上
damititi at gmail dot com
16 年前
首先,感謝 sk89q 的函數!這正是我要找的。

我做了一個變更。根據字母的不同,文字的垂直對齊方式不正確。
我將這一行取代為
$line_height = $dimensions[1] - $dimensions[7];
替換為以下程式碼
$line_height = $size+4;

無論寫的是 mama 或 jeje,垂直位置都會相同。
llewellyntd at gmail dot com
16 年前
大家好,

我奮鬥了幾個月才使用 GD 函式庫做到像樣的文字換行。以下是我使用的程式碼

<?php
// 文字換行
$warpText = wordwrap($text, 30, "\n");
// 顯示文字
imagettftext($image, $fontSize, 0, $x, $y, $fontColor, $font, $warpText);
?>

希望這對某些人有幫助。

乾杯
m0r1arty at mail dot ru
16 年前
抱歉我的英文不好。
我在 Windows 下使用 imagettftext 時遇到問題。
我無法使用字型的簡短名稱(例如 "arial"、"arialbd.ttf" 等)。PHP 說找不到這個字型。
操作環境 GDFONTPATH 無效。
這是我的解決方案
<?php
$dir
=opendir('./font/');//字型目錄
if($dir)
while(
$f=readdir($dir)){
if(
preg_match('/\.ttf$/',$f)){
$font=explode('.',$f);
define($font[0],realpath('./font/'.$f));
}
}
if(
$dir)
closedir($dir);
?>
目錄「font」有兩個檔案:arial.ttf 和 arialbd.ttf
現在可以使用常數字型名稱來呼叫 imagettftext
imagettftext($img,12,0,25,28,$color,arialbd,'一些文字');
Roy van Arem
18 年前
如果你想在目錄中顯示字型清單並查看它們的外觀,你可以執行類似這樣的操作

<HTML><BODY>

<?php

$folder
=dir("fonts/"); //您的字型所在的目錄

while($font=$folder->read())
{

if(
stristr($font,'.ttf'))echo '<IMG SRC="img.php?'.substr($font,0,strpos($font,'.')).'">'; //僅限 ttf 字型

}

$folder->close();

?>

</BODY></HTML>

'img.php' 檔案的內容應該像這樣

<?php

$font
=$_SERVER["QUERY_STRING"];

header("Content-type: image/png");
$im=@imagecreatetruecolor(200,30)or die("無法初始化新的 GD 影像串流");

$black=imagecolorallocate($im,0,0,0);
$white=imagecolorallocate($im,255,255,255);

imagefill($im,0,0,$white);

imagettftext($im,18,0,5,25,$black,"fonts/".$font,$font);

imagepng($im);
imagedestroy($im);

?>

我在 http://font.beginstart.com 上實作了類似的東西
ben at evolutioncomputing co uk
18 年前
一個集中式的文字浮水印 - 長度不限,會自動調整大小到約寬度的 70%,並且可以旋轉到任何角度。

<?php
/* 取得影像資訊 */
$Image = @ImageCreateFromJPEG ("YourImage.jpg") ;
$sx = imagesx($Image) ;
$sy = imagesy($Image) ;
if (
$WatermarkNeeded)
{
/* 設定文字資訊 */
$Text="Copyright Ben Clay" ;
$Font="arial.ttf" ;
$FontColor = ImageColorAllocate ($Image,255,255,255) ;
$FontShadow = ImageColorAllocate ($Image,0,0,0) ;
$Rotation = 30 ;
/* 建立一個複製影像 */
$OriginalImage = ImageCreateTrueColor($sx,$sy) ;
ImageCopy ($OriginalImage,$Image,0,0,0,0,$sx,$sy) ;
/* 迭代取得合適的大小 */
$FontSize=1 ;
do
{
$FontSize *= 1.1 ;
$Box = @ImageTTFBBox($FontSize,0,$Font,$Text);
$TextWidth = abs($Box[4] - $Box[0]) ;
$TextHeight = abs($Box[5] - $Box[1]) ;
}
while (
$TextWidth < $sx*0.7) ;
/* 複雜的數學運算,以取得文字在正確位置的起點 */
$x = $sx/2 - cos(deg2rad($Rotation))*$TextWidth/2 ;
$y = $sy/2 + sin(deg2rad($Rotation))*$TextWidth/2 + cos(deg2rad($Rotation))*$TextHeight/2 ;
/* 先製作陰影文字,然後再製作實體文字 */
ImageTTFText ($Image,$FontSize,$Rotation,$x+4,$y+4,$FontShadow,$Font,$Text);
ImageTTFText ($Image,$FontSize,$Rotation,$x,$y,$FontColor,$Font,$Text);
/* 將原始影像合併到帶有文字的版本,以顯示透過文字的影像 */
ImageCopyMerge ($Image,$OriginalImage,0,0,0,0,$sx,$sy,50) ;
}

ImageJPEG ($Image) ;
?>
Ole Clausen
17 年前
回覆:Sohel Taslim (03-Aug-2007 06:19)

感謝您的函式,我稍微修改了一下。在新版本中,行之間有相同的間距(您範例中的 g 會在行之間產生較大的間距)- 由參數 '$Leading' 設定。

我使用了 for 迴圈來獲得更好的效能,並稍微精簡了其餘部分 :)

/**
* @name : makeImageF
*
* 使用選定的字型從文字建立影像的函式。對齊影像中的文字 (0-左對齊, 1-右對齊, 2-置中)。
*
* @param String $text : 要轉換為影像的字串。
* @param String $font : 文字的字型名稱。將字型檔案放在同一個資料夾中。
* @param int $Justify : 對齊影像中的文字 (0-左對齊, 1-右對齊, 2-置中)。
* @param int $Leading : 行之間的間距。
* @param int $W : 影像的寬度。
* @param int $H : 影像的高度。
* @param int $X : 文字在影像中的 x 座標。
* @param int $Y : 文字在影像中的 y 座標。
* @param int $fsize : 文字的字型大小。
* @param array $color : 文字顏色的 RGB 顏色陣列。
* @param array $bgcolor : 背景的 RGB 顏色陣列。
*
*/
function imagettfJustifytext($text, $font="CENTURY.TTF", $Justify=2, $Leading=0, $W=0, $H=0, $X=0, $Y=0, $fsize=12, $color=array(0x0,0x0,0x0), $bgcolor=array(0xFF,0xFF,0xFF)){

$angle = 0;
$_bx = imageTTFBbox($fsize,0,$font,$text);
$s = split("[\n]+", $text); // 行的陣列
$nL = count($s); // 行數
$W = ($W==0)?abs($_bx[2]-$_bx[0]):$W; // 如果寬度未由程式設計師初始化,則會偵測並指派完美的寬度。
$H = ($H==0)?abs($_bx[5]-$_bx[3])+($nL>1?($nL*$Leading):0):$H; // 如果高度未由程式設計師初始化,則會偵測並指派完美的高度。

$im = @imagecreate($W, $H)
or die("無法初始化新的 GD 影像串流");

$background_color = imagecolorallocate($im, $bgcolor[0], $bgcolor[1], $bgcolor[2]); // RGB 背景顏色。
$text_color = imagecolorallocate($im, $color[0], $color[1], $color[2]); // RGB 文字顏色。

if ($Justify == 0){ //左對齊
imagettftext($im, $fsize, $angle, $X, $fsize, $text_color, $font, $text);
} else {
// 建立包含所有國際字元的字母數字字串 - 包括大小寫
$alpha = range("a", "z");
$alpha = $alpha.strtoupper($alpha).range(0, 9);
// 使用字串來判斷行的高度
$_b = imageTTFBbox($fsize,0,$font,$alpha);
$_H = abs($_b[5]-$_b[3]);
$__H=0;
for ($i=0; $i<$nL; $i++) {
$_b = imageTTFBbox($fsize,0,$font,$s[$i]);
$_W = abs($_b[2]-$_b[0]);
//定義 X 座標。
if ($Justify == 1) $_X = $W-$_W; // 右對齊
else $_X = abs($W/2)-abs($_W/2); // 置中對齊

// 定義 Y 座標。
$__H += $_H;
imagettftext($im, $fsize, $angle, $_X, $__H, $text_color, $font, $s[$i]);
$__H += $Leading;
}
}

return $im;
}
simbiat at bk dot ru
9 年前
另一種使用 wordwrap 換行和置中的方法,並學習該 wordwrap 結果中的行數

<?php

$text
="privet privet privet privet privet privet2 privet2 privet2 privet2 privet2 privet3";
$text=wordwrap($text, 35, "\n", TRUE);

//設定圖片標頭以便正確顯示圖片
header("Content-Type: image/png");
//嘗試建立圖片
$im = @imagecreate(460, 215)
or die(
"無法初始化新的 GD 圖片串流");
//設定圖片的背景顏色
$background_color = imagecolorallocate($im, 0x00, 0x00, 0x00);
//設定文字的顏色
$text_color = imagecolorallocate($im, 0xFF, 0xFF, 0xFF);
//將字串加入圖片

$font = "verdana.ttf";
$font_size = 20;
$angle = 0;

$splittext = explode ( "\n" , $text );
$lines = count($splittext);

foreach (
$splittext as $text) {
$text_box = imagettfbbox($font_size,$angle,$font,$text);
$text_width = abs(max($text_box[2], $text_box[4]));
$text_height = abs(max($text_box[5], $text_box[7]));
$x = (imagesx($im) - $text_width)/2;
$y = ((imagesy($im) + $text_height)/2)-($lines-2)*$text_height;
$lines=$lines-1;
imagettftext($im, $font_size, $angle, $x, $y, $text_color, $font, $text);
}

imagepng($im);
imagedestroy($im);
?>
Borgso
17 年前
從 "webmaster at higher-designs dot com" 的程式碼中取得靠右對齊
<?php
$color
= imagecolorallocate($im, 0, 0, 0);
$font = 'visitor.ttf';
$fontsize = "12";
$fontangle = "0";
$imagewidth = imagesx($im);
$imageheight = imagesy($im);

$text = "我的靠右對齊文字";

$box = @imageTTFBbox($fontsize,$fontangle,$font,$text);
$textwidth = abs($box[4] - $box[0]);
$textheight = abs($box[5] - $box[1]);
$xcord = $imagewidth - ($textwidth)-2; // 2 = 右邊的一些空間。
$ycord = ($imageheight/2)+($textheight/2);

ImageTTFText ($im, $fontsize, $fontangle, $xcord, $ycord, $black, $font, $text);
?>
--Colibri--
18 年前
如果您已配置並編譯 PHP,且所有必要的命令列選項都已設定,但仍然收到錯誤

致命錯誤:呼叫未定義的函數 imagettftext()

請嘗試在建置 php apache 模組之前執行 "make clean"

./configure [...]
make clean
make
make install

這可能會解決您的問題 (並希望讓您避免浪費數小時嘗試不同的編譯選項!)
erik[at]phpcastle.com
19 年前
記住!!!

將字型上傳到您的網站時,您必須將傳輸模式設定為二進位。我花了一些時間才發現:P。試著從我的網站下載字型,結果損壞了。

在您的腳本中,字型的路徑請使用 realpath("arial.ttf"),這樣就不會對此產生混淆。
jwe
18 年前
我發現這行有點令人困惑

"可能包含十進位數字字元參照 (形式為:&#8364;),以存取字型中位置 127 以外的字元。"

我正在使用一個字型,其單引號和雙引號儲存在非標準位置,因此 imagettftext 將它們呈現為空格。這行似乎暗示了一種解決方案,但我花了一段時間才弄清楚。

結果,「十進位數字字元參照」是您想要字元的 *unicode* 位置的十六進位值的十進位轉換。有一段時間我嘗試使用 ASCII 位置 (我知道在 Windows 中輸入所需字元的 ALT+ 程式碼)。

在 Windows XP 字元對應表中,unicode 位置顯示為 U+2018 或 U+201C 等。忽略 U+,將該十六進位數字轉換為十進位,然後在您的文字字串中加上 &# 在前面和 ; 在結尾,然後將其傳遞給 imagettftext。

--Julian
To Top