PHP Conference Japan 2024

imagefttext

(PHP 4 >= 4.0.7, PHP 5, PHP 7, PHP 8)

imagefttext使用 FreeType 2 將文字寫入影像

說明

imagefttext(
    GdImage $image,
    浮點數 $size,
    浮點數 $angle,
    整數 $x,
    整數 $y,
    整數 $color,
    字串 $font_filename,
    字串 $text,
    陣列 $options = []
): 陣列|false

注意事項:

在 PHP 8.0.0 之前,imagefttext()imagettftext() 的擴展變體,它額外支援 options 參數。從 PHP 8.0.0 開始,imagettftext() 成為了 imagefttext() 的別名。

參數

image

一個 GdImage 物件,由圖像創建函數之一返回,例如 imagecreatetruecolor()

size

使用的字體大小,以點為單位。

angle

角度,以度為單位,0 度表示從左到右閱讀的文字。較大的值表示逆時針旋轉。例如,值 90 將導致從下到上閱讀的文字。

x

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

y

y 坐標。這設定字體基線的位置,而不是字元的底部。

color

文字所需顏色的索引,請參閱 imagecolorexact()

font_filename

要使用的 TrueType 字體的路徑。

根據 PHP 使用的 GD 函式庫版本,*當 font_filename 不是以 / 開頭時,會在檔名後面附加 .ttf*,函式庫會嘗試沿著函式庫定義的字體路徑搜尋該檔名。

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

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

// 指定要使用的字體名稱(注意沒有 .ttf 副檔名)
$font = 'SomeFont';
?>

text

要插入圖像的文字。

options

options 可能的陣列索引
鍵值 類型 意義
linespacing 浮點數 定義繪製的行距

返回值

此函數返回一個陣列,該陣列定義了方框的四個點,從左下角開始逆時針移動

0 左下角 x 坐標
1 左下角 y 坐標
2 右下角 x 坐標
3 右下角 y 坐標
4 右上角 x 坐標
5 右上角 y 坐標
6 左上角 x 坐標
7 左上角 y 坐標

失敗時,返回 false

更新日誌

版本 說明
8.0.0 image 參數現在需要一個 GdImage 實例;先前需要的是有效的 gd 資源

範例

範例 #1 imagefttext() 範例

<?php
// 建立一個 300x100 的影像
$im = imagecreatetruecolor(300, 100);
$red = imagecolorallocate($im, 0xFF, 0x00, 0x00);
$black = imagecolorallocate($im, 0x00, 0x00, 0x00);

// 將背景設為紅色
imagefilledrectangle($im, 0, 0, 299, 99, $red);

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

// 使用 13 號字型繪製文字 'PHP Manual'
imagefttext($im, 13, 0, 105, 55, $black, $font_file, 'PHP Manual');

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

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

注意事項

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

參見

新增筆記

使用者貢獻的筆記 15 則筆記

ben at tNOSPAManjNOSPAMo dot cnospamordots dot om
22 年前
如果您想關閉 FreeType 字體微調,請在 gd 原始碼 (gdft.c) 中搜尋以下這一行:
err = FT_Load_Glyph (face, glyph_index, FT_LOAD_DEFAULT);
並將其替換為:
err = FT_Load_Glyph (face, glyph_index, FT_LOAD_NO_HINTING);

重新編譯 GD,然後瞧:美麗的抗鋸齒效果。
MagicalTux at FF dot st
19 年前
當您使用 FreeType 2 支援編譯 PHP 時,如果您使用 debian 且沒有自行編譯 freetype2,您可能會遇到一些問題…
如果在顯示「如果設定失敗,請嘗試 --with-xpm-dir…」後設定失敗,則很可能是您安裝了 FreeType1,但沒有安裝 freetype2…

以 root 身份執行以下指令:
apt-get install libfreetype6-dev

我花了一些時間才發現 apt-get install freetype2 實際上安裝的是 freetype1…
aidan at php dot net
19 年前
此函式與 imageffttext() 非常相似,您可能會發現其手冊頁面上提供的資訊很有幫助

https://php.dev.org.tw/imagettftext
sebastiand at gmx dot de
21 年前
在花了一個晚上處理自動生成的圖片後,我想到了關閉抗鋸齒功能(看看某些字體這樣是否會看起來更好),結果發現這並不容易。

實際上,您必須使用所需顏色的負值才能關閉抗鋸齒功能。我附上程式碼中對應的行(行已斷開):

// 使用所需顏色的負值來關閉抗鋸齒功能
ImageFTText ($neuesBild,$fontsize,$fontangle,$TextPosX,$TextPosY,
-$custom_fg,$fonttype,$text,array());
KeepSake at crimebloc dot com
15 年前
一個設計專案要求我在字元之間要有間距;由於 imagefttext 不支援此功能,所以我建立了一個支援此功能的函式。

參數與 imagefttext 相同,除了 (array)$extrainfo 現在接受 'character_spacing' 間距參數。傳回值與預期相同,包含整個字串的圖像邊界,包括字元間距。

缺點是 $angle 會旋轉每個字母,而不是旋轉整個單字(可以視為一個獨立的功能)。

我希望這對某些人有所幫助。
- KeepSake

<?php
// Required header (assuming we use png images)
header("Content-type: image/png");

// Create a basic image with a dark background.
$image = imagecreatetruecolor(300, 20);
imagefill($image, 0, 0, imagecolorallocate($image, 21, 21, 21));

// Function call, arguments are the same as imagefttext, expect that (array)$extrainfo takes a new paramenter called character_spacing.
$imageBox = imagefttext2($image, 9, 0, 2, 15, imagecolorallocate($image, 255, 255, 255), 'tahomabold.ttf', 'The quick brown fox...', array('character_spacing' => 5));

// Output the file, and clear the resources
imagepng($image);
imagedestroy($image);

function
imagefttext2($imageResource, $font_size, $text_angle, $start_x, $start_y, $color, $font_file, $text, $extra_info = array()) {
if(
$extra_info['character_spacing'] == NULL || !is_numeric($extra_info['character_spacing'])) {
$extra_info['character_spacing'] = 0;
}
$lastX = $start_x - $extra_info['character_spacing'];
foreach(
str_split($text) as $v) {
$coordinates = imagefttext($imageResource, $font_size, $text_angle, $lastX + $extra_info['character_spacing'], $start_y, $color, $font_file, $v, $extra_info);
$lastX = max($coordinates[2], $coordinates[4]);
}
// Return the newly generated image box coordinates:
return array($start_x, $start_y, $coordinates[2], $coordinates[3], $coordinates[4], $coordinates[5], $start_x, $coordinates[7]);
}

?>
d underscore brown x at hotmail dot
17 年前
realpath(".")
realpath(getenv("SCRIPT_FILENAME"));

可能有所不同。這在設定 GDFONTPATH 時很有幫助。
darren at badpun dot co dot uk
17 年前
我在構建使用者可自訂輸出 DPI 的圖表時,很難準確地以點數表示字體大小(基本上,使用者可以指定圖表的大小,單位為毫米或任何其他實際單位,以及 DPI,以建立任意大小的圖表,以便在實際列印的文件中正常顯示)。

GD1 沒問題,因為它使用像素來渲染字體,但 GD2 使用點數,這只有在您知道它在影像表面上渲染文字時假設的 DPI 的情況下才有意義。我在這份文件中找不到相關資訊,但我檢查了 GD2 的原始碼,它似乎在內部假設 DPI 為 96。然而,這在 GD2 原始碼中很容易自訂,因此不能假設所有 PHP 直譯器都使用內部 DPI 為 96 編譯的 GD2。

如果確實如此,而且您正在使用它來構建目標 DPI 不是 96 的影像,您可以像這樣計算提供給 imageftbox() 和 imagefttext() 的點數大小

<?php
/* 100mm x 100mm 影像 */
$imageWidth = 100;
$imageHeight = 100;

/* 300 dpi 影像,因此影像是 1181 x 1181 像素 */
$imageDPI = 300;

/* 除非我們這樣做,否則文字會小約 3 倍 */
$realFontSize = ($fontPt * $targetDPI) / 96;
?>
匿名
18 年前
我在 WinXP 電腦上使用 php 5.1.2。我正在研究 TrueType 字體,想看看哪些字體最適合融入網頁影像。所以我建立了以下腳本,它會印出在我的 C:\Windows\Fonts 目錄中找到的所有 TrueType 字體的樣本。該腳本只接受一個請求參數 - 'fsize'。它代表字體大小,讓您可以以任何大小查看每個字體——我將其限制在 5 到 48 之間。希望這對除了我之外的人也有幫助 :)

如果我的任何程式碼不是最漂亮的 php 程式碼,我提前道歉——我過去一周才開始用 php 編碼(我通常是一個 perl 使用者)。

<?php
list($x, $y, $maxwidth) = array(0, 0, 0);

$fsize = (int)$_REQUEST['fsize'];
if (
$fsize < 5 or $fsize > 48) $fsize = 8;

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

// don't know how wide or tall the font samples will be.
// create a huge image for now, we'll copy it smaller
// later when we know how large the image needs to be.
$im = imagecreate(1000, 20000) or die('could not create!');
$clr_white = imagecolorallocate($im, 255, 255, 255);
$clr_black = imagecolorallocate($im, 0, 0, 0);

$font_path = "C:/Windows/Fonts/";
$dh = opendir($font_path);
while ((
$file = readdir($dh)) !== FALSE) {
// we're only dealing with TTY fonts here.
if (substr(strtolower($file), -4) != '.ttf') continue;

$str = "Sample text for '$file'";
$bbox = imagettfbbox(
$fsize, 0, "{$font_path}{$file}", $str
);
$ww = $bbox[4] - $bbox[6];
$hh = $bbox[1] - $bbox[7];

imagettftext(
$im, $fsize, 0, $x, $y,
$clr_black, "{$font_path}{$file}", $str
);

$y += $hh + 20;
if (
$ww > $maxwidth) $maxwidth = $ww;
}

closedir($dh);

// ok, now we can chop off the extra space from the
// 1000 x 20000 image.
$im2 = imagecreate($maxwidth + 20, $y);
imagecopyresized(
$im2, $im, 0, 0, 0, 0, $maxwidth + 20,
$y, $maxwidth + 20, $y
);
imagejpeg($im2);
imagedestroy($im);
imagedestroy($im2);
?>
vsazel at atlas dot cz
19 年前
如果您想在單色字體渲染中獲得最佳結果,請將 render_mode 更改為 FT_LOAD_RENDER。它是 FT_Load_Glyph() 函式(在 gdft.c 中)的最後一個參數。
dnf at seznam dot cz
19 年前
對於負片影像,您必須在 $grayColor 計算之後添加一行

$grayColor = ~ $grayColor & 0x7FFFFFF;
kagaku at gmail dot com
19 年前
我發現我需要一個靠右對齊的函式,並在 imagepstext 手冊頁面上找到了一個。我想像我不是唯一需要使用它的人,所以這裡有一個稍微修改過的版本,它適用於 imagefttext

<?
function align_right($string, $fontfile, $imgwidth, $fontsize){
$spacing = 0;
$line = array("linespacing" => $spacing);
list($lx,$ly,$rx,$ry) = imageftbbox($fontsize,0,$fontfile,$string,$line);
$textwidth = $rx - $lx;
$imw = ($imgwidth-10-$textwidth);
return $imw;
}
?>
eshenk at comcast dot net
20 年前
我寫了一小段程式碼,用這個腳本來收集目錄中所有的 .ttf 檔案,並將它們隨機化,在我的網站的標頭圖片上寫入文字。唯一要注意的是,字體檔案必須命名為 1.ttf、2.ttf 等等。

<?php

srand
((double)microtime()*1234567); // 啟動隨機裝置
$image = imagecreatefromjpeg(rand(1,exec('ls *.jpg | wc -l')) . ".jpg"); // 取得背景圖片
$font = rand(1,exec('ls *.ttf | wc -l')) . ".ttf"; // 取得字體
$textcolor = imagecolorallocate($image,0,0,0); // 設定文字顏色

$text1 = "shenko.homedns.org"; // 這是我們的文字

imagettftext($image, 50, 0, 20, 50, $textcolor, $font, $text1); // 使用字體寫入文字

header("Content-type: image/jpeg"); // 它是 JPEG 格式
imagejpeg($image,'',90); // 將它輸出到瀏覽器
imagedestroy($image); // 釋放記憶體

?>
cory at lavacube dot com
18 年前
由於這個函式沒有說明文件,我覺得最好還是針對 extrainfo 參數做一些說明。

您可以在 GD 參考手冊中看到完整的說明文件
http://www.boutell.com/gd/manual2.0.33.html#gdImageStringFTEx

基本上,它接受一個陣列,其中包含以下選項作為鍵,以及相關聯的值
(int) flags [更多資訊請參考 GD 參考手冊]
(double/float) linespacing (行距)
(int) charmap (字元對應表)
(int) hdpi (水平 DPI)
(int) vdpi (垂直 DPI)
(string) xshow (xshow 字串)
(string) fontpath (字體路徑)

我的 C/C++ 不是很好,但這是我所能提供的最佳解釋。請閱讀說明文件以了解更多資訊。 :-)

一個非常簡單的使用範例如下:

<?php

imagefttext
( $img_pointer, 12, 0, 10, 10, [-insertsomecolour-], '/path/to/font.ttf', "THIS IS A TEST\nTHIS IS LINE 2\nTHIS IS LINE3", array('lineheight'=>2.0) );

?>
jwilliam at kcr dot uky dot edu
22 年前
感謝提供這個腳本!我修改了它來顯示我想要使用的幾種字體。我使用的是 GD-2.0.7、FreeType-2.1.3(包含文字旋轉修正等)和 PHP-4.2.3,並且必須加入陣列資訊才能讓它運作。

程式碼變更如下
$fontfile="/usr/local/fonts/ttf/bookantbd.ttf";
// 瀑布式點數大小,以查看 Freetype 2 的自動微調效果
//
for($i=4;$i<=12;$i++){
ImageFtText($image,$i,0,10,(280+$i*14),$forecolor,$fontfile, bookantbd . $i . ". " . $string, array("linespacing" => 1.0));
}

John
php@davehirschD0TK0MM
14 年前
我不確定這是 PHP 的問題還是 GD 的問題,但在升級到 PHP 5.3.2 之後,以一定角度寫入的文字變成頂部對齊(因此「N」和「n」的頂部相同,但「N」的底部比「n」的底部低)。我寫了一個粗糙的解決方法,將文字寫入未旋轉的臨時影像,然後將臨時影像旋轉複製到主影像上。之所以粗糙,是因為我似乎無法提取字體資訊,尤其是基準線和最底部之間的距離(我已將其硬編碼為字體大小的 30%)
我希望這個錯誤可以被修復(如果它確實是一個錯誤),或者其他人可以改進這段程式碼

<?php
// Function that draws rotated text by creating a temporary image and rotating it, since rotated text appears to be busted
function imageTextRotated($image, $size, $angle, $x, $y, $inColor, $fontfile, $text, $info=array()) {
// Force some demo text that contains risers and descenders:
// $text = "Nlfbacejygq!";

$bbox = imageftbbox($size, 0, $fontfile, $text, $info);
$dropdown = $size*0.3;
$xsize = abs($bbox[2] - $bbox[0]);
$ysize = abs($bbox[5] - $bbox[3]);
$tmpImage = imagecreatetruecolor($xsize*1.25, $ysize*1.25); // need the extra space to accommodate risers and descenders
$transparent = imagecolorallocate($tmpImage, 255, 255, 154);
if (!
$transparent) {
error_log("Color allocate failed");
}
imagecolortransparent($tmpImage, $transparent);
if (!
imagefill($tmpImage, 0, $ysize, $transparent)) {
error_log("Fill failed");
}
$rgb = imagecolorsforindex($image, $inColor);
$color = imagecolorexact($tmpImage, $rgb['red'], $rgb['green'], $rgb['blue']);
if (
$color == -1) {
$color = imagecolorallocate($tmpImage, $rgb['red'], $rgb['green'], $rgb['blue']);
if (!
$color) {
error_log("Color allocate 2 failed");
}
}

$newbbox = imagefttext($tmpImage, $size, 0, 0, $ysize*1.0, $color, $fontfile, $text, $info);
$tmpImage = imagerotate($tmpImage, $angle, $transparent);
$newWidth = imagesx($tmpImage);
$newHt = imagesy($tmpImage);
imagecopymerge($image, $tmpImage, $x-$newWidth+$dropdown, $y-$newHt, 0, 0, $newWidth, $newHt, 100);

// Highlight the desired starting point (baseline) with a green dot:
// $green = imagecolorallocate($image, 0, 251, 0);
// imagefilledellipse($image, $x, $y, 10, 10, $green);
imagedestroy($tmpImage);
?>

-Dave
To Top