PHP 日本研討會 2024

imagettfbbox

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

imagettfbbox使用 TrueType 字型取得文字的邊界框

描述

imagettfbbox(
    float $size,
    float $angle,
    string $font_filename,
    string $string,
    array $options = []
): array|false

此函式計算並傳回 TrueType 文字的邊界框,單位為像素。

注意:

在 PHP 8.0.0 之前,imageftbbox()imagettfbbox() 的延伸變體,額外支援 extrainfo。 從 PHP 8.0.0 開始,imagettfbbox()imageftbbox() 的別名。

參數

size

字體大小,單位為點。

angle

測量 string 時的角度,單位為度。

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

string

要測量的字串。

傳回值

imagettfbbox() 成功時會傳回一個包含 8 個元素的陣列,表示文字邊界框的四個點,錯誤時則傳回 false

key 內容
0 左下角,X 位置
1 左下角,Y 位置
2 右下角,X 位置
3 右下角,Y 位置
4 右上角,X 位置
5 右上角,Y 位置
6 左上角,X 位置
7 左上角,Y 位置

這些點相對於文字,與 angle 無關,因此「左上」表示水平檢視文字時的左上角。

更新日誌

版本 描述
8.0.0 已新增 options

範例

範例 #1 imagettfbbox() 範例

<?php
// 建立一個 300x150 的圖片
$im = imagecreatetruecolor(300, 150);
$black = imagecolorallocate($im, 0, 0, 0);
$white = imagecolorallocate($im, 255, 255, 255);

// 設定背景為白色
imagefilledrectangle($im, 0, 0, 299, 299, $white);

// 字型檔的路徑
$font = './arial.ttf';

// 首先,我們建立第一個文字的邊界框
$bbox = imagettfbbox(10, 45, $font, 'Powered by PHP ' . phpversion());

// 這是我們的 X 和 Y 座標
$x = $bbox[0] + (imagesx($im) / 2) - ($bbox[4] / 2) - 25;
$y = $bbox[1] + (imagesy($im) / 2) - ($bbox[5] / 2) - 5;

// 寫入文字
imagettftext($im, 10, 45, $x, $y, $black, $font, 'Powered by PHP ' . phpversion());

// 建立第二個文字的邊界框
$bbox = imagettfbbox(10, 45, $font, 'and Zend Engine ' . zend_version());

// 設定座標使其緊鄰第一個文字
$x = $bbox[0] + (imagesx($im) / 2) - ($bbox[4] / 2) + 10;
$y = $bbox[1] + (imagesy($im) / 2) - ($bbox[5] / 2) - 5;

// 寫入文字
imagettftext($im, 10, 45, $x, $y, $black, $font, 'and Zend Engine ' . zend_version());

// 輸出到瀏覽器
header('Content-Type: image/png');

imagepng($im);
imagedestroy($im);
?>

注意事項

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

另請參閱

新增註解

使用者貢獻的註解 37 則註解

blackbart at simail dot it
14 年前
我寫了一個簡單的函數,可以計算*精確*的邊界框(單一像素精度)。
該函數會回傳一個具有以下鍵的關聯陣列
left, top:您將傳遞給 imagettftext 的座標
width, height:您必須建立的圖像尺寸

<?php
function calculateTextBox($font_size, $font_angle, $font_file, $text) {
$box = imagettfbbox($font_size, $font_angle, $font_file, $text);
if( !
$box )
return
false;
$min_x = min( array($box[0], $box[2], $box[4], $box[6]) );
$max_x = max( array($box[0], $box[2], $box[4], $box[6]) );
$min_y = min( array($box[1], $box[3], $box[5], $box[7]) );
$max_y = max( array($box[1], $box[3], $box[5], $box[7]) );
$width = ( $max_x - $min_x );
$height = ( $max_y - $min_y );
$left = abs( $min_x ) + $width;
$top = abs( $min_y ) + $height;
// to calculate the exact bounding box i write the text in a large image
$img = @imagecreatetruecolor( $width << 2, $height << 2 );
$white = imagecolorallocate( $img, 255, 255, 255 );
$black = imagecolorallocate( $img, 0, 0, 0 );
imagefilledrectangle($img, 0, 0, imagesx($img), imagesy($img), $black);
// for sure the text is completely in the image!
imagettftext( $img, $font_size,
$font_angle, $left, $top,
$white, $font_file, $text);
// start scanning (0=> black => empty)
$rleft = $w4 = $width<<2;
$rright = 0;
$rbottom = 0;
$rtop = $h4 = $height<<2;
for(
$x = 0; $x < $w4; $x++ )
for(
$y = 0; $y < $h4; $y++ )
if(
imagecolorat( $img, $x, $y ) ){
$rleft = min( $rleft, $x );
$rright = max( $rright, $x );
$rtop = min( $rtop, $y );
$rbottom = max( $rbottom, $y );
}
// destroy img and serve the result
imagedestroy( $img );
return array(
"left" => $left - $rleft,
"top" => $top - $rtop,
"width" => $rright - $rleft + 1,
"height" => $rbottom - $rtop + 1 );
}
?>
jodybrabec at gmail dot com
13 年前
非常清晰的函式版本,帶有範例....

<?php

function calculateTextBox($text,$fontFile,$fontSize,$fontAngle) {
/************
這個簡單的函式會計算 *精確的* 邊界框(單像素精度)。
函式會回傳一個包含以下鍵的關聯陣列:
left, top: 您將傳遞給 imagettftext 的座標
width, height: 您必須建立的影像的尺寸
*************/
$rect = imagettfbbox($fontSize,$fontAngle,$fontFile,$text);
$minX = min(array($rect[0],$rect[2],$rect[4],$rect[6]));
$maxX = max(array($rect[0],$rect[2],$rect[4],$rect[6]));
$minY = min(array($rect[1],$rect[3],$rect[5],$rect[7]));
$maxY = max(array($rect[1],$rect[3],$rect[5],$rect[7]));

return array(
"left" => abs($minX) - 1,
"top" => abs($minY) - 1,
"width" => $maxX - $minX,
"height" => $maxY - $minY,
"box" => $rect
);
}

// 使用範例 - gif 影像輸出

$text_string = "哈囉 世界";
$font_ttf = "./fonts/arial.ttf";
$font_size = 22;
$text_angle = 0;
$text_padding = 10; // 影像邊距 - 文字周圍

$the_box = calculateTextBox($text_string, $font_ttf, $font_size, $text_angle);

$imgWidth = $the_box["width"] + $text_padding;
$imgHeight = $the_box["height"] + $text_padding;

$image = imagecreate($imgWidth,$imgHeight);
imagefill($image, imagecolorallocate($image,200,200,200));

$color = imagecolorallocate($image,0,0,0);
imagettftext($image,
$font_size,
$text_angle,
$the_box["left"] + ($imgWidth / 2) - ($the_box["width"] / 2),
$the_box["top"] + ($imgHeight / 2) - ($the_box["height"] / 2),
$color,
$font_ttf,
$text_string);

header("Content-Type: image/gif");
imagegif($image);
imagedestroy($image);

?>

[ 請注意:由於 header() 呼叫的關係,在 <?php ... ?> 標籤前後不要有空格! ]
marclaz
18 年前
請注意,由於 imageTTFBbox 和 imageTTFText 函式會回傳一個座標陣列,其中可能包含負數,因此在計算高度和寬度時必須小心。

正確的做法是使用 abs() 函式

對於水平文字

$box = @imageTTFBbox($size,0,$font,$text);
$width = abs($box[4] - $box[0]);
$height = abs($box[5] - $box[1]);

然後,若要將文字置中於 ($x,$y) 位置,程式碼應如下所示

$x -= $width/2;
$y += $heigth/2;

imageTTFText($img,$size,0,$x,$y,$color,$font,$text);

這是因為 (0,0) 頁面原點位於頁面左上角,而 (0,0) 文字原點位於可讀文字的左下角。

希望這對您有幫助。
ryan at retronetworks dot com
19 年前
這是一個函式,可讓您使用自己的「字元間距」級別(每個字元之間分隔的像素數量)來寫入字串。它使用 imagettfbbox 來判斷每個字元的寬度,因此它不會歧視較窄的字元。在此範例中,$t = 您想要將每個字元與其相鄰字元分隔的像素距離。

<?php
function ImageTTFTextWithTracking($im, $size, $angle, $t, $x, $y, $color, $font, $text) {
$numchar = strlen($text);
for(
$i = 0; $i < $numchar; $i++) {
# 指定字元
$char[$i] = substr($text, $i, 1);

# 寫入字元
imagettftext($im, $size, $angle, ($x + $w + ($i * $t)), $y, $color, $font, $char[$i]);

# 取得字元的寬度
$width = imagettfbbox($size, $angle, $font, $char[$i]);
$w = $w + $width[2];
}
}
?>

請注意,它目前不適用於 0 預設值以外的角度(我不需要這樣)。
Anonymous
12 年前
值得指出的是,GD2 使用的「點」單位對應於 gd.h 中定義的 96 dpi。
#define GD_RESOLUTION 96 /* 每英吋像素 */

因此,如果您想將邊界框轉換回字體點數,您需要將所有座標乘以 72/96 = 3/4。
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 像素。玩得開心!
peterjwest3 at gmail dot com
14 年前
正如你們許多人所知,此函式在幾個 PHP 版本中存在錯誤。它應該傳回相對於字體基準線的座標。因此,如果您的文字包含 g 和 p 之類的字元,則邊界框應該在 Y 軸上延伸到零以下,但它沒有。這是一個問題,因為 imagettftext() 使用基準線定位文字,因此您的所有文字都會錯位。

我的解決方案是使用 imagettfbbox() 和 imagettftext() 建立一個使用所有 ASCII 字元的所需字體和字體大小的圖片。此圖片的高度用作實際圖片的高度。

然後我分析圖片以取得文字的垂直偏移(背景顏色應為 $baseColor)
<?php
function getYOffset($image, $baseColor) {
for(
$y = 0; $y < $this->height(); $y++)
for(
$x = 0; $x < $this->width(); $x++)
if (
imagecolorat($image, $x, $y) !== $baseColor)
return
$y; }
?>

此偏移可以用作字體的基準線(對於此字體大小)。您可以對水平偏移使用類似的技巧,但這會根據第一個字元而改變。
decimealgo at gmail dot com
16 年前
這是一個將文字字串重新格式化為給定寬度的文字區塊的函式。
當您有一個長的單行字串,並且想要將其放入固定寬度但不在意其高度時,此函式很有用

<?php
function makeTextBlock($text, $fontfile, $fontsize, $width)
{
$words = explode(' ', $text);
$lines = array($words[0]);
$currentLine = 0;
for(
$i = 1; $i < count($words); $i++)
{
$lineSize = imagettfbbox($fontsize, 0, $fontfile, $lines[$currentLine] . ' ' . $words[$i]);
if(
$lineSize[2] - $lineSize[0] < $width)
{
$lines[$currentLine] .= ' ' . $words[$i];
}
else
{
$currentLine++;
$lines[$currentLine] = $words[$i];
}
}

return
implode("\n", $lines);
}
?>
go4christian at gmail dot com
12 年前
自動換行:如果您想在圖片上寫文字,這個簡單的函式可以自動建立換行符號。您只需指定最大長度。

<?php
function write_multiline_text($image, $font_size, $color, $font, $text, $start_x, $start_y, $max_width)
{
//將字串分割
//逐字建立新的字串
//每次加入一個字時都檢查字串是否仍然符合寬度
//否則,移除最後一個字,貼上目前的字串,並在新的一行重新開始
$words = explode(" ", $text);
$string = "";
$tmp_string = "";

for(
$i = 0; $i < count($words); $i++)
{
$tmp_string .= $words[$i]." ";

//檢查字串大小
$dim = imagettfbbox($font_size, 0, $font, $tmp_string);

if(
$dim[4] < $max_width)
{
$string = $tmp_string;
} else {
$i--;
$tmp_string = "";
imagettftext($image, 11, 0, $start_x, $start_y, $color, $font, $string);

$string = "";
$start_y += 22; // 更改此值以調整行高。此外,您可以使用「dim」陣列中的資訊來自動計算您必須「向下移動」多少
}
}

imagettftext($image, 11, 0, $start_x, $start_y, $color, $font, $string); //「繪製」剩餘的字串
?>
magnum dot tc dot mr at gmail dot com
12 年前
請注意,第三個參數實際上是一個「路徑」。
<?php
imagettfbbox
(10, 0, 'arial.ttf', 'Hello, World!'); // 將會產生「Warning: imagettfbbox(): Could not find/open font in ...php on line ...」的警告
?>

請改用類似以下的寫法
<?php imagettfbbox(10, 0, './arial.ttf', 'Hello, World!'); ?>

<?php imagettfbbox(10, 0, getcwd().'/arial.ttf', 'Hello, World!'); ?>
mike at mikeleigh dot com
17 年前
我測試這個函式一段時間了,並遇到了許多其他人也曾觸及的相同問題。無法正確計算文字的寬度。或者,如果找到解決方案,它將無法處理像 'j' 這樣的下垂字母或負起始字母。

和 Ralph 一樣,我也想在一些文字周圍繪製一個方框,這將需要我的字體像素完美。問題是我不知道會使用哪種字體或哪種大小。這讓我提出了以下我正在分享的解決方案。

<?php
function imagettfbboxextended($size, $angle, $fontfile, $text) {
/*這個函式擴展了 imagettfbbox 並在傳回的陣列中包含了實際的文字寬度和高度,以及文字應從哪個 x 和 y 坐標繪製才能正確渲染。目前這只適用於零角度,並修正了下垂字母(例如 jpqg)的問題*/
$bbox = imagettfbbox($size, $angle, $fontfile, $text);

//計算 x 基線
if($bbox[0] >= -1) {
$bbox['x'] = abs($bbox[0] + 1) * -1;
} else {
//$bbox['x'] = 0;
$bbox['x'] = abs($bbox[0] + 2);
}

//計算實際文字寬度
$bbox['width'] = abs($bbox[2] - $bbox[0]);
if(
$bbox[0] < -1) {
$bbox['width'] = abs($bbox[2]) + abs($bbox[0]) - 1;
}

//計算 y 基線
$bbox['y'] = abs($bbox[5] + 1);

//計算實際文字高度
$bbox['height'] = abs($bbox[7]) - abs($bbox[1]);
if(
$bbox[3] > 0) {
$bbox['height'] = abs($bbox[7] - $bbox[1]) - 1;
}

return
$bbox;
}
?>

上面的函式提供了文字應該從哪個位置繪製的正確 x 和 y 坐標,並且還提供了實際的圖像寬度和高度。這已使用從 6 到 144 點的各種字體和大小進行了測試。某些輸出似乎不正確,並且在右側有一個額外的像素,例如,使用 144 大小的 verdana 並輸出字符 'Q'。這不是錯誤,因為這是字體輸出的抗鋸齒效果的一部分。

範例用法
<?php
$font
= 'c:\windows\fonts\verdana.ttf';
$font_size = 144;
$text = 'jÜyZgQ';
$bbox = imagettfbboxextended($font_size, 0, $font, $text);
?>

傳回值
陣列
(
[0] => -8
[1] => 40
[2] => 715
[3] => 40
[4] => 715
[5] => -177
[6] => -8
[7] => -177
[x] => 6
[width] => 722
[y] => 176
[height] => 216
)

更多說明和函式輸出圖像可以在這裡找到 http://mikeleigh.com/links/imagettfbbox
indraaaa34 at gmail dot com
9 年前
傳回的陣列順序如下
-----------------------------
| X:4 Y:5 | X: Y:7 |
-----------------------------
| X:0 Y:1 | X:2 Y:3 |
-----------------------------

例如
4 代表左上角的 X
5 代表左上角的 Y,依此類推。
a2hansolo at gmail dot com
13 年前
測量背景圖片大小,將文字換行以符合圖片寬度

<?php
$mx
= imagesx($main_img);
$my = imagesy($main_img);

//TEXT VARS/////////
$main_text = ;
$main_text_size = ;
$main_text_x = ($mx/2);

$main_text_color = imagecolorallocate($main_img, $main_text_red, $main_text_green, $main_text_blue);
$words = explode(' ', $main_text);
$lines = array($words[0]);
$currentLine = 0;
for(
$i = 1; $i < count($words); $i++)
{
$lineSize = imagettfbbox($main_text_size, 0, $mt_f, $lines[$currentLine] . ' ' . $words[$i]);
if(
$lineSize[2] - $lineSize[0] < $mx)
{
$lines[$currentLine] .= ' ' . $words[$i];
}
else
{
$currentLine++;
$lines[$currentLine] = $words[$i];
}
}
$line_count = 1;
// Loop through the lines and place them on the image
foreach ($lines as $line)
{
$line_box = imagettfbbox($main_text_size, 0, $mt_f, "$line");
$line_width = $line_box[0]+$line_box[2];
$line_height = $line_box[1]-$line_box[7];
$line_margin = ($mx-$line_width)/2;
$line_y = (($line_height+12) * $line_count);
imagettftext($main_img, $main_t_s, 0, $line_margin, $line_y, $main_text_color, $mt_f, $line);

// Increment Y so the next line is below the previous line
$line_count ++;
}
?>
Somerset Ben
3 年前
文字推移。

我想要將各種文字放置在圖片的角落,所以我建立了一個函式,接受圖片中的位置,然後將文字的角落(例如右、上)放置在該位置。不支援旋轉。

函式的輸入相當標準。「align」參數是兩個字元,X 軸對齊使用 R|M|L(右、中、左),Y 軸對齊使用 T|M|B(上、中、下);例如,「LT」表示左上角。省略「align」參數則不會顯示任何內容。

函式會傳回文字區塊的大小,如果失敗則傳回 false。

<?php
function imagettfalign (&$im,$size,$x,$y,$col,$font,$text,$align='')
{
$box = imagettfbbox ($size,0,$font,$text) ;
if (!
$box) return false ;
if (
$align)
{
switch (
strtoupper($align[0])) // X 軸位置
{
case
'L' : $tX = $x - $box[0] ; break ;
case
'R' : $tX = $x - $box[2] ; break ;
case
'M' : $tX = $x - $box[2]/2 ; break ;
default : return
false ;
}
switch (
strtoupper($align[1])) // Y 軸位置
{
case
'B' : $tY = $y - $box[1] ; break ;
case
'T' : $tY = $y - $box[7] ; break ;
case
'M' : $tY = $y - $box[7]/2 ; break ;
default : return
false ;
}
if (!
imagettftext ($im,$size,0,$tX,$tY,$col,$font,$text)) return false ;
}
$r[0]=abs($box[2]) ;
$r[1]=abs($box[7]) ;
return
$r ;
}
?>

一個範例(不包括字型宣告等)如下:
<?php
$im
= @imagecreatetruecolor(400,200) ;
$colBlack = imagecolorallocate($im,0, 0, 0);
$xy = imagettfalign ($im,12,200,100,$colBlack,$ttFont,"The middle",'MM') ;
?>

這會在圖片的正中央顯示「The middle」。

最後,對於非標準的縮排,我在此致歉。我多年來都是這樣做的...
james dot heazlewood at crownbet com au
7 年前
我發現嘗試旋轉和對齊文字方塊時,邊界方塊有點難以使用。我寫的這個函式允許你設定靠左、靠右或置中對齊的文字,並且可以旋轉文字。

<?php
/**
* 渲染任何字型或顏色的可旋轉和對齊文字
*
* @param resource $img 圖像資源
* @param string $text 文字內容
* @param int $x X 座標
* @param int $y Y 座標
* @param int $fontSize 字體大小
* @param string $fontFile 字體檔案的完整路徑
* @param array $color 紅、綠、藍顏色值,可以是整數 (255) 或十六進位 (0xFF)
* @param string $align 對齊方式,接受 'left'、'right',預設為居中
* @return void
*/
function gd_text_aligned($img, $text, $x, $y, $fontSize, $fontFile, $color = [0, 0, 0], $align = 'left') {

// 建立顏色資源
$textColor = imagecolorallocate($img, $color[0], $color[1], $color[2]);

// 建立邊界框座標
$boundingBox = imagettfbbox($fontSize, $rotation, $fontFile, $text);
$textBox = imagettfbbox($fontSize, 0, $fontFile, $text);

// 邊界框陣列鍵的意義
//
// $bBox[0] = 左下 X
// $bBox[1] = 左下 Y
// $bBox[2] = 右下 X
// $bBox[3] = 右下 Y
// $bBox[4] = 右上 X
// $bBox[5] = 右上 Y
// $bBox[6] = 左上 X
// $bBox[7] = 左上 Y
//
// 6,7 | 4,5
// -----+-----
// 0,1 | 2,3
//
$boundingBoxWidth = $boundingBox[4] - $boundingBox[0];
$boundingBoxHeight = $boundingBox[5] - $boundingBox[1];
$flatHeight = $textBox[5] - $textBox[1];

// 對齊方式:左對齊、右對齊或置中?
if($align == 'left') {
$drawX = $x - sin($rotation * M_PI / 180) * ($flatHeight / 2);
$drawY = $y - cos($rotation * M_PI / 180) * ($flatHeight / 2);
} else if(
$align == 'right') {
$drawX = $x - $boundingBoxWidth + sin($rotation * M_PI / 180) * ($flatHeight / 2);
$drawY = $y - $boundingBoxHeight + cos($rotation * M_PI / 180) * ($flatHeight / 2);
} else {
// 無對齊(置中)
$drawX = $x - $boundingBoxWidth / 2;
$drawY = $y - $boundingBoxHeight / 2;
}

// 繪製文字
imagettftext(
$img,
$fontSize,
$rotation, $drawX, $drawY,
$textColor, $fontFile, $text
);

}
Andrey Zakharov
13 年前
對於在圖像上繪製混合文字,此函數給出的高度無用,並導致文字在基線上跳動。

我只會使用這個
<?php
$size
= 12;// 字體高度
$font = 'Arial';// 你的字體
$char = 'Test';
$char = 'With W';
$char = 'without w but with p and y and q';

$rect = imagettfbbox($size, 0, $font, $char);

$image_height =abs( $rect[7] );// 不考慮底部邊距
$imw = $rect[2] - $rect[0]; // 和往常一樣
$bx = abs( $rect[ 0 ] ); // X 偏移量
$by = $size * 1.25; // Y 偏移量 - 我們將使用常數 LINEHEIGHT
?>
tuxedobob
8 年前
如果你記得字體的粗體版本不一定與該字體的正常版本高度相同,你可能會節省大量時間和頭痛!

(事實上,它可能會更短!)
dvladimirov77 at gmail dot com
4 年前
如果該行以窄字元開頭,例如:「1」

function new_imagettfbbox($size, $angle, $fontfile, $text)
{
$first = substr($text, 0, 1);
$sub = substr($text, 1);

switch ($first)
{
case '1'
$text = '0' . $sub;
break;
}

return imagettfbbox($size, $angle, $fontfile, $text);
}
hkc@taiwan
15 年前
我想直接將文字的邊界框輸出為圖像。我這樣做

<?php

$text
= "<?php echo \"hello, world\"; ?>";
$font = "./arial.ttf";
$size = "60";

$bbox = imagettfbbox($size, 0, $font, $text);

$width = abs($bbox[2] - $bbox[0]);
$height = abs($bbox[7] - $bbox[1]);

$image = imagecreatetruecolor($width, $height);

$bgcolor = imagecolorallocate($image, 255, 255, 255);
$color = imagecolorallocate($image, 0, 0, 0);

$x = $bbox[0] + ($width / 2) - ($bbox[4] / 2);
$y = $bbox[1] + ($height / 2) - ($bbox[5] / 2);

imagefilledrectangle($image, 0, 0, $width - 1, $height - 1, $bgcolor);
imagettftext($image, $size, 0, $x, $y, $color, $font, $text);

$last_pixel= imagecolorat($image, 0, 0);

for (
$j = 0; $j < $height; $j++)
{
for (
$i = 0; $i < $width; $i++)
{
if (isset(
$blank_left) && $i >= $blank_left)
{
break;
}

if (
imagecolorat($image, $i, $j) !== $last_pixel)
{
if (!isset(
$blank_top))
{
$blank_top = $j;
}
$blank_left = $i;
break;
}

$last_pixel = imagecolorat($image, $i, $j);
}
}

$x -= $blank_left;
$y -= $blank_top;

imagefilledrectangle($image, 0, 0, $width - 1, $height - 1, $bgcolor);
imagettftext($image, $size, 0, $x, $y, $color, $font, $text);

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

?>
bushj at rpi dot edu
17 年前
顯然 imagettftext 和 imagettfbbox 回傳的邊界框並不相同,而且 imagettftext 在計算實際邊界框時似乎做得更好(可能是因為它必須渲染每個字元,然後找出它實際渲染的所有位置)。

因此,您可以建立一個虛擬影像,將文字渲染到該影像上,並取得更好的邊界框。以下是一個範例函式
<?php
function better_imagettfbbox($size, $angle, $font, $text) {
$dummy = imagecreate(1, 1);
$black = imagecolorallocate($dummy, 0, 0, 0);
$bbox = imagettftext($dummy, $size, $angle, 0, 0, $black, $font, $text);
imagedestroy($dummy);
return
$bbox;
}
?>
如果您經常使用這個函式,最好保留一個虛擬影像,而不是不斷建立和銷毀影像。
user107
9 年前
我找到了一個對我有效的簡單解決方案

<?php
if(!isset($_GET['size'])) $_GET['size'] = 44;
if(!isset(
$_GET['text'])) $_GET['text'] = "Hello, world!";

$size = imagettfbbox($_GET['size'], 0, "ARIAL", $_GET['text']);
$xsize = abs($size[0]) + abs($size[2]);
$ysize = abs($size[5]) + abs($size[1]);

$image = imagecreate($xsize, $ysize);
$blue = imagecolorallocate($image, 0, 0, 255);
$white = ImageColorAllocate($image, 255,255,255);
imagettftext($image, $_GET['size'], 0, abs($size[0]), abs($size[5]), $white, "ARIAL", $_GET['text']);

header("content-type: image/png");
imagepng($image);
imagedestroy($image);
?>

這是帶有範例的連結
http://www.tuxradar.com/practicalphp/11/2/6#null
rasmus at mindplay dot dk
11 年前
請注意,此函式回傳的邊界框座標並不精確 - 關於此問題的錯誤回報已存在 5 年,因此預期此問題可能永遠不會被修復。

更多資訊請參閱此處

https://gist.github.com/mindplay-dk/4429153
Dario
15 年前
我解決基線下字元的方法是在計算邊界時,簡單地套用較小的角度和一些邊距,使函式認為您的文字延伸到基線下方。例如:

<?php
// 取得文字的邊界
$bounds = imagettfbbox($size*1.05, $angle-3, $font, $text);
?>
Anonymous
16 年前
簡單的覆載函式:為座標點新增 TTF 置中和靠右對齊。
正確示範了邊界框 TTF 函式及其回傳的座標陣列的用法。

在取得數值並根據一組數值 [L, C, R] 調整後,它使用基於文字長度的簡單數學運算,將其從原點 (x = 0) 移動。

<?php
function imagettftextalign($image, $size, $angle, $x, $y, $color, $font, $text, $alignment='L')
{

//檢查文字寬度
$bbox = imagettfbbox ($size, $angle, $font, $text);
$textWidth = $bbox[2] - $bbox[0];
switch (
$alignment) {
case
"R":
$x -= $textWidth;
break;
case
"C":
$x -= $textWidth / 2;
break;
}

//寫入文字
imagettftext ($image, $size, $angle, $x, $y, $color, $font, $text);

}
?>
beosman at gmail dot com
16 年前
我一直在檢視計算給定字型的文字框的程式碼,但我沒有找到一個可以針對非零的不同角度正常運作的程式碼,因此我製作了一個比上面的程式碼更簡單的函式

<?php

function calculateTextBox($text,$fontFile,$fontSize,$fontAngle) {
$rect = imagettfbbox($fontSize,$fontAngle,$fontFile,$text);

$minX = min(array($rect[0],$rect[2],$rect[4],$rect[6]));
$maxX = max(array($rect[0],$rect[2],$rect[4],$rect[6]));
$minY = min(array($rect[1],$rect[3],$rect[5],$rect[7]));
$maxY = max(array($rect[1],$rect[3],$rect[5],$rect[7]));

return array(
"left" => abs($minX),
"top" => abs($minY),
"width" => $maxX - $minX,
"height" => $maxY - $minY,
"box" => $rect
);
}

?>

使用此函式,您可以將帶角度的字串置於任何影像中

<?php

$mystring
= "Hello world!";

$imgWidth = 300;
$imgHeight = 150;

$image = imagecreate($imgWidth,$imgHeight);
imagefill($image,imagecolorallocate($image,200,200,200));

$box = calculateTextBox($mystring,"./Verdana.ttf",15,45);
$color = imagecolorallocate($image,0,0,0);
imagettftext($image,
15,
45,
$box["left"] + ($imgWidth / 2) - ($box["width"] / 2),
$box["top"] + ($imgHeight / 2) - ($box["height"] / 2),
$color,
"./Verdana.ttf",
$mystring);

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

?>
mihai.draghicioiu at gmailcom
16 年前
為了取得文字行的正確高度,我發現使用以下程式碼很有幫助

<?php

$bbox
= imagettfbbox($size, 0, $ttf, " \n "); // 空格、換行、空格

$height = $bbox[3] - $bbox[5];

?>

希望這對您有所幫助。之前我使用字串 "Tj",但有時會不夠用,尤其是對於一些奇怪的字體。
heshan at sjtu dot edu dot cn
16 年前
imagettfbbox 和 imagettftext 的怪異之處在於

1. imagettfbbox 和 imagettftext 具有相同的回傳值,而且當角度不等於零時,兩者都是錯誤的。
2. 當角度為零時,imagettfbbox 會回傳正確的邊界框。
3. 邊界框具有一個座標系統,其中 x 從左到右變大,y 從上到下變大。
4. imagettftext 中使用的「基準點」是邊界框座標系統中的原點。
5. 當角度不是 0 時,實際上是在以基準點為中心的坐標系統中旋轉。因此,如果我們知道角度為零時的邊界框坐標,我們可以通過數學方程式手動進行旋轉來獲得新的邊界框坐標。
6. 為了達到像素級的精確度,我們還應該注意另一件事。假設軸線是這樣:|_|_|_|,邊界框坐標使用垂直線上的點,而圖像函數使用水平線上的點,所以您應該注意這 1 個像素的差異。

以下程式碼片段會建立包含不同字體和旋轉角度的字母的最小圖像。這在驗證碼腳本中特別有用。

<?php

function create_font_image( $size, $angle, $font, $char )
{
$rect = imagettfbbox( $size, 0, $font, $char );
if(
0 == $angle ) {
$imh = $rect[1] - $rect[7];
$imw = $rect[2] - $rect[0];
$bx = -1 - $rect[0];
$by = -1 - $rect[7];
} else {
$rad = deg2rad( $angle );
$sin = sin( $rad );
$cos = cos( $rad );
if(
$angle > 0 ) {
$tmp = $rect[6] * $cos + $rect[7] * $sin;
$bx = -1 - round( $tmp );
$imw = round( $rect[2] * $cos + $rect[3] * $sin - $tmp );
$tmp = $rect[5] * $cos - $rect[4] * $sin;
$by = -1 - round( $tmp );
$imh = round( $rect[1] * $cos - $rect[0] * $sin - $tmp );
} else {
$tmp = $rect[0] * $cos + $rect[1] * $sin;
$bx = -1 - round( $tmp );
$imw = round( $rect[4] * $cos + $rect[5] * $sin - $tmp );
$tmp = $rect[7] * $cos - $rect[6] * $sin;
$by = -1 - round( $tmp );
$imh = round( $rect[3] * $cos - $rect[2] * $sin - $tmp );
}
}
$im = imagecreatetruecolor( $imw, $imh );
imagefill( $im, 0, 0, imagecolorallocate( $im, 255, 0, 255 ) );
imagettftext( $im, $size, $angle, $bx, $by, imagecolorallocate( $im, 0, 0, 0 ), $font, $char );
imagegif( $im, trim( $font, './' ) . ord( $char ) . $angle . '.gif' );
imagedestroy( $im );
}

$chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890';
$angles = array( -30, -20, -10, 0, 10, 20, 30 );
$fonts = array( './latinwide.ttf', './verdana.ttf', './times.ttf', './broadway.ttf' );
foreach(
$angles as $angle )
foreach(
$fonts as $font )
for(
$i = 0; $i < strlen( $chars ); ++$i )
create_font_image( 100, $angle, $font, $chars[$i] );
?>
intuz et gmx dt de
17 年前
我嘗試使用 imagettfbbox 旋轉 imagettftext 時仍然遇到問題。

它的位置計算大多是錯誤的。所以我嘗試使用 IMAGEROTATE 旋轉 ttftext。

作為特殊情況,結果是黑色字體顏色和透明背景。

希望它對某些人有幫助(感謝 convertBoundingBox 函數,請閱讀下方)

<?
function ImgText($text,$fontsize,$font,$angle){
$im = '';
if($text){
if(!$fontsize || $fontsize < 1) $fontsize = 12;
if(!$font) $font = "fonts/arial.ttf";
$bbox = imagettfbbox($fontsize, 0, $font, $text);
$size=convertBoundingBox($bbox);
$im = ImageCreatetruecolor($size['width'],$size['height']);

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

imagefill ($im, 0, 0, $white );
imagettftext($im, $fontsize, 0, $size['xOffset'], $size['yOffset'], $black, $font, $text);
$im = imagerotate( $im,$angle, $white);
imagecolortransparent ($im,$white);
}else{
// 沒有文字
}
}
?>
Ruquay
17 年前
一些評論表明,此函數的輸出通常與預期的不符,尤其是在文字旋轉時。

對於那些想要了解文字旋轉時邊界框發生什麼情況的視覺表示的人,請看這裡

http://ruquay.com/sandbox/imagettf/
Nate Sweet
17 年前
對 convertBoundingBox 函數的改進。先前的函數完全錯誤。我的困惑來自於像 "1" 和 "_" 這樣的字符,它們被渲染在基準點的右側或下方(在我使用的字體中)。我最終使用了 mike at mikeleigh dot com 的函數,並對這些字符進行了修復,以及一個 "belowBasepoint" 值。
<?php
function convertBoundingBox ($bbox) {
if (
$bbox[0] >= -1)
$xOffset = -abs($bbox[0] + 1);
else
$xOffset = abs($bbox[0] + 2);
$width = abs($bbox[2] - $bbox[0]);
if (
$bbox[0] < -1) $width = abs($bbox[2]) + abs($bbox[0]) - 1;
$yOffset = abs($bbox[5] + 1);
if (
$bbox[5] >= -1) $yOffset = -$yOffset; // 修正基準線以下的字元。
$height = abs($bbox[7]) - abs($bbox[1]);
if (
$bbox[3] > 0) $height = abs($bbox[7] - $bbox[1]) - 1;
return array(
'width' => $width,
'height' => $height,
'xOffset' => $xOffset, // 使用 xCoord + xOffset 與 imagettftext 會將文字最左邊的像素放在 xCoord。
'yOffset' => $yOffset, // 使用 yCoord + yOffset 與 imagettftext 會將文字最上邊的像素放在 yCoord。
'belowBasepoint' => max(0, $bbox[1])
);
}
?>
Nate Sweet
17 年前
我花了一些時間才充分利用 imagettfbbox。希望以下的函式能讓其他人更容易使用。

<?php
function convertBoundingBox ($bbox) {
if (
$bbox[0] >= -1)
$leftOfBasepoint = -abs($bbox[0] + 1);
else
$leftOfBasepoint = abs($bbox[0] + 2);
$rightOfBasepoint = abs($bbox[2] - $bbox[0]);
if (
$bbox[0] < -1) $rightOfBasepoint = abs($bbox[2]) + abs($bbox[0]) - 1;
$aboveBasepoint = abs($bbox[5] + 1);
$height = abs($bbox[7]) - abs($bbox[1]);
if (
$bbox[3] > 0) $height = abs($bbox[7] - $bbox[1]) - 1;
$width = $leftOfBasepoint + $rightOfBasepoint;
$belowBasepoint = $height - $aboveBasepoint;
return array(
'width' => $width,
'height' => $height,
'leftOfBasepoint' => $leftOfBasepoint,
'rightOfBasepoint' => $rightOfBasepoint,
'aboveBasepoint' => $aboveBasepoint,
'belowBasepoint' => $belowBasepoint
);
}
?>

感謝 mike 在 mikeleigh dot com 網站上提供這個函式的核心程式碼。

請記住,基準點是您使用 imagettftext 繪製文字時所使用的 x, y 座標。一個有用的方法是使用像這樣的字串...
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567890
...並使用 "aboveBasepoint" 值作為字體的高度。現在您可以繪製線條,並使用「字體的高度 * 行距」作為文字行之間的距離,其中行距是像 1.45 這樣的數字(表示 45% 的行距)。
Nate Sweet
17 年前
這個腳本會並排顯示以特定大小渲染的字體,以及以該大小的倍數渲染,然後縮小相同倍數的相同字體之間的差異。這似乎對小尺寸有幫助,而對大尺寸的影響較小。這個腳本可以讓您了解是否值得在您的情況下實施。下面包含來自 mike 在 mikeleigh dot com 網站的偉大 "imagettfbboxextended" 函式。

$size = 30;
$factor = 16;

$smallSize = imagettfbboxextended($size, 0, "fonts/MPlantin.ttf", "The quick brown fox jumps over the lazy dog.");
$smallWidth = $smallSize['width'];
$smallHeight = $smallSize['height'];
$canvas = imagecreatetruecolor($smallWidth + 20, $smallHeight * 2 + 20);
imagefill($canvas, 0, 0, imagecolorallocate($canvas, 255, 255, 255));
imagettftext($canvas, $size, 0, 10 + $smallSize['x'], 10 + $smallSize['y'], imagecolorallocate($canvas, 0, 0, 0), "fonts/MPlantin.ttf", "The quick brown fox jumps over the lazy dog.");

$largeSize = imagettfbboxextended($size * $factor, 0, "fonts/MPlantin.ttf", "The quick brown fox jumps over the lazy dog.");
$largeWidth = $largeSize['width'];
$largeHeight = $largeSize['height'];
$temp = imagecreatetruecolor($largeWidth, $largeHeight);
imagefill($temp, 0, 0, imagecolorallocate($canvas, 255, 255, 255));
imagettftext($temp, $size * $factor, 0, $largeSize['x'], $largeSize['y'], imagecolorallocate($temp, 0, 0, 0), "fonts/MPlantin.ttf", "The quick brown fox jumps over the lazy dog.");
imagecopyresampled($canvas, $temp, 10 + $smallSize['x'], 10 + $smallSize['y'] + 10, 0, 0, $smallWidth, $smallHeight, $largeWidth, $largeHeight);
imagepng($temp, "temp.png");

imagepng($canvas, "test.png");

function imagettfbboxextended($size, $angle, $fontfile, $text) {
/*此函式擴展了 imagettfbbox 並在返回的陣列中包含
實際文字的寬度和高度,以及要正確渲染文字的 x 和 y 座標。這目前僅適用於
角度為零的情況,並修正了懸掛字母的問題,例如 jpqg*/

$bbox = imagettfbbox($size, $angle, $fontfile, $text);

//計算 x 基準線
if($bbox[0] >= -1) {
$bbox['x'] = abs($bbox[0] + 1) * -1;
} else {
//$bbox['x'] = 0;
$bbox['x'] = abs($bbox[0] + 2);
}

//計算實際文字寬度
$bbox['width'] = abs($bbox[2] - $bbox[0]);
if($bbox[0] < -1) {
$bbox['width'] = abs($bbox[2]) + abs($bbox[0]) - 1;
}

//計算 y 基準線
$bbox['y'] = abs($bbox[5] + 1);

//計算實際文字高度
$bbox['height'] = abs($bbox[7]) - abs($bbox[1]);
if($bbox[3] > 0) {
$bbox['height'] = abs($bbox[7] - $bbox[1]) - 1;
}

return $bbox;
}
lassial dot gmail dot com
17 年前
Ralph Bolton 評論了計算邊界框大小與對齊文字基準線之間的差異。

這個問題的解決方法是計算基準線以下的字元和基準線以上的字元之間的高度差。這可能會因字體而異,所以我建議使用類似這樣的東西

<?php

function fontBaselineOffset($font, $fontSize)
{
//這應該在基線之上
$test2="H";
//其中一些額外的字母應該在它之下
$test3="Hjgqp";

//取得這兩個的尺寸:

$box2 = imageTTFBbox($fontSize,0,$font,$test2);
$box3 = imageTTFBbox($fontSize,0,$font,$test3);

//回傳偏移值

return abs((abs($box2[5]) + abs($box2[1])) - (abs($box3[5]) + abs($box3[1])));

}
?>

這還不夠完美。您應該定義一個允許低於基線的字元範圍,將它們與實際在字串中找到的字元進行比較,並使用它們而不是上面範例函數中使用的字串 $test3。這應該可以避免字母低於基線的程度不同的問題(例如,'g' 和 'p' 之間可能存在差異)
gw at example dot com
8 年前
一點小東西可以替換 blackbart 的提示

// 開始掃描 (0=> 黑色 => 空白)
$rleft = $w4 = $width<<2;
$rright = 0;
$rbottom = 0;
$rtop = $h4 = $height<<2;
for( $x = 0; $x < $w4; $x++ )
for( $y = 0; $y < $h4; $y++ )
if( imagecolorat( $img, $x, $y ) ){
$rleft = min( $rleft, $x );
$rright = max( $rright, $x );
$rtop = min( $rtop, $y );
$rbottom = max( $rbottom, $y );
}

使用

// 開始掃描 (0=> 黑色 => 空白)
$break = false;
$rleft = $w4 = $width<<2;
$rright = 0;
$rbottom = 0;
$rtop = $h4 = $height<<2;
// 從左到右掃描,當找到像素時中斷,從另一側掃描:避免掃描所有像素!
for($x=0; $x<$w4; $x++){
for($y=0; $y<$h4; $y++)
if(imagecolorat($img,$x,$y)){
$rtop = min($rtop, $y); $rleft = min($rleft, $x);
$break = true; break;
}
if($break) break;
}
// 從右到左掃描,當找到像素時中斷
for($x=($w4-1); $x>$rleft; $x--){
for($y=0; $y<$h4; $y++)
if(imagecolorat($img,$x,$y)){
$rright = max($rright, $x); $rbottom = max($rbottom, $y);
$break = true; break;
}
if($break) break;
}
//... //

檢查圖片是直向還是橫向可能會更好,從左到右 (橫向) 或從上到下 (直向) 開始迴圈
peisenmann at gmail dot com
18 年前
另一個用於置中文字字串的函式。
它的作用:產生一個文字字串的 truecolor .png 圖像。圖像的大小將足以包含文字和 2 像素的邊框,並且文字將在其內置中。

它是從任何其他頁面呼叫的,如下所示...
<img src="linkImg.php?text=php.net is great&border=out" /> // 帶有 #&+"'\<> 的文字需要被跳脫,但我發現空格不會導致錯誤。我還沒有用其他任何語言測試過。

以下程式碼是名為 linkImg.php 的檔案
該檔案的設計目的不是在此處包含任何其他內容,並且開頭和結尾的 php 標籤應該分別是頁面的第一個和最後一個字元,因為外部的空白有時可能會有點問題。
<?php
//Obtain text and border via GET
//Border can be out, in, or flat
$text = $_GET['text'];
$border = $_GET['border'];

$font = "fontpath"; //(str) "fonts/sasquatchlives.ttf"
$fontsize = font size; //(int) pixels in GD 1, or points in GD 2

//Register box
$box = imagettfbbox ($fontsize, 0, $font, $text);
//Find out the width and height of the text box
$textW = $box[2] - $box[0];
$textH= $box[3]-$box[5];
//Add padding
$paddingx = 10;
$paddingy = 10;
//Set image dimentions
$width = $textW+$paddingx;
$height= $textH+$paddingy;

//Bottom left corner of text
$textx = $paddingx/2;
$texty = $height - $paddingy/2;

//Shadow offset (pixels)
$shadoffx = 1;
$shadoffy = 1;

//Create the image
$img = imagecreatetruecolor($width,$height);
//Define some colors
$white = imagecolorallocate($img,255,255,255);
$black = imagecolorallocate($img,0,0,0);
$lightgrey = imagecolorallocate($img,200,200,200);
$grey = imagecolorallocate($img,100,100,100);
//Define Text (fg) and background (bg) colors
$bgcol = imagecolorallocate($img,192,213,196); //Celadon (light pastel green)
$fgcol = imagecolorallocate($img,243,104,88); //Peach
// Fill image with background color
imagefill($img,0,0,$bgcol);

//Write Shadow
imagettftext($img, $fontsize, 0, $textx+$shadoffx, $texty+$shadoffy, $grey, $font, $text);

//Write Text
imagettftext($img, $fontsize, 0, $textx, $texty, $fgcol, $font, $text);

//Bordering

//Embossed border (button-looking)
if ($border == "out")
{
imageline ($img,0,0,$width,0,$white);imageline ($img,0,0,0,$height,$white);
imageline ($img,1,1,$width,1,$lightgrey);imageline ($img,1,1,1,$height-1,$lightgrey);
imageline ($img,0,$height-1,$width-1,$height-1,$black);imageline ($img,$width-1,$height-1,$width-1,0,$black);
imageline ($img,2,$height-2,$width-2,$height-2,$grey);imageline ($img,$width-2,$height-2,$width-2,2,$grey);

}
//Flat border
if ($border == "flat")
{
imageline ($img,0,0,$width,0,$white);imageline ($img,0,0,0,$height,$white);
imageline ($img,1,1,$width,1,$grey);imageline ($img,1,1,1,$height-1,$grey);
imageline ($img,0,$height-1,$width-1,$height-1,$white);imageline ($img,$width-1,$height-1,$width-1,0,$white);
imageline ($img,2,$height-2,$width-2,$height-2,$grey);imageline ($img,$width-2,$height-2,$width-2,2,$grey);
}

//Engraved border (pushed button)
if ($border == "in")
{
imageline ($img,0,0,$width,0,$black);imageline ($img,0,0,0,$height,$black);
imageline ($img,1,1,$width,1,$grey);imageline ($img,1,1,1,$height-1,$grey);
imageline ($img,0,$height-1,$width-1,$height-1,$white);imageline ($img,$width-1,$height-1,$width-1,0,$white);
imageline ($img,2,$height-2,$width-2,$height-2,$lightgrey);imageline ($img,$width-2,$height-2,$width-2,2,$lightgrey);
}

// Header info
header("Content-type: image/png");
//Sends the image
imagepng($img);
imagedestroy($img);
?>

希望這能對某些人有所幫助!
-Patrick-
Stefan at colulus dot com
16 年前
我設計了一個腳本,允許將字母數字資料傳輸到圖像上。HTML 功能是 img src,而 php 功能是 imagettftext。這個簡單的程式碼將在圖像上從 1 遞增到 3。

程式碼

<?php
//ImageCall.php -- 這個腳本將呼叫一個腳本來產生圖像。
for($next = 1;$next < 4; $next++){
print
"Image $next:<br>";
print
"<img src = 'Image.php?\$text=$next'>";
print
"<br><br>";
}
?>

<?php
//Image.php -- 這個腳本建立一個正方形圖像,並將文字放在上面。

// 圖像大小和顏色
$im = ImageCreate(77,77);
$color1 = ImageColorAllocate($im,0x66,0xCC,0x00);
$color2 = ImageColorAllocate($im,0x33,0x66,0x00);
$color3 = ImageColorAllocate($im,0x00,0x99,0x00);
$color4 = ImageColorAllocate($im,0x3D,0x3D,0x3D);

// 圖像建立
ImageFilledRectangle($im,1,1,76,76,$color1);
ImageFilledpolygon($im, array (76,1,1,76,76,76),3,$color2);
ImageFilledRectangle($im,5,5,72,72,$color3);

// 確定圖像的數字中心
$size = ImageTTFBBox(45,0,'impact',$_GET['$text']);
$X = (77 - (abs($size[2]- $size[0])))/2;
$Y = ((77 - (abs($size[5] - $size[3])))/2 + (abs($size[5] - $size[3])));

// 將數字資訊放在圖像上
ImageTTFText($im,45,0,($X-1),$Y,$color4,'impact',$_GET['$text']);

// 將完成的圖像回傳給呼叫腳本
Header('Content-Type: image/png');
Imagepng($im);

?>
ralphbolton at mail2sexy dot com
17 年前
測量字型大小和在文字周圍繪製方塊時會有些麻煩。當使用 ImageTTFbbox 測量字型時,會回傳正確的垂直高度。也就是說,短語 "Hanging" 的測量將從 "H" 的頂部到 "g" 的底部。

問題在於像 imageTTFtext 這樣的函式會以文字的「線條」對齊,也就是說,在「Hanging」這個詞中,對齊方式是在「H」的下方,而不是「g」的底部。這表示如果你在文字後面繪製一個矩形,它會因為懸掛的「g」超出方框外而產生錯誤的對齊。

舉例來說,以下程式碼的執行結果不如你預期的那樣(因為「g」懸掛在方框下方)
<?php
// 取得字型方塊的大小
$textbox = imageTTFBbox($size, 0, $font, 'Hanging');
$textwidth = abs($textbox[4] - $textbox[0]);
$textheight = abs($textbox[5] - $textbox[1]);

// 現在在圖片上繪製一個矩形
$colour = ImageColorAllocate($im, 100, 100, 100);
imagefilledrectangle($im, $x, $y - $textheight, $x + $textwidth, $y, $colour );

// 現在繪製文字
$black = ImageColorAllocate($im, 0, 0, 0);
ImageTTFText($image['resource'], $size, 0, $x, $y, $black, $font, 'Hanging');
?>
此外,以上範例中的矩形看起來也位於文字左邊 1 像素的位置。

我還沒有找到正確解決這個問題的方法。相反地,我擴大了矩形,然後將文字放入其中。我不認為這個方法對所有字型都絕對正確,所以這並不是一個完美的解決方案。然而,總比沒有好!以下是一個程式碼片段:
<?php
$enlargex
= $textwidth * 0.08;
$enlargey = $textheight * 0.1;
$enlargey2 = $textheight * 0.5;

// 現在在圖片上繪製一個矩形
$colour = ImageColorAllocate($im, 100, 100, 100);
imagefilledrectangle($im, $x - $enlargex, $y - $textheight - $enlargey, $x + $textwidth + $enlargex, $y + $enlarge2, $colour );
?>
To Top