• 3
name

A PHP Error was encountered

Severity: Notice

Message: Undefined index: userid

Filename: views/question.php

Line Number: 191

Backtrace:

File: /home/prodcxja/public_html/questions/application/views/question.php
Line: 191
Function: _error_handler

File: /home/prodcxja/public_html/questions/application/controllers/Questions.php
Line: 433
Function: view

File: /home/prodcxja/public_html/questions/index.php
Line: 315
Function: require_once

name Punditsdkoslkdosdkoskdo

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.

    • What you have to do is calculate the coordinates of where you want the text to go. Use imagettfbbox to see what size your text will be, then subtract it from the height of the image and divide by 2.
      • 1
    • Well, that's the thing! Imagettfbbox() gives me the bounding box, great but utterly useless for vertical alignment, because imagettftext doesn't use the distance to the top of the bounding box or the bottom, but instead to the baseline, which makes aligning text difficult, for I have no idea of the position of the baseline realtive to the text box.
      • 1
    • Thanks for asking this, I am also looking for an answer, but it doesn't seem that one is available. I am generating some ID tags, and want the name to fill the available space. For me the issue is letters which hang down (qypjg...). Words with those letters take up the available height (calculated using imagettfbbox) at a smaller font size, but don't fill the space because they hang below the bottom of the space. Not the end of the world, but it does make things look inconsistent and off centre.

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.

  • 11
Reply Report
      • 2
    • Wow, Marco, that is exactly what I had been looking for all this time. I thought I had found a solution by adding a third of the font size to the height (because that seemed about the difference between baseline and bottom), but your solution is more precise. Thank you!

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);
?>
  • 5
Reply Report
    • No, that's not what I need. I am aware of the function imagettfbbox, but it calculates the bounding box, whereas imagettftext uses the distance to the BASELINE as the Y parameter, not to the top or bottom of the box.
      • 2
    • okay, I think you are confusing yourself or overthinking here. If you want to vertically align text, Yes you do need imagettfbbox(). To get the y argument for imagettftext(), you take the height of the image divided by 2. That is your vertical center, let's call that $ivc. Then you take the height calculated from imagettfbbox() and divide that by 2, lets call that $tvc. Then, $y = $ivc - $tvc;
      • 1
    • Well I don't know what to tell you, perhaps it is the font you are using or perhaps a charset you are using. Maybe it is buggy or not fully supported or the GD library is otherwise having trouble with it. Because my example code as-is works just fine.

Warm tip !!!

This article is reproduced from Stack Exchange / Stack Overflow, please click

Trending Tags

Related Questions