imagettftext, Writing in Arabic from RTL - php

I have this code, but my problem is that the starting point from left to right as in English, and I got no clue how to make it RTL
here's my code:
$test = "بسم الله الرحمن الرحيم";
$test = $Arabic->utf8Glyphs($test);
$test= $test;
$angle = 0;
$font_size =40;
// Get image dimensions
$width = imagesx($jpg_image);
$height = imagesy($jpg_image);
// Get center coordinates of image
$centerX = $width / 2;
$centerY = $height / 2;
// Get size of text
list($left, $bottom, $right, , , $top) = imageftbbox($font_size, $angle, $font_path, $test);
$left_offset = ($right - $left) / 2;
$top_offset = ($bottom - $top) / 2;
$x = $centerX - $left_offset;
$y = $centerY - $top_offset;
imagettftext($jpg_image, $font_size, $angle, $x + 950, 665, $color, $font_path, $test);

Related

imageantialias() doesn't seem to do anything on circles

I create an image with:
$image = #imagecreatetruecolor(320, 45) or die("Cannot Initialize new GD image stream.");
imageantialias($image, true);
imagefill($image, 0, 0, imagecolorallocate($image, 255, 255, 255);
Later, I add some text and on top of that, a shape:
imagearc($image, $x + 5, $y - 7, $size, $size, 0, 360, $color);
But the the circle is still very jaggy:
I'm running php 8 with gd installed. I'm getting no errors.
Ok, this guy has a whole web page devoted to algorithms to work around this limitation: https://create.stephan-brumme.com/antialiased-circle/
Awesome work.
I went with "Wu's Algorithm" which provides the best quality. Works well.
Here's my version modified to use my global $image variable. It creates a perfect circle. The $my_x and $my_y are the x and y coordinates on the canvas.
function create_circle($my_x, $my_y, $size, $color) {
global $image;
$width = $size;
$height = $size;
$centerX = $my_x; $radiusX = ($width -20) / 2;
$centerY = $my_y; $radiusY = ($height-20) / 2;
static $maxTransparency = 0x7F; // 127
$radiusX2 = $radiusX * $radiusX;
$radiusY2 = $radiusY * $radiusY;
// upper and lower halves
$quarter = round($radiusX2 / sqrt($radiusX2 + $radiusY2));
for ($x = 0; $x <= $quarter; $x++) {
$y = $radiusY * sqrt(1-$x*$x/$radiusX2);
$error = $y - floor($y);
$transparency = round($error * $maxTransparency);
$alpha = $color | ($transparency << 24);
$alpha2 = $color | (($maxTransparency - $transparency) << 24);
setpixel4($centerX, $centerY, $x, floor($y), $alpha);
setpixel4($centerX, $centerY, $x, floor($y)+1, $alpha2);
}
// right and left halves
$quarter = round($radiusY2 / sqrt($radiusX2 + $radiusY2));
for ($y = 0; $y <= $quarter; $y++) {
$x = $radiusX * sqrt(1-$y*$y/$radiusY2);
$error = $x - floor($x);
$transparency = round($error * $maxTransparency);
$alpha = $color | ($transparency << 24);
$alpha2 = $color | (($maxTransparency - $transparency) << 24);
setpixel4($centerX, $centerY, floor($x), $y, $alpha);
setpixel4($centerX, $centerY, floor($x)+1, $y, $alpha2);
}
}
// helper function, draws pixel and mirrors it
function setpixel4($centerX, $centerY, $deltaX, $deltaY, $alpha) {
global $image;
imagesetpixel($image, $centerX + $deltaX, $centerY + $deltaY, $alpha);
imagesetpixel($image, $centerX - $deltaX, $centerY + $deltaY, $alpha);
imagesetpixel($image, $centerX + $deltaX, $centerY - $deltaY, $alpha);
imagesetpixel($image, $centerX - $deltaX, $centerY - $deltaY, $alpha);
}

Position array text in PHP GD on middle of specific part of image

I have an array of a string to fit on a page, i managed to center it horizontal now i need to do that vertical in a specific part of image.
$imgWidth = 240;
$imgHeight = 900;
$IMG = imagecreatetruecolor($imgWidth,$imgHeight);
$font_type_bold = '/dejavu/DejaVuSansCondensed-Bold.ttf';
$background = imagecolorallocate($IMG, 78,129,154);
$text_white = imagecolorallocate($IMG, 255,255,255);
$IMG = imagecreatetruecolor($imgWidth,$imgHeight);
$max_lenght_of_title = 15;
$special_issue_name_mod="This is some example text to be put on the page and split into array to fit he width of frame";
$text = explode("\n", wordwrap($special_issue_name_mod, $max_lenght_of_title));
$line_height=30;
imageline($IMG, 0, 500, 240, 500, $text_white);
imageline($IMG, 0, 100, 240, 100, $text_white);
for($i=0;$i<count($text);$i++) {
$font_size_si_name_horizontal = 21;
//Center the text
$size = imagettfbbox(20, 0, $font_type_bold, $text[$i]);
$long_text = $size[2] + $size[0];
$posx = ($imgWidth - $long_text) / 2;
imagettftext($IMG, $font_size_si_name_horizontal, 0, $posx - 5, 150+ $line_height + $line_height * $i , $text_white, $font_type_bold, $text[$i]);
}
header("Content-type: image/png");
imagepng($IMG);
imagecolordeallocate($IMG, $text_color );
imagecolordeallocate($IMG, $background );
The result is this and i need it to be in specific part of page, for example selected one
So how can i make this to not be the fixed middle but adjustive one depending on what part of page the text will be.
Note: Text can be longer, so thats the main problem. Depending on lenght of text the title should be in the middle
<?php
$imgWidth = 240;
$imgHeight = 900;
$IMG = imagecreatetruecolor($imgWidth,$imgHeight);
$font_type_bold = 'BioRhyme/BioRhyme-Regular.ttf';
$background = imagecolorallocate($IMG, 78,129,154);
$text_white = imagecolorallocate($IMG, 255,255,255);
$IMG = imagecreatetruecolor($imgWidth,$imgHeight);
$max_lenght_of_title = 15;
$special_issue_name_mod="This is some example text to be put on the page and split into array to fit he width of frame";
$text = explode("\n", wordwrap($special_issue_name_mod, $max_lenght_of_title));
$line_height=30;
$vert = ($imgHeight/5);
for($i=0;$i<count($text);$i++) {
$font_size_si_name_horizontal = 21;
//Center the text
$size = imagettfbbox(20, 0, $font_type_bold, $text[$i]);
$long_text = $size[2] + $size[0];
$posx = ($imgWidth - $long_text) / 2;
imagettftext($IMG, $font_size_si_name_horizontal, 0, $posx - 5, $vert+ $line_height + $line_height * $i , $text_white, $font_type_bold, $text[$i]);
}
header("Content-type: image/png");
imagepng($IMG);
imagecolordeallocate($IMG, $text_color );
imagecolordeallocate($IMG, $background );
?>
I have added $vert = ($imgHeight/5); and put into imagettftext() for dynamically calculted vertical Y index!
I figured out a way to solve this
$middle_of_page = 350;
for($i=0;$i<count($text);$i++) {
$middle_of_page = $middle_of_page - 21;
}
imagettftext($IMG, $font_size_si_name_horizontal, 0, $posx - 5, $middle_of_page+$line_height + $line_height * $i , $text_white, $font_type_bold, $text[$i]);
With the $middle_of_page part i regulate the point where text with array size of one will be, and then i just remove by font size of 21 for every $i that stands for array size of string.

Simple captcha php script not displaying text on image

I was hoping to get in touch with someone on a situation that I cannot find the solution to anywhere.
I am trying to create a captcha on my website using php and although I was able to create an image and create the random captcha text.
I am unable to over lay the two. Here is my code:
<?PHP
session_start();
function generateRandomString($length = 10) {
$letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
$len = strlen($letters);
$letter = $letters[rand(0, $len - 1)];
$text_color = imagecolorallocate($image, 0, 0, 0);
$word = "";
for ($i = 0; $i < 6; $i++) {
$letter = $letters[rand(0, $len - 1)];
imagestring($image, 7, 5 + ($i * 30), 20, $letter, $text_color);
$word .= $letter;
}
$_SESSION['captcha_string'] = $word;
}
function security_image(){
// $code = isset($_SESSION['captcha']) ? $_SESSION['captcha'] : generate_code();
//$font = 'content/fonts/comic.ttf';
$width = '110';
$height = '20';
$font_size = $height * 0.75;
// $image = #imagecreate($width, $height) or die('GD not installed');
global $image;
$image = imagecreatetruecolor($width, $height) or die("Cannot Initialize new GD image stream");
$background_color = imagecolorallocate($image, 255, 255, 255);
imagefilledrectangle($image,0,0,200,50,$background_color);
$line_color = imagecolorallocate($image, 64,64,64);
for($i=0;$i<10;$i++) {
imageline($image,0,rand()%50,200,rand()%50,$line_color);
}
$pixel_color = imagecolorallocate($image, 0,0,255);
for($i=0;$i<1000;$i++) {
imagesetpixel($image,rand()%200,rand()%50,$pixel_color);
}
//$textbox = imagettfbbox($font_size, 0, $font, $code);
//$textbox = imagettfbbox($font_size, 0, $randomString);
$x = ($width - $textbox[4]) / 2;
$y = ($height - $textbox[5]) / 2;
// imagettftext($image, $font_size, 0, $x, $y, $text_color, $font , $code);
imagettftext($image, $font_size, 0, $x, $y, $text_color , $word);
$images = glob("*.png");
foreach ($images as $image_to_delete) {
#unlink($image_to_delete);
}
imagepng($image, "image" . $_SESSION['count'] . ".png");
header('Content-Type: image/png');
imagepng($image);
imagedestroy($image);
}
security_image();
?>
I have no idea what I’m doing wrong. I’ve spent over 10 hours on this “display text” issue. I don’t understand and I am desperate for help. I even downloaded working captcha version from other resources that break once I upload it to my server. I have no idea whats going on. At first I thought there was something wrong with my server but the fact that I can even create the pixels, lines image means that it is at least working.
Please help!!!! 
UPDATE---------------------------------------------
Thank you for your suggestions. Here is the edited code. I'm still getting the same issue.
<?PHP
session_start();
function security_image(){
global $image;
// $code = isset($_SESSION['captcha']) ? $_SESSION['captcha'] : generate_code();
$font = 'content/fonts/comic.ttf';
$width = '110';
$height = '20';
$font_size = $height * 0.75;
$image = imagecreatetruecolor($width, $height) or die("Cannot Initialize new GD image stream");
$background_color = imagecolorallocate($image, 255, 255, 255);
imagefilledrectangle($image,0,0,200,50,$background_color);
$line_color = imagecolorallocate($image, 64,64,64);
for($i=0;$i<10;$i++) {
imageline($image,0,rand()%50,200,rand()%50,$line_color);
}
$pixel_color = imagecolorallocate($image, 0,0,255);
for($i=0;$i<1000;$i++) {
imagesetpixel($image,rand()%200,rand()%50,$pixel_color);
}
$letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
$len = strlen($letters);
$letter = $letters[rand(0, $len - 1)];
$text_color = imagecolorallocate($image, 0, 0, 0);
$word = "";
for ($i = 0; $i < 6; $i++) {
$letter = $letters[rand(0, $len - 1)];
imagestring($image, 7, 5 + ($i * 30), 20, $letter, $text_color);
$word .= $letter;
}
$_SESSION['captcha_string'] = $word;
/*texbox unitinitialized (removed for the sake of just showing the word size doesnt matter)
$x = ($width - $textbox[4]) / 2;
$y = ($height - $textbox[5]) / 2;
*/
$x = ($width) / 2;
$y = ($height) / 2;
imagettftext($image,$font, 4, $x, $y, $word);
header('Content-Type: image/png');
imagepng($image);
imagedestroy($image);
}
security_image();?>
i made some suggested changes but the code seems to still do the same thing. Just display the lines and pixels as expected but the text still is missing... ?
There are some several "errors" in your functions, let's fix them:
In generateRandomString()
generateRandomString($length = 10)
$lenght is not used its scope.
$text_color = imagecolorallocate($image, 0, 0, 0);
$image is uninitialized
In security_image() function:
$textbox is uninitialized
$text_color and $word is uninitialized.
And Wrong parameter count for imagettftext() You add 7 parameters, and forget the font file parameter.
found the problem. using this:
http://php.net/manual/en/function.imagettftext.php
i was able to see that the font location was incorrect. using the example on that page and editing it to my needs worked.

Resize image size according to size of text

The PHP code below generates text as a dynamically created image, how would I be able to get the image to only be as large as the text? Thanks.
<?php
header('Content-Type: image/jpeg');
$text='Test';
$img = imageCreate(200,200);
imagecolorallocate($img, 255, 255, 255);
$textColor = imagecolorallocate($img, 0, 0, 0);
imagefttext($img, 15, 0, 0, 55, $textColor, 'bgtbt.ttf', $text);
imagejpeg($img);
imagedestroy($img);
?>
UPDATE 1: I found the answer here with the example of the original poster - Creating IMage from Text in PHP - how can I make multiline?
UPDATE 2: Martin Geisler's version also works well
When using a TrueType font, you use the imageftbbox function to obtain the bounding box for a string typeset with your font. The bounding box gives the offsets from the base-point to the four corners in the rectangle occupied by the text. So if you store the bounding box in $bb and use imagefttext to put text at ($x, $y), then the corners will have these coordinates:
($x + $bb[6], $y + $bb[7]) ($x + $bb[4], $y + $bb[5])
+-------+
| Hello |
+-------+
($x + $bb[0], $y + $bb[1]) ($x + $bb[2], $y + $bb[3])
That tells us that we want an image width of ($x + $bb[2]) - ($x + $bb[6]) = $bb[2] - $bb[6] and similarly an image height of $bb[3] - $bb[7]. The text should then be rendered at coordinates (-$bb[6], -$bb[7]) inside that picture since we want to have
(0, 0) = ($x + $bb[6], $y + $bb[7]) ==> $x = -$bb[6] and $y = -$bb[7]
You can try it out with this code. Put it into a file called img.php and browse to img.php?q=Hello to test:
<?php
header("Content-type: image/png");
$q = $_REQUEST['q'];
$font = "Impact.ttf";
$size = 30;
$bbox = imageftbbox($size, 0, $font, $q);
$width = $bbox[2] - $bbox[6];
$height = $bbox[3] - $bbox[7];
$im = imagecreatetruecolor($width, $height);
$green = imagecolorallocate($im, 60, 240, 60);
imagefttext($im, $size, 0, -$bbox[6], -$bbox[7], $green, $font, $q);
imagepng($im);
imagedestroy($im);
?>
If you use the bitmap fonts instead, then look at the imagefontwidth and imagefontheight functions.
#Martin Geisler's answer is almost correct, but I couldn't get my text to fit completely inside the image. I tried this instead, which works perfectly!
From the PHP Manual's User Contributed Notes:
$text = "<?php echo \"hello, world\"; ?>";
$font = "./arial.ttf";
$size = "60";
$bbox = imagettfbbox($size, 0, $font, $text);
$width = abs($bbox[2] - $bbox[0]);
$height = abs($bbox[7] - $bbox[1]);
$image = imagecreatetruecolor($width, $height);
$bgcolor = imagecolorallocate($image, 255, 255, 255);
$color = imagecolorallocate($image, 0, 0, 0);
$x = $bbox[0] + ($width / 2) - ($bbox[4] / 2);
$y = $bbox[1] + ($height / 2) - ($bbox[5] / 2);
imagefilledrectangle($image, 0, 0, $width - 1, $height - 1, $bgcolor);
imagettftext($image, $size, 0, $x, $y, $color, $font, $text);
$last_pixel= imagecolorat($image, 0, 0);
for ($j = 0; $j < $height; $j++)
{
for ($i = 0; $i < $width; $i++)
{
if (isset($blank_left) && $i >= $blank_left)
{
break;
}
if (imagecolorat($image, $i, $j) !== $last_pixel)
{
if (!isset($blank_top))
{
$blank_top = $j;
}
$blank_left = $i;
break;
}
$last_pixel = imagecolorat($image, $i, $j);
}
}
$x -= $blank_left;
$y -= $blank_top;
imagefilledrectangle($image, 0, 0, $width - 1, $height - 1, $bgcolor);
imagettftext($image, $size, 0, $x, $y, $color, $font, $text);
header('Content-type: image/png');
imagepng($image);
imagedestroy($image);

Creating IMage from Text in PHP - how can I make multiline?

I have a script that generates images from text using PHP. It's working fine except that I would like it to generate multiline text as well with differing colors. How can it be done using PHP, GD and Freetype? Below is the code I use to generate single line text images.
$textval = 'This is some text to be an image';
$textcolor = '666666';
$font="arial.ttf";
$size = 9;
$padding= 1;
$bgcolor= "ffffff";
$transparent = 0;
$antialias = 0;
$fontfile = $fontpath.$font;
$box= imageftbbox( $size, 0, $fontfile, $textval, array());
$boxwidth= $box[4];
$boxheight= abs($box[3]) + abs($box[5]);
$width= $boxwidth + ($padding*2) + 1;
$height= $boxheight + ($padding) + 0;
$textx= $padding;
$texty= ($boxheight - abs($box[3])) + $padding;
// create the image
$png= imagecreate($width, $height);
$color = str_replace("#","",$bgcolor);
$red = hexdec(substr($bgcolor,0,2));
$green = hexdec(substr($bgcolor,2,2));
$blue = hexdec(substr($bgcolor,4,2));
$bg = imagecolorallocate($png, $red, $green, $blue);
$color = str_replace("#","",$textcolor);
$red = hexdec(substr($textcolor,0,2));
$green = hexdec(substr($textcolor,2,2));
$blue = hexdec(substr($textcolor,4,2));
$tx = imagecolorallocate($png, $red, $green, $blue);
imagettftext( $png, $size, 0, $textx, $texty, $tx, $fontfile, $textval );
header("content-type: image/jpeg");
imagejpeg($png);
imagedestroy($png);
exit;
Add this function to wrap the text before it goes into your function.
function wrap($fontSize, $angle, $fontFace, $string, $width){
$ret = "";
$arr = explode(' ', $string);
foreach ( $arr as $word ){
$teststring = $ret.' '.$word;
$testbox = imagettfbbox($fontSize, $angle, $fontFace, $teststring);
if ( $testbox[2] > $width ){
$ret.=($ret==""?"":"\n").$word;
} else {
$ret.=($ret==""?"":' ').$word;
}
}
return $ret;
}
Source: http://www.php.net/imagettftext

Categories