欢迎各位兄弟 发布技术文章

这里的技术是共享的

You are here

图形处理函数库 ImageTTFText


ImageTTFText

写 TTF 文字到图中。

语法: array ImageTTFText(int im, int size, int angle, int x, int y, int col, string fontfile, string text);

返回值: 数组

函数种类: 图形处理

 

 

 
内容说明

 

本函数将 TTF (TrueType Fonts) 字型文字写入图片。参数 size 为字形的尺寸;angle 为字型的角度,顺时针计算,0 度为水平,也就是三点钟的方向 (由左到右),90 度则为由下到上的文字;x,y 二参数为文字的坐标值 (原点为左上角);参数 col 为字的颜色;fontfile 为字型文件名称,亦可是远端的文件;text 当然就是字符串内容了。返回值为数组,包括了八个元素,头二个分别为左下的 x、y 坐标,第三、四个为右下角的 x、y 坐标,第五、六及七、八二组分别为右上及左上的 x、y 坐标。治募注意的是欲使用本函数,系统要装妥 GD 及 Freetype 二个函数库。

 

 

 
使用范例

 

本例建立一个 400x30 pixel 大小的黑底图,并用 Arial 向量字体写出 I am NUMBER ONE !! 的白字。

<?php
Header
("Content-type: image/gif");
$im imagecreate(400,30);
$black ImageColorAllocate($im0,0,0);
$white ImageColorAllocate($im255,255,255);
ImageTTFText($im2001020$white"/somewhere/arial.ttf""I am NUMBER ONE !!");
ImageGif($im);
ImageDestroy($im);
?>

来自  http://www.t086.com/code/php/function.php-ImageTTFText.php

绝对详解PHP 的imageTtfText()函数

 10237人阅读 评论(2) 收藏 举报
 分类:
 
 
 

目录(?)[+]

 

图片处理,是许多程序的功能之一;而文字渲染则是绘图的基本组成部分。PHP通过很多扩展库来支持图片的处理,最常用的还是GD库,通过一系列imagexxx()函数来提供绘图功能。本文专注于非常细小的一点:绘制文字。熟悉Win32的人都知道,TextOut()就可以轻松显示任何文字了,然而到了PHP的世界里,有些事情并不轻松。

1 详细解释imageTtfText()函数

 
对于PHP绘图初学者,首先遇到的一个问题就是,imageString()这个函数并不支持汉字的绘制。这往往会给入门者当头一棒,不过不要着急,因为还有一个imageTtfText()函数,这个函数能绘制UTF-8编码的字符串,当然可以绘制汉字了。然而使用它并不十分简单。先来看看其原型声明:
 
 
 
一共有8个参数,缺一不可,而且官方文档这些参数的解释并不透彻,这里笔者尽力做更详细清晰的解释:
(1)$image 这个是画布资源,无需再解释;
(2)$size,官方文档的解释是,字体大小,其长度单位依赖于GD库的版本,对于GD1来说是像素,对于GD2来说是磅(point)。现在一般都是GD2了,那么这个磅究竟是什么意思呢?这涉及到字体设计的基本知识。
 
简单来说,磅是一个长度度量单位,如果把一英寸等分成72份,每一份就是1磅。这里需要强调的是,磅是个绝对物理单位,与显示设备无关。
 
而像素呢?像素没有固定的大小,而是与分辨率相关,高分辨率的显示器像素就很小,如iphone视网膜屏上一个像素的大小要比普通LCD显示器的像素小很多。然而有些东西是不存在分辨率这个概念的,如单纯的位图图片,它的最小组成部分就是像素,本身也是通过每个像素的颜色值来定义的。把同样的图片显示在不同分辨率的显示器上,最终呈现出的大小是不同的。
 
操作位图时,以像素位单位最精确合理,那么使用GD2库的时候,如何绘制大小为20像素的字呢?也就是多少磅才能等于20个像素呢?这必须通过分辨率才能计算出来,而问题是位图本身并没有分辨率的概念。
 
现在把问题返回来,如果给定$size=20磅,那么imageTtfText()绘制完成时,究竟会占用多少像素。无论如何,imageTtfText()最终还是要把文字绘制落实到具体的位图像素上。
 
1磅 = PPI/72 个像素
 
这个问题确实非常棘手,此函数内部必然会使用某个分辨率PPI来计算被渲染的像素区域。而GD2库却没有提供任何让用户设置或者读取这个分辨率的方法。那么,我们只能动手测试了。使用不同的磅值绘制文字,然后测量文字占据的像素,通过公式:
PPI = (72*像素数)/磅值。实验得出的结论是:
[plain] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. 1磅==>4像素, PPI=288  
  2. 2磅==>5像素, PPI=180  
  3. 3磅==>7像素, PPI=168  
  4. 4磅==>8像素, PPI=144  
  5. 5磅==>9像素, PPI=129.6  
  6. 6磅==>10像素, PPI=120  
  7. 7磅==>11像素, PPI=113.14285714286  
  8. 8磅==>12像素, PPI=108  
  9. 9磅==>14像素, PPI=112  
  10. 10磅==>15像素, PPI=108  
  11. 11磅==>16像素, PPI=104.72727272727  
  12. 12磅==>17像素, PPI=102  
  13. 13磅==>18像素, PPI=99.692307692308  
  14. 14磅==>19像素, PPI=97.714285714286  
  15. 15磅==>21像素, PPI=100.8  
  16. 16磅==>22像素, PPI=99  
  17. 17磅==>23像素, PPI=97.411764705882  
  18. 18磅==>25像素, PPI=100  
  19. 19磅==>26像素, PPI=98.526315789474  
  20. 20磅==>27像素, PPI=97.2  
  21. 21磅==>28像素, PPI=96  
  22. 22磅==>29像素, PPI=94.909090909091  
  23. 23磅==>30像素, PPI=93.913043478261  
  24. 24磅==>32像素, PPI=96  
  25. 25磅==>33像素, PPI=95.04  
  26. 26磅==>34像素, PPI=94.153846153846  
  27. 27磅==>35像素, PPI=93.333333333333  
  28. 28磅==>36像素, PPI=92.571428571429  
  29. 29磅==>38像素, PPI=94.344827586207  
  30. 30磅==>39像素, PPI=93.6  
  31. 31磅==>40像素, PPI=92.903225806452  
  32. 32磅==>41像素, PPI=92.25  
  33. 33磅==>43像素, PPI=93.818181818182  
  34. 34磅==>44像素, PPI=93.176470588235  
  35. 35磅==>46像素, PPI=94.628571428571  
  36. 36磅==>47像素, PPI=94  
  37. 37磅==>48像素, PPI=93.405405405405  
  38. 38磅==>48像素, PPI=90.947368421053  
  39. 39磅==>50像素, PPI=92.307692307692  
  40. 40磅==>51像素, PPI=91.8  
  41. 41磅==>52像素, PPI=91.317073170732  
  42. 42磅==>53像素, PPI=90.857142857143  
  43. 43磅==>55像素, PPI=92.093023255814  
  44. 44磅==>56像素, PPI=91.636363636364  
  45. 45磅==>57像素, PPI=91.2  
  46. 46磅==>58像素, PPI=90.782608695652  
  47. 47磅==>60像素, PPI=91.914893617021  
  48. 48磅==>62像素, PPI=93  
  49. 49磅==>63像素, PPI=92.571428571429  
  50. 50磅==>63像素, PPI=90.72  
  51. 51磅==>64像素, PPI=90.352941176471  
  52. 52磅==>67像素, PPI=92.769230769231  
  53. 53磅==>68像素, PPI=92.377358490566  
  54. 54磅==>69像素, PPI=92  
  55. 55磅==>70像素, PPI=91.636363636364  
  56. 56磅==>71像素, PPI=91.285714285714  
  57. 57磅==>72像素, PPI=90.947368421053  
  58. 58磅==>74像素, PPI=91.862068965517  
  59. 59磅==>75像素, PPI=91.525423728814  
  60. 60磅==>76像素, PPI=91.2  
  61. 61磅==>77像素, PPI=90.885245901639  
  62. 62磅==>78像素, PPI=90.58064516129  
  63. 63磅==>79像素, PPI=90.285714285714  
  64. 64磅==>81像素, PPI=91.125  
  65. 65磅==>83像素, PPI=91.938461538462  
  66. 66磅==>84像素, PPI=91.636363636364  
  67. 67磅==>85像素, PPI=91.34328358209  
  68. 68磅==>86像素, PPI=91.058823529412  
  69. 69磅==>86像素, PPI=89.739130434783  
  70. 70磅==>88像素, PPI=90.514285714286  
  71. 71磅==>90像素, PPI=91.267605633803  
  72. 72磅==>91像素, PPI=91  
  73. 73磅==>92像素, PPI=90.739726027397  
  74. 74磅==>93像素, PPI=90.486486486486  

可见当大于46磅时,PPI稳定在90,而小于46磅时,PPI一直在微变。
所以,如果你想绘制20个像素大小的字体,那么必须设置$size参数为:14.5磅。
另外需要注意的是,$size并不完全对应字体的显示大小,因为同样的$size,不同的字符占据的空间并不是一样的。例如,汉字“国”的宽度会比数字1的宽度大得多,对于标点符号,则更是这样,半角和全角符号也不同。
总之,使用imageTtfText()不可能精确控制到像素级别,只能大概。这也算是矢量字体的一个小缺陷。
 
(3)$angle是旋转角度。这个官网解释的比较清楚,需要说明有两点:一是角度单位是度而不是弧度,二是旋转的中心点就是参数$x,$y。
 
(4)(5)$x,$y 被绘制字符串的第一个字符的基线点。单位是像素。这里涉及到字体设计的基本知识--基线。这个点绝对不是左上角,而具体是什么取决于所使用的字体是如何设计的。对于宋体、楷体、黑体等常见的字体中的汉字,这个点大概位于字体的左下部分;而对于英文字母和标点符号,则各不相同。如下图:
 
 
 
 
 
(6)$color 字体的颜色,不多解释。
 
(7)$fontfile 字体文件。也就是包含trueType字体字模的文件,如楷体字体文件simkai.ttf。这种文件的格式是有标准规范的,而且与平台无关。所以可以直接把Windows系统的字体文件拷贝到Linux下使用。
 
(8)$text 要渲染的字符串。需要注意必须是UTF-8编码的字符串。说到字符串不得不提PHP的string数据类型。虽然名为string,其实PHP语言本身并不认识各种字符编码,它只是简单的把string看做是动态增长的“字节”数组,例如strlen()就是返回的字节数。而我们知道除了ASCII编码的字符和字节是相同的外,几乎没有其他字符编码中的字符对应一个字节,例如一个汉字的UTF-8编码占用3个字节。至于怎么解释其中的字符编码,需要专门的库函数如iconv_strlen()。如果字符串使用字面量,那么其所在的php源文件就必须编码为UTF-8存储。
 

2 几个小技巧

(1)字处理软件的复杂之处
尽管这个函数可以显示字符串,但是针对于字处理软件(如Word)来说,并不能使用。因为一旦涉及到对其的问题,此函数即不能使用了。因为它不能处理字间距,当然也就无法实现分散对齐等功能。再加上每行的“避首尾”(如,不能位于行首)要求,做好字处理并不简单。
 
变通的方式是,首先通过复杂的公式计算出各个字符的准确位置,然后针对每一个字符调用此函数。
 
(2)如何显示加粗字体
对于本身就有粗体的字体文件来说,这不存在任何问题,只要使用粗体文件就可以了。问题是很多字体文件并没有针对粗体单独设计。GD库中也没有一个能加粗显示的函数。其解决方法说出来有点可笑,就是针对每个字符绘制两次,第二次绘制时的$x会第一次的$x多1个像素即可。


来自  http://blog.csdn.net/smstong/article/details/43955705

imagettftext

(PHP 4, PHP 5, PHP 7)

imagettftext — 用 TrueType 字体向图像写入文本

说明 ¶

array imagettftext ( resource $image , float $size , float $angle , int $x , int $y , int $color ,string $fontfile , string $text )

使用 TrueType 字体将 指定的 text 写入图像。

参数 ¶

image

由图象创建函数(例如imagecreatetruecolor())返回的图象资源。

size

字体的尺寸。根据 GD 的版本,为像素尺寸(GD1)或点(磅)尺寸(GD2)。

angle

角度制表示的角度,0 度为从左向右读的文本。更高数值表示逆时针旋转。例如 90 度表示从下向上读的文本。

x

由 xy 所表示的坐标定义了第一个字符的基本点(大概是字符的左下角)。这和 imagestring() 不同,其xy 定义了第一个字符的左上角。例如 "top left" 为 0, 0。

y

Y 坐标。它设定了字体基线的位置,不是字符的最底端。

color

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

fontfile

是想要使用的 TrueType 字体的路径。

根据 PHP 所使用的 GD 库的不同,当 fontfile 没有以 / 开头时则 .ttf 将被加到文件名之后并且会在库定义字体路径中尝试搜索该文件名。

当使用的 GD 库版本低于 2.0.18 时,一个空格字符 而不是分号将被用来作为不同字体文件的“路径分隔符”。不小心使用了此特性将会导致一条警告信息:Warning: Could not find/open font。对受影响的版本来说唯一解决方案就是将字体移动到不包含空格的路径中去。

很多情况下字体都放在脚本的同一个目录下。下面的小技巧可以减轻包含的问题。

<?php
// Set the enviroment variable for GD
putenv('GDFONTPATH=' realpath('.'));

// Name the font to be used (note the lack of the .ttf extension)
$font 'SomeFont';
?>
text

UTF-8 编码的文本字符串。

可以包含十进制数字化字符表示(形式为:&#8364;)来访问字体中超过位置 127 的字符。UTF-8 编码的字符串可以直接传递。

命名实体,比如 &copy; 是不支持的。可以考虑使用 html_entity_decode() 来解码命名实体为 UTF-8 字符。 (自 PHP 5.0.0 开始 html_entity_decode() 开始支持)

如果字符串中使用的某个字符不被字体支持,一个空心矩形将替换该字符。

返回值 ¶

返回一个含有 8 个单元的数组表示了文本外框的四个角,顺序为坐下角,右下角,右上角,左上角。这些点是相对于文本的而和角度无关,因此“左上角”指的是以水平方向看文字时其左上角。

更新日志 ¶

版本说明
5.2.0It is now possible to specify an hexadecimal entity in text.

范例 ¶

Example #1 imagettftext() 例子

本例中的脚本将生成一个白色的 400x30 像素 PNG 图像,其中有黑色(带灰色阴影)Arial 字体写的“Testing...”。

<?php
// Set the content-type
header('Content-Type: image/png');

// Create the image
$im imagecreatetruecolor(40030);

// Create some colors
$white imagecolorallocate($im255255255);
$grey imagecolorallocate($im128128128);
$black imagecolorallocate($im000);
imagefilledrectangle($im0039929$white);

// The text to draw
$text 'Testing...';
// Replace path by your own font path
$font 'arial.ttf';

// Add some shadow to the text
imagettftext($im2001121$grey$font$text);

// Add the text
imagettftext($im2001020$black$font$text);

// Using imagepng() results in clearer text compared with imagejpeg()
imagepng($im);
imagedestroy($im);
?>

以上例程的输出类似于:

例子输出:imagettftext()

注释 ¶

Note:

本函数同时需要 GD 库和 » FreeType 库。.

参见 ¶

add a note add a note

User Contributed Notes 66 notes

Valentijn de Pagter ¶
8 years ago
If you're looking for easy text alignment, you need to use the imagettfbbox() command. When given the correct parameters, it will return the boundaries of your to-be-made text field in an array, which will allow you to calculate the x and y coordinate that you need to use for centering or aligning your text.

A horizontal centering example:

<?php

$tb 
imagettfbbox(170'airlock.ttf''Hello world!');

?>

$tb would contain:

Array
(
    [0] => 0 // lower left X coordinate
    [1] => -1 // lower left Y coordinate
    [2] => 198 // lower right X coordinate
    [3] => -1 // lower right Y coordinate
    [4] => 198 // upper right X coordinate
    [5] => -20 // upper right Y coordinate
    [6] => 0 // upper left X coordinate
    [7] => -20 // upper left Y coordinate
)

For horizontal alignment, we need to substract the "text box's" width { $tb[2] or $tb[4] } from the image's width and then substract by two.

Saying you have a 200px wide image, you could do something like this:

<?php

$x 
ceil((200 $tb[2]) / 2); // lower left X coordinate for text
imagettftext($im170$x$y$tc'airlock.ttf''Hello world!'); // write text to image

?>

This'll give you perfect horizontal center alignment for your text, give or take 1 pixel. Have fun!
suyog at suyogdixit dot com ¶
2 years ago
For your general edification: The following drop-in function will place a block of fully justified text onto a GD image. It is a little CPU heavy, so I suggest caching the output rather than doing it on-the-fly. 

Arguments: 

$image - the GD handle of the target canvas 
$size - text size 
$angle - slope of text (does not work very well), leave at 0 for horizontal text 
$left - no. of pixels from left to start block 
$top - no. of pixels from top to start block 
$color - handle for colour (imagecolorallocate result) 
$font - path to .ttf font 
$text - the text to wrap and justify 
$max_width - the width of the text block within which the text should be wrapped and fully justified 
$minspacing - the minimum number of pixels between words 
$linespacing - a multiplier of line height (1 for normal spacing; 1.5 for line-and-a-half etc.)

eg.
$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;
}
Paul Reinheimer ¶
11 years ago
If you compiled PHP yourself but get an error:
Fatal error: Call to undefined function imagettftext().

You need to compile PHP with more options.

--with-gd
--enable-gd-native-ttf
--with-png
--with-zlib-dir=/usr/local/lib/zlib-1.2.1
--with-ttf
--with-jpeg-dir=/usr/local/lib/jpeg-6b/
--with-freetype-dir=/usr/local/lib/freetype-2.1.9/
--with-xpm-dir=/usr/X11R6/

The next set deal with setting up GD, and the appropriate options. Just enabling GD, ttf, png & jpeg is NOT enough. You also need Freetype and XPM.
pillepop2003 at nospam dot yahoo dot de ¶
11 years ago
Hey guys,

check this function if you want to rotate the text around its center and not its "lower left" pivot-point:

<?php
        
// Put center-rotated ttf-text into image
        // Same signature as imagettftext();
        
function imagettftext_cr(&$im$size$angle$x$y$color$fontfile$text)
        {
            
// retrieve boundingbox
            
$bbox imagettfbbox($size$angle$fontfile$text);
            
            
// calculate deviation
            
$dx = ($bbox[2]-$bbox[0])/2.0 - ($bbox[2]-$bbox[4])/2.0;         // deviation left-right
            
$dy = ($bbox[3]-$bbox[1])/2.0 + ($bbox[7]-$bbox[1])/2.0;        // deviation top-bottom
            
            // new pivotpoint
            
$px $x-$dx;
            
$py $y-$dy;
            
            return 
imagettftext($im$size$angle$px$py$color$fontfile$text);
        }


?>

Big up
Phil
John Conde ¶
5 years ago
If you want to create a paragraph you will need to break your text up into lines and then place each line individually one below the next.

Here's a basic example of how to do that:

<?php
// Basic font settings
$font ='./times.ttf';
$font_size 15;
$font_color =  0x000000

// Text to be placed as a paragraph
$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.';

// Break it up into pieces 125 characters long
$lines explode('|'wordwrap($text115'|'));

// Starting Y position
$y 513;

// Loop through the lines and place them on the image
foreach ($lines as $line)
{
    
imagettftext($image$font_size050$y$font_color$font$line);

    
// Increment Y so the next line is below the previous line
    
$y += 23;
}


?>
ben at spooty dot net ¶
7 years ago
Here's a simple function to wrap text going into an image. It'll wrap onto as many lines as it needs to, but $angle has to be zero. The $width parameter is the width of the image.

<?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;
}

?>
web at evanreeves dot com ¶
7 years ago
I was having trouble trying to render non antialiased text using a pixel font. The tips about setting a negative value for the color are valid, but I was still having trouble with the text I was trying to render because it was black. I discovered that if I changed the imagecolorallocate() function from:

$color = imagecolorallocate($base, 0, 0, 0);

to 

$color = imagecolorallocate($base, 1, 1, 1); (near black)

and then used the negative value for the color in imagettftext(), it would work properly. The difference is that my first implementation set $color = 0. Obviously, you can't have $color = -0, it made no difference. When I switched to (1,1,1) it became $color = 1 which I could take a negative value for.
JohnB ¶
6 years ago
Just in case you were--like me--unaware of this, in Windows, ttf fonts don't necessarily antialias at all font sizes. Arial appears to work at all sizes but Calibri, for example, only antialiases at a point size of 8 and then at all sizes 16 and up. Not only that but at fonts sizes like 10 and 12 characters don't print at the expected angle: the characters are all printed upright on an angled baseline.
philip at webdesco dot com ¶
7 years ago
Hi,
for the dummies (like myself) if you are having problems including your font file, prefix the file name with ./

On my development server the following worked fine
$myfont = "coolfont.ttf";

on my hosting server the only way i could get the font to work was as follows
$myfont = "./coolfont.ttf";

hope this helps someone out!
BuddyHacker ¶
10 years ago
A correction to Paul Reinheimer's note above regarding this PHP error:

Fatal error: Call to undefined function imagettftext().

Paul states that you need XPM libraries to resolve this issue.  This is not true.  There is an error message that originates from "configure" which mistakenly shows itself when other components are missing.  For instance, if you tell "configure" to add JPEG support, and it can't find the libraries, it will tell you it can't find the JPEG libraries AND it will recommend adding --with-xpm to solve the problem.  This recommendation is ill-placed and misleading.

I received the same error message above, along with the recommendation to add XPM supprt.  However I resolved it by adding the --with-freetype-dir  AND --enable-gd-native-ttf  options  to the "configure" command line.  I did _not_ need XPM.

There are other variations to this error message, such as the script recommending adding JPEG support or PNG support to resolve it's own inability to locate other libraries.  The script needs some cleanup in order to fix these poorly placed recommendations.

FYI, imagettftext() is a call to one of the truetype fonts functions.  It is NOT related in any way to the XPM libraries, so it is not required unless you explicitly want XPM functionality.
danielslcosta at gmail dot com ¶
11 months ago
Note that imagettftext and imagettfbbox will keep file handles open for fonts used (at least in Windows, Apache 2, PHP 5.3.24) - there is a bug report on that but it's related to FreeType, so if you load several types of fonts, or temporary fonts, you may find your system reaching max handles open. Also, you won't be able to unlink it or remove folders that contain the font.
lilfo ¶
2 years ago
If you need to rotate text around center you can use this function instead of imagettftext_cr() by pillepop2003 that doesn't mantain the same center of the original image (shifting a bit):

function imagettftext_center_rotate(&$im, $size, $angle, $x, $y, $color, $fontfile, $text)
        {
            // retrieve boundingbox of the non rotated text
            $bbox = imagettfbbox($size, 0, $fontfile, $text);
            //calculate the parameters of the line from lowerleft to upperright point
            $m1 = ($bbox[5]-$bbox[1])/($bbox[4]-$bbox[0]);
            $q1 = $bbox[1]-($bbox[0]*$m1);
            //calculate the parameters of the line from upperleft to lowerright point
            $m2 = ($bbox[3]-$bbox[7])/($bbox[2]-$bbox[6]);
            $q2 = $bbox[7]-($bbox[6]*$m2);
            //calculate the rectangle center (intersection of the two lines)
            $vx = ($q1-$q2)/($m2-$m1);
            $vy = ($m1*($q1-$q2)/($m2-$m1))+$q1;

            // retrieve boundingbox of the rotated text
            $bbox = imagettfbbox($size, $angle, $fontfile, $text);
            //calculate the parameters of the line from lowerleft to upperright point
            $m1 = ($bbox[5]-$bbox[1])/($bbox[4]-$bbox[0]);
            $q1 = $bbox[1]-($bbox[0]*$m1);
            //calculate the parameters of the line from upperleft to lowerright point
            $m2 = ($bbox[3]-$bbox[7])/($bbox[2]-$bbox[6]);
            $q2 = $bbox[7]-($bbox[6]*$m2);
            //calculate the rectangle center (intersection of the two lines)
            $nx = ($q1-$q2)/($m2-$m1);
            $ny = ($m1*($q1-$q2)/($m2-$m1))+$q1;

            //calculate the x and y shifting needed
            $dx = $nx - $vx;
            $dy = $ny - $vy;            
            
            // new pivotpoint
            $px = $x-$dx;
            $py = $y-$dy;

            //output
            return imagettftext($im, $size, $angle, $px, $py, $color, $fontfile, $text);
        }
Endeer ¶
5 years ago
If latin characters with accents don't work for you (blank characters or rectangles), then it may be perhaps caused by PHP being compiled with --enable-gd-jis-conv. Verified on PHP 5.2.13.
cameron at prolifique dot com ¶
7 years ago
"php at yvanrodrigues dot com" is right...this function is not reliable on extended characters. User beware.

In my case, it produced different results with OpenType vs. TrueType versions of the same font. (Converted my OT font to TT using FontForge as suggested. Strangely, the resulting TT font file was twice as big as the OT version and didn't look the same...heavier weight and slightly different spacing.) While the TT version was more accurate at displaying certain characters, neither was totally reliable, both yielding boxes in place of perfectly valid character glyphs that I could verify existed in the font. (Both fonts showed the same characters perfectly on an HTML page with UTF-8 charset.)

What's more, using this same function with the same font on our development vs. production server also produced different results: some chars worked on dev but not production. Stranger still, the font spacing and size were slightly different between the two. Font file is identical. Dev server is Linux, production server is Windows, but should that matter? Suspect it has more to do with differing versions of FreeType (2.1 vs. 1.9 respectively).

Anyway, careful with this function...best to stick within the rather small range of safe characters and avoid anything else.
php at yvanrodrigues dot com ¶
7 years ago
After many hours of failure may I suggest:

This function will work on OpenType fonts with Postscript outlines, but from what I can tell, characters > ASCII 127 do not display correctly or at all, even if the text is correctly coded as UTF-8.

Converting the font to truetype or possibly OpenType with truetype outlines; or buying the font as such fixes the problem.

I used FontForge to open the otf and export as ttf and it works perfectly.
sk89q ¶
7 years ago
I updated my imagettftextbox function considerably. It fixes the problems of the older imagettftextbox code I uploaded a few months ago (that's now gone).

You can get it here:
http://sk89q.therisenrealm.com/2008/08/ttf-textbox-in-php/

It has both horizontal and vertical alignment, custom line spacing, borders, width, height, etc.
Anonymous ¶
8 years ago
Just to comment on Sohel Taslims great function...
if anyone needs to add BACKGROUND TRANSPARENCY to this kind of function (which almost does everyone one would want already) then add 

$bg_color = imagecolorat($im,1,1);
imagecolortransparent($im, $bg_color);

ABOVE the "if($L_R_C == 0){ //Justify Left"  line
mitch at electricpulp dot com ¶
8 years ago
If you're having issues with fonts not working... (Could not find/open font) check your permissions on the folder/font files and make sure they're 775, especially if you've just pulled them from a windows box. Hope this helps!
Ole Clausen ¶
8 years ago
Comment to: Sohel Taslim (03-Aug-2007 06:19)

Thanks for the function which I have modified a bit. In the new version the lines have equal space between them (the g's in your example create bigger space between the lines) - set by the parameter '$Leading'.

I have used the for-loop for better performance and slimmed the rest a little  :)

    /**
     * @name                    : makeImageF
     * 
     * Function for create image from text with selected font. Justify text in image (0-Left, 1-Right, 2-Center).
     *
     * @param String $text     : String to convert into the Image.
     * @param String $font     : Font name of the text. Kip font file in same folder.
     * @param int    $Justify  : Justify text in image (0-Left, 1-Right, 2-Center).
     * @param int    $Leading  : Space between lines.
     * @param int    $W        : Width of the Image.
     * @param int    $H        : Hight of the Image.
     * @param int    $X        : x-coordinate of the text into the image.
     * @param int    $Y        : y-coordinate of the text into the image.
     * @param int    $fsize    : Font size of text.
     * @param array  $color    : RGB color array for text color.
     * @param array  $bgcolor  : RGB color array for background.
     * 
     */
    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);  // Array of lines
        $nL = count($s);  // Number of lines
        $W = ($W==0)?abs($_bx[2]-$_bx[0]):$W;    // If Width not initialized by programmer then it will detect and assign perfect width. 
        $H = ($H==0)?abs($_bx[5]-$_bx[3])+($nL>1?($nL*$Leading):0):$H;    // If Height not initialized by programmer then it will detect and assign perfect height. 
        
        $im = @imagecreate($W, $H)
            or die("Cannot Initialize new GD image stream");
        
        $background_color = imagecolorallocate($im, $bgcolor[0], $bgcolor[1], $bgcolor[2]);  // RGB color background.
        $text_color = imagecolorallocate($im, $color[0], $color[1], $color[2]); // RGB color text.
        
        if ($Justify == 0){ //Justify Left
            imagettftext($im, $fsize, $angle, $X, $fsize, $text_color, $font, $text);
        } else {
            // Create alpha-nummeric string with all international characters - both upper- and lowercase
            $alpha = range("a", "z");
            $alpha = $alpha.strtoupper($alpha).range(0, 9);
            // Use the string to determine the height of a line
            $_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]);
                //Defining the X coordinate.
                if ($Justify == 1) $_X = $W-$_W;  // Justify Right
                else $_X = abs($W/2)-abs($_W/2);  // Justify Center
                
                //Defining the Y coordinate.
                $__H += $_H;
                imagettftext($im, $fsize, $angle, $_X, $__H, $text_color, $font, $s[$i]);
                $__H += $Leading;
            }
        }
        
        return $im;
    }
php at gilbertson dot me dot uk ¶
9 years ago
Users may note a problem trying to use this function to display the Euro symbol.

The reason is that it is a late addition. Although the operating systems generally recognise code 0x80 (128 decimal) as Euro, this is not where it necessarily appears in the font. Some have it there, but many just have it in the extended character set at position 0x20AC (8364 decimal).

I have yet to find a font with it only at 0x80, so here is the fix:

<?php
$image
=imagecreate(135,24);
$bg=imagecolorallocate($image,0,0,0);
$fg=imagecolorallocate($image,0,255,0);
$text 'coffee - €3.50';
$friendly eurofix($text);
imagettftext($image,16,0,5,20,$fg,"Papyrus.ttf",$friendly);
imagegif ($image);
imagedestroy ($image);

function 
eurofix($str) {
$euro=utf8_encode('&#8364;');
$str preg_replace('/\x80/',$euro,$str);
return (
$str);
}

?>

You should note, however, this won't help with fonts older than about 1999. It can only make sure the Euro is displayed where available.
jwe ¶
9 years ago
Quick tip for anyone who is receiving text like in the example in this page (ie: through $_GET['text'] or something similar) and needs to format the text into multiple lines.  The trick is finding the spaces...

<?php
$text 
$_GET['text'];
// for a maximum of 38 characters on a line...
while(strlen($text) > 38) {
   
$startPoint 37;
   
// find a space to break the line on
   
while(substr($text$startPoint1) != " ") {
        
$startPoint--;
   }
   
$line[] = trim(substr($text0$startPoint));
   
$text substr($text$startPoint);
}

$line[] = trim($text);
?>

The result is an array called $line that contains all the lines of text you need to output in order.

The only tasks left are to determine the correct height of the image based on the font size you want to use.  Don't forget to leave some padding space for punctuation and descenders between lines (commas, g, q, p, y, etc).

imagettftext is unbelievably useful when you need to create header images using non-standard fonts.  Amazing.  Huge thanks to the devs.

--Julian
simbiat at bk dot ru ¶
1 year ago
Another way to wrap and center using wordwrap and learning the number of lines in the result of that wordwrap

<?php

$text
="privet privet privet privet privet privet2 privet2 privet2 privet2 privet2 privet3";
$text=wordwrap($text35"\n"TRUE);

//setting the image header in order to proper display the image
header("Content-Type: image/png");
//try to create an image
$im = @imagecreate(460215)
    or die(
"Cannot Initialize new GD image stream");
//set the background color of the image
$background_color imagecolorallocate($im0x000x000x00);
//set the color for the text
$text_color imagecolorallocate($im0xFF0xFF0xFF);
//adf the string to the image

$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);
?>
gav-alex at bk dot ru ¶
10 years ago
Hi all!
When my hoster updated his php's libs at first minutes i've got the same problem as some of you.
Php couldn't find the path to true type fonts.
The solution in my case was to make the path look like this
<?php
imagettftext
($im200620260$secondary_color"./tahoma.ttf" "NEWS");
?>
so as you can see i simply added "./"

another tip that i wanted to add here is how to write in RUssian on image using imagettftext
you simply have to change the function argument like this
<?php
imagettftext
($im150575300$secondary_color"./tahoma.ttf" win2uni("some word in russian"));
?>
where win2uni is the function that converts win1251 to unicode. here is the code of it
<?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;
  }

?>

That's all today! Thanks for your attention!
Alex
plusplus7 at hotmail dot com ¶
11 years ago
If you are getting all rectangles instead of text, it may well mean that your ttf font is not opentype, particularly if it is an older freeware one. This requirement didn't exist in older versions so you may find that your font stops working after you upgrade. To fix this problem, try downloading the free MS Volt utility. From there, open your font file, and then click on Compile, and resave.
s.pynenburg _at_ gm ail dotcom ¶
7 years ago
I had an image generator where the user could position where they wanted the text to begin - however it kept going off the side of an image. So I made this basic function: it measures if the inputted text and x-position will cause the string to go off the edge, and if so, it will fit as much as it can on the first line, then go down to the next one. 
Limitations: 
-It only performs this once (i.e. it won't split into three lines) 
-I'm pretty sure it won't work with angled text. 

<?PHP 

function imagettftextwrap($im$size$angle$x_pos$y_pos$color$font$instr

    
$box = @imagettfbbox($size0$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($fsize10$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($fsize10$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$angle0$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 
    




?>
damititi at gmail dot com ¶
8 years ago
First of all, thanks sk89q for the func! it was exactly I was looking for.

I made a change. Depending on the letter, the text were incorrect vertical aligned.
I replace the line:
                $line_height = $dimensions[1] - $dimensions[7];
for the following:
                $line_height = $size+4;

No matter if mama or jeje is written, the vertical position will be the same.
sk89q ¶
8 years ago
Here is an update to my imagettftextwrapped function. I had posted the old version that cut off lines if it wordwrapped.

Here's a new version with the bug fixed, a list of arguments closer to imagettftext(), and partial angle support (the text is angled, but the left margins for each line are not adjusted for the angle).

It's a function I wrote a few years ago to do unjustified aligned text.

<?php
define
("ALIGN_LEFT""left");
define("ALIGN_CENTER""center");
define("ALIGN_RIGHT""right");

function 
imagettftextbox(&$image$size$angle$left$top$color$font$text$max_width)
{
        
$text_lines explode("\n"$text); // Supports manual line breaks!
        
        
$lines = array();
        
$line_widths = array();
        
        
$largest_line_height 0;
        
        foreach(
$text_lines as $block)
        {
            
$current_line ''// Reset current line
            
            
$words explode(' '$block); // Split the text into an array of single words
            
            
$first_word TRUE;
            
            
$last_width 0;
            
            for(
$i 0$i count($words); $i++)
            {
                
$item $words[$i];
                
$dimensions imagettfbbox($size$angle$font$current_line . ($first_word ?'' ' ') . $item);
                
$line_width $dimensions[2] - $dimensions[0];
                
$line_height $dimensions[1] - $dimensions[7];
                
                if(
$line_height $largest_line_height$largest_line_height $line_height;
                
                if(
$line_width $max_width && !$first_word)
                {
                    
$lines[] = $current_line;
                    
                    
$line_widths[] = $last_width $last_width $line_width;
                    
                    
/*if($i == count($words))
                    {
                        continue;
                    }*/
                    
                    
$current_line $item;
                }
                else
                {
                    
$current_line .= ($first_word '' ' ') . $item;
                }
                
                if(
$i == count($words) - 1)
                {
                    
$lines[] = $current_line;
                    
                    
$line_widths[] = $line_width;
                }
                
                
$last_width $line_width;
                    
                
$first_word FALSE;
            }
            
            if(
$current_line)
            {
                
$current_line $item;
            }
        }
        
        
$i 0;
        foreach(
$lines as $line)
        {
            if(
$align == ALIGN_CENTER)
            {
                
$left_offset = ($max_width $line_widths[$i]) / 2;
            }
            elseif(
$align == ALIGN_RIGHT)
            {
                
$left_offset = ($max_width $line_widths[$i]);
            }
            
imagettftext($image$size$angle$left $left_offset$top +$largest_line_height + ($largest_line_height $i), $color$font$line);
            
$i++;
        }
        
        return 
$largest_line_height count($lines);
}

?>
matt at mmkennedy dot net ¶
8 years ago
For anyone attempting to print black barcodes, and trying to turn of anti-aliasing, remember that -1 * [0,0,0] is 0, not -0.
denis at reddodo dot com ¶
8 years ago
Small but very dangerous bug in function ttfWordWrappedText, written by waage, just try ttfWordWrappedText("aaaaa\naa",4) and your script will run into endless loop. 
You can fix it with code below:
<?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;
}

?>
better solutions is to check input text for lines longer than needed wrap point.
denis at reddodo dot com ¶
8 years ago
Small but very dangerous bug in function ttfWordWrappedText, written by waage, just try ttfWordWrappedText("aaaaa\naa",4) and your script will run into endless loop. 
You can fix it with code below:
<?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$startPoint1) != " ") {
                
$startPoint--;
           }
           
$line[$i][] = trim(substr($text0$startPoint));
           
$text substr($text$startPoint);
        }
        
$line[$i][] = trim($text);
        
$i++;
    }
   
    return 
$line;
}

?>
better solutions is to check input text for lines longer than needed wrap point.
dotpointer ¶
8 years ago
For those trying to disable the font smoothing or font cleartype:ing, take a look at the color parameter for this function. The correct word for what you're looking for is antialiasing.
lassial at gmail dot com ¶
9 years ago
Roy van Arem suggested a neat code for listing TTFs on a machine. However, it has some problems (such as lower and upper case distinction of file extension and defective fonts) that I have corrected in the following script, which can be implemented as a single PHP script (name as you like):

<?php //make sure there are no blank lines above
        

$ffolder="/usr/local/bin/fonts"//The directory where your fonts reside

if (empty($_GET['f']))
{

$folder=dir($ffolder); //open directory
echo "<HTML><BODY>\n";
    
while(
$font=$folder->read())
  if(
stristr($font,'.ttf')) //only ttf fonts
        
$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 ¶
9 years ago
I have found the kerning (spacing between letters) pretty poor with GD - it's not up to your average designer's standards. Here are some ways to improve it:
- Place the letters one by one using their bounding box instead of using one string
- adjust with a $kerning value
- For small text, sample it down from a larger size to adjust in increments less than 1px

Eg:

<?PHP

$STRING 
"NOTRE PHILOSOPHIE";

// ---- PRESETS
$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
);

// ---- CREATE CANVAS + PALETTE
$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 $canvas00$bg_color );

// ---- DRAW

$array str_split($STRING);
$hpos 0;

for(
$i=0$i<count($array); $i++)
{
    
$bbox imagettftext$canvas$FONT_SIZE*40$hpos$BASELINE*4$txt_color$FONT,$array[$i] );
    
    
$hpos $bbox[2]+$KERNING;
}


// ---- SAMPLE DOWN & OUTPUT
$final imageCreateTrueColor($WIDTH,$HEIGHT);

imageCopyResampled$final$canvas0,0,0,0$WIDTH$HEIGHT$WIDTH*4$HEIGHT*);

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

imagePNG($final);

imageDestroy($canvas);
imageDestroy($final);

?>
Roy van Arem ¶
9 years ago
If you want to display a list of fonts in a directory and see what they look like, you could do something like this:

<HTML><BODY>

<?php

$folder
=dir("fonts/"); //The directory where your fonts reside

while($font=$folder->read())
  {

  if(
stristr($font,'.ttf'))echo '<IMG SRC="img.php?'.substr($font,0,strpos($font,'.')).'">';//only ttf fonts

  
}

$folder->close();

?>

</BODY></HTML>

The file for 'img.php' should be something like this:

<?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);

?>

Something similar I implemented at http://font.beginstart.com
Tom Pike ¶
9 years ago
Ref: Craig at frostycoolslug dot com

"Using the negative of a color index has the effect of turning off antialiasing."

This is true, but only if the image has been created with imagecreate() (as opposed to imagecreatetruecolor())
Craig at frostycoolslug dot com ¶
9 years ago
This one caught me out a little bit as confusing, so in an attempt to help others..

"Using the negative of a color index has the effect of turning off antialiasing."

Simply put:

<?php

$textColour 
ImageColorAllocate($image255255255);
ImageTTFText($image8000, -$textColour$font$text);

?>

Note the - (minus) before the $textColor in ImageTTFText, this creates the negative colour index, and switches off AA on text.
jwe ¶
9 years ago
I found this line a little confusing:

"May include decimal numeric character references (of the form: &#8364;) to access characters in a font beyond position 127."

I was using a font that had apostrophes and quotes stored in a non-standard position, and so they were being rendered as spaces by imagettftext.  This line seemed to suggest a solution, but it took a while to figure it out.

Turns out, a "decimal numeric character reference" is a decimal conversion of the hex value of the *unicode* position of the character you want.  For a while I was trying ASCII positions (I knew the ALT+ code for typing the character I needed in Windows).

In the Windows XP character map, the unicode positions are shown as U+2018 or U+201C, etc.  Ignore the U+ and convert that hex number to decimal, and then stick that in your text string with the &# on the front and ; on the end, and pass it to imagettftext.

--Julian
mats dot engstrom at gmail dot com ¶
10 years ago
I'll second the note from --colobri--.  

Just adding --with-ttf and --with-freetype-dir=/usr/lib/ on the ./configure and then doing a "make; make install" is not enough.

I had to do a "make clean" and then a "make install" in order to get the FreeType-support enabled.

Here are my relevant ./configure lines:
--with-gd \
--enable-gd-native-ttf \
--with-ttf \
--with-freetype-dir=/usr/lib/ \
--with-jpeg-dir=/usr/lib/libjpeg.so.62 \
--enable-exif \
admin at phpru dot com ¶
10 years ago
On my conf: php5.1.2+apache 1.33
iconv() function works very well with all cyrillic encodings, so you needn't to write your function like win2uni
--Colibri-- ¶
10 years ago
If you have configured and compiled PHP with all the necessary command-line options and still get the error:

Fatal error: Call to undefined function imagettftext()

Try doing a "make clean"  before building the php apache module:

./configure [...]
make clean
make
make install 

This may solve your problem (and hopefully keep you from wasting hours trying different compile options!)
Mer`Zikain ¶
10 years ago
I was looking for a way to add kerning to my text and finally just made this function to do it. Of course, if you're generating the size of the image based on the text you're putting in it, you'll have to figure out the new size to fit the new text width but I'm sure you can figure that out.

for($i=0;$i<strlen($text);$i++){
        // Get single character
    $value=substr($text,$i,1);
    if($pval){ // check for existing previous character
        list($lx,$ly,$rx,$ry) = imagettfbbox($fontsize,0,$font,$pval);
        $nxpos+=$rx+3;
    }else{
        $nxpos=0;
    }
        // Add the letter to the image
    imagettftext($im, $fontsize, 0, $nxpos, $ypos, $fontcolor, $font, $value);
    $pval=$value; // save current character for next loop
}
alexey at NOSPAMPLS dot ozerov dot de ¶
10 years ago
Notice that the path to the TrueType font has to be included in open_basedir list if open_basedir restriction is activated in php.ini.
nick ¶
11 years ago
A trivial function to get right or centre aligned horizontal text:

function imagettftextalign($image, $size, $angle, $x, $y, $color, $font, $text, $alignment='L') {
    
    //check width of the text
    $bbox = imagettfbbox ($size, $angle, $font, $text);
    $textWidth = $bbox[2] - $bbox[0];
    switch ($alignment) {
        case "R":
            $x -= $textWidth; 
            break;
        case "C":
            $x -= $textWidth / 2;
            break;
    }
        
    //write text
    imagettftext ($image, $size, $angle, $x, $y, $color, $font, $text);

}
adam at worldwrestlingmania dot cjb dot net ¶
6 years ago
Here's a good number verification captcha i just made:

1. on the page/s it will be used on, enter:
<?php
$pageToGo 
"http://example.com/#the page to go to if captcha correct
if ($_POST["captchaused"] == "true")
{
if (
$_POST["numcaptcha"] == $_POST["captcha"])
{

header('Location: ' $pageToGo);
}
else
{
echo 
'<form action="' $_SERVER['php_self'] . '" method="post">';
$text mt_rand();
echo 
'<input type="hidden" name="captchaused" value="true" />';
echo 
'<input type="hidden" name="numcaptcha" value="' $text '" />';
echo 
'Enter the numbers you see: <br><input type="text" name="captcha" />';
require_once(
'numcaptcha.php');
echo 
'<input type="submit" value="enter site" /></form>';
}

?>

2. create a page called numcaptcha.php and enter:
<?php
header
('Content-type: image/png');
$im imagecreatetruecolor(40030);
$white imagecolorallocate($im255255255);
$grey imagecolorallocate($im128128128);
$black imagecolorallocate($im000);
imagefilledrectangle($im0039929$white);
imagettftext($im2001121$grey$font$text);
imagettftext($im2001020$black$font$text);
imagepng($im);
imagedestroy($im);
?>

it might have a few security issues but it still works fine.
erik[at]phpcastle.com ¶
11 years ago
Remember!!!

When uploading a font to your website you have to set the transfer mode to binary. It took me some time to find out :P. Tried to download the font from my website and it was spoiled.

In your script, the path to your font, use realpath("arial.ttf") so there is no confusion about that.
roland dot hentschel at t-online dot de ¶
7 years ago
Hi! 

I played around with that multi-line-script "makeImageF". 
Added some features, mainly: you can read text-files 
or add text as parameter - eg : 
imagettftext.php?file=test.txt 
imagettftext.php?text=hello|world! 

have fun! 

====================================== 

<?php 

/* 
* @name: makeImageF 
http://de3.php.net/manual/en/function.imagettftext.php#77739 

* @param String $file : Textfile. 
* @param String $text : Text (New Line : "|"). 
* @param String $font : Font name. 
* @param int $fsize: Font size. 
* @param int $pos : Justify (0-Left, 1-Right, 2-Center). 
* @param int $Leading : Space between lines. 
* @param int $W: Width of the Image. 
* @param int $H: Hight of the Image. 
* @param int $X: x-coordinate of the text into the image. 
* @param int $Y: y-coordinate of the text into the image. 
* @param array $rgb: RGB color array for text & background color. 

*/ 


$type $_REQUEST['type']  ? $_REQUEST['type'] : "png"
switch(
$type) { 
case 
"gif" 
    
header("Content-type: image/gif"); 
    
imageGIF(imagettfpostext($text$font
    
$fsize$pos$rgb),"wm.gif"9); break; 
case 
"png" 
    
header("Content-type: image/png"); 
    
imagePNG(imagettfpostext($text$font
    
$fsize$pos$rgb),"wm.png"9); break; 



function 
rgb2hex($rgb) { 
  
$color = array("black"=>"#000""grn"=>"#090"
  
"red"=>"#f00""blu"=>"00f"); 
  
$trans = array("a"=>"10""b"=>"11""c"=>"12"
  
"d"=>"13""e"=>"14""f"=>"15"); 
  
$hex = array(); 
  
$rgb str_replace("#",""
    
str_replace(array_keys($color), array_values($color), strtolower($rgb))); 
  for (
$x=0$x<strlen($rgb); $x++) 
  
$hex[] = strtr($rgb[$x],$trans); 
  if (
count($hex)==3) { 
    
$hex[5] = $hex[2]; $hex[4] = $hex[2]; 
    
$hex[3] = $hex[1]; $hex[2] = $hex[1]; 
    
$hex[1] = $hex[0]; 
  }; 
  
$hex = ($hex[0]*16+$hex[1]) 
  .
"x".($hex[2]*16+$hex[3]) 
  .
"x".($hex[4]*16+$hex[5]); 
  return 
$hex


$file  $_GET['file']  
$_GET['file'] : "logo.txt"
if (
$_GET['file']) { 
  
$fp = @fopen($file"r");  
  while (!
feof($fp)) $text .= fgets($fp);  fclose($fp); 
} else 
$text str_replace("|","\n",$_GET['text']); 
$pos   $_GET['pos']   
$_GET['pos'] : 0
$font  $_GET['font']  
"./fonts/".$_GET['font'].".ttf" "./fonts/verdana.ttf"
$fsize $_GET['fsize'
$_GET['fsize'] : 12
$rgb   $_GET['rgb']   
$_GET['rgb'] : "#ff9,#393"

imagepng(imagettfpostext($text$font$fsize$pos$rgb)); 

function 
imagettfpostext($text$font$fsize$pos$rgb
    
$Leading=0$W=0$H=0$X=0$Y=0) { 
  
$angle 0
  
$_bx imageTTFBbox($fsize,0,$font,$text); 
  
$str split("[\n]+",$text); 
  
$nL  count($str); 
  
$W   = ($W==0
  ? 
abs($_bx[2]-$_bx[0]) 
  : 
$W
  
$H = ($H==0
  ? 
abs($_bx[5]-$_bx[3])+($nL>
  
? ($nL*$Leading
  : 
0
  : 
$H
  
$im = @imagecreate($W$H
  or die(
"Cannot Initialize new GD image stream"); 
  
$rgb explode(",",$rgb); 
  
$tc  explode("x",rgb2hex($rgb[1])); 
  
$bc=explode("x",rgb2hex($rgb[0])); 
  
$bc  imagecolorallocate($im$bc[0], $bc[1], $bc[2]); 
  
$tc  imagecolorallocate($im$tc[0], $tc[1], $tc[2]); 
  if (
$pos == 0) { 
    
imagettftext($im$fsize$angle$X
    
$fsize$tc$font$text); 
  } else { 
    
$alpha range("a""z"); 
    
$alpha $alpha.strtoupper($alpha).range(09); 
    
$_b imageTTFBbox($fsize0$font$alpha); 
    
$_H abs($_b[5]-$_b[3]); 
    
$__H 0
    for (
$i=0$i<$nL$i++) { 
      
$_b imageTTFBbox($fsize0$font$str[$i]); 
      
$_W abs($_b[2]-$_b[0]); 
      if (
$pos == 1$_X $W-$_W;     
      else 
$_X abs($W/2)-abs($_W/2); 
      
$__H += $_H
      
imagettftext($im$fsize$angle$_X$__H
      
$tc$font$str[$i]); 
      
$__H += $Leading
    } 
  } 

  if (
$_REQUEST["trans"]) { 
   
$bg_color ImageColorAt($im,1,1); 
   
ImageColorTransparent($im$bg_color); 
  } 

  return 
$im


?>
llewellyntd at gmail dot com ¶
8 years ago
Hi All,

I struggled for moths to do a decent text warp with GD lib. Here is the code that I made use of:

<?php
//word wrap
$warpText wordwrap($text30"\n");
//display text
imagettftext($image$fontSize0$x$y$fontColor$font$warpText);
?>

Hope this helps somebody.

Cheers
m0r1arty at mail dot ru ¶
8 years ago
Sorry my English.
I have trouble with using imagettftext under Windows.
I can't used short name of fonts(example "arial","arialbd.ttf" etc). PHP say what not find this font.
Manipulation with environment GDFONTPATH lost.
This is my solution
<?php
$dir
=opendir('./font/');//directory with fonts
if($dir)
    while(
$f=readdir($dir)){
        if(
preg_match('/\.ttf$/',$f)){
            
$font=explode('.',$f);
            
define($font[0],realpath('./font/'.$f));
        }
    }
if(
$dir)
    
closedir($dir);
?>
Directory "font" have two file: arial.ttf and arialbd.ttf
Now one can using constant font name by calling imagettftext:
imagettftext($img,12,0,25,28,$color,arialbd,'some text');
waage ¶
8 years ago
I had some issues trying to get both word wrapping and new line detection but with some of the help from the comments below i got this. (thanks to jwe for the main part of the code here)

<?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$startPoint1) != " ") {
                
$startPoint--;
           }
           
$line[$i][] = trim(substr($text0$startPoint));
           
$text substr($text$startPoint);
        }
        
$line[$i][] = trim($text);
        
$i++;
    }
    
    return 
$line;
}

?>

This returns an array for each newline entered and subarray for each wordwrapped line to print.

ie.

Array
(
    [0] => Array
        (
            [0] => This is the first long line
            [1] => that i entered.
        )

    [1] => Array
        (
            [0] => And this is the new line after that.
        )
)
Borgso ¶
8 years ago
Right align out of "webmaster at higher-designs dot com" code
<?php
$color 
imagecolorallocate($im000);
$font 'visitor.ttf';
$fontsize "12";
$fontangle "0";
$imagewidth imagesx($im);
$imageheight imagesy($im);

$text "My right align text";

$box = @imageTTFBbox($fontsize,$fontangle,$font,$text);
$textwidth abs($box[4] - $box[0]);
$textheight abs($box[5] - $box[1]);
$xcord $imagewidth - ($textwidth)-2// 2 = some space from right side.
$ycord = ($imageheight/2)+($textheight/2);

ImageTTFText ($im$fontsize$fontangle$xcord$ycord$black$font$text);
?>
ben at evolutioncomputing co uk ¶
9 years ago
A centralised text watermark - of  any length, that automatically sizes to about 70% of the width, and can be rotated to any angle.

<?php
/* Get image info */
$Image = @ImageCreateFromJPEG ("YourImage.jpg") ;
$sx imagesx($Image) ;
$sy imagesy($Image) ;
if (
$WatermarkNeeded)
    {
    
/* Set text info */
    
$Text="Copyright Ben Clay" ;
    
$Font="arial.ttf" ;
    
$FontColor ImageColorAllocate ($Image,255,255,255) ;
    
$FontShadow ImageColorAllocate ($Image,0,0,0) ;
    
$Rotation 30 ;
    
/* Make a copy image */
    
$OriginalImage ImageCreateTrueColor($sx,$sy) ;
    
ImageCopy ($OriginalImage,$Image,0,0,0,0,$sx,$sy) ;
    
/* Iterate to get the size up */
    
$FontSize=;
    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) ;
    
/*  Awkward maths to get the origin of the text in the right place */ 
    
$x $sx/cos(deg2rad($Rotation))*$TextWidth/;
    
$y $sy/sin(deg2rad($Rotation))*$TextWidth/cos(deg2rad($Rotation))*$TextHeight/;
    
/* Make shadow text first followed by solid text */
    
ImageTTFText ($Image,$FontSize,$Rotation,$x+4,$y+4,$FontShadow,$Font,$Text);
    
ImageTTFText ($Image,$FontSize,$Rotation,$x,$y,$FontColor,$Font,$Text);
    
/* merge original image into version with text to show image through text */
    
ImageCopyMerge ($Image,$OriginalImage,0,0,0,0,$sx,$sy,50) ;
    }


ImageJPEG ($Image) ;
?>
admin at sgssweb dot com ¶
10 years ago
Another way of the bellow. After creating a child class of GMIPluggableSet class, which should override two method: getExpression() and getVariables(), throw it to a instance of FontImageGenerator class.
For example, the code follows:

<?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();

?>

This output a image with the text defined in $_GET['text'], the font in $_GET['font'], the text color in $_GET['color'], the background in $_GET['bgcolor'], and so on.

The script file is available at: http://sgssweb.com/experiments/?file=PHPFontImageGenerator .
limalopex.eisfux.de ¶
10 years ago
If you have problems displaying german umlauts or other chars with an ascii value > 127, try to convert the text-parameter first. The following function converts character-values > 127 (both: UTF-8 + ANSI) to HTML's numeric coded entities:

<?php
define
('EMPTY_STRING''');

function 
foxy_utf8_to_nce
  
$utf EMPTY_STRING 
) { 
  if(
$utf == EMPTY_STRING) return($utf); 

  
$max_count 5// flag-bits in $max_mark ( 1111 1000 == 5 times 1) 
  
$max_mark 248// marker for a (theoretical ;-)) 5-byte-char and mask for a 4-byte-char; 

  
$html EMPTY_STRING
  for(
$str_pos 0$str_pos strlen($utf); $str_pos++) { 
    
$old_chr $utf{$str_pos}; 
    
$old_val ord$utf{$str_pos} ); 
    
$new_val 0

    
$utf8_marker 0

    
// skip non-utf-8-chars 
    
if( $old_val 127 ) { 
      
$mark $max_mark
      for(
$byte_ctr $max_count$byte_ctr 2$byte_ctr--) { 
        
// actual byte is utf-8-marker? 
        
if( ( $old_val $mark  ) == ( ($mark << 1) & 255 ) ) { 
          
$utf8_marker $byte_ctr 1
          break; 
        } 
        
$mark = ($mark << 1) & 255
      } 
    } 

    
// marker found: collect following bytes 
    
if($utf8_marker and isset( $utf{$str_pos 1} ) ) { 
      
$str_off 0
      
$new_val $old_val & (127 >> $utf8_marker); 
      for(
$byte_ctr $utf8_marker$byte_ctr 1$byte_ctr--) { 

        
// check if following chars are UTF8 additional data blocks 
        // UTF8 and ord() > 127 
        
if( (ord($utf{$str_pos 1}) & 192) == 128 ) { 
          
$new_val $new_val << 6
          
$str_off++; 
          
// no need for Addition, bitwise OR is sufficient 
          // 63: more UTF8-bytes; 0011 1111 
          
$new_val $new_val | ( ord$utf{$str_pos $str_off} ) & 63 ); 
        } 
        
// no UTF8, but ord() > 127 
        // nevertheless convert first char to NCE 
        
else { 
          
$new_val $old_val
        } 
      } 
      
// build NCE-Code 
      
$html .= '&#'.$new_val.';'
      
// Skip additional UTF-8-Bytes 
      
$str_pos $str_pos $str_off
    } 
    else { 
      
$html .= chr($old_val); 
      
$new_val $old_val
    } 
  } 
  return(
$html); 
}

?>
mirza_aqueel_qau at hotmail dot com ¶
4 years ago
To make a font underline and bold without using the fonts file available in fonts directory of windows use this code. I hope this will help alot of you out there. 

<?php 
// Create the image 
$im imagecreatetruecolor(499330); 

// Create some colors 
$white imagecolorallocate($im255255255); 
$black imagecolorallocate($im000); 
imagefilledrectangle($im00499329$white); 

// The text to draw 

$text ="Muhammad Sarfraz"
$text ="Khurram Faraz"
$text ="Mohammad Imran"
$text ="Zulfiqar Ahmed Khan"
$text="Najam ul Hasnain Shah"
$text="Abdul Rehman Daniyal"
$text="Yasir Siddiqui"
$text="Sohail ur Rehman"
$text="Hamad Aziz Sheikh"
$text="Nauman Khalid"
$text="Saad Ahmed"
$text="Nasir Mehmood Butt"
$text="Mohammad Aqeel Mirza"

// Replace path by your own font path 
$font 'walt.ttf'// Place this file in your code directory or if font is in font directory set its path with font name as $font=$path.'arial.ttf'; 

// Add the text 

$x=10
$y=120
$font_size=40
$angle=0
$total_width=0
$counter=0

for(
$i=0$i<strlen($text); $i++) 

    
//$text_to_write=urldecode(substr($text,$i,1)."%0D_"); 
    
$dimensions imagettfbbox($font_size$angle$fontsubstr($text,$i,1)); 
    
$total_width+=($dimensions[2]); 
    
    
    

echo 
"<pre>"
$dimensions imagettfbbox($font_size$angle$font$text); 
echo 
"Dimension of full string=".$dimensions[2]."<br/>"

echo 
"Total width calcuated by algorithm=".$total_width."<br/>"
$difference=$dimensions[2]-$total_width

echo 
"Difference=".$difference
imagettftext($im$font_size$angle$x+1$y+1$black$font$text); 
imagettftext($im$font_size$angle$x$y$black$font$text); 

$x2=$x+$total_width+$difference+2
//echo $total_width; 
echo "<pre/>"
//imageline( $im , $x , $y+4 , $x2 , $y+4 , $black ); 
imageBoldLine($im$x$y+4$x2$y+4$black$BoldNess=4$func='imageLine'); 

// Using imagepng() results in clearer text compared with imagejpeg() 
imagepng($im,"underline.png"); 
echo 
"<img src='underline.png'/>"
imagedestroy($im); 
?>
eee ess c p 9 9 AT yahoo DOT com ¶
5 years ago
If you get letters cut off (clipped) by adjacent letters when using imagettftext with transparency (i.e., imagealphablending set to false), try setting imagealphablending back to TRUE before calling the imagettftext function.

<?php
$im 
imagecreatetruecolor(300300);

imagealphablending($imfalse);
imagesavealpha($imtrue);

// Create colors and draw transparent background
$trans imagecolorallocatealpha($im255255255127);
$black imagecolorallocate($im000);
imagefilledrectangle($im00299299$trans);

// Bad text
imagettftext($im22050100$black'arial.ttf''Bad: Oj Pj wj');

// Good text
imagealphablending($imtrue);
imagettftext($im22050150$black'arial.ttf''Good: Oj Pj wj');

/*** You'll need a copy of the arial.ttf font file in the same location as the PHP script ***/

// Output PNG

header("Content-type: image/png");
imagepng($im);
imagedestroy($im);
?>
webmaster at higher-designs dot com ¶
9 years ago
I spent days looking for this, couldn't find it, so just made it myself. This is an ultra simple text banner that keeps the text pretty much centered (not perfect when text is angled) vertically and horizontally. Size, font, colors are easy to edit and in HTML version for the colors.

Any additions (maybe for multi-line functionality) can be added if you desire.

<?php
### Declare this script will be displayed as a PNG image.
header("Content-type: image/png");

####################### BEGIN USER EDITS #######################
$imagewidth 500;
$imageheight 100;
$fontsize "20";
$fontangle "0";
$font "arial.ttf";
$text "123456789";
$backgroundcolor "003366";
$textcolor "FFCC66";
######################## END USER EDITS ########################

### Convert HTML backgound color to RGB

if( eregi"([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})"$backgroundcolor$bgrgb ) )
{
$bgred hexdec$bgrgb[1] );   $bggreen hexdec$bgrgb[2] );   $bgblue hexdec$bgrgb[3] );}

### Convert HTML text color to RGB
if( eregi"([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})"$textcolor$textrgb ) )
{
$textred hexdec$textrgb[1] );   $textgreen hexdec$textrgb[2] );   $textblue hexdec($textrgb[3] );}

### Create image
$im imagecreate$imagewidth$imageheight );

### Declare image's background color
$bgcolor imagecolorallocate($im$bgred,$bggreen,$bgblue);

### Declare image's text color
$fontcolor imagecolorallocate($im$textred,$textgreen,$textblue);

### Get exact dimensions of text string
$box = @imageTTFBbox($fontsize,$fontangle,$font,$text);

### Get width of text from dimensions
$textwidth abs($box[4] - $box[0]);

### Get height of text from dimensions
$textheight abs($box[5] - $box[1]);

### Get x-coordinate of centered text horizontally using length of the image and length of the text
$xcord = ($imagewidth/2)-($textwidth/2)-2;

### Get y-coordinate of centered text vertically using height of the image and height of the text
$ycord = ($imageheight/2)+($textheight/2);

### Declare completed image with colors, font, text, and text location
imagettftext $im$fontsize$fontangle$xcord$ycord$fontcolor$font$text );

### Display completed image as PNG
imagepng($im);

### Close the image
imagedestroy($im);
?>
nospam at nospam dot nospam ¶
10 years ago
I've found that upsampling your text by a factor of 8 or more can really improve the readability of generated text, especially in smaller font sizes (9 or less). I find it also helps with fonts that have kerning to reduce space between letters such as capital T and capital A (TA) where the top-right of the T will be cut off due to GD "features".

I can't tell you, the reader, exactly how to do this, as it will depend on how you are currently generating your text, but essentially what you want to try doing is upsize your font by a factor of 8 and then scale down the resulting image by the same factor.

So if you were using font size 10, use font size 80 and use imagecopyresampled() to divide the width/height down again by 8. The resulting image will be a few pixels different in width / height compared to direct text writing, so make sure to check your image sizes if you are using fixed dimensions.

Play around with other factors, 16 is a bit nicer but results in a higher CPU/RAM load when processing. Any higher is unnecessary I think. If possible you should also cache the image to a file instead of reprocessing it each request.
Lassial at the google mail dot com ¶
8 years ago
Creating multiline text with GD is bit complicated, one of the issues I've ran to is how to set line spacing, a normal feature in all type setting (even type writers). By default, line spacing with imagettftext seems to be 150 % or more, too much for me anyhow. Thus I've used the function below to get the lines closer to each other. By default, it appears to create 100 % linespacing, but it has not been tested thoroughly.

null imagettfmultilinetext
(resource $image, float $size, float $angle, int $x, int $y, int $color, string $fontfile, string $text , $spacing)

spacing is a coefficient, comparable to Line spacing in a word processors or graphics software, causing a shift relative to font size in the line spacing

<?php
function imagettfmultilinetext($image$size$angle$x$y$color$fontfile,  $text,$spacing=1)
{


$lines=explode("\n",$text);
for(
$i=0$icount($lines); $i++)
    {
    
$newY=$y+($i $size $spacing);
    
imagettftext($image$size$angle$x$newY$color$fontfile,  $lines[$i], $spacing);
    }
return 
null;
}

?>
contact at pointhunter dot net ¶
5 years ago
Print username on the picture from a sent variable. (u)

<?php
$USERNAME
=$_REQUEST['u'];
// Set the content-type
header('Content-type: image/png');

// Create the image
$im imagecreatetruecolor(35030);

// Create some colors
$white imagecolorallocate($im000);
$grey imagecolorallocate($im128128128);
$black imagecolorallocate($im255255255);
imagefilledrectangle($im0039929$white);

// The text to draw
$text 'Welcome, '.$USERNAME;
// Replace path by your own font path
$font 'cour.ttf';

// Add some shadow to the text
imagettftext($im2001121$grey$font$text);

// Add the text
imagettftext($im2001020$black$font$text);

// Using imagepng() results in clearer text compared with imagejpeg()
imagepng($im);
imagedestroy($im);
?>
Sohel Taslim ¶
8 years ago
Left Right Center align/justify of text in image. It is easy and simple to do in PHP.
Create an image from text and align them as you want. After that save or display image.

<?php
/**
* Function for converting Text to Image.
* Kip CENTURY.TTF file in same folder.

* @author Taslim Mazumder Sohel
* @deprecated 1.0 - 2007/08/03

*/
     //Example call.
    
$str "New life in programming.\nNext Line of Image.\nLine Number 3\n" .
        
"This is line numbet 4\nLine number 5\nYou can write as you want.";    
    
header("Content-type: image/gif");    
    
imagegif(imagettfJustifytext($str,"CENTURY.TTF",2));
    
//End of example.
    
    
    /**
     * @name                    : makeImageF
     * 
     * Function for create image from text with selected font. Justify text in image (0-Left, 1-Right, 2-Center).
     * 
     * @param String $text     : String to convert into the Image.
     * @param String $font     : Font name of the text. Kip font file in same folder.
     * @param int    $W        : Width of the Image.
     * @param int    $H        : Hight of the Image.
     * @param int    $X        : x-coordinate of the text into the image.
     * @param int    $Y        : y-coordinate of the text into the image.
     * @param int    $fsize    : Font size of text.
     * @param array  $color       : RGB color array for text color.
     * @param array  $bgcolor  : RGB color array for background.
     * 
     */
    
function imagettfJustifytext($text$font="CENTURY.TTF"$Justify=2$W=0$H=0$X=0,$Y=0$fsize=12$color=array(0x0,0x0,0x0), $bgcolor=array(0xFF,0xFF,0xFF)){
        
        
$angle 0;
        
$L_R_C $Justify
        
$_bx imageTTFBbox($fsize,0,$font,$text);

        
$W = ($W==0)?abs($_bx[2]-$_bx[0]):$W;    //If Height not initialized by programmer then it will detect and assign perfect height. 
        
$H = ($H==0)?abs($_bx[5]-$_bx[3]):$H;    //If Width not initialized by programmer then it will detect and assign perfect width. 

        
$im = @imagecreate($W$H)
            or die(
"Cannot Initialize new GD image stream");
            
            
        
$background_color imagecolorallocate($im$bgcolor[0], $bgcolor[1], $bgcolor[2]);        //RGB color background.
        
$text_color imagecolorallocate($im$color[0], $color[1], $color[2]);           //RGB color text.
        
        
if($L_R_C == 0){ //Justify Left
            
            
imagettftext($im$fsize$angle$X$fsize$text_color$font$text);
            
        }elseif(
$L_R_C == 1){ //Justify Right
            
$s split("[\n]+"$text);
            
$__H=0;
            
            foreach(
$s as $key=>$val){
            
                
$_b imageTTFBbox($fsize,0,$font,$val);
                
$_W abs($_b[2]-$_b[0]); 
                
//Defining the X coordinate.
                
$_X $W-$_W;
                
//Defining the Y coordinate.
                
$_H abs($_b[5]-$_b[3]);  
                
$__H += $_H;              
                
imagettftext($im$fsize$angle$_X$__H$text_color$font$val);    
                
$__H += 6;
                
            }
            
        }
        elseif(
$L_R_C == 2){ //Justify Center
            
            
$s split("[\n]+"$text);
            
$__H=0;
            
            foreach(
$s as $key=>$val){
            
                
$_b imageTTFBbox($fsize,0,$font,$val);
                
$_W abs($_b[2]-$_b[0]); 
                
//Defining the X coordinate.
                
$_X abs($W/2)-abs($_W/2);
                
//Defining the Y coordinate.
                
$_H abs($_b[5]-$_b[3]);  
                
$__H += $_H;              
                
imagettftext($im$fsize$angle$_X$__H$text_color$font$val);    
                
$__H += 6;
                
            }
            
        }        
                        
        return 
$im;
        
    }
        
  

?>
David ¶
1 year ago
If you get:

"configure: error: freetype.h not found."

then do:

yum install freetype-devel
nadavkav at gmail dot com ¶
7 years ago
for passing hebrew (and maybe other rtl language text) you can use the following code (as suggested by udi and which worked for me) :
<?php
$returnedtext 
iconv("ISO-8859-8""UTF-8"hebrev(iconv("UTF-8""ISO-8859-8",$originaltext)));
?>
a4W ¶
10 years ago
This function will make your text bold:
<?php
function drawboldtext($image$size$angle$x_cord$y_cord$r$g$b$fontfile$text

   
$color ImageColorAllocate($image$r$g$b); 
   
$_x = array(1010, -1, -110, -1); 
   
$_y = array(0, -1, -100, -1111); 
   for(
$n=0;$n<=8;$n++) 
   { 
      
ImageTTFText($image$size$angle$x_cord+$_x[$n], $y_cord+$_y[$n], $color$fontfile,$text); 
   } 

?>
Amir ¶
6 years ago
In order to pass text of RTL language to imagettftext function, I used this function. 

<?php 
    
function revUni($text) { 
    
        
$wordsArray explode(" "$text); 

        
$rtlCompleteText=''
        for (
$i sizeOf($wordsArray); $i > -1$i $i-1) { 

            
//$lettersArray = explode("|", str_replace(";|", ";", $wordsArray[$i])); 
            
$lettersArray explode(";"$wordsArray[$i]); 
            
            
$rtlWord=''
            for (
$k sizeOf($lettersArray); $k > -1$k $k-1) { 
                if (
strlen($lettersArray[$k]) > 1) { // make sure its full unicode letter 
                    
$rtlWord $rtlWord."".$lettersArray[$k].";"
                } 
            } 
            
            
$rtlCompleteText $rtlCompleteText." ".$rtlWord
            
        } 
        
        return 
$rtlCompleteText
    } 

?>
Stefan at colulus dot com ¶
8 years ago
I worked out a script the allows the transfer of alphanumeric data to be placed on an image. The HTML feature is img src and the php feature is imagettftext. This simple code will increment from 1 to 3 on images.

code:

<?php
//ImageCall.php -- This script will call a script to produce the image.
for($next 1;$next 4$next++){
print 
"Image $next:<br>";
print 
"<img src = 'Image.php?\$text=$next'>";
print 
"<br><br>";
}

?>

<?php
//Image.php -- This script creates a square image and places the text on it.

// image size and color

$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);

// image creation
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);

// determine numeric center of image
$size ImageTTFBBox(45,0,'impact',$_GET['$text']);
$X = (77 - (abs($size[2]- $size[0])))/2;
$Y = ((77 - (abs($size[5] - $size[3])))/+ (abs($size[5] - $size[3])));

//places numeric information on image
ImageTTFText($im,45,0,($X-1),$Y,$color4,'impact',$_GET['$text']);

//returns completed image to calling script
Header('Content-Type: image/png');
Imagepng($im);

?>
ugo dot quaisse at gmail dot com ¶
10 years ago
This is a script that aim at center the (multi) lines :

<?php
header
("Content-type: image/png");

//1line per column
$text=array(0=>"line 1",1=>"line 2");

$largeur=500;
$line_height=30;
$hauteur=sizeof($text)*$line_height;

// Create the image
$im imagecreatetruecolor($largeur$hauteur);

// Create some colors
$white imagecolorallocate($im255255255);
$grey imagecolorallocate($im225225225);
$blue imagecolorallocate($im062126);
imagefilledrectangle($im00$largeur$hauteur$white);

// Replace path by your own font path
$font 'font.ttf';

for(
$i=0;$i<=sizeof($text);$i++) {
//Center the text
$size imagettfbbox(200$font$text[$i]);
$long_text $size[2]+$size[0];
$posx=($largeur-$long_text)/2;
// Add the text
imagettftext($im200$posx$line_height+$line_height*$i$blue$font$text[$i]);
}


imagepng($im);
imagedestroy($im);
?>
 
来自  http://php.net/manual/zh/function.imagettftext.php
普通分类: