Typographic headlines with PHP (Part 1)
By Kai Seidler on Oct 21, 2009
My recent blog post about scaling images with PHP gave me the idea to write something about creating typographic headlines with PHP. At Apache Friends we're using this technique since many years to get rid of the usual boring and everywhere available "web fonts" like Helvetica, Times and Verdana.
For this example I chose the font Tusj by Norwegian graphic designer Magnus Cederholm. Okay, this font will only work for very large headlines, but it's looks cool and it's perfect for this demo's purposes because the TTF file is very huge (1.5 MB) and that makes the processing in PHP quite slow. (Yes, in this case, I want to slow down my PHP script.)
First, I define some basic parameter: TTF font file, the font size, and an example text.
$font_file = "./FFF Tusj.ttf"; $font_size = 64; $text = "An Example";
In the next step I've to find out, how big my image needs to be to take the rendered text. That's not so trivial because it strongly depends on the used characters, the choosen size and of course the font itself. To solve this problem PHP offers the imagettfbbox() function:
$bb = imagettfbbox($font_size, 0, $font_file, $text); $bb_width = $bb-$bb; $bb_height = $bb-$bb;
With imagecreate() I now can create the image using $bb_width and $bb_width for the size:
$image = imagecreate($bb_width, $bb_height);
Define two colors: one for the background and one for the foreground.
$fillcolor = imagecolorallocate($image, 255, 255, 255); $fontcolor = imagecolorallocate($image, 69, 138, 186);
Fill the background using $fillcolor:
imagefill($image, 0, 0, $fillcolor);
Render the text to the image:
imagettftext($image, $font_size, 0, abs($bb),$bb_height-$bb, $fontcolor, $font_file, $text);
I don't want to go into the details of this function, for a detailed explanation of all parameters please refer to the PHP manual.
And finally send it to the browser:
header("Content-Type: image/png"); imagepng($image);
Basically that's all you need to do. Here's the output of the above PHP script:
Because I used imagecreate() and imagepng() the file I got is an indexed-colored 8-bit PNG with a file size of 8 KB.
If I use imagecreatetruecolor() and imagepng() I will get a truecolored 24-bit PNG with a file size of 41 KB:
And if I use imagejpeg() instead of imagepng() I will get a truecolored 24-bit JPEG with a quality setting of 100 and a file size of 41 KB:
All three variations look exactly the same, but the indexd-colored 8-bit PNG is the smallest one. So for this purpose an 8-bit PNG seems to be the best choice.
Turning off antialiasing?
By default imagettftext() uses an antialiasing algorithm to smooth the output. Using the negative of a color index turns this feature off:
imagettftext ($image, $font_size, 0, abs($bb),$bb_height-$bb, -$font_color, $font_file, $text);
Sometimes (usually in case of small font sizes) this will give you a sharper and better looking result, but in this special case it definitely looks worse:
Welcome to the Real World
As I mentioned in the beginning, I intentionally chose a font based on a very large TTF file, which makes it very expensive for PHP to render a headline. Let's take a look at some quick benchmark results:
% ab -n 1000 http://demo/headline.php This is ApacheBench, Version 2.3 ... Benchmarking demo (be patient) ... Document Path: /headline.php Document Length: 7888 bytes ... Requests per second: 33.52 [#/sec] (mean) ...
Autsch... 33 requests per second is far to slow for a real world scenario. Yes, if I had chosen a smaller font the results would be much better, but probably the script will still be not suitable for use in a production environment. However, a simple caching mechanism should easily solve this issue.
But not today, stay tuned for part 2 of this tutorial. Live long and prosper.