Outputting text

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

array imagettfbbox ( int size, int angle, string fontfile, string text)

Although outputting nicely formatted text is what HTML does best, there are many times when it is better to create an image with the text in. For example, using text inside an image is great for when you want to use a non-standard font, or want to overlay the text onto an image.

To output text using PHP you first need fonts. PHP allows you to use TrueType (TTF) fonts, PostScript Type 1 (PS) fonts, or FreeType 2 fonts, with TTF tending to be the most popular due to the availability of fonts. If you are running Windows, you will probably have at least 20 TTF fonts already installed that you can use - check in the "Fonts" subdirectory of your Windows directory to see what is available. Many Unix distros come with TTF fonts installed also - either check in /usr/share/fonts/truetype, or run a search for them. If you do not have any, never fear - if you have a Windows CD around, you can borrow some from there. Alternatively, try hunting around the Internet for fonts to use, as there are quite a few freeware fonts around. Note that the Free Software Foundation has a set of free fonts that you can grab from their web site.

For this next example, I will be using the font Arial, which is stored in the same directory as my PHP script. Save this code as addingtext.php:

<?php
    $image = imagecreate(400,300);
    $blue = imagecolorallocate($image, 0, 0, 255);
    $white = ImageColorAllocate($image, 255,255,255);

    if(!isset($_GET['size'])) $_GET['size'] = 44;
    if(!isset($_GET['text'])) $_GET['text'] = "Hello, world!";

    imagettftext($image, $_GET['size'], 15, 50, 200, $white, "ARIAL", $_GET['text']);
    header("content-type: image/png");
    imagepng($image);
    imagedestroy($image);
?>

You should by now be familiar with the first few lines, so I will skip them. Note, however, that imagecreate() is used rather than imagecreatetruecolor() - this is really just for convenience, as it will automatically use $blue as the background colour. The two isset() lines are there to make sure there is a default font size, 44, and default text, "Hello, world!" for our image - these are set only if you do not pass in your own values using addingtext.php?size=26&text=Foobarbaz

Next comes the important function, imagettftext(), which takes eight parameters in total: the image resource to draw on, font size to use, angle to draw at, X co-ordinate, Y co-ordinate, colour, font file, and the text to write. A few of those parameters are exactly the same as parameters we've used in other functions, but font size in points, angle, name of font, and the text to print are all new. The X and Y co-ordinates might fool you at first because they should be set to the position you want the lower-left corner of the first character to appear.

The angle parameter works almost in the same manner as the angle parameters used in imagefilledarc() with the difference being that it works in the opposite direction - the angles in imagefilledarc() work in a clockwise direction from 3 o'clock, whereas imagettftext() works anti-clockwise. That is, specifying 15 as the angle will make the text rotate fifteen degrees so that it slants upwards.

The font name parameter needs to point to the TTF file you want to use. If this filename does not begin with /, PHP will automatically add ".ttf" to the end and search locally. On Unix machines, you may find PHP searches in /usr/share/fonts/truetype. As you can see in the example, "ARIAL" is specified, so ARIAL.TTF will be loaded and used for printing the text.

The final parameter for the function is the text to print, and you should be sure to specify any new lines as \n\r, not one or the other. You may find that certain fonts do not have various special characters - in this situation you will see empty boxes drawn rather than the special characters.

So, with just nine lines of PHP script we can generate a neat picture - manipulating text really couldn't be easier!

Author's Note: If you do not want your text to be anti-aliased (smooth-edged), put a minus sign before your colour, e.g. -$white.

Fitting text into an exact space is a complex art, particularly when you rotate the text too. PHP makes the job easier with the function imagettfbbox(), which will return an array containing the co-ordinates of a bounding box around the text - literally how big it is in each of its dimensions. The complication here is that it is tricky to get the co-ordinate system right, as the numbers returned seem easier to use than they actually are.

To call imagettfbbox(), you need to pass in four parameters: font point size, rotation angle, font name, and text string to measure. This is essentially a cut-down version of imagettftext(), so you can just copy your existing call to that and remove the unnecessary parameters.

What you will get back is an array of eight elements, which are, in order:

0

Lower-left corner, X co-ordinate

1

Lower-left corner, Y co-ordinate

2

Lower-right corner, X co-ordinate

3

Lower-right corner, Y co-ordinate

4

Upper-right corner, X co-ordinate

5

Upper-right corner, Y co-ordinate

6

Upper-left corner, X co-ordinate

7

Upper-left corner, Y co-ordinate

Now, that might seem simple enough, but you should take into account that each of those co-ordinates are relative to the text itself, viewed horizontally. That is, although 0 should be the lower-left corner of our first letter, you can almost bet neither the lower-left X or the lower-left Y will be 0, particularly if your text is rotated. For example, in our previous example we rotated text 15 degrees anti-clockwise, which would put the lower-left-hand corner of our rotated text to the right and above the lower-left-hand corner of the horizontal text. Add to that the fact that the numbers are frequently a little off, especially if you use large fonts and you should be ready for problems!

However, if you are not rotating your text, or if you are rotating only a little (under about 20 degrees), you are not likely to encounter any problems, and you can use a fairly simple script like this next one to get your image fitting your text closely:

<?php
    if(!isset($_GET['size'])) $_GET['size'] = 44;
    if(!isset($_GET['text'])) $_GET['text'] = "Hello, world!";

    $size = imagettfbbox($_GET['size'], 0, "ARIAL", $_GET['text']);
    $xsize = abs($size[0]) + abs($size[2]);
    $ysize = abs($size[5]) + abs($size[1]);

    $image = imagecreate($xsize, $ysize);
    $blue = imagecolorallocate($image, 0, 0, 255);
    $white = ImageColorAllocate($image, 255,255,255);
    imagettftext($image, $_GET['size'], 0, abs($size[0]), abs($size[5]), $white, "ARIAL", $_GET['text']);

    header("content-type: image/png");
    imagepng($image);
    imagedestroy($image);
?>

Note the generous use of the abs() function to convert negative numbers to positive - without this it is even more difficult to use imagettfbbox()!

If you were wondering why abs($size['5']) is used as the Y co-ordinate for the text as opposed to just $ysize, you will be pleased to know there is another complication with imagettfbbox(), and that is that it returns its values from the lower-left corner of the baseline of the text string, not the absolute lower-left corner. The baseline of a letter is where it would sit if you were hand writing it on lined paper - for example, the letter "a" sits on the line, whereas the letter "y" sits below the line, with the "v" of the letter resting on the baseline.

I strongly suggest you have a good play around with imagettfbbox() to get an idea of its uses and limitations. As long as you are doing horizontal text, using imagettfbbox() should be easy, and I'd rather have it in its current, hard-to-use format than not have it at all!

 

Want to learn PHP 7?

Hacking with PHP has been fully updated for PHP 7, and is now available as a downloadable PDF. Get over 1200 pages of hands-on PHP learning today!

If this was helpful, please take a moment to tell others about Hacking with PHP by tweeting about it!

Next chapter: Loading existing images >>

Previous chapter: Complex shapes

Jump to:

 

Home: Table of Contents

Copyright ©2015 Paul Hudson. Follow me: @twostraws.