abstract |
 |
This is an example of using Gd / FreeType to generate image text labels with TTF font. Provided script could be used as "text rasterization service" to generate arbitrarily text-images for a web site. MD5-based authorization is used to avoid image generation by unauthorized users.
compatible |
 |
PHP 5 or higherPHP 4.1 or higherGd 2.x, FreeType support in PHP
Our "text rasterization service" does the following:
- Receives text generation parameters(text and font-size) and md5 sign of secret key + parameters.
- Checks(by md5 sign) if rasterized text image exists in cache directory. If so, sends it to web browser and quits.
- Checks md5 authorization: computes md5 of secret key + parameters. If computed md5-sign equals to provided md5-sign,
then request is valid. Otherwise — somebody else is trying to use our "text rasterization service".
- Generates text image with imagettftext. Image size
exactly matches text size (using imagettfbbox)
- Sends generated image to browser
So, it is possible to automatically generate a lot of image text labels for a whole web site. Caching technique will decrease server load: images would be generated only once.
<?php
// Checking for gd and Freetype support
if (!function_exists('gd_info'))
die('No <a href="http://ua.php.net/manual/en/ref.image.php">gd</a> support in PHP.');
$gd = gd_info();
if ($gd["FreeType Support"] == false)
die('No FreeType support in gd</a>');
// If you're sure about gd & freetype support
// -- comment out this block
// directory for caching generated images
// should be writable
$cache_dir = '/homa/anyexample/cache'; // DO NOT FORGET TO CHANGE
// testing cache dir
// remove these lines if you're sure
// that your cache dir is really writable to PHP scripts
$tf = $cache_dir.'/'.md5(rand()).".test";
$f = @fopen($tf, "w");
if ($f == false)
die("Fatal error! {$cache_dir} is not writable. Set 'chmod 777 {$cache_dir}'
or something like this");
fclose($f);
unlink($tf);
// testing cache dir END
// full path to preferred TTF font
// you could change this to be HTTP parameter
$font = '/home/anyexample/FuturaBook.ttf'; // DO NOT FORGET TO CHANGE
// md5 secret
$md5_secret_key = 'changeme'; // DO NOT FORGET TO CHANGE
// md5 sign of parameters
$auth_sign = isset($_GET['a'])?$_GET['a']:'';
// checking for cached file:
$cache_file = $cache_dir.'/'.$auth_sign.'.png';
if (file_exists($cache_file))
{
// if cached file exists
// output it and quit
header("Content-type: image/png");
readfile($cache_file);
exit();
}
// no cached file exists
// input parameters: text and size
$text = isset($_GET['text'])?$_GET['text']:'default';
$font_size = isset($_GET['size'])?intval($_GET['size']):30;
if ($font_size == 0) $font_size = 30;
//
// basic sign checking:
$computed_sign = md5($md5_secret_key.$text.$font_size);
// computing md5 sum of concatenation
// of secret key and parameters
// hmac-based alrorithm would fit this case more
// but for real-world purpose md5 of concatenation
// is enought
if ($computed_sign != $auth_sign)
die('Auth failed'); // auth error, provided sign is invalid
// getting bounding box
$bbox = imagettfbbox($font_size, 0, $font, $text);
// imagettfbbox returns very strange results
// so transforming them to plain width and height
$size_w = abs($bbox[2] - $bbox[0]);
// width: right corner X - left corner X
$size_h = abs($bbox[7] - $bbox[1]);
// height: top Y - bottom Y
// This is a lower-left corner
// but imagettfbbox() sets (0,0) point
// inside bounding box
// so we shifting lower-left corner
$x = -abs($bbox[0]);
$y = $size_h - abs($bbox[1]);
$im = imagecreatetruecolor($size_w, $size_h);
// creating image
$back = imagecolorallocate($im, 255, 255, 255); // background color
$fore = imagecolorallocate($im, 0, 0, 0); // foreground color
imagefilledrectangle($im, 0, 0, $size_w - 1, $size_h - 1, $back);
// filling with background color
imagettftext($im, $font_size, 0, $x, $y, $fore, $font, $text);
// rendering text
imagepng($im, $cache_file); // outputing PNG image to file cache
imagedestroy($im); // destroy image
// sending data from cache file
header("Content-type: image/png");
readfile($cache_file);
?>
To generate image 'Hello World', 90 pixels size you should call this script as (assuming you've saved it as font.php):
<img src="./font.php?text=Hello+World&size=90&a=4c9a240e98490275d845c96fdb8e5a19">
Note parameter 'a=4c9a240e98490275d845c96fdb8e5a19'. '4c9a240e98490275d845c96fdb8e5a19' is a result of md5('changemeHello World90'): concatenation of
secret key, text and font size.
You could use some helper function to set script arguments, like 'image_params':
<?php
$md5_secret_key = 'changeme';
// returns parameters and md5 sign for
// text generating service
function img_params($text, $size)
{
global $md5_secret_key;
$p = '?text='.urlencode($text).'&size='.$size.'&a=';
return $p.md5($md5_secret_key.$text.$size);
}
?>
<html><head><title>Font test</title></head>
<body>
<center>
<img src="./font.php<?php echo img_params('Hello World', 90);?>">
<br><br>
<img src="./font.php<?php echo img_params('Enjoy the font generating service script from', 30); ?>">
<br><br>
<a href="http://www.anyexample.com/">
<img src="./font.php<?php echo img_params('AnyExample', 100); ?>">
</a>
</center>
</body>
</html>
See generated page.
warning |
 |
'If-Modified-Since' and HTTP 304-based browser-caching is not used. You could implement it as in this example.
tested |
 |
FreeBSD 6.2 :: PHP 5.2.1RHEL 5.0 :: PHP 4.4.5