Forum Moderators: coopster

Message Too Old, No Replies

Font issue using GD

Is it possible to change fonts midstream?

         

IamStang

12:34 am on Oct 18, 2006 (gmt 0)

10+ Year Member



Hello everyone,

I am developing a script that places multiple lines of text on an image. The goal is to be able to set the font, font size and color for each line. Here is the code so far:

$txt = array('This is Text line 1','This is Text line 2', 'This is Text line 3');
$fntSize = array(18,14,12);
$fntHex = array('00FF00','FFFFFF','000000');
$fnt = array('arial','impact','verdana');

$a = count($txt);

$totY = 5;
$i = 0;
while ($i <= $a)
{
//insert title text
$bbox = imageftbbox($fntSize[$i], 0, $fnt[$i], $txt[$i], array("linespacing" => 1));
$width = abs($bbox[0]) + abs($bbox[2]); // distance from left to right
$height = abs($bbox[1]) + abs($bbox[5]); // distance from top to bottom
$xcoord = ($imgWidth - $width - 184) / 2;
$ycoord = $height + $totY;
$int = hexdec($fntHex[$i]);
$arr = array("red" => 0xFF & ($int >> 0x10),
"green" => 0xFF & ($int >> 0x8),
"blue" => 0xFF & $int);
$tcolor = ImageColorAllocate($background, $arr["red"], $arr["green"], $arr["blue"]);
imagettftext($background, $fntSize[$i], 0, $xcoord, $ycoord, $tcolor, $fnt[$i], $txt[$i]);
$totY = $ycoord + 5;
$i++;
}

This works great, IF I omit the $fnt array and replace it with one font. Is it possible to change fonts midstream like this? As it is, the script throws an error at the first instance of $fnt[$i].

Any and all help is always appreciated!

Thanks!
IamStang

dreamcatcher

8:02 am on Oct 18, 2006 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Hi IamStang,

Should your while loop actually be a for loop?

Try changing:
while ($i <= $a)

to:
for ($i=0; $i<$a; $i++)

The $i var has no value inside your while loop.

dc

IamStang

10:56 am on Oct 18, 2006 (gmt 0)

10+ Year Member



I will try it using the "for" method you have suggested. However ........

$i has no value inside the loop? I need an explanation please. [us3.php.net...] shows this as an example


<?php
/* example 1 */

$i = 1;
while ($i <= 10) {
echo $i++; /* the printed value would be
$i before the increment
(post-increment) */
}

/* example 2 */

$i = 1;
while ($i <= 10):
echo $i;
$i++;
endwhile;
?>

Are you saying that, in my case,

$bbox = imageftbbox($fntSize[$i], 0, $fnt[$i], $txt[$i], array("linespacing" => 1));

is actually
$bbox = imageftbbox($fntSize[], 0, $fnt[], $txt[], array("linespacing" => 1));

(basically inside the while 0 = nothing)?

This is new to me, I've done numerous while statements just like I have it in my original post with absolutely no problems.

Thanks!
IamStang

IamStang

11:20 am on Oct 18, 2006 (gmt 0)

10+ Year Member



Nope, using the "for" loop method throws the same errors as the "while" loop.

Any other ideas?

Thanks!
Stang66

eelixduppy

11:23 am on Oct 18, 2006 (gmt 0)




As it is, the script throws an error at the first instance of $fnt[$i].

Can you please share the error with us? :)

Also, are you sure that the font path is correct?

dreamcatcher

2:58 pm on Oct 18, 2006 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Yep, sorry about that, I didn`t see your increment.

dc

IamStang

9:19 pm on Oct 18, 2006 (gmt 0)

10+ Year Member



The error:

Warning: imageftbbox() [function.imageftbbox]: Could not find/open font in C:\AppServ\www\direct\test.php on line 147

Windows 2000pro running apache and php of course. Fonts are all stored in the same location. Setting the script to $fnt = 'arial'; (ommiting the array) works fine. And it will regardless of which font on my machine I set it to.

I found one site on the web where the fella was doing some sort of editorial on another coding type, cant remember what it was, but he knocked php for not being able to change fonts. That is the only place I have found on the web that has said that this cannot be done.

I also looked into the imageloadfont function - [us3.php.net...] This WILL change fonts midstream, however it uses *.gdf fonts. I can create these fonts, so that isnt a problem. But this function does not use anti-aliasing and just plain looks like crap on a plate.

Thus, I am open to suggestions.

Thanks!
IamStang

coopster

6:42 pm on Oct 19, 2006 (gmt 0)

WebmasterWorld Administrator 10+ Year Member



You should be able to use different fonts, don't see why not. Here is a relative "bounding box" discussion [webmasterworld.com] that shows how to position text. The next step is how to change the font and font sizes. I hardcoded some changes to see if the test would work and it does so yes, you can change font and font size. Perhaps the issue is that we aren't finding that TrueType Font? Adding the extension?
$font = array('arial.ttf', 'impact.ttf', 'verdana.ttf'); 

No, that didn't make a difference.

Either way, I received errors when I tried to run your script as is. It errored on this line ...

imagettftext($background, $fntSize[$i], 0, $xcoord, $ycoord, $tcolor, $fnt[$i], $txt[$i]);

... even after I added the $background variable to my scope.

eelixduppy

7:23 pm on Oct 19, 2006 (gmt 0)




The path to the TrueType font you wish to use.

Depending on which version of the GD library PHP is using, when fontfile does not begin with a leading / then .ttf will be appended to the filename and the library will attempt to search for that filename along a library-defined font path.

When using versions of the GD library lower than 2.0.18, a space character, rather than a semicolon, was used as the 'path separator' for different font files. Unintentional use of this feature will result in the warning message: Warning: Could not find/open font. For these affected versions, the only solution is moving the font to a path which does not contain spaces.

In many cases where a font resides in the same directory as the script using it the following trick will alleviate any include problems.


<?php
// Set the enviroment variable for GD
putenv('GDFONTPATH=' . realpath('.'));

// Name the font to be used (note the lack of the .ttf extension)
$font = 'SomeFont';
?>


[us2.php.net...]

This may shed some light on this problem.

Good luck!

IamStang

11:15 pm on Oct 19, 2006 (gmt 0)

10+ Year Member



coopster

Thanks for the link and for taking the time to look at this issue!

eelixduppy

I tried your suggestion and still get the same errors. Here is my code in full if anyone cares to try to figure it out.

<?php
Header("Content-type: image/png");
//

$fontpath = realpath('./fonts/');
putenv('GDFONTPATH='.$fontpath);

$imgHgt = 100;
$imgWidth= 400;
$imgColorHex="487239";

$txt = array('This is Text line 1','This is Text line 2','This is Text line 3','This is Text line 4');
$fntSize = array(18,14,12,10);
$fntHex = array('00FF00','FFFFFF','000000','00FF00');
$fntShad = array(1,0,0,0);
$fnt = array('./arial','./impact','./arial','./impact'); //THIS DOESNT WORK
$font = "arial"; //THIS WORKS

$background = @imagecreate($imgWidth, $imgHgt) or die("Cannot Initialize new GD image stream");
$background_color = imagecolorallocate($background, 0, 0, 254);

$t = count($txt);
$totY = 5;
$i = 0;
while ($i <= $t)
{
//insert title text
if($fntShad[$i] == 1)
{
//THE FOLLOWING LINE WORKS
//$bbox = imageftbbox($fntSize[$i], 0, $font, $txt[$i], array("linespacing" => 1));
//END LINE WORKS

$bbox = imageftbbox($fntSize[$i], 0, $fnt[$i], $txt[$i], array("linespacing" => 1));
$width = abs($bbox[0]) + abs($bbox[2]); // distance from left to right
$height = abs($bbox[1]) + abs($bbox[5]); // distance from top to bottom
$xcoord = (($imgWidth - $width) / 2) + 2;
$ycoord = $height + $totY + 2;
$int = hexdec("000000");
$arr = array("red" => 0xFF & ($int >> 0x10),
"green" => 0xFF & ($int >> 0x8),
"blue" => 0xFF & $int);
$tcolor = ImageColorAllocate($background, $arr["red"], $arr["green"], $arr["blue"]);

//THE FOLLOWING LINE WORKS
//imagettftext($background, $fntSize[$i], 0, $xcoord, $ycoord, $tcolor, $font, $txt[$i]);
//END WORKS

imagettftext($background, $fntSize[$i], 0, $xcoord, $ycoord, $tcolor, $fnt[$i], $txt[$i]);
$totY = $ycoord + 5;
$i++;
}
else
{
//THE FOLLOWING LINE WORKS
//$bbox = imageftbbox($fntSize[$i], 0, $font, $txt[$i], array("linespacing" => 1));
//END LINE WORKS

$bbox = imageftbbox($fntSize[$i], 0, $fnt[$i], $txt[$i], array("linespacing" => 1));
$width = abs($bbox[0]) + abs($bbox[2]); // distance from left to right
$height = abs($bbox[1]) + abs($bbox[5]); // distance from top to bottom
$xcoord = ($imgWidth - $width) / 2;
$ycoord = $height + $totY;
$int = hexdec($fntHex[$i]);
$arr = array("red" => 0xFF & ($int >> 0x10),
"green" => 0xFF & ($int >> 0x8),
"blue" => 0xFF & $int);
$tcolor = ImageColorAllocate($background, $arr["red"], $arr["green"], $arr["blue"]);

//THE FOLLOWING LINE WORKS
//imagettftext($background, $fntSize[$i], 0, $xcoord, $ycoord, $tcolor, $font, $txt[$i]);
//END WORKS

imagettftext($background, $fntSize[$i], 0, $xcoord, $ycoord, $tcolor, $fnt[$i], $txt[$i]);
$totY = $ycoord + 5;
$i++;
}
}
imagepng($background);
ImageDestroy($background);
?>

Good Luck! (cause I'm not having any)

EDIT:
(NOTE: I used the IF statement to see if the script was atleast attempting to use the first font.)

[edited by: IamStang at 11:26 pm (utc) on Oct. 19, 2006]

eelixduppy

3:34 am on Oct 20, 2006 (gmt 0)



The following works PERFECTLY for me. There must be something wrong with your font location.



<?php
header("Content-type: image/png");

$imgHgt = 100;
$imgWidth= 400;
$imgColorHex="487239";

$txt = array('This is Text line 1','This is Text line 2','This is Text line 3','This is Text line 4');
$fntSize = array(18,14,12,10);
$fntHex = array('00FF00','FFFFFF','000000','00FF00');
$fntShad = array(1,0,0,0);
$fnt = array('arial','impact','arial','impact');
$font = "arial";

$background = @imagecreate($imgWidth, $imgHgt) or die("Cannot Initialize new GD image stream");
$background_color = imagecolorallocate($background, 0, 0, 254);

$t = count($txt);
$totY = 5;
$i = 0;
while ($i < $t)
{

if($fntShad[$i] == 1)
{
$bbox = imageftbbox($fntSize[$i], 0, $fnt[$i], $txt[$i], array("linespacing" => 1));
$width = abs($bbox[0]) + abs($bbox[2]);
$height = abs($bbox) + abs($bbox[5]);
$xcoord = (($imgWidth - $width) / 2) + 2;
$ycoord = $height + $totY + 2;
$int = hexdec("000000");
$arr = array("red" => 0xFF & ($int >> 0x10),
"green" => 0xFF & ($int >> 0x8),
"blue" => 0xFF & $int);
$tcolor = ImageColorAllocate($background, $arr["red"], $arr["green"], $arr["blue"]);

imagettftext($background, $fntSize[$i], 0, $xcoord, $ycoord, $tcolor, $fnt[$i], $txt[$i]);
$totY = $ycoord + 5;
$i++;
}
else
{

$bbox = imageftbbox($fntSize[$i], 0, $fnt[$i], $txt[$i], array("linespacing" => 1));
$width = abs($bbox[0]) + abs($bbox[2]);
$height = abs($bbox[1]) + abs($bbox[5]);
$xcoord = (($imgWidth - $width) / 2) + 2;
$ycoord = $height + $totY + 2;
$int = hexdec($fntHex[$i]);
$arr = array("red" => 0xFF & ($int >> 0x10),
"green" => 0xFF & ($int >> 0x8),
"blue" => 0xFF & $int);
$tcolor = ImageColorAllocate($background, $arr["red"], $arr["green"], $arr["blue"]);

imagettftext($background, $fntSize[$i], 0, $xcoord, $ycoord, $tcolor, $fnt[$i], $txt[$i]);
$totY = $ycoord + 5;
$i++;
}
}
imagepng($background);
ImageDestroy($background);
?>

IamStang

11:51 am on Oct 20, 2006 (gmt 0)

10+ Year Member



Thanks for the confirmation! I will investigate it later tonight.

I'm on a windows machine so I will see if there is some problem caused by that first. Then go from there.

Thanks again!

eelixduppy

1:22 pm on Oct 20, 2006 (gmt 0)




I'm on a windows machine so I will see if there is some problem caused by that first.

I tested it on my windows machine, and it works fine ;)

Best of luck!

IamStang

11:00 pm on Oct 20, 2006 (gmt 0)

10+ Year Member



What the H%#@! It is working fine here now as well.

I must have changed something inadvertantly that corrected the issue. LOL. Now I will have to figure out what it was or it will bug me to no end.

Thanks everyone for the help!

IamStang

12:18 pm on Oct 21, 2006 (gmt 0)

10+ Year Member



OK, I figured out what I was doing wrong on my machine. Man, I feel like such an idiot too.

When I posted the script here, I changed the fonts in the script to 2 that I felt most everyone had, arial and impact. Prior to that I was using 4 different ones from my collection.

However, the name you see in the font folder on a Windows machine is not the actual file name of the font. The file name is in the next column (on my machine).

EX: "Comic Sans MS Bold". The actual filename is "comicbd.ttf".

Thanks again everyone!
IamStang

Once I realized this, it works flawlessly for any font I use. Even though I feel like such an idiot and find it really embarrassing, I decided to post this so that some other individual might not have to go through all of this in the future.

Somebody smack me!

eelixduppy

2:49 pm on Oct 21, 2006 (gmt 0)



Glad you got it ;)