What I'm trying to do, is put a border around each of the text strings I output, with a bit of padding around them. I can figure this out manually, by loading the image up in Gimp and checking the x,y, and applying that value to the rectangle() I draw, but that doesn't scale well, if the user changes font faces or font sizes.
This is as close as I could get, but it puts the border right up against the image text. No way to pad it as I see it.
Also, this can probably be refactored to push the levels and colors into a loop. I'm not good with that kind of construct in perl. Any help there?
Working code so far below:
use warnings; use strict; use GD; use Color::Rgb; # Font you wish to use for this output image my $fontpath = '/usr/share/fonts/truetype/'; my $font = $fontpath . 'ttf-bitstream-vera/VeraSeBd.ttf'; my $rgb = new Color::Rgb(rgb_txt=>'/usr/X11R6/lib/X11/rgb.txt'); # Create a new image my $width = 200; my $height = 200; my $im = new GD::Image($width, $height); $im->colorAllocate(0,0,0); my $white = $im->colorAllocate($rgb->hex2rgb('#ffffff')); my $black = $im->colorAllocate($rgb->hex2rgb('#000000')); # Allocate colors for rated levels # From: http://advogato.org/css/global.css my $level0 = $im->colorAllocate($rgb->hex2rgb('#c1c1c1')); my $level1 = $im->colorAllocate($rgb->hex2rgb('#c0ffc8')); my $level2 = $im->colorAllocate($rgb->hex2rgb('#c0d0ff')); my $level3 = $im->colorAllocate($rgb->hex2rgb('#e0d0ff')); my $level4 = $im->colorAllocate($rgb->hex2rgb('#e0d0c0')); my $level0_bord = $im->colorAllocate($rgb->hex2rgb('#606060')); my $level1_bord = $im->colorAllocate($rgb->hex2rgb('#008000')); my $level2_bord = $im->colorAllocate($rgb->hex2rgb('#2040ff')); my $level3_bord = $im->colorAllocate($rgb->hex2rgb('#8000c0')); my $level4_bord = $im->colorAllocate($rgb->hex2rgb('#804020')); # Make the background transparent and interlaced $im->interlaced('false'); # Create a Border around the image $im->rectangle(0, 0, $width-1, $height-1, $level0_bord); my $x1 = 50; my $y1 = 20; # Can I put all of this in a "smarter" loop? my @bounds = $im->stringFT($level0, $font, 10, 0, $x1, $y1, 'Neophyte' +); # This is ugly, but does work for now. This needs a loop. $bounds[2] += 3; $bounds[3] += 3; $bounds[6] += -5; $bounds[7] += -5; $im->rectangle(@bounds[6,7], @bounds[2,3], $level0_bord); $im->stringFT($level1, $font, 10, 0, $x1, $y1 + 40, 'Apprentice'); $im->stringFT($level2, $font, 10, 0, $x1, $y1 + 80, 'Journeyer'); $im->stringFT($level3, $font, 10, 0, $x1, $y1 + 120, 'Master'); $im->stringFT($level4, $font, 10, 0, $x1, $y1 + 160, 'Undefined'); open(IMG, ">picture.png") or die("Cannot open file!"); binmode IMG; print IMG $im->png; close IMG;
I think I solved most of this now.. except the ability to resize the image itself to match the width and height of the text. I think I have to create the image larger than I need, and crop it down, using @bounds. This code shows that, but for some reason, some images are cropped more than others. There doesn't seem to be any reason why. Suggestions?
use warnings; use strict; use GD; use GD::Text; use Color::Rgb; # Font you wish to use for this output image my $fontpath = '/usr/share/fonts/truetype/'; my $font = $fontpath . 'ttf-bitstream-vera/VeraSe.ttf'; my $fontsize = '10'; my $rgb = new Color::Rgb(rgb_txt=>'/usr/X11R6/lib/X11/rgb.txt'); # Create a new image my $width = 200; my $height = 200; # Allocate colors for rated levels # From: http://advogato.org/css/global.css my @advo = ( {name => 'Neophyte', color => '#c1c1c1', border => '#606060'}, {name => 'Apprentice', color => '#c0ffc8', border => '#008000'}, {name => 'Journeyer', color => '#c0d0ff', border => '#2040ff'}, {name => 'Master', color => '#e0d0ff', border => '#8000c0'}, {name => 'Undefined', color => '#e0d0c0', border => '#804020'}, ); for my $certs (@advo) { my $gd_text = GD::Text->new() or die GD::Text::error(); $gd_text->set_font($font, $fontsize) or die $gd_text->error; $gd_text->set_text($certs->{name}); my ($w, $h) = $gd_text->get('width', 'height'); my $im = new GD::Image($w+11, $h+6); my $x1 = 5; my $y1 = 15; $im->colorAllocate($rgb->hex2rgb("$certs->{color}")); my $black = $im->colorAllocate(0,0,0); my $color = $im->colorAllocate($rgb->hex2rgb("$certs->{color} +")); my $border = $im->colorAllocate($rgb->hex2rgb("$certs->{border +}")); my @bounds = $im->stringFT($black, $font, $fontsize, 0, $x1, $ +y1, $certs->{name}); $bounds[2] += 3; $bounds[3] += 3; $bounds[6] += -5; $bounds[7] += -5; $im->rectangle(@bounds[6,7], @bounds[2,3], $border); open(IMG, ">$certs->{name}.png") or die("Cannot open file!"); binmode IMG; print IMG $im->png; close IMG; }
In reply to Automagic text-to-image border calculations by hacker
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |