...

View Full Version : Generating the gradiented TXT with imagettftext, can't make it look smooth



Sandrix
07-20-2008, 05:09 PM
Hi guys, I've coded a simple script that makes you able to generate a text using any true type font you want. the result is PNG24 image. It's really useful when you need to dynamically generate a menu item or something on your website...

code:


<?
header("content-type: image/png");
/*
if (file_exists("_cache_img/".$_GET['text'].".png"))
{
echo file_get_contents("_cache_img/".$_GET['text'].".png");
die();
}
*/
if(!isset($_GET['size'])) { $_GET['size'] = 10; }
if(!isset($_GET['text'])) { $_GET['text'] = "GENERATED IMAGE"; }
if(!isset($_GET['font'])) { $_GET['font'] = "Sanet.ttf"; } //key sensitive
if(!isset($_GET['color'])) { $_GET['color'] = '#000000'; }
if(!isset($_GET['contur'])) { $_GET['contur'] = "#252423"; }
$size = imagettfbbox($_GET['size'], 0, $_GET['font'], $_GET['text']);

$cont = html2rgb($_GET['contur']);
$color_array = html2rgb($_GET['color']);


$xsize = abs($size[0]) + abs($size[2]) + 1; // + 1 ar moashoro! achris mere da bolo asos enzreva.
$ysize = abs($size[5]) + abs($size[1]);

$image = imagecreate($xsize, $ysize);



// transparent

// imageSaveAlpha($image, true);
// ImageAlphaBlending($image, true);

//imagecolorallocate($image, $cont[0], $cont[1], $cont[2]);
imagecolorallocatealpha($image, $cont[0], $cont[1], $cont[2], 127);
//imagefill($image, 0, 0, $transparentColor);




// end transparent

function html2rgb($color)
{
if ($color[0] == '#')
$color = substr($color, 1);

if (strlen($color) == 6)
list($r, $g, $b) = array($color[0].$color[1],
$color[2].$color[3],
$color[4].$color[5]);
elseif (strlen($color) == 3)
list($r, $g, $b) = array($color[0].$color[0], $color[1].$color[1], $color[2].$color[2]);
else
return false;

$r = hexdec($r); $g = hexdec($g); $b = hexdec($b);

return array($r, $g, $b);
}







$color = ImageColorAllocate($image, $color_array[0],$color_array[1],$color_array[2]);

imagettftext($image, $_GET['size'], 0, abs($size[0]), abs($size[5]), $color, $_GET['font'], $_GET['text']);




imagepng($image);

imagedestroy($image);

?>

Usage:


<img src="font.php?size=40&font=ARIAL.TTF&text=BlahBlah&color=FF0000&contur=CCCCCC" />


Ok, it's really simple and result looks great.

No I'm trying to add a gradient effect to the text so I did something like:


<?
header("content-type: image/png");
/*
if (file_exists("_cache_img/".$_GET['text'].".png"))
{
echo file_get_contents("_cache_img/".$_GET['text'].".png");
die();
}
*/
if(!isset($_GET['size'])) { $_GET['size'] = 10; }
if(!isset($_GET['text'])) { $_GET['text'] = "GENERATED IMAGE"; }
if(!isset($_GET['font'])) { $_GET['font'] = "Sanet.ttf"; } //key sensitive
if(!isset($_GET['color'])) { $_GET['color'] = '#000000'; }
if(!isset($_GET['contur'])) { $_GET['contur'] = "#252423"; }
$size = imagettfbbox($_GET['size'], 0, $_GET['font'], $_GET['text']);

$cont = html2rgb($_GET['contur']);
$color_array = html2rgb($_GET['color']);


$xsize = abs($size[0]) + abs($size[2]) + 1; // + 1 ar moashoro! achris mere da bolo asos enzreva.
$ysize = abs($size[5]) + abs($size[1]);

$image = imagecreate($xsize, $ysize);



// transparent

// imageSaveAlpha($image, true);
// ImageAlphaBlending($image, true);

//imagecolorallocate($image, $cont[0], $cont[1], $cont[2]);
imagecolorallocatealpha($image, $cont[0], $cont[1], $cont[2], 127);
//imagefill($image, 0, 0, $transparentColor);




// end transparent

function html2rgb($color)
{
if ($color[0] == '#')
$color = substr($color, 1);

if (strlen($color) == 6)
list($r, $g, $b) = array($color[0].$color[1],
$color[2].$color[3],
$color[4].$color[5]);
elseif (strlen($color) == 3)
list($r, $g, $b) = array($color[0].$color[0], $color[1].$color[1], $color[2].$color[2]);
else
return false;

$r = hexdec($r); $g = hexdec($g); $b = hexdec($b);

return array($r, $g, $b);
}







$color = ImageColorAllocate($image, $color_array[0],$color_array[1],$color_array[2]);

imagettftext($image, $_GET['size'], 0, abs($size[0]), abs($size[5]), $color, $_GET['font'], $_GET['text']);


// imagepng($image,"_cache_img/".$_GET['text'].".png");
// imagepng($image);
// imagedestroy($image);


//GET TYPE (THAT USER WANTS)
$type = @$_GET['type'];
if ($type == false) {
$type = 'top';
}

//GET DIMENTIONS (THAT USER WANTS)
$height = intval($ysize);
if ($height == 0) {
$height = 50;
}
$width = intval($xsize);
if ($width == 0) {
$width = 100;
}

//GET HEX COLOURS (THAT USER WANTS)
$start_colour = $_GET['start_colour'];
if ($start_colour == false) {
$start_colour = 'FF0000';
}
$end_colour = $_GET['end_colour'];
if ($end_colour == false) {
$end_colour = '000000';
}

//CONVERT HEX COLOURS TO RGB
$hex_r = substr($start_colour, 0, 2);
$hex_g = substr($start_colour, 2, 2);
$hex_b = substr($start_colour, 4, 2);

$start_r = hexdec($hex_r);
$start_g = hexdec($hex_g);
$start_b = hexdec($hex_b);

$hex_r = substr($end_colour, 0, 2);
$hex_g = substr($end_colour, 2, 2);
$hex_b = substr($end_colour, 4, 2);

$end_r = hexdec($hex_r);
$end_g = hexdec($hex_g);
$end_b = hexdec($hex_b);



if ($type == 'top') {


//LOOP THROUGH ALL THE PIXELS
for($y = 0; $y < $height; $y++) {

//LOOP THROUGH ROW
for($x=0; $x < $width; $x++) {


//CALCULATE THIS ROWS RGB COLOURS

if ($start_r == $end_r) {
$new_r = $start_r;
}
$difference = $start_r - $end_r;
$new_r = $start_r - intval(($difference / $height) * $y);

//====

if ($start_g == $end_g) {
$new_g = $start_g;
}
$difference = $start_g - $end_g;
$new_g = $start_g - intval(($difference / $height) * $y);

//===

if ($start_b == $end_b) {
$new_b = $start_b;
}
$difference = $start_b - $end_b;
$new_b = $start_b - intval(($difference / $height) * $y);

//===

//ALLOCATE THE COLOR
$row_color = imagecolorresolve($image, $new_r, $new_g, $new_b);

//CREATE ROW OF THIS COLOR

$col = imagecolorat ($image, $x, $y);
$col = imagecolorsforindex ($image, $col);

$col_text['red'] = $color_array[0];
$col_text['green'] = $color_array[1];
$col_text['blue'] = $color_array[1];
$col_text['alpha'] = 0;

$col2 = imagecolorat($image, $x, $y);
$col2 = imagecolorsforindex($image, $col2);

$col_text2['red'] = $new_r;
$col_text2['green'] = $new_g;
$col_text2['blue'] = $new_b;
$col_text2['alpha'] = 0;




// print_r($col); echo "<br>"; print_r($col_text); echo "<br><br>";

if($col_text == $col) {
imagesetpixel($image, $x, $y, $row_color);

}

$newblue = imagecolorclosest($image, $cont[0], $cont[1], $cont[2]);

//imagesetpixel($image, $x, $y, $row_color);

}

}

}


/*
if ($type == 'left') {

//LOOP THROUGH ALL THE PIXELS
for($x = 0; $x < $width; $x++) {

//LOOP THROUGH COLUMN
for($y=0; $y < $height; $y++) {

//CALCULATE THIS ROWS RGB COLOURS

if ($start_r == $end_r) {
$new_r = $start_r;
}
$difference = $start_r - $end_r;
$new_r = $start_r - intval(($difference / $width) * $x);

//====

if ($start_g == $end_g) {
$new_g = $start_g;
}
$difference = $start_g - $end_g;
$new_g = $start_g - intval(($difference / $width) * $x);

//===

if ($start_b == $end_b) {
$new_b = $start_b;
}
$difference = $start_b - $end_b;
$new_b = $start_b - intval(($difference / $width) * $x);

//===

//ALLOCATE THE COLOR
$row_color = imagecolorresolvealpha($image, $new_r, $new_g, $new_b, 127);

//CREATE ROW OF THIS COLOR
imagesetpixel($image, $x, $y, $row_color);

}

}

}
*/

imagepng($image);

imagedestroy($image);

?>

The Problem is that I can't make it look smoother.. result is really crappy. I know that the code is messy but test it and you'll know what I meant.

Sorry for my english.
Help is really appreciated.

p4plus2
07-20-2008, 07:01 PM
Can we see a sample output? It may help diagnose the problem a bit better.

Sandrix
07-20-2008, 07:09 PM
Can we see a sample output? It may help diagnose the problem a bit better.

Sure,



I still don't get how you're going to diagnose the code without testing it on server but here's the screen

http://img230.imageshack.us/img230/726/samplebu1.png

thanks

p4plus2
07-20-2008, 07:21 PM
Well, based on what I see there it is the worst on letters with major curves such as the 'S'. I am not sure how fixable it...This is a problem most programs(eg. paint) have. Straight lines are simple and clear but the moment you add a curve its goes whack....I will see what I can do though and get back to you, but there are no guarantees.

Fou-Lu
07-20-2008, 07:42 PM
I'm the furthest thing from a graphics artist, but I'll give my two cents anyway.
I think that what you are getting is simply because of the font size. The glyph thats in use is a bitmap type instead of a vector type font, so when you increases its font size it does so by magnifying the blocks within it instead of recalculating the differences between the vector's points. Like I said though, I'm not an artist and can't be sure if this is the problem.

Looks great to me though, I wouldn't worry about a little pixelization!


I lied. According to this article: http://computer.howstuffworks.com/question460.htm, ttf files are vector based not bitmap based. Methinks that may be as clears as you'll get it to be. Like I said, looks good for a dynamic image.

p4plus2
07-20-2008, 08:12 PM
I am sorry to say I did not find any problems in your source, or a fix for that matter. I recommend sticking with a more "block like" font. It should come out much more smooth.

oesxyl
07-20-2008, 08:17 PM
I'm the furthest thing from a graphics artist, but I'll give my two cents anyway.
I think that what you are getting is simply because of the font size. The glyph thats in use is a bitmap type instead of a vector type font, so when you increases its font size it does so by magnifying the blocks within it instead of recalculating the differences between the vector's points. Like I said though, I'm not an artist and can't be sure if this is the problem.

Looks great to me though, I wouldn't worry about a little pixelization!


I lied. According to this article: http://computer.howstuffworks.com/question460.htm, ttf files are vector based not bitmap based. Methinks that may be as clears as you'll get it to be. Like I said, looks good for a dynamic image.

yes, ttf is vector font, :) but, in my opinion, you are correct because the script work with raster format, :)
also that's half of the problem, I guess, the other half is numeric aproximation, :).

regards

Sandrix
07-21-2008, 07:50 AM
Well the problem occurs only in gradient version.. So I don't think that it's because of size or because of font type. here's the output without the gradient & it looks great:

http://img521.imageshack.us/img521/484/sample2uo8.png

p4plus2
07-21-2008, 02:58 PM
remove color(set it transparent...or something), then try the script again...or add the white border to the other image for same results

Sandrix
07-21-2008, 04:35 PM
You can't set the color to transparent and/or remove the actual color it's is need for script to work...
I don't need an advice about how-to change the values of my own variables... I need a logical solution.

anyone?

p4plus2
07-21-2008, 10:09 PM
can you add 1 more pixel to the white border then? that may make it a little bit better.

Sandrix
07-22-2008, 04:26 PM
Unfortunately I can't... Cuz The that's not exactly a white color, it has an alpha blending value witch is set by imagecolorallocatealpha() function... I can't interact with it.

Problem is not phisical, it's logical.

oesxyl
07-22-2008, 04:39 PM
Unfortunately I can't... Cuz The that's not exactly a white color, it has an alpha blending value witch is set by imagecolorallocatealpha() function... I can't interact with it.

Problem is not phisical, it's logical.
why you can't interact with it? what do you mean when you say "logical"?

regards

Sandrix
07-23-2008, 10:59 AM
I can't interact with it cuz it works by it self I can only run it when I want.

I mean that I'm using the wrong method:



if($col_text == $col) {
imagesetpixel($image, $x, $y, $row_color);

}

$newblue = imagecolorclosest($image, $cont[0], $cont[1], $cont[2]);


the problem is here, I can't determine the exact solid color of the text and replace it with gradient. Because some of the pixels are using the alpha blending value. I can't add a gradient to them. I need a code snippet.

oesxyl
07-23-2008, 01:17 PM
apply same method to a pictures 2-3 times bigger then you need and rescale after.

regards

Sandrix
07-25-2008, 08:56 AM
Could you please drop the code snippet? cuz I already tried before to do that but without any results.

oesxyl
07-25-2008, 10:21 AM
the idea is:


$scalefactor = 3;
$xsize = $scalefactor *(abs($size[0]) + abs($size[2]) + 1); // + 1 ar moashoro! achris mere da bolo asos enzreva.
$ysize = $scalefactor * (abs($size[5]) + abs($size[1]));


and after you draw everything, rescale back to $xsize and $ysize.
The problem is that the original script you start with is very poor coded.


Could you please drop the code snippet? cuz I already tried before to do that but without any results.
I'm sorry but I don't do that. I rewrite this script few times and I hate it. Once time I rewrite it for somebody on this forum, somewhere between dec. 2007 and mar./apr.2008, so if you are lucky you can find it. I just search for it but I fail.
Even I could pass over that I have a lot of work for my own and this take some time.

regards

Sandrix
07-27-2008, 06:09 PM
Can't find them either, ok thanks for "help" anyway.

Maybe some1 else(who's not as busy as you) can drop a snippet...

southparksam
12-01-2008, 08:54 AM
change this line of code



imagettftext($image, $_GET['size'], 0, abs($size[0]), abs($size[5]), $color, $_GET['font'], $_GET['text']);


to this



imagettftext($image, $_GET['size'], 0, abs($size[0]), abs($size[5]), -$color, $_GET['font'], $_GET['text']);


What that does is turn of antialiasing when you draw the text, which will mean that colours are solid and will not blend with the background, dont worry though, antialiasing will be taken care of by your gradient code.



EZ Archive Ads Plugin for vBulletin Copyright 2006 Computer Help Forum