PHP 中的“imagettfbbox()”是如何工作的?
Posted
技术标签:
【中文标题】PHP 中的“imagettfbbox()”是如何工作的?【英文标题】:How does "imagettfbbox()" in PHP work? 【发布时间】:2012-09-09 09:46:42 【问题描述】:您能否解释一下imagettfbbox()
的返回值究竟是什么意思? The manual says:
imagettfbbox() 返回一个包含 8 个元素的数组,代表四个 点使文本的边界框在成功和 FALSE 上 错误。 [...这里的积分表...] 无论角度如何,这些点都是相对于文本的,所以“上 left" 表示在左上角水平看文字。
但是,我发现它不是很清楚。例如返回值:
array(-1, 1, 61, 1, 61, -96, -1, -96)
表示以下几点:
(-1, -96) ------ (61, -96)
| |
| |
| |
| |
| |
| |
(-1, 1) -------- (61, 1)
我应该如何解释它们?
为什么会有负值?
【问题讨论】:
你传递给函数的参数是什么? 只将其视为笛卡尔网格 【参考方案1】:你应该看看comment by "marclaz" on the imagettfbbox
manual page:
请注意,由于 imageTTFBbox 和 imageTTFText 函数返回一个 可能是负数的坐标数组,必须注意 采用高度和宽度计算。
正确的方法是使用 abs() 函数:
对于横向文本:
$box = @imageTTFBbox($size,0,$font,$text); $width = abs($box[4] - $box[0]); $height = abs($box[5] - $box[1]);
然后将您的文本居中在 ($x,$y) 位置,代码应该是这样的 那:
$x -= $width/2; $y += $heigth/2; imageTTFText($img,$size,0,$x,$y,$color,$font,$text);
这是因为 (0,0) 页面原点是页面左上角和 (0,0) 文本 原点是左下角的可读文本角。
【讨论】:
“这是因为 (0,0) 页面原点是左上角,而 (0,0) 文本原点是左下角可读文本角。”起源于图形设计的标准还是 php 主义? 投反对票。 “正确的方法是使用 abs() 函数” 这是错误的。正确的做法是$width = $box[2] - $box[0]
(没有abs()
)。否则,如果字符延伸到其 0 位置的左侧,则宽度将低于应有的宽度。我不明白为什么这个答案有这么多赞成。例如,如果一个字符的最左边的位置是 -2,它的最右边的位置是 5,那么它的宽度就是 7。如果你使用abs()
,它的宽度就会变成 3。【参考方案2】:
以下资源对此进行了解释: http://www.tuxradar.com/practicalphp/11/2/6 (via archive.org)
只需使用abs()。这是来自上面的资源:“[函数]从文本字符串基线的左下角返回它的值,而不是绝对的左下角。如果你是,字母的基线是它所在的位置手写在横格纸上”
【讨论】:
链接页面错误地在单个坐标值上使用abs
,而不是在对它们进行数学运算。这样做会导致错位,
@Charles 现在链接坏了,问题解决了吗? ?
@totymedli 哦,感谢您注意到这一点。我在archive.org 上找到了坏文章的副本,并更新了帖子中的链接。它仍然不正确。谢谢!【参考方案3】:
Alain Tiemblo 和 Charles 的回答对我来说只是部分有效,一些字符,比如“1”,并不是像素完美的。
但是同一页面上的comment of blackbart at simail dot it 效果很好:
我写了一个简单的函数来计算精确边界框(单像素精度)。 该函数返回一个具有这些键的关联数组: 左,上:您将传递给 imagettftext 的坐标 宽度,高度:您必须创建的图像的尺寸
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 );
【讨论】:
以上是关于PHP 中的“imagettfbbox()”是如何工作的?的主要内容,如果未能解决你的问题,请参考以下文章