如果您有兴趣关闭 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 Manual');
// 将图像输出到浏览器
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,则可能会遇到一些问题...
如果配置在显示“If configure fails, try --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解释器都使用内部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;
?>
我在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 = "' $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 图像中裁剪掉多余的空间。
// 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