如果您有兴趣关闭 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,瞧!:美丽的抗锯齿。
(PHP 4 >= 4.0.7, PHP 5, PHP 7, PHP 8)
imagefttext — 使用 FreeType 2 将文本写入图像
$image
,$size
,$angle
,$x
,$y
,$color
,$font_filename
,$text
,$options
= []注意:
在 PHP 8.0.0 之前,imagefttext() 是 imagettftext() 的扩展变体,它还支持
options
。从 PHP 8.0.0 开始,imagettftext() 是 imagefttext() 的别名。
image
一个 GdImage 对象,由图像创建函数之一返回,例如 imagecreatetruecolor()。
size
要使用的字体大小,以磅为单位。
angle
以度为单位的角度,0 度表示从左到右的文本。较高的值表示逆时针旋转。例如,值为 90 将导致从下到上的文本。
x
由 x
和 y
给出的坐标将定义第一个字符的基点(大致是字符的左下角)。这与 imagestring() 不同,在 imagestring() 中,x
和 y
定义第一个字符的左上角。例如,“左上角”为 0, 0。
y
纵坐标。这设置字体的基线位置,而不是字符的最底部。
color
文本所需颜色的索引,请参见 imagecolorexact()。
font_filename
要使用的 TrueType 字体的路径。
根据 PHP 使用的 GD 库的版本,当 font_filename
不以 /
开头时,会将 .ttf
附加到文件名,并且库将尝试在库定义的字体路径中搜索该文件名。
在许多情况下,如果字体与使用它的脚本位于同一个目录中,以下技巧可以避免任何包含问题。
<?php
// 设置 GD 的环境变量
putenv('GDFONTPATH=' . realpath('.'));
// 命名要使用的字体(注意没有 .ttf 扩展名)
$font = 'SomeFont';
?>
text
要插入图像的文本。
options
键 | 类型 | 意义 |
---|---|---|
linespacing |
float | 定义绘制行间距 |
此函数返回一个数组,定义框的四个点,从左下角开始,逆时针移动
0 | 左下角 x 坐标 |
1 | 左下角 y 坐标 |
2 | 右下角 x 坐标 |
3 | 右下角 y 坐标 |
4 | 右上角 x 坐标 |
5 | 右上角 y 坐标 |
6 | 左上角 x 坐标 |
7 | 左上角 y 坐标 |
失败时,返回 false
。
示例 #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 手册”
imagefttext($im, 13, 0, 105, 55, $black, $font_file, 'PHP 手册');
// 将图像输出到浏览器
header('Content-Type: image/png');
imagepng($im);
imagedestroy($im);
?>
注意: 此函数仅在 PHP 使用 freetype 支持编译时可用 (--with-freetype-dir=DIR)
如果您有兴趣关闭 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,瞧!:美丽的抗锯齿。
使用 FreeType 2 支持编译 PHP 时,如果(例如)您使用的是 debian 并且没有自己编译 freetype2,您可能会遇到一些问题...
如果在显示“如果配置失败,请尝试 --with-xpm-dir...”后配置失败,您很可能安装了 FreeType1,但没有安装 freetype2...
以 root 身份执行以下操作
apt-get install libfreetype6-dev
我花了一些时间才发现 apt-get install freetype2 实际上是安装了 freetype1...
此函数与 imageffttext() 非常相似,您可能会发现其手册页上提供的信息对您有所帮助
https://php.net/imagettftext
在用了一晚上的时间研究自动生成图像之后,我突发奇想想要关闭抗锯齿功能(看看这样字体会不会更好),结果却发现并没有那么容易。
实际上,要关闭抗锯齿,你需要使用目标颜色的负值。我将代码中的对应行(代码拆分)包含在这里:
// 使用目标颜色的负值来关闭抗锯齿
ImageFTText ($neuesBild,$fontsize,$fontangle,$TextPosX,$TextPosY,
-$custom_fg,$fonttype,$text,array());
为了一个设计项目,我需要在字符之间添加空格;由于 imagefttext 不支持此功能,我创建了一个支持此功能的函数。
函数参数与 imagefttext 相同,只是 (array)$extrainfo 现在接受了一个名为 'character_spacing' 的间距参数。返回值与预期一致,包括整个字符串的图像边界(包括字符间距)。
缺点是 $angle 会旋转每个字母,而不是旋转整个单词(这本身可以被视为一个功能)。
我希望这对某些人有用。
- KeepSake
<?php
// 需要的头文件(假设我们使用 png 图片)
header("Content-type: image/png");
// 创建一个带有深色背景的基本图像。
$image = imagecreatetruecolor(300, 20);
imagefill($image, 0, 0, imagecolorallocate($image, 21, 21, 21));
// 函数调用,参数与 imagefttext 相同,除了 (array)$extrainfo 可以接受一个名为 character_spacing 的新参数。
$imageBox = imagefttext2($image, 9, 0, 2, 15, imagecolorallocate($image, 255, 255, 255), 'tahomabold.ttf', 'The quick brown fox...', array('character_spacing' => 5));
// 输出文件,并清除资源
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 array($start_x, $start_y, $coordinates[2], $coordinates[3], $coordinates[4], $coordinates[5], $start_x, $coordinates[7]);
}
?>
realpath(".")
realpath(getenv("SCRIPT_FILENAME"));
可能有所不同。这在设置 GDFONTPATH 时有所帮助。
我难以弄清楚如何在构建图表时以点大小准确地表示字体,这些图表具有用户可自定义的输出 DPI(基本上,用户可以指定以毫米(或任何其他物理尺寸)为单位的图表大小,以及要创建任意大小的图表的 DPI,以在真实的打印文档中正常工作)。
GD1 还可以,因为它使用像素进行字体渲染,但 GD2 使用点,只有在你了解它在图像表面上渲染文本时假设的 DPI 才能有意义。我在文档中找不到任何相关信息,但我检查了 GD2 源代码,它似乎在内部假设 DPI 为 96。然而,这很容易在 GD2 源代码中进行自定义,因此不能假设所有 PHP 解释器都使用内部编译了 96dpi 的 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;
?>
我在 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");
// 不知道字体样本的宽度和高度。
// 现在创建一个巨大的图像,稍后我们将根据图像的实际大小进行裁剪。
$im = imagecreate(1000, 20000) or die('无法创建!');
$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) {
// 我们只处理 TTY 字体。
if (substr(strtolower($file), -4) != '.ttf') continue;
$str = "示例文本 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);
// 好的,现在我们可以从 1000 x 20000 图像中裁剪掉多余的空间。
$im2 = imagecreate($maxwidth + 20, $y);
imagecopyresized(
$im2, $im, 0, 0, 0, 0, $maxwidth + 20,
$y, $maxwidth + 20, $y
);
imagejpeg($im2);
imagedestroy($im);
imagedestroy($im2);
?>
如果您希望在单色字体渲染中获得最佳效果,请将 render_mode 更改为 FT_LOAD_RENDER。它是 FT_Load_Glyph() 函数的最后一个参数(在 gdft.c 中)。
我发现自己需要一个右对齐函数,并在 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;
}
?>
我写了一段代码来使用这个脚本收集目录中的所有 .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); // 释放内存
?>
由于此函数没有文档记录,我认为最好解释一下 extrainfo 参数。
您可以在 GD 参考手册中查看完整的文档
http://www.boutell.com/gd/manual2.0.33.html#gdImageStringFTEx
基本上,它接受一个包含以下选项作为键以及相关值的数组
(int) flags [在 GD 参考手册中了解更多信息]
(double/float) linespacing
(int) charmap
(int) hdpi
(int) vdpi
(string) 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) );
?>
感谢您的脚本!我修改了它来显示我想使用的几种字体。我使用的是 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 问题还是 GD 问题,但升级到 PHP 5.3.2 后,倾斜角度的文字变成了顶端对齐(所以 "N" 和 "n" 顶部相同,但 "N" 的底部比 "n" 的底部更低)。我写了一个笨拙的解决方法,它将文字写入一个未旋转的临时图像,然后将临时图像复制到主图像上并进行旋转。这种笨拙是为了解决我无法提取字体信息,特别是基线与最底部之间距离(我将其硬编码为字体大小的 30%)的问题。
我希望这个错误能得到修复(如果它确实是一个错误),或者其他人可以改进这段代码。
<?php
// 函数通过创建临时图像并旋转来绘制旋转的文字,因为旋转的文字似乎有问题
function imageTextRotated($image, $size, $angle, $x, $y, $inColor, $fontfile, $text, $info=array()) {
// 强制一些包含升降线的演示文字:
// $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); // 需要额外的空间来容纳升降线
$transparent = imagecolorallocate($tmpImage, 255, 255, 154);
if (!$transparent) {
error_log("颜色分配失败");
}
imagecolortransparent($tmpImage, $transparent);
if (!imagefill($tmpImage, 0, $ysize, $transparent)) {
error_log("填充失败");
}
$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("颜色分配 2 失败");
}
}
$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);
// 使用绿点突出显示所需的起始点(基线):
// $green = imagecolorallocate($image, 0, 251, 0);
// imagefilledellipse($image, $x, $y, 10, 10, $green);
imagedestroy($tmpImage);
?>
-Dave