Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

imagettfbbox calculates wrong rectangle when text begins with number

The issue is, that when using imagettfbbox to calculate text dimensions, too small rectangle is returned when input text begins with numbers. This is my code:

$fontSize = 150;
$font = "font/courier_new.ttf";
$text = $_GET["text"];

//Determine font dimensions
$bbox = imagettfbbox($fontSize, 0, $font, $text);   
$bbox["width"]=  abs($bbox[4]-$bbox[0]);
$bbox["height"]= abs($bbox[5]-$bbox[1]);

$im = imagecreatetruecolor($bbox["width"], $bbox["height"]);

echo "<b>Image size:</b>\n";
print_r($bbox);

// This part makes transparent background
imagesavealpha($im, true);
$bg = imagecolorallocatealpha($im, 254, 254, 254,127); 
$text_color= imagecolorallocate($im, 0, 0, 0);
imagealphablending($im, false);
imagefilledrectangle($im, 0, 0, imagesx($im), imagesy($im), $bg );
imagealphablending($im, true); 


header("X-Img-Size: ".$bbox["width"]."x".$bbox["height"]."");

imagettftext($im, $fontSize, 0, 0, $bbox["height"], $text_color, $font, $text);

// This is output    
header("Content-Type: text/html");  
ob_start();
imagepng($im);
$image_data = ob_get_contents();
ob_end_clean();
imagedestroy($im);

echo "<img src=\"data:image/png;base64,".base64_encode($image_data)."\" />";

Online test here

These are results I get for different input text:

image description

image description

image description

How can I fix that?

like image 820
Tomáš Zato - Reinstate Monica Avatar asked Apr 29 '16 04:04

Tomáš Zato - Reinstate Monica


1 Answers

The problem was caused by misconception. The values of imagettfbbox also define where do you have to start drawing - and often those coordinates are even negative. I always assumed you can start at [0, 0] coordinates. That is not true, drawing coordinates can be negative.

This function, also mentioned in comments and originating from PHP.net user contributions calculates the start coordinates, as well as the width and height (which was correct in the code in question).

// Source: http://php.net/manual/en/function.imagettfbbox.php#75407
function imagettfbboxextended($size, $angle, $fontfile, $text) {
    /*this function extends imagettfbbox and includes within the returned array
    the actual text width and height as well as the x and y coordinates the
    text should be drawn from to render correctly.  This currently only works
    for an angle of zero and corrects the issue of hanging letters e.g. jpqg*/
    $bbox = imagettfbbox($size, $angle, $fontfile, $text);

    //calculate x baseline
    if($bbox[0] >= -1) {
        $bbox['x'] = abs($bbox[0] + 1) * -1;
    } else {
        //$bbox['x'] = 0;
        $bbox['x'] = abs($bbox[0] + 2);
    }

    //calculate actual text width
    $bbox['width'] = abs($bbox[2] - $bbox[0]);
    if($bbox[0] < -1) {
        $bbox['width'] = abs($bbox[2]) + abs($bbox[0]) - 1;
    }

    //calculate y baseline
    $bbox['y'] = abs($bbox[5] + 1);

    //calculate actual text height
    $bbox['height'] = abs($bbox[7]) - abs($bbox[1]);
    if($bbox[3] > 0) {
        $bbox['height'] = abs($bbox[7] - $bbox[1]) - 1;
    }

    return $bbox;
}

But it is imperative that you use x and y coordinates given by this function when drawing:

imagettftext($im, $fontSize, 0, $bbox["x"], $bbox["y"], $text_color, $font, $text);
like image 143
Tomáš Zato - Reinstate Monica Avatar answered Oct 08 '22 17:10

Tomáš Zato - Reinstate Monica