Reputation: 916
I am overlaying text on an image using GD lib. I want to wrap a string within a bounding box and get the best fit for the text as possible.
Here's what I've got so far:
//dimension of the image I'm placing the text on
$img_w = imagesx($this->img);
$img_h = imagesy($this->img);
//Get the dimensions of the text bounding box
$bbox = imagettfbbox($size, 0, $font, $text);
$w = (abs($bbox[2])+(abs($bbox[0])));
$h = (abs($bbox[5])+(abs($bbox[3])));
Next I need to do a few checks. If $w > $img_w
then I want to add a line break in the middle of the string. Then check $w > $img_w
again. If it is still too big then split into thirds and so on until it fits within the image width.
I also need to check each time I add a line break if the $h > $img_h. If this is true, then I've run out of space to fit the text within the image at this size. So I need to start decrementing the text size until this fits.
You can see something identical to what I want to achieve here: http://memegenerator.net/Instagram
I have a recursive method to retrieve the text size so I can center it on the image when I overlap it:
private function get_text_size($size, $font, $text){
//dimension of the image I'm placing the text on
$img_w = imagesx($this->img);
$img_h = imagesy($this->img);
//Get the dimensions of the text bounding box
$bbox = imagettfbbox($size, 0, $font, $text);
//add some space around the text too
$w = (abs($bbox[2])+(abs($bbox[0]));
$h = (abs($bbox[5])+(abs($bbox[3]));
if( $w > $img_w ){
//split string in half
$tmp = explode(' ', $text);
$word_count = (count($tmp)/2);
$tmp[$word_count] .= "\n";
//rebuild the string with the line break(s) and check the size again.
$text = '';
foreach($tmp as $word){
$text .= $word.' ';
}
return $this->get_text_size($size, $font, $text);
}
return array($size, $w, $h);
}
This just gets me stuck in an infinite loop, like the line break isn't working. I've checked similar questions (How do I add a line break at the mid point of a string split by whitespace, Wrap lines of text within image boundaries using gd) but none of them really solve this problem.
I kind of expected there would a simple function to do this but I can't find one and can't figure out the best way to do it.
Upvotes: 2
Views: 1649
Reputation: 4786
I was having the same issues and I found this PHP library: https://github.com/kus/php-image
Which helps wrap the text into a textbox, you can set it like this (Copy and modified from developer example):
$background = 'image/background.jpg';
$image = new PHPImage();
$image->setDimensionsFromImage($background );
$image->draw($background );
$image->setFont('font/arial.ttf');
$image->setTextColor(array(255, 255, 255));
$image->setStrokeWidth(1);
$image->setStrokeColor(array(0, 0, 0));
$image->textBox('Auto wrap and scale font size to multiline text box width and height bounds. Vestibulum venenatis risus scelerisque enim faucibus, ac pretium massa condimentum. Curabitur faucibus mi at convallis viverra. Integer nec finibus ligula, id hendrerit felis.', array(
'width' => 150,
'height' => 140,
'fontSize' => 16, // Desired starting font size
'x' => 50,
'y' => 150
));
$image->show();
//$image->save("image/temp.jpg");//If you want to save image instead of show it
Upvotes: 1