PHP imagettftext() center text - php

I want to center the text I add to my image using :
imagettftext($image, 85, 0, 250, 350, $color, $font, $txt );
I tried something like this :
$fontwidth1 = imagefontwidth($font);
$center1 = (imagesx($image)/2) - ($fontwidth1*(strlen($txt)/2));
However unfortunately it's not working.
The imagefontwidth($font) part does not work :(
Anyone has faced this issue before and know an solution / alternative method ?

The function imagefontwidth works best with fixed-width fonts. Like Austin Brunkhorst said, the most reliable way to get centered text uses imagettfbbox, like so:
$bbox = imagettfbbox(85, 0, $font, $txt);
$center1 = (imagesx($image) / 2) - (($bbox[2] - $bbox[0]) / 2);

Related

Creating image with fix background and randomly displayed text from a pre-defined list

I would like to create a script which is generating an image with one fix background image but display a randomly selected sentence on the image from a list which is previously given in the script.
So far I have a base and I've tried many variations for the random text, but none of them worked until this time.
Here is the script itself:
<?php
header('Content-type: image/png');
$text = 'The text which will be displayed';
$background_path = 'assets/bg_image.jpg';
$image = imagecreatetruecolor(1280, 720);
$background = imagecreatefromjpeg($background_path);
$color = imagecolorallocate($image, 255, 255, 255);
$title_sizes = imagettfbbox(24, 0, 'assets/roboto-medium.ttf', $text);
$title_height = $title_sizes[3];
$title_width = $title_sizes[4];
imagecopy($image, $background, 0, 0, 0, 0, 1280, 720);
imagettftext($image, 24, 0, (640 - $title_width / 2), (360 - $title_height / 2), $color, 'assets/roboto-medium.ttf', $text);
imagepng($image);
imagedestroy($image);
imagedestroy($background);
?>
So the thing is that the line "$text" allows only one sentence to be displayed. I would like to have multiple lines (various sentences) instead which will be displayed on the given background image randomly upon refresh.
Can you please help me to solve this problem?
Thank you very much in advance!
Regards,
Adam

Center text on a curve, PHP GD

I'm attempting to wrap text around a curve using the function found below. However, this does not take into account aligning the text centered no matter how wide the text maybe be. As an attempt to solve this problem I calculated the width of the text using a binding box.
$type_space=imagettfbbox($fontSize, 0, $fontname, $text);
$image_width = abs($type_space[4] - $type_space[0]) + 10;
However, from this, I need to work out a way that it can adjust the start $angle based on the width. I've played around with lots of settings, however just can't seem to find the correct maths. Any help would be amazing, thank you!
Curve Function
function imagettftextarc($image, $size, $angle, $x, $y, $r, $color, $fontfile, $text, $dir=false){
$sbox=imagettfbbox($size, 0, $fontfile, ' ');
$sbox=($sbox[2]-$sbox[0])*0.1;
$angle=$angle*M_PI/180;
foreach(preg_split('//u', $text) AS $t){
$px=$x+$r*cos($angle);
$py=$y+$r*sin($angle);
$dirangle=(360-(M_PI/2+$angle)*180/M_PI+($dir?180:0))%360;
imagettftext($image, $size, $dirangle, $px, $py, $color, $fontfile, $t);
$box=imagettfbbox($size, 0, $fontfile, $t);
$dx=$box[2]-$box[0];
$da=abs(asin(($dx+$sbox)/$r));
if($dir){
$angle-=$da;
}else{
$angle+=$da;
}
}
}
Possible Solution
I'm not sure how to execute this but the possibility could be to work out the length of the curve if it was a full 360 circle unwrapped horizontally. Then divide the new width with the unwrapped width to create the value that correlates to how many degrees it needs to be altered.

Fit the text into image PHP GD

Helllo, Using GD I'm creating a png image from a $text. The $text is script generated and may take a few lines.
So, here is my code:
$imageWidth=400;
$imageHeight=100;
$logoimg = imagecreatetruecolor($imageWidth, $imageHeight); //create Image
imagealphablending($logoimg, false);
imagesavealpha($logoimg, true);
$col=imagecolorallocatealpha($logoimg,255,255,255,127);
imagefill($logoimg, 0, 0, $col);
$white = imagecolorallocate($logoimg, 0, 0, 0);
$font = "TNR.ttf"; //font path
$fontsize=14;
$x=10;
$y=20;
$angle=0;
imagettftext($logoimg, $fontsize,$angle , $x, $y, $white, $font, $text);
$target="temp.png"; //path of target
imagepng($logoimg,$target);
My problem is that sometimes the text goes cropped by a few pixels. Here is an example:
So, the question is, how can I make the text fit the image? Thank you for your time!
You may use imagettfbox function to check edges before writing the text:
http://www.php.net/manual/en/function.imagettfbbox.php
Or, perhaps, add a border around text.

What is the correct way to determine text coordinates a from bounding box?

Given the result of a call to imagettfbbox(), what is the correct, pixel-perfect point to provide to imagettftext() such that the text will not extend beyond its bounding box?
I am determining the width/height and x/y of the baseline from the bounding box like this:
$box = imagettfbbox($size, $angle, $font, $text);
$boxXCoords = array($box[0], $box[2], $box[4], $box[6]);
$boxYCoords = array($box[1], $box[3], $box[5], $box[7]);
$boxWidth = max($boxXCoords) - min($boxXCoords);
$boxHeight = max($boxYCoords) - min($boxYCoords);
$boxBaseX = abs(min($boxXCoords));
$boxBaseY = abs(min($boxYCoords));
I then draw a filled rectangle on my image of the dimensions of the bounding box:
imagefilledrectangle($image, 0, 0, $boxWidth - 1, $boxHeight - 1, $color);
After that, I draw the text:
imagettftext($image, $size, $angle, $boxBaseX, $boxBaseY, $color, $font, $text);
However, this causes the text to extend beyond the rectangle by a pixel or two. I have seen several attempts to fix this issue on PHP's imagettfbbox() documentation, but they all just suggest substracting a pixel or two here and there, which seems like a hack to me. What's happening here, and why should we need to fudge the numbers to get things right?
I believe there is no perfect way to place text with single-pixel precision on an image based on what imagettfbbox() returns and also using .ttf non-monospaced fonts. Over at the PHP manual many users have posted ways to accomplish this (with and without fudging the numbers); I recommend using jodybrabec's simple function over at the PHP manual, which calculates the exact bounding box. I have tested this one and only in extreme cases is the text positioned at most 1 pixel off in one direction. Nonetheless, if you add some padding (even if it is just 2 or 3 pixels) to your image your text will be within the dimensions of the image 100% of the time.
What happens when you don't subtract one from each of the dimensions in this line:
imagefilledrectangle($image, 0, 0, $boxWidth - 1, $boxHeight - 1, $color);
and instead do this:
imagefilledrectangle($image, 0, 0, $boxWidth, $boxHeight, $color);
The SlightlyMagic HQ Card Generator project renders cards for the strategy card game Magic: the Gathering. The generator is powered by PHP with an advanced text rendering engine built in. I don't know about logic behind the calculations, but the renderer is dead accurate for the purposes of this application. Here's the function that calculates proper bounding boxes (HQ Card Generator 8.x/scripts/classes/font.php):
private function convertBoundingBox ($bbox) {
// Transform the results of imagettfbbox into usable (and correct!) values.
if ($bbox[0] >= -1)
$xOffset = -abs($bbox[0] + 1);
else
$xOffset = abs($bbox[0] + 2);
$width = abs($bbox[2] - $bbox[0]);
if ($bbox[0] < -1) $width = abs($bbox[2]) + abs($bbox[0]) - 1;
$yOffset = abs($bbox[5] + 1);
if ($bbox[5] >= -1) $yOffset = -$yOffset;
$height = abs($bbox[7]) - abs($bbox[1]);
if ($bbox[3] > 0) $height = abs($bbox[7] - $bbox[1]) - 1;
return array(
'width' => $width,
'height' => $height,
'xOffset' => $xOffset, // Using xCoord + xOffset with imagettftext puts the left most pixel of the text at xCoord.
'yOffset' => $yOffset, // Using yCoord + yOffset with imagettftext puts the top most pixel of the text at yCoord.
'belowBasepoint' => max(0, $bbox[1])
);
}
I know this is a little late but imagettfbbox is in points not pixels.
pixel font size in imagettftext instead of point size

imagettfbbox & imagettftext - resize,position,rotate

Ok, now it's officialy 10 hours that I'm trying to make this work, but by every minute I'm farther and farther from the final goal...
The thing is, I need to create a function, class or whatever that by the selected TTF or truetype font create, properly resize, and fill the image with a text given by the url. The image shouldn't be longer than that text.
I've given up on all my codes, and the best thing I've got so far is taken from the net ...
<?php
if(!isset($_GET['size'])) $_GET['size'] = 20;
if(!isset($_GET['text'])) $_GET['text'] = "Moj tekst";
$get_font = ( isset( $_GET['font'] ) ) ? $_GET['font'] : 'arial';
$size = imagettfbbox($_GET['size'], 0, "font/".$get_font.".ttf", $_GET['text']);
$xsize = abs($size[0]) + abs($size[2]);
$ysize = abs($size[5]) + abs($size[1]);
$image = imagecreate($xsize, $ysize);
imageSaveAlpha($image, true);
ImageAlphaBlending($image, false);
$transparentColor = imagecolorallocatealpha($image, 200, 200, 200, 127);
Imagefill($image, 0, 0, $transparentColor);
$blue = imagecolorallocate($image, 0, 0, 255);
$white = ImageColorAllocate($image, 255,255,255);
$black = ImageColorAllocate($image, 0,0,0); //-($_GET['size']/20)
imagettftext($image, $_GET['size'], 0, abs($size[0]), abs($size[5]), $black, "font/".$get_font.".ttf", $_GET['text']);
header("content-type: image/png");
imagepng($image);
imagedestroy($image);
?>
This code is ok, although the edge of the last or first latter is sometimes partly hidden or just it doesn't fit into the created image (depending on font size), which isn't the problem with smaller font size. And the function i really need is by changing image's rotation to change the entire images proportions so the text fits in.
Example : http://img199.imageshack.us/img199/9368/32739521.jpg
Also, if there is finished function or class that does this, it would be great.. :'( :)
If you are always missing one letter of the end of the beginning, why not just add the width of a single letter to your final size?
In my experience, imagettfbbox doesn't do a very good job of deciding what does and doesn't fit within a bounding box - you need to fudge it a little yourself :)
Hope this helps.
Luke Peterson

Categories