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

纵坐标。这设置了字体基线的位置,而不是字符的最底部。

color

颜色索引。使用颜色索引的负数具有关闭抗锯齿的效果。参见 imagecolorallocate()

fontfile

要使用的 TrueType 字体的路径。

根据 PHP 使用的 GD 库的版本,fontfile 不以 / 开头时,将向文件名追加 .ttf,并且库将尝试沿着库定义的字体路径搜索该文件名。

在使用低于 2.0.18 的 GD 库版本时,使用 空格 字符而不是分号作为不同字体文件的“路径分隔符”。意外使用此功能会导致警告消息:警告:找不到/无法打开字体。对于这些受影响的版本,唯一的解决方案是将字体移动到不包含空格的路径。

在许多情况下,当字体驻留在与使用它的脚本相同的目录中时,以下技巧将缓解任何包含问题。

<?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 图像,其中包含用黑色(带灰色阴影)的 Arial 字体书写的“Testing...”字样。

<?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] },然后减去 2。

假设您有一个 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
10 年前
为了您的普遍了解:以下插入函数将在一块 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
16 年前
如果您在使用字体方面遇到问题...(找不到/打开字体)请检查您对文件夹/字体文件的权限,并确保它们为 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) //if the text doesn't fit on the image
{
$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)) //add one char from the string as long as it's not overflowing
{
$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]; //add the rest of the string to a new line
}
imagettftext($im, $size, $angle, $x_pos, $y_pos, $color, $font, $str); // print out the smaller line
imagettftext($im, $size, $angle, 0, $y_pos + $height, $color, $font, $restof); //and the rest of it
}
else
{
imagettftext($im, $size, $angle, $x_pos, $y_pos, $color, $font, $instr); //otherwise just do normally
}

}

?>
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
13 年前
如果你想创建一个段落,你需要将文本拆分成多行,然后将每行逐个放置在下一行下方。

以下是如何操作的基本示例

<?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 年前
对于那些尝试禁用字体平滑或字体清晰度的人来说,请查看此函数的颜色参数。你所寻找的正确词是抗锯齿。
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'>Fonts available in $ffolder</th></tr>"
."\n<tr><th>Name</th><th>Appereance</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
"No fonts found from $ffolder";
echo
"\n</HTML></BODY>";
}

else
{
$im=@imagecreatetruecolor(200,30)
or die(
"Cannot Initialize new GD image stream");

$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
17 年前
参考:Craig at frostycoolslug dot com

"使用负的颜色索引会关闭抗锯齿功能。"

这是真的,但前提是图像使用 imagecreate()(而不是 imagecreatetruecolor())创建的
Craig at frostycoolslug dot com
17 年前
这个让我有点困惑,所以为了帮助其他人...

"使用负的颜色索引会关闭抗锯齿功能。"

简单来说

<?php

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

?>

注意 ImageTTFText 中 $textColor 前面的 -(减号),它创建了负的颜色索引,并关闭了文本的 AA(抗锯齿)。
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
18 年前
注意,如果在 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
16 年前
我尝试让文字换行和换行符检测同时生效时遇到了一些问题,但在参考了下面的评论后,我得到了以下代码。(感谢 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] => Array
(
[0] => 这是我输入的第一行长文本
[1] => 这是我输入的第一行长文本。
)

[1] => Array
(
[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
16 年前
仅对 Sohel Taslims 的伟大功能进行评论...
如果有人需要为此类功能添加背景透明度(几乎所有想要的人都希望如此),请添加

$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,'some text');
Roy van Arem
17 年前
如果您想显示目录中的字体列表并查看它们的外观,您可以执行以下操作

<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("Cannot Initialize new GD image stream");

$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
17 年前
一个集中式的文本水印 - 任何长度,自动调整大小到大约 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
16 年前
评论: 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