Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP imagettftext baseline workaround

I am writing to print text to an image using PHP. However, the function imagettftext() uses the baseline, whereas I need the text vertically centered.

So, I either need a method to print text with y not the distance from top to baseline, but from top to top of bounding box OR I need a method using which I could determine the distance between top of bounding box and baseline.

Apparently, I am confusing you. So, to make it clear: I am aware of the function imagettfbbox(). Using that function I can determine height and width of resulting text box. Its height, however, is utterly useless for vertical alignment when printing with imagettftext(), because the Y parameter is not the distance to the top of the box (or even the bottom, but at least something I could have used having the height) but the distance to the baseline of the text within.

EDIT: Why am I not accepting the latest answer?

See my latest comment below the answer, and use this image as a reference.

like image 219
arik Avatar asked Jul 18 '11 18:07

arik


2 Answers

I do not know if the answer still interested.However, the imagettfbbox() function give you more information than simply the height and the width of the bounding box. It's designed exactly to return information needed by the imagettftext() to manage the text as you want.

The trick lies in the fact that the coordinates returned from imagettfbbox() are not related to the absolute top left corner, but to the baseline of the font for the particular text. This is the reason because the box is specified in point coordinates, and these are often negative.

In short:

$dims = imagettfbbox($fontsize, 0, $font, $text);

$ascent = abs($dims[7]);
$descent = abs($dims[1]);
$width = abs($dims[0])+abs($dims[2]);
$height = $ascent+$descent;

...

// In the example code, for the vertical centering of the text, consider
// the simple following formula

$y = (($imageHeight/2) - ($height/2)) + $ascent;

This works perfectly for my projects. Hope this help.

Sorry for english. Marco.

like image 134
Marco Jacovone Avatar answered Sep 21 '22 00:09

Marco Jacovone


Not entirely sure what your asking...can you give an example? Perhaps imagettfbbox is what you need?

// get bounding box dims
$dims = imagettfbbox($fontsize, 0, $font, $quote);

// do some math to find out the actual width and height
$width = $dims[4] - $dims[6]; // upper-right x minus upper-left x 
$height = $dims[3] - $dims[5]; // lower-right y minus upper-right y

edit: Here is an example of vertically centered text

<?php
$font = 'arial.ttf';
$fontsize = 100;
$imageX = 500;
$imageY = 500;

// text
$text = "FOOBAR";

// create a bounding box for the text
$dims = imagettfbbox($fontsize, 0, $font, $text);

// height of bounding box (your text)
$bbox_height = $dims[3] - $dims[5]; // lower-right y minus upper-right y

// Create image
$image = imagecreatetruecolor($imageX,$imageY);

// background color
$bgcolor = imagecolorallocate($image, 0, 0, 0);

// text color
$fontcolor = imagecolorallocate($image, 255, 255, 255);

// fill in the background with the background color
imagefilledrectangle($image, 0, 0, $imageX, $imageY, $bgcolor);

$x = 0; 
$y = (($imageY/2) - ($bbox_height/2)) + $fontsize;
imagettftext($image, $fontsize, 0, $x, $y , $fontcolor, $font, $text);

// tell the browser that the content is an image
header('Content-type: image/png');
// output image to the browser
imagepng($image);

// delete the image resource 
imagedestroy($image);
?>
like image 40
Crayon Violent Avatar answered Sep 20 '22 00:09

Crayon Violent