imagettftext and arabic language: how can I write in RTL mode? - php

I need to write in RTL mode to imagettftext, 'caus arabic language is in this way: and I don't mean to revert the letters, I mean a css-like RTL (direction:rtl), so aligned-flag on the right... how can I?
My easy code:
require('static/I18N/Arabic.php');
$Arabic = new I18N_Arabic('Glyphs');
$font="static/ArabicModern-Light.ttf";
$testo=$Arabic->utf8Glyphs($testo);
imagettftext($im, 26, 0, 560, 345, $textcolor, $font, "\"".$testo."\"");
Thanks!

After eventually finding and downloading Ar-PHP 4.0 I've updated this answer to use Arabic. Since I don't understand Arabic I've used the text 'العَرَبِيَّة' from the Arabic Wikipedia page.
Source:
<?php
require_once('./Arabic.php');
$iw = 300; // image width.
$ih = 150; // image height.
$size = 40;
$angle = 0;
$font = 'arial';
$text = 'العَرَبِيَّة';
$obj = new I18N_Arabic('Glyphs');
$text = $obj->utf8Glyphs($text);
$box = imagettfbbox($size, $angle, $font, $text);
$tw = abs($box[6] - $box[4]); // text width.
$th = abs($box[7] - $box[1]); // text height.
$im = imagecreatetruecolor($iw, $ih);
imagefill($im, 0, 0, 0x00c0c0c0); // set a grey background.
// left aligned.
imagettftext($im, $size, $angle, 0, $th, 0x00000000, $font, $text);
// centre aligned.
imagettftext($im, $size, $angle, ($iw / 2) - ($tw / 2), $th * 2, 0x00000000, $font, $text);
// right aligned.
imagettftext($im, $size, $angle, $iw - $tw, $th * 3, 0x00000000, $font, $text);
header('Content-Type: image/png');
imagepng($im);
imagedestroy($im);
Result (generated with PHP 7.1):
Reference image from Wikipedia:
Edit: Below is a comparison of the first five lines from the text you linked to in your comment, run through the code I wrote above (obviously with some minor changes to handle multiple lines):
Your original image (cropped) on the left, my generated image on the right.
Aside from not aligning correctly it's a match.

Related

imagettfbbox calculates wrong rectangle when text begins with number

The issue is, that when using imagettfbbox to calculate text dimensions, too small rectangle is returned when input text begins with numbers. This is my code:
$fontSize = 150;
$font = "font/courier_new.ttf";
$text = $_GET["text"];
//Determine font dimensions
$bbox = imagettfbbox($fontSize, 0, $font, $text);
$bbox["width"]= abs($bbox[4]-$bbox[0]);
$bbox["height"]= abs($bbox[5]-$bbox[1]);
$im = imagecreatetruecolor($bbox["width"], $bbox["height"]);
echo "<b>Image size:</b>\n";
print_r($bbox);
// This part makes transparent background
imagesavealpha($im, true);
$bg = imagecolorallocatealpha($im, 254, 254, 254,127);
$text_color= imagecolorallocate($im, 0, 0, 0);
imagealphablending($im, false);
imagefilledrectangle($im, 0, 0, imagesx($im), imagesy($im), $bg );
imagealphablending($im, true);
header("X-Img-Size: ".$bbox["width"]."x".$bbox["height"]."");
imagettftext($im, $fontSize, 0, 0, $bbox["height"], $text_color, $font, $text);
// This is output
header("Content-Type: text/html");
ob_start();
imagepng($im);
$image_data = ob_get_contents();
ob_end_clean();
imagedestroy($im);
echo "<img src=\"data:image/png;base64,".base64_encode($image_data)."\" />";
Online test here
These are results I get for different input text:
How can I fix that?
The problem was caused by misconception. The values of imagettfbbox also define where do you have to start drawing - and often those coordinates are even negative. I always assumed you can start at [0, 0] coordinates. That is not true, drawing coordinates can be negative.
This function, also mentioned in comments and originating from PHP.net user contributions calculates the start coordinates, as well as the width and height (which was correct in the code in question).
// Source: http://php.net/manual/en/function.imagettfbbox.php#75407
function imagettfbboxextended($size, $angle, $fontfile, $text) {
/*this function extends imagettfbbox and includes within the returned array
the actual text width and height as well as the x and y coordinates the
text should be drawn from to render correctly. This currently only works
for an angle of zero and corrects the issue of hanging letters e.g. jpqg*/
$bbox = imagettfbbox($size, $angle, $fontfile, $text);
//calculate x baseline
if($bbox[0] >= -1) {
$bbox['x'] = abs($bbox[0] + 1) * -1;
} else {
//$bbox['x'] = 0;
$bbox['x'] = abs($bbox[0] + 2);
}
//calculate actual text width
$bbox['width'] = abs($bbox[2] - $bbox[0]);
if($bbox[0] < -1) {
$bbox['width'] = abs($bbox[2]) + abs($bbox[0]) - 1;
}
//calculate y baseline
$bbox['y'] = abs($bbox[5] + 1);
//calculate actual text height
$bbox['height'] = abs($bbox[7]) - abs($bbox[1]);
if($bbox[3] > 0) {
$bbox['height'] = abs($bbox[7] - $bbox[1]) - 1;
}
return $bbox;
}
But it is imperative that you use x and y coordinates given by this function when drawing:
imagettftext($im, $fontSize, 0, $bbox["x"], $bbox["y"], $text_color, $font, $text);

How to account for font swash with PHP and GD

I have the following code to print text on an image. I am also adding a debug box around the text. However, I noticed the text on the left lies outside of the box that PHP gives me with imagettfbbox.
This looks like an issue with the font swash. Is there anyway to account for this? Can I figure out the distance between the start of the swash and the actual position imagettfbbox gives to me?
I don't think this is an issue with the font, as I tried it with a few script style fonts and the results were similar.
<?php
$font = 'scriptin.ttf';
$text = 'Ipsum';
$size = 30;
$image = imagecreatetruecolor(200, 200);
$fontColour = imagecolorallocate($image, hexdec('11'), hexdec('11'), hexdec('11'));
$bgColour = imagecolorallocate($image, hexdec('CC'), hexdec('CC'), hexdec('CC'));
imagefilledrectangle($image, 0, 0, 200, 200, $bgColour);
$dimensions = imagettfbbox($size, 0, $font, $text);
imagefilledrectangle(
$image,
$dimensions[0] + 40,
$dimensions[7] + 50,
$dimensions[2] + 40,
$dimensions[3] + 50,
imagecolorallocate($image, mt_rand(1, 180), mt_rand(1, 180), mt_rand(1, 180))
);
imagettftext(
$image,
$size,
0,
40,
50,
$fontColour,
$font,
$text
);
header('Content-Type: image/png');
imagepng($image);
The code and font is available here: https://github.com/AydinHassan/image-swash-example
If you point a VHOST at the repository, you can just hit swash.php
Edit: This appears to be fixed in PHP 7.0.12 (bug #53504) so the code below shouldn't be required.
Based on a comment in the PHP manual I've written the following function to calculate and return the difference between where GD thinks the left side of the bounding box is and where the leftmost pixel is found:
function xadjust($size, $angle, $fontfile, $text)
{
$bbox = imagettfbbox($size, $angle, $fontfile, $text);
$width = $bbox[4] - $bbox[6]; // upper right x - upper left x;
$height = $bbox[1] - $bbox[7]; // lower left y - upper left y;
// create an image with height and width doubled to fit any 'swash'.
$im = imagecreatetruecolor($width * 2, $height * 2);
// set background color to opaque black.
imagefill($im, 0, 0, 0x00000000);
// draw the text in opaque white.
imagettftext(
$im,
$size,
0,
$width / 2,
$height,
0x00ffffff,
$fontfile,
$text
);
// set the min-width to its possible maximum.
$min_x = $width * 2;
for ($x = 0; $x < $width * 2; $x++) {
// each x-pixel (horizontal)
for ($y = 0; $y < $height * 2; $y++) {
// each y-pixel (vertical)
if (imagecolorat($im, $x, $y) > 0) {
// non-black pixel found!
$min_x = min($x, $min_x);
}
}
}
imagedestroy($im);
// return the difference between where GD thinks the bounding box is and
// where we found the leftmost non-black pixel.
return (($width / 2) - $min_x) - abs($bbox[0]);
}
This can be integrated to your script fairly easily:
$font = 'scriptin.ttf';
$text = 'Ipsum';
$size = 30;
$image = imagecreatetruecolor(200, 200);
$fontColour = imagecolorallocate($image, hexdec('11'), hexdec('11'), hexdec('11'));
$bgColour = imagecolorallocate($image, hexdec('CC'), hexdec('CC'), hexdec('CC'));
imagefilledrectangle($image, 0, 0, 200, 200, $bgColour);
$xadjust = xadjust($size, 0, $font, $text); // 1. get the adjust value.
$dimensions = imagettfbbox($size, 0, $font, $text);
imagefilledrectangle(
$image,
$dimensions[0] + 40 - $xadjust, // 2. move the left-side of the box to the left.
$dimensions[7] + 50,
$dimensions[2] + 40 - $xadjust, // 3. move the right-side of the box to the left.
$dimensions[3] + 50,
imagecolorallocate($image, mt_rand(1, 180), mt_rand(1, 180), mt_rand(1, 180))
);
imagettftext(
$image,
$size,
0,
40,
50,
$fontColour,
$font,
$text
);
header('Content-Type: image/png');
imagepng($image);
This gives me the following output:
I've run it with a few other fonts and sizes and it seems to be accurate to within 1 pixel.

Add Dynamic Text to images using GD Library or any other plugin in PHP

I want to make an app where user can see their meaning of name. I am done with the php part its just I am stuck how to output it to good looking image. I have used PHP image magician library before. But I am still not able to get it in the format I wanted.
Any help will be useful.
CHECK the image format below
https://fbexternal-a.akamaihd.net/safe_image.php?d=AQDPCj8lZUELWsXD&w=470&h=246&url=http%3A%2F%2Fs3.alegra.me%2Fname%2Fnombre.php%3Fnombre%3Djayanta&cfs=1&upscale
$im = imagecreatefromjpeg('xc7ci4ptuxmgy3nd0brz.jpg');
$font="tahoma.ttf";
$red = imagecolorallocate($im, 255,0,0);
$string="JAYANTA";
$last_string= substr( $string, 1 );
$temp_x = 105;
$down_string[0]="JUST";
$down_string[1]="AMUSING";
$down_string[2]="YOUNG";
$down_string[3]="AMUSING";
$down_string[4]="NICE";
$down_string[5]="TOUGH";
$down_string[6]="AMUSING";
$bbox = imagefttext($im, 80, 0,90, 190, $red, $font, $string);
$temp_y=205; //y cord. of $down_string
for($x=1;$x < count($down_string);$x++){
for($y=0;$y < count($down_string);$y++){
$bbox = imagefttext($im, 12, 0, $temp_x, $temp_y, $red, $font, $down_string[$y][$x]);
$temp_x += 56+$y*1.8;
}
$temp_x = 105;
$temp_y+=15;
}
header('Content-type: image/png');
imagepng($im);
imagedestroy($im);
As you can see, ther is a lot of problems, but the solution is in the imagefttext function.

How we can change the font opacity and shadowing in imagettftext function?

I am creating a Text-Image on given template in which all parameter are dynamic,Its working fine! and creating image like,my php script is,
<?php
// To fetch template info from database
$template_query = mysql_query("SELECT * FROM templates WHERE templateID = '".$fetch['templateID']."'");
$temp_data = mysql_fetch_assoc($template_query);
//create and save images
$temp = '../'. $temp_data['blank_templates'];
//check image type
$image_extension = strtolower(substr(strrchr($temp_data['blank_templates'], "."), 1));
$im = imagecreatefromjpeg($temp);
$black = hexdec($temp_data['font_color']);
// Replacing path by your own font path
$font = '..'.$temp_data['font_file_upload'];
// Break it up into pieces 125 characters long
$no_of_characters_line = $temp_data['no_of_characters_line'];
$lines = explode('|', wordwrap($message, $no_of_characters_line, '|'));
// Starting Y position and X position
$y = $temp_data['position_from_top'];
$x = $temp_data['position_from_left'];
$font_size = $temp_data['font_size'];
$rotation_angle = $temp_data['rotation'];
$line_height = $temp_data['line_height'];
foreach ($lines as $line)
{
imagettftext($im, $font_size,$rotation_angle, $x, $y, $black, $font, $line);
// Increment Y so the next line is below the previous line
$y += $line_height;
}
$id = uniqid();
$save = '../messagesimage/'.$id. '.'.$image_extension;
$path_save = substr($save, 3);
// Using imagepng() results in clearer text compared with imagejpeg()
imagejpeg($im,$save);
imagedestroy($im);
Which is creating image like..!
Now I want to add the ability to change font opacity and shadowing dynamically,Is it possible ? If yes then please help me to do this ..
Thanks in Advance
Wow, you've been waiting a while.
To give your text some transparency, you'll need to define your text color with an alpha channel.
$black = imageallocatecoloralpha(0,0,0,16);
To give your text some shadow
$shadow = imageallocatecoloralpha(0,0,0,64); // more transparent
imagettftext($im, $font_size,$rotation_angle, $x+1, $y+1, $shadow, $font, $line);
imagettftext($im, $font_size,$rotation_angle, $x, $y, $black, $font, $line);
Even later, but it seems the current answer is incorrect.
To define a color with transparency, you use the function imagecolorallocatealpha():
$black = imagecolorallocatealpha($image, 0, 0, 0, 50);
Shadows, like Michael pointed out, are quite simple(Just use the correct function name, and make sure you add the image object). However, if you want a more shadowy looking shadow, blur it a bit:
$shadow = imagecolorallocatealpha($im, 0, 0, 0, 50);
//Draw shadow text
imagettftext($im, $font_size, 0, $x, $y, $shadow, $fontn, $text);
//Blur
imagefilter($im, IMG_FILTER_GAUSSIAN_BLUR);
//Draw text
imagettftext($im, $font_size, 0, $x, $y, $white, $fontn, $text);
After applying the above shadow method to an image, it renders similar to this:

Create White Box around Text GD-Lib

i want to add a white box around some text i add to an image via GD-Lib.
but i don't know how to do this best.
Here is my current code:
<?php
$textImg = imagecreatefromjpeg($tempImage);
$black = imagecolorallocate($textImg, 0, 0, 0);
$font = 'lib/verdana.ttf';
// Add the text
imagettftext($textImg, 20, 0, imagesx($textImg)*$textData['x']/100, imagesy($textImg)*$textData['y']/100, $black, $font, $textData['text']);
imagejpeg($textImg,$tempImage,$jpegQuality);
?>
I hope you can help me out.
You can use imagettfbbox() to get the coordinates of the bounding box by passing the same settings you use for the text itself (same text, font and size etc).
Once you have these coordinates you can use imagerectangle() to draw a border around the text, or you can use imagefilledrectangle() to draw a solid rectangle. Be sure to call it before you render the text with imagettftext()
A basic example is below but will need some tweaking as most of it is from memory and I suspect the $x and $y calculation could be done better as it probably doesn't work with varying canvas sizes as it is now. However, it demonstrates the principle.
// Set the content-type
header('Content-Type: image/png');
// Create the image
$im = imagecreatetruecolor(400, 30);
// Create some colors
$white = imagecolorallocate($im, 255, 255, 255);
$black = imagecolorallocate($im, 0, 0, 0);
imagefilledrectangle($im, 0, 0, 399, 29, $black);
// The text to draw
$text = 'Testing';
// Replace path by your own font path
$font = 'verdana.ttf';
// Add the text
$bbox = imagettfbbox(20, 0, $font, $text);
$x = $bbox[1] + (imagesx($im) / 2) - ($bbox[4]);
$y = $bbox[3] + (imagesy($im) / 2) - ($bbox[5]);
imagerectangle($im, 0, 0, $x, $y, $white);
imagettftext($im, 20, 0, 0, 20, $white, $font, $text);
// Using imagepng() results in clearer text compared with imagejpeg()
imagejpeg($im);
imagedestroy($im);

Categories