imagettfbbox / imagettftext bugs
This page is dedicated to my wonderful fianceé, Nadine! Info on the bugs is below.
Kerning
Kerning, the spacing between letters, may change with some fonts as the text is rotated.
- rotate 180 degrees
- use "fixed" method
- word still jumps out of the bounding box!
Alignment
Sometimes, the text baseline shifts throughout writing.
- rotate 90 degrees
- use text "YoYoYo" or "TaTaTa"
- use Arial font
- baseline shifts up (relative to text) as writing continues!
Varying Height
The height of the bounding box varies as it is rotated.
- rotate 90 degrees
- use text "hanging"
- use "normal" method ("fixed" corrects this)
- the box collapses to exclude hanging / tall text!
Incorrect Box Coordinates
- rotate between 30-330 degrees
- use "normal" method
- anything beyond 30 degrees of rotation starts to get seriously wrong!
Fixing Function
The fix for some of the above problems can be handled with the function below, from helpful user comments on the php manual. The function gets the bounding box for non-rotated text, then rotates the whole box. This doesn't, of course, fix the change in kerning or the (presumably GD) bug that mis-aligns rotated text.
<?php
function imagettfbbox_t($size, $angle, $fontfile, $text){
// compute size with a zero angle
$coords = imagettfbbox($size, 0, $fontfile, $text);
// convert angle to radians
$a = deg2rad($angle);
// compute some usefull values
$ca = cos($a);
$sa = sin($a);
$ret = array();
// perform transformations
for($i = 0; $i < 7; $i += 2){
$ret[$i] = round($coords[$i] * $ca + $coords[$i+1] * $sa);
$ret[$i+1] = round($coords[$i+1] * $ca - $coords[$i] * $sa);
}
return $ret;
}
?>
Generating the image
I've received a few mails asking about the source of the image. Here it is:
<?php
// dimensions
$w = 500;
$h = 500;
// create an image
$img = imagecreatetruecolor($w, $h);
switch(@$_GET['font']){
case 'arial':
$font = 'support/fonts/arial.ttf';
break;
case 'castelar':
$font = 'support/fonts/CASTELAR.TTF';
break;
case 'comicbd':
$font = 'support/fonts/comicbd.ttf';
break;
case 'bradhitc':
$font = 'support/fonts/BRADHITC.TTF';
break;
default: $font = 'support/fonts/arial.ttf';
}
// BASIC COLORS
$black = imagecolorallocate($img, 0, 0, 0);
$white = imagecolorallocate($img, 255, 255, 255);
$red = imagecolorallocate($img, 255, 0, 0);
$green = imagecolorallocate($img, 0, 255, 0);
$purple = imagecolorallocate($img, 200, 0, 255);
$blue = imagecolorallocate($img, 64, 64, 255);
$orange = imagecolorallocate($img, 255, 100, 0);
$yellow = imagecolorallocate($img, 255, 255, 0);
// DATA FROM THE POST PASSED VIA GET
$str = isset($_GET['string']) ? $_GET['string'] : 'nadine';
if(!$str){$str = 'nadine';}
// CENTER THE TEXT
$x = $w/2;
$y = $h/2;
// ROTATION
$ang = isset($_GET['rotation']) ? $_GET['rotation'] : 0;
if(!is_numeric($ang)){$ang = 0;}
$ang = $ang % 360;
// FONT SIZE
$fontsize = isset($_GET['fontsize']) ? $_GET['fontsize'] : 50;
if(!is_numeric($fontsize)){$fontsize = 50;}
$dotsize = 6;
// COMPUTES THE DISTANCE
function distance($x1, $y1, $x2, $y2){
$x = $x1 - $x2;
$y = $y1 - $y2;
$dist = sqrt(pow($x, 2) + pow($y, 2));
return sprintf('%0.1f', $dist);
}
// WRITE TEXT AND GET BOUNDING BOX
imagettftext($img, $fontsize, $ang, $x, $y, $white, $font, $str);
// if they chose to fix the bounding box, recalculate
if(@$_GET['method'] == 'fixed'){
function imagettfbbox_t($size, $angle, $fontfile, $text){
// compute size with a zero angle
$coords = imagettfbbox($size, 0, $fontfile, $text);
// convert angle to radians
$a = deg2rad($angle);
// compute some usefull values
$ca = cos($a);
$sa = sin($a);
$ret = array();
// perform transformations
for($i = 0; $i < 7; $i += 2){
$ret[$i] = round($coords[$i] * $ca + $coords[$i+1] * $sa);
$ret[$i+1] = round($coords[$i+1] * $ca - $coords[$i] * $sa);
}
return $ret;
}
// get the fixed bounding box
$b = imagettfbbox_t($fontsize, $ang, $font, $str);
}else{
$b = imagettfbbox($fontsize, $ang, $font, $str);
}
// write some bbox vals on the image
imagestring($img, 2, 10, 10, "({$b[6]},{$b[7]})", $yellow);
imagestring($img, 2, 60, 10, '---', $red);
imagestring($img, 2, 85, 10,"({$b[4]},{$b[5]})", $yellow);
// bottom
imagestring($img, 2, 10, 30, "({$b[0]},{$b[1]})", $orange);
imagestring($img, 2, 60, 30, '---', $red);
imagestring($img, 2, 85, 30, "({$b[2]},{$b[3]})", $orange);
// middle
imagestring($img, 2, 20, 20, '|', $blue);
imagestring($img, 2, 100, 20, '|', $blue);
imagestring($img, 2, 50, 20, 'text', $white);
// SHIFT THE BOUNDING BOX
for($i=0; $i<7; $i+=2){
$b[$i] += $x;
$b[$i+1] += $y;
}
// WRITE WIDTH AND HEIGHT and DIAGONAL
$coords = 'w: '.distance($b[4], $b[5], $b[6], $b[7]);
imagestring($img, 2, 160, 10, $coords, $red);
$coords = 'h: '.distance($b[0], $b[1], $b[6], $b[7]);
imagestring($img, 2, 160, 20, $coords, $blue);
$coords = 'diag: '.distance($b[0], $b[1], $b[4], $b[5]);
imagestring($img, 2, 230, 10, $coords, $purple);
// PHP VERSION AND GD VERSION IN UPPER RIGHT CORNER
$coords = 'PHP '.phpversion();
imagestring($img, 2, 310, 10, $coords, $white);
$gdinfo = gd_info();
$coords = 'GD '.$gdinfo['GD Version'];
imagestring($img, 2, 310, 20, $coords, $white);
// MAKE A NICE POLYGON
imageline($img, $b[0], $b[1], $b[2], $b[3], $red);// bottom
imageline($img, $b[4], $b[5], $b[6], $b[7], $red);// top
imageline($img, $b[0], $b[1], $b[6], $b[7], $blue);// left
imageline($img, $b[2], $b[3], $b[4], $b[5], $blue);// right
imageline($img, $b[0], $b[1], $b[4], $b[5], $purple);// diagonal
// DOTS ON THE CORNER POINTS
for($i=0; $i<8; $i+=2){
$col = $i < 4 ? $orange : $yellow;
imagefilledellipse($img, $b[$i], $b[$i+1], $dotsize, $dotsize, $col);
}
// WRITE THE EQUATION ON THE BOTTOM
$coords = "imagettfbbox({$fontsize}, {$ang}, \$font, '{$str}')";
imagestring($img, 2, 10, 480, $coords, $green);
imagestring($img, 2, 10, 468, 'bbox values relative to green dot (0, 0)', $green);
// CREATE A "STARTING POINT" FOR THE COORDINATES OF FONT WRITING
imagefilledellipse($img, $x, $y, $dotsize, $dotsize, $green);
header('Content-type: image/gif');
imagegif($img);
imagedestroy($img);
exit;
?>
- PHP imagettfbbox Bugs
- Button Test
- XML Cleaner
- Email Address Ripper
- Letter frequency in text
- Forwarded Email Cleaner
- German character transcriber
- Text to Binary Converter
- Letter Swap Encryption
- ROT 13 Conversion
- Letter Swap Decryption
- Letter Swapper
- Reverser
- Word Reverser
- Caesar Cipher Scrambler
- Dot Message Encoder
- ASCII Character Table