Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using the imagettftext function with multiple lines?

I'm creating transparent text -> png images with php and so far so good. The only problem is that I want the ability to have the text word wrap due to a fixed width.. Or alternatively be able to insert breaklines into the text. Has anyone had any exp doing this? here is my code...

<?php

$font = 'arial.ttf';
$text = 'Cool Stuff! this is nice LALALALALA LALA HEEH EHEHE';
$fontSize = 20;

$bounds = imagettfbbox($fontSize, 0, $font, $text); 

$width = abs($bounds[4]-$bounds[6]); 
$height = abs($bounds[7]-$bounds[1]); 



$im = imagecreatetruecolor($width, $height);
imagealphablending($im, false);
imagesavealpha($im, true);


$trans = imagecolorallocatealpha($im, 255, 255, 255, 127);

// Create some colors
$white = imagecolorallocate($im, 255, 255, 255);
$grey = imagecolorallocate($im, 128, 128, 128);
$black = imagecolorallocate($im, 0, 0, 0);


imagecolortransparent($im, $black);
imagefilledrectangle($im, 0, 0, $width, $height, $trans);


// Add the text
imagettftext($im, $fontSize, 0, 0, $fontSize-1, $grey, $font, $text);


imagepng($im, "image.png");
imagedestroy($im);


?>
like image 553
ionfish Avatar asked May 29 '11 06:05

ionfish


3 Answers

Try this:

$text = 'Cool Stuff! this is nice LALALALALA LALA HEEH EHEHE';
$text = wordwrap($_POST['title'], 15, "\n");
like image 115
Prajwol Onta Avatar answered Nov 12 '22 20:11

Prajwol Onta


Simply explode the text on spaces to get an array of words, then start building lines by looping through the words array, testing the addition of each new word via imagettfbbox to see if it creates a width that exceeds the maxwidth you set. If it does, start the next word on a fresh new line. I find it easier to simply create a new string with special line breaks characters added, and then just explode that string again to create an array of lines, each of which you will write onto the final image separately.

Something like this:

$words = explode(" ",$text);
$wnum = count($words);
$line = '';
$text='';
for($i=0; $i<$wnum; $i++){
  $line .= $words[$i];
  $dimensions = imagettfbbox($font_size, 0, $font_file, $line);
  $lineWidth = $dimensions[2] - $dimensions[0];
  if ($lineWidth > $maxwidth) {
    $text.=($text != '' ? '|'.$words[$i].' ' : $words[$i].' ');
    $line = $words[$i].' ';
  }
  else {
    $text.=$words[$i].' ';
    $line.=' ';
  }
}

Where the pipe character is the line break character.

like image 36
Drew Avatar answered Nov 12 '22 18:11

Drew


Of all the answers posted I liked Genius in trouble's the best but it just adds a linebreak every 15 characters rather than letting the text "flow" as it would in a modern word processor with variable line lengths depending on font choice & which characters are used (e.g. lowercase L takes less horizontal space than uppercase W--l vs. W).

I came up with a solution which I've released as open source at https://github.com/andrewgjohnson/linebreaks4imagettftext

To use you would simply change:

$font = 'arial.ttf';
$text = 'Cool Stuff! this is nice LALALALALA LALA HEEH EHEHE';
$fontSize = 20;
$bounds = imagettfbbox($fontSize, 0, $font, $text); 
$width = abs($bounds[4]-$bounds[6]); 

To:

$font = 'arial.ttf';
$text = 'Cool Stuff! this is nice LALALALALA LALA HEEH EHEHE';
$fontSize = 20;
$bounds = imagettfbbox($fontSize, 0, $font, $text); 
$width = abs($bounds[4]-$bounds[6]);

// new code to add the "\n" line break characters to $text
require_once('linebreaks4imagettftext.php'); //https://raw.githubusercontent.com/andrewgjohnson/linebreaks4imagettftext/master/source/linebreaks4imagettftext.php
$text = \andrewgjohnson\linebreaks4imagettftext($fontSize, 0, $font, $text, $width);

Here is an example of the before & after with a longer piece of text:

Example

like image 30
Andrew G. Johnson Avatar answered Nov 12 '22 18:11

Andrew G. Johnson