PHP GD center multiple lines (dynamically text) - php

Im drawing a dynamically text on a image centersized with GD library.
Whats the best way to align all lines center?
<?php
function imagettfstroketext(&$image, $size, $angle, $x, $y, &$textcolor, &$strokecolor, $fontfile, $text, $px) {
for($c1 = ($x-abs($px)); $c1 <= ($x+abs($px)); $c1++)
for($c2 = ($y-abs($px)); $c2 <= ($y+abs($px)); $c2++)
$bg = imagettftext($image, $size, $angle, $c1, $c2, $strokecolor, $fontfile, $text);
return imagettftext($image, $size, $angle, $x, $y, $textcolor, $fontfile, $text);
}
$image = "12.png";
$font = "./impact.ttf";
$font_size = "50";
$image_2 = imagecreatefrompng($image);
$black = imagecolorallocate($image_2, 255,255,255);
$black2 = imagecolorallocate($image_2, 0,0,0);
$image_width = imagesx($image_2);
$image_height = imagesy($image_2);
$margin = 35;
$text = "This is the Text. It is dynamically long. This text will be split using the function under this text.";
//explode text by words
$text_a = explode(' ', $text);
$text_new = '';
foreach($text_a as $word){
//Create a new text, add the word, and calculate the parameters of the text
$box = imagettfbbox($font_size, 0, $font, $text_new.' '.$word);
//if the line fits to the specified width, then add the word with a space, if not then add word with new line
if($box[2] > $image_width - $margin*2){
$text_new .= "\n".$word;
} else {
$text_new .= " ".$word;
}
}
$text_box = imagettfbbox($font_size,0,$font,$text_new);
$text_width = $text_box[2]-$text_box[0]; // lower right corner - lower left corner
$text_height = $text_box[3]-$text_box[1];
$x = ($image_width/2) - ($text_width/2);
$y = ($image_height/2) - ($text_height/2);
$font_color = imagecolorallocate($image_2, 255, 255, 255);
$font_color2 = imagecolorallocate($image_2, 0, 0, 0);
$stroke_color = imagecolorallocate($image_2, 0, 0, 0);
$white = imagecolorallocate($im, 255, 255, 255);
$black = imagecolorallocate($im, 0, 0, 0);
$grey = imagecolorallocate($im, 175, 175, 175);
imagettfstroketext($image_2, $font_size ,0,$x,$y,$font_color, $stroke_color, $font, $text_new, 0);
header ("Content-type: image/png");
imagejpeg($image_2, "../img/output.png");
imagedestroy($image_2);
?>
This is what it looks right now:
This is what it should look like:
Using three times "imagettfstroketext" with adding "$y+50" would do the trick but the text is dynamic.
Any suggestions?
best regards

I would create a temporary image on one line, storing the accumulated length in an array. Then determine exactly which words fit on a line, and the offset to center each line. Then create the image.
Alternatively you can create separate images for each line, then combine them with the right offset.

Related

Write text over image dynamically and center the text

I have a script that is writing a text over an image.
It works fine, but the text is aligned to the left.
I am trying to center the text horizontally, but not sure how can I do that.
Here is the code that I have at the moment
//content type
header('Content-Type: image/png');
if (isset($_GET['text'])){$text = $_GET['text'];}else{$text = "";}
//font
$font = 'Ubuntu-Medium.ttf';
//font size
$font_size = 18;
//image width
$width = 400;
//text margin
$margin = 90;
//explode text by words
$text_a = explode(' ', $text);
$text_new = '';
foreach($text_a as $word){
//Create a new text, add the word, and calculate the parameters of the text
$box = imagettfbbox($font_size, 0, $font, $text_new.' '.$word);
//if the line fits to the specified width, then add the word with a space, if not then add word with new line
if($box[2] > $width - $margin*2){
$text_new .= "\n".$word;
} else {
$text_new .= " ".$word;
}
}
//trip spaces
$text_new = trim($text_new);
//new text box parameters
$box = imagettfbbox($font_size, 0, $font, $text_new);
//new text height
$height = $box[1] + $font_size + $margin * 2;
//create image
$im = imagecreatefromjpeg('source.jpg');
//create colors
$white = imagecolorallocate($im, 255, 255, 255);
$black = imagecolorallocate($im, 51, 95, 32);
//color image
imagefilledrectangle($im, 0, 0, $width, $black);
// determine the size of the text so we can center it
$box = imagettfbbox($font_size, 0, $font, $text_new);
$text_width = abs($box[2]) - abs($box[0]);
$text_height = abs($box[5]) - abs($box[3]);
$image_width = imagesx($im);
$image_height = imagesy($im);
$x = ($image_width - $text_width) / 2;
$y = ($image_height + $text_height) / 2;
//add text to image
imagettftext($im, $font_size, 0, $x, $y, $black, $font, $text_new);
//return image
imagepng($im);
//frees any memory associated with image
imagedestroy($im);
Any ideas on how can I center the text?
I already centered the box that the text is placed, so the box is in the center of the image. The problem is that the text is aligned left and I need it in the center.

Underline text using imagettftext

My question is, how do I underline all the text in the image?Code:
function createImage($text)
{
$text .= "\n";
$text = wordwrap($text, 40, "\n");
$newlines = substr_count($text, "\n");
if($newlines == 0)
{
$height = 30;
}
else
{
$height = 30*$newlines-$newlines*7;
}
putenv('GDFONTPATH=' . realpath('.'));
header('Content-Type: image/png');
$im = imagecreatetruecolor(315, $height);
$white = imagecolorallocate($im, 255, 255, 255);
$grey = imagecolorallocate($im, 128, 128, 128);
$black = imagecolorallocate($im, 0, 0, 0);
$purple = imagecolorallocate($im, 97, 26, 139);
imagefilledrectangle($im, 0, 0, 399, $height, $white);
$font = 'arialbd.ttf';
imagettftext($im, 11, 0, 10, 20, $purple, $font, $text);
imagepng($im);
imagedestroy($im);
}
createImage("Stackoverflow Stackoverflow Stackoverflow Stackoverflow Stackoverflow Stackoverflow Stackoverflow Stackoverflow Stackoverflow Stackoverflow Stackoverflow Stackoverflow ");
RESULT
http://i.imgur.com/Jdr7HPy.png
I want all the text to be underlined, I've found some solutions but they're only from left to right, not depending on words.
Use the Unicode underline combining character U+0332.
You will need a loop to or clever array merge to modify the text,
$e = explode(' ', $text);
for($i=0;$i<count($e);$i++) {
$e[$i] = implode('̲', str_split($e[$i]));
}
$text = implode(' ', $e);
You can do this by finding out dimensions of the text in pixels using imagettfbbox(), then use it as reference to draw lines beneath the text. I've played around with it and here's my try:
function createImage($text){
putenv('GDFONTPATH=' . realpath('.'));
$text = wordwrap($text, 40, "\n");
$padding = 10; // padding around text
$uOffs = 2; // distance between the line and the text above it
$uHeight = 1; // height of the under-line
$lines = explode("\n", $text); // split text in lines
$lineLengths = array(); // will store length of each line
$textSize = 11;
$font = 'arialbd.ttf';
// bounding box of all text
$textBoundingBox = array_map('abs', imagettfbbox($textSize, 0, $font, $text));
list($blx, $bly, $brx, $bry, $trx, $try, $tlx, $tly) = $textBoundingBox;
// calculate image dimensions based on the bounding box data
$x = max($brx, $trx) + ($padding * 4);
$y = max($blx, $bly) + ($padding * 4);
$img = imagecreatetruecolor($x, $y);
// determine length of each line of text
foreach($lines as $i => $line){
$box = imagettfbbox($textSize, 0, $font, $line);
$lineLengths[$i] = max($box[2], $box[4]);
}
$white = imagecolorallocate($img, 255, 255, 255);
$grey = imagecolorallocate($img, 128, 128, 128);
$black = imagecolorallocate($img, 0, 0, 0);
$purple = imagecolorallocate($img, 97, 26, 139);
imagefilledrectangle($img, 0, 0, $x - 1, $y - 1, $white);
imagettftext($img, $textSize, 0, $padding + min($tlx, $blx), $padding + min($tly, $bly), $purple, $font, $text);
// starting Y position of the under-line
$uY = $padding + min($tly, $bly);
// underline text...
foreach($lineLengths as $length){
imagefilledrectangle($img, $padding + min($tlx, $blx), $uY + $uOffs, $padding + $length, $uY + $uOffs + $uHeight, $purple);
$uY += 19;
}
header('Content-Type: image/png');
imagepng($img);
imagedestroy($img);
}
Result:
This is a little more flexible that using Unicode chars because you have control over the line height, and position relative to the text above it.

Aligning php Generated Image dynamic text in center

i want to align the text generated on the image to the center of the image. for the moment, i dont know if it is possible to align it. below is the code.
$im = #imagecreatefromjpeg('poloroid.jpg');
// Create some colors
$white = imagecolorallocate($im, 255, 255, 255);
$grey = imagecolorallocate($im, 128, 128, 128);
$black = imagecolorallocate($im, 0, 0, 0);
//imagefilledrectangle($im, 0, 0, 399, 29, $white);
// The text to draw
//$text = 'John...';
$fbid = $_POST["id"];
$text = $_POST["want"];
$fb_email =$_POST["email"];
$fb_name=$_POST["name"];
$uploads_dir = 'uploaded_files/';
// Replace path by your own font path
$font = 'verdana.ttf';
//image file name
//$name ="$fbid.png";
$name = $uploads_dir.$fbid.".png"; //this saves the image inside uploaded_files folder
// Add some shadow to the text
imagettftext($im, 20, 0, 25, 126, $grey, $font, $text);
// Add the text
imagettftext($im, 20, 0, 25, 125, $black, $font, $text);
// Using imagepng() results in clearer text compared with imagejpeg()
//imagepng($im);
imagepng($im,$name,9);
imagedestroy($im);
thanks for the help guys.
$im = #imagecreatefromjpeg('poloroid.jpg');
// Create some colors
$white = imagecolorallocate($im, 255, 255, 255);
$grey = imagecolorallocate($im, 128, 128, 128);
$black = imagecolorallocate($im, 0, 0, 0);
//imagefilledrectangle($im, 0, 0, 399, 29, $white);
// The text to draw
//$text = 'John...';
$fbid = $_POST["id"];
$text = $_POST["want"];
$fb_email =$_POST["email"];
$fb_name=$_POST["name"];
$uploads_dir = 'uploaded_files/';
// Replace path by your own font path
$font = 'verdana.ttf';
$font_size = 20;
$angle = 45;
//image file name
//$name ="$fbid.png";
$name = $uploads_dir.$fbid.".png"; //this saves the image inside uploaded_files folder
// Get image Width and Height
$image_width = imagesx($im);
$image_height = imagesy($im);
// Get Bounding Box Size
$text_box = imagettfbbox($font_size,$angle,$font,$text);
// Get your Text Width and Height
$text_width = $text_box[2]-$text_box[0];
$text_height = $text_box[7]-$text_box[1];
// Calculate coordinates of the text
$x = ($image_width/2) - ($text_width/2);
$y = ($image_height/2) - ($text_height/2);
// Add some shadow to the text
imagettftext($im, $font_size, 0, $x, $y+1, $grey, $font, $text);
// Add the text
imagettftext($im, $font_size, 0, $x, $y, $black, $font, $text);
// Using imagepng() results in clearer text compared with imagejpeg()
//imagepng($im);
imagepng($im,$name,9);
imagedestroy($im);
You can use stil/gd-text class. Disclaimer: I am the author.
<?php
use GDText\Box;
use GDText\Color;
$im = #imagecreatefromjpeg('poloroid.jpg');
$textbox = new Box($im);
$textbox->setFontSize(20);
$textbox->setFontFace('verdana.ttf');
$textbox->setFontColor(new Color(0, 0, 0)); // black
$textbox->setTextShadow(
new Color(0, 0, 0, 80), // black color, but 60% transparent
0,
-1 // shadow shifted 1px to top
);
$textbox->setBox(
0, // distance from left edge
0, // distance from top edge
imagesx($im), // textbox width, equal to image width
imagesy($im) // textbox height, equal to image height
);
// now we have to align the text horizontally and vertically inside the textbox
// the texbox covers whole image, so text will be centered relatively to it
$textbox->setTextAlign('center', 'center');
// it accepts multiline text
$textbox->draw($text);
$uploads_dir = 'uploaded_files/';
//image file name
//$name ="$fbid.png";
$name = $uploads_dir.$fbid.".png"; //this saves the image inside uploaded_files folder
imagepng($im, $name, 9);
imagedestroy($im);
Demonstration:
I've updated your code a little:
function ImageTTFCenter($image, $text, $font, $size, $angle = 45)
{
$xi = imagesx($image);
$yi = imagesy($image);
$box = imagettfbbox($size, $angle, $font, $text);
$xr = abs(max($box[2], $box[4]));
$yr = abs(max($box[5], $box[7]));
$x = intval(($xi - $xr) / 2);
$y = intval(($yi + $yr) / 2);
return array($x, $y);
}
$im = #imagecreatefromjpeg('poloroid.jpg');
// Create some colors
$white = imagecolorallocate($im, 255, 255, 255);
$grey = imagecolorallocate($im, 128, 128, 128);
$black = imagecolorallocate($im, 0, 0, 0);
//imagefilledrectangle($im, 0, 0, 399, 29, $white);
// The text to draw
//$text = 'John...';
$fbid = $_POST["id"];
$text = $_POST["want"];
$fb_email =$_POST["email"];
$fb_name=$_POST["name"];
$uploads_dir = 'uploaded_files/';
// Replace path by your own font path
$font = 'verdana.ttf';
//image file name
//$name ="$fbid.png";
$name = $uploads_dir.$fbid.".png"; //this saves the image inside uploaded_files folder
list($x, $y) = ImageTTFCenter($im, $text, $font, 20)
// Add some shadow to the4 text
imagettftext($im, 20, 0, $x, $y+1, $grey, $font, $text);
// Add the text
imagettftext($im, 20, 0, $x, $y, $black, $font, $text);
// Using imagepng() results in clearer text compared with imagejpeg()
//imagepng($im);
imagepng($im,$name,9);
imagedestroy($im);
The ImageTTFCenter function will find the center coordinates of you image which you will tell imagettftext
foreach ($user as $key=>$value){
$bb = imagettfbbox($value['font-size'],0,$fontname,$value['name']);
$WW = abs($bb[2]-$bb[0]);
$XX = ($value['XPos']+$WW);
$HH = abs($bb[5]-$bb[3]);
$HH +=1;
$HHH += $HH;
imagettftext($im, $value['font-size'], 0, $value['XPos'], $value['YPos'], $color[$value['color']], $fontname, $value['name']);
$HHH += 1;
$WIDE = abs($bb[2]-$bb[0]);
$endpoint=$value['XPos']+$WIDE;
$bb2 = imagettfbbox($value['font-size'],0,$fontname,$value['name']);
$WW2 = abs($bb2[2]-$bb2[0]);
$x2pos= $endpoint-$WW2;
imagettftext($im, $value['font-size'], 0, $x2pos, $value['YPos'], $color[$value['color']], $fontname, $value['name']);
}

get lowermost left corner of an iamge and write text there

I'm trying to get the lowermost left (x,y) coordinates of an image.
I'm doing that to be able to write a text in different-sized picture, in the left lowermost corner. Below is the code. Could you please help?
<?php
$white = imagecolorallocate($image2, 255, 255, 255);
$grey = imagecolorallocate($image2, 128, 128, 128);
$black = imagecolorallocate($image2, 0, 0, 0);
$textsize = 30;
$size = imagettfbbox($textsize, 0, $font, $text);
$xsize = abs($size[0]) + abs($size[2]);
$ysize = abs($size[5]) + abs($size[1]);
$image2size = getimagesize("image2.jpg");
$textleftpos = round(($image2size[0] - $xsize) / 2);
$texttoppos = round(($image2size[1] + $ysize) / 2);
imagettftext($image2, $textsize, 0, $textleftpos, $texttoppos, $white, $font, $text);
imagejpeg($image2, "image3.jpg");
?>
$indentfromedge = 5; // or whatever you want for an indent
$textleftpos = $indentfromedge;
$texttoppos = $image2size[1] - $ysize - $indentfromedge;
I think is what you're going for. Replace the two lines with $text*pos in them with the above code.
On the left edge means an x-coordinate of 0
On the bottom edge means an y-coordinate equal to the height of the image minus the height of the text
So, say your text size is 30px:
$size = imagesize($img);
$x = 0;
$y = $size[1] - 30;
// assuming you're using GD1
imagettftext($image, 30, 0, $x, $y, $color, $font, "sample text");

How to create multiple line-breaks in a dynamic image when needed?

Currently I've got the following working just fine without any problems (yet).
header ("Content-type: image/png");
$string = $_REQUEST['text'];
$font = 15;
$width = 300;
$height = 350;
$image = imagecreate($width, $height);
$back = ImageColorAllocate($image, 255, 255, 255);
$border = ImageColorAllocate($image, 0, 0, 0);
ImageFilledRectangle($image, 0, 0, $width, $height, $border);
ImageFilledRectangle($image, 1, 1, $width-2, $height-2, $back);
$text_color = imagecolorallocate($image, 255, 0, 0);
ImageStringWrap($image, $font, 3, 2, $string, $text_color, $width-2 );
imagepng($image);
function ImageStringWrap($image, $font, $x, $y, $text, $color, $maxwidth) {
$fontwidth = ImageFontWidth($font);
$fontheight = ImageFontHeight($font);
if ($maxwidth != NULL) {
$maxcharsperline = floor($maxwidth / $fontwidth);
$text = wordwrap($text, $maxcharsperline, "\n", false);
}
while (list($numl, $line) = each($lines)) {
ImageString($image, $font, $x, $y, $line, $color);
$y += $fontheight;
}
}
While the above works great, one thing I've been failing to work is be able to get line breaks like would come out akin to nl2br().
The text that this is pulling from in $_REQUEST['text'] is from the database, which was originally inserted from a textarea and passed to this script via URL. Naturally when people type in a textarea, there are line breaks that come from that. While printing it to the browser via text is easy, I can't seem to get the same result within an image.
I haven't spend a long time working with the GD library, but after searching around I really can't find anything about how to do this. Is it just not possible?

Categories