How does “imagettfbbox()” in PHP work?

那年仲夏 提交于 2019-12-30 08:15:14

问题


Could you please explain what exactly the return value of imagettfbbox() mean? The manual says:

imagettfbbox() returns an array with 8 elements representing four points making the bounding box of the text on success and FALSE on error. [...Table of points here...] The points are relative to the text regardless of the angle, so "upper left" means in the top left-hand corner seeing the text horizontally.

But, I found it not very clear. For example, the return value:

array(-1, 1, 61, 1, 61, -96, -1, -96)

means the following points:

(-1, -96) ------ (61, -96)
    |                |
    |                |
    |                |
    |                |
    |                |
    |                |
 (-1, 1) -------- (61, 1)              

How should I interpret them?

Why there are negative values?


回答1:


You should take a look at the comment by "marclaz" on the imagettfbbox manual page :

Please note that as imageTTFBbox and imageTTFText functions return an array of coordinates which could be negative numbers care must be taken with height and width calculations.

The rigth way to do that is to use the abs() function:

for an horizontal text:

$box = @imageTTFBbox($size,0,$font,$text); $width = abs($box[4] -
$box[0]); $height = abs($box[5] - $box[1]);

Then to center your text at ($x,$y) position the code should be like that:

$x -= $width/2; $y += $heigth/2;

imageTTFText($img,$size,0,$x,$y,$color,$font,$text);

this because (0,0) page origin is topleft page corner and (0,0) text origin is lower-left readable text corner.




回答2:


The following resource explains this: http://www.tuxradar.com/practicalphp/11/2/6

Just use abs(). This is from the resource above: "[the function] 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"




回答3:


The answer of Alain Tiemblo and Charles only partly worked for me, a few characters, like '1' weren't pixel perfect.

But the comment of blackbart at simail dot it on the same page worked very nice:

I wrote a simple function that calculates the exact bounding box (single pixel precision). The function returns an associative array with these keys: left, top: coordinates you will pass to imagettftext width, height: dimension of the image you have to create

function calculateTextBox($font_size, $font_angle, $font_file, $text) { $box = imagettfbbox($font_size, $font_angle, $font_file, $text); if( !$box ) return false; $min_x = min( array($box[0], $box[2], $box[4], $box[6]) ); $max_x = max( array($box[0], $box[2], $box[4], $box[6]) ); $min_y = min( array($box[1], $box[3], $box[5], $box[7]) ); $max_y = max( array($box[1], $box[3], $box[5], $box[7]) ); $width = ( $max_x - $min_x ); $height = ( $max_y - $min_y ); $left = abs( $min_x ) + $width; $top = abs( $min_y ) + $height; // to calculate the exact bounding box i write the text in a large image $img = @imagecreatetruecolor( $width << 2, $height << 2 ); $white = imagecolorallocate( $img, 255, 255, 255 ); $black = imagecolorallocate( $img, 0, 0, 0 ); imagefilledrectangle($img, 0, 0, imagesx($img), imagesy($img), $black); // for sure the text is completely in the image! imagettftext( $img, $font_size, $font_angle, $left, $top, $white, $font_file, $text); // start scanning (0=> black => empty) $rleft = $w4 = $width<<2; $rright = 0; $rbottom = 0; $rtop = $h4 = $height<<2; for( $x = 0; $x < $w4; $x++ ) for( $y = 0; $y < $h4; $y++ ) if( imagecolorat( $img, $x, $y ) ){ $rleft = min( $rleft, $x ); $rright = max( $rright, $x ); $rtop = min( $rtop, $y ); $rbottom = max( $rbottom, $y ); } // destroy img and serve the result imagedestroy( $img ); return array( "left" => $left - $rleft, "top" => $top - $rtop, "width" => $rright - $rleft + 1, "height" => $rbottom - $rtop + 1 ); }



来源:https://stackoverflow.com/questions/12338072/how-does-imagettfbbox-in-php-work

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!