ultranerds has asked for the wisdom of the Perl Monks concerning the following question:

Hi,

I'm trying to write a script that will:

1: Grab an image (a pre-defined one)
2) Overlay some text (the date) over this image.

I've had a google around, and can't find anything (unless I'm not searching for the correct queries =))

Could anyone provide me with some example code? At the moment, I've got the basics - but need to have an image showing towards the back of the image:

#!/usr/local/bin/perl use CGI::Carp qw(fatalsToBrowser); print qq|Content-type: image/png \n\n|; use GD; # create a new image my $im = new GD::Image(100,100); # allocate some colors my $white = $im->colorAllocate(255,255,255); my $black = $im->colorAllocate(0,0,0); my $red = $im->colorAllocate(255,0,0); my $blue = $im->colorAllocate(0,0,255); # make the background transparent and interlaced $im->transparent($white); $im->interlaced('true'); # Put a black frame around the picture $im->rectangle(0,0,99,99,$black); # Draw a blue oval $im->arc(50,50,95,75,0,360,$blue); # And fill it with red $im->fill(50,50,$red); # my $courier = GD::Font->load('/home/trust/domain.pro/cgi-bin/trust +/LiberationSerif-Bold.ttf') or die "Can't load font"; $im->string(gdSmallFont,5,10,"Testing",$black); # make sure we are writing to a binary stream binmode STDOUT; # Convert the image to PNG and print it on standard output print $im->png;

TIA

Andy

Replies are listed 'Best First'.
Re: GD + layering text over existing image
by BrowserUk (Patriarch) on Nov 22, 2008 at 13:36 UTC

    As far as I can see, the only thing missing from your script is that you are creating a new image instead of loading an existing one. (Unsurprising I guess as it appears to be the code from the GD pod synopsis.)

    If you replace my $im = new GD::Image(100,100); with

    $im = GD::Image->new( $filename );

    Provided that $filename contains the path and name of a image in any one of the formats GD supports (and that file is readable from the web server), then the rest of your code should work pretty much as it is, if you also change "Testing" for scalar localtime.


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
      Hi, THANKS! Worked like a charm :) (always simple when you know how <G>) Cheers Andy
      Thank you very much.. I am new bee to perl CGI, working on some task from last two days... I made a small change i made as you suggested above, then it starts working... <3 ... For Perl CGI lack of materials.. i think Perl is not upgrading with the competitive IT world... For new bees it is very difficult to find some stuff and tutorials... And some days back i saw TPT is started training so i mailed them, its been 3 months still they didnt replied.. OK any way thanks for your suggestion.

        Wow. Nine years. That has to be a record for the longest time before receiving a response. Anyway, glad to have helped.

        For new bees it is very difficult to find some stuff and tutorials

        Let's see. Where would a "new bee" start? Probably at perl.org. Click "Docs", click "Tutorials". Not so difficult.

        Where else might they start? Maybe with the FAQ where there's a whole section (number 2) about where to go for learning materials.

        Maybe they would come to PerlMonks where there's a Tutorials section linked on every page.

        Or maybe they would try a search engine like DuckDuckGo or Google

        If you could explain how these methods could be made less difficult for perl neophytes then that would be most illuminating.

Re: GD + layering text over existing image
by Lawliet (Curate) on Nov 22, 2008 at 18:11 UTC

    Take a look at google's preview for Perl Graphics Programming. There is a section 'Images from User Input: A Customized Billboard' (p.29) that is almost exactly what you want (I think).

    I'm so adjective, I verb nouns!

    chomp; # nom nom nom

Re: GD + layering text over existing image
by bruno (Friar) on Nov 22, 2008 at 21:09 UTC
    There is an easy solution that does not require Perl: ImageMagick.

    It's a command line tool for lots of image processing tasks (there is a wrapper module in CPAN also, if you'd still prefer using perl).

    In particular, it has a "-draw" command that lets you add text labels to images: http://www.imagemagick.org/script/command-line-options.php#draw

        Hi zentara,

        Thanks for your reply too :) I was tempted to use Image::Magick - but I was lead to believe that its a bit more of a resource hog in comparison to GD (we're going to be serving about 1 million of the "script calls" a day - so every bit extra CPU isn't desirable :))

        Cheers

        Andy
      Hi,

      Mmm.. got a weird problem :/

      http://members.domain.com/cgi-bin/art/page.cgi?p=test

      ...thats using exactly the same code.

      Images are:

      http://www.domain.pro/images/badges/badgeXL500.png
      http://www.domain.pro/images/badges/badgeMD500.png
      http://www.domain.pro/images/badges/badgeSM500.png

      http://www.domain.pro/images/badges/badgeXL.png
      http://www.domain.pro/images/badges/badgeMD.png
      http://www.domain.pro/images/badges/badgeSM.png

      The code is pretty bog standard:

      my $size = lc($IN->param('size')) || "m"; print qq|Content-type: image/png \n\n|; # print "FOO"; use GD; my $filename; if ($size eq "l") { $filename = qq|/home/domain/domain.pro/www/images/badges/badge +XL500.png|; } elsif ($size eq "m") { $filename = qq|/home/domain/domain.pro/www/images/badges/badge +MD500.png|; } elsif ($size eq "s") { $filename = qq|/home/domain/domain.pro/www/images/badges/badge +SM500.png|; } # create a new image # my $im = new GD::Image(100,100); my $im = GD::Image->new( $filename ); # allocate some colors my $black = $im->colorAllocate(0,0,0); if ($size eq "l") { $im->string(gdMediumBoldFont,27,44,"Secure " . GT::Date::date_ +get() ,$black); } elsif ($size eq "m") { $im->string(gdMediumBoldFont,29,26,"Secure " . GT::Date::date_ +get(),$black); } elsif ($size eq "s") { $im->string(gdTinyFont,15,26,"Safe " . GT::Date::date_get() ,$ +black); } # make sure we are writing to a binary stream binmode STDOUT; # Convert the image to PNG and print it on standard output print $im->png;


      ..however, its confusing the hell out of me with whats going on with the text color. Could it have something to do with the pallet of the image?

      TIA!

      Andy
        whats going on with the text color. Could it have something to do with the pallet of the image?

        Without having access to the original images I'd guess: probably.

        Perhaps the easiest way to avoid the problem would be to ensure that the image files get loaded as 'truecolor' (Ie. full 24-bit colour). You can do that by setting GD::Image->trurColor( 1 ); prior to loading the image. You'd then dump the colorAllocate() call and specify the text color directly using its rgb value. Simply 0 for black:

        ... ## Set the default to truecolor images. GD::Image->trueColor( 1 ); # create a new image my $im = GD::Image->new( $filename ); if ($size eq "l") { $im->string(gdMediumBoldFont,27,44,"Secure ". GT::Date::date_g +et(), 0 ); } elsif ($size eq "m") { $im->string(gdMediumBoldFont,29,26,"Secure ". GT::Date::date_g +et(), 0 ); } elsif ($size eq "s") { $im->string(gdTinyFont,15,26,"Safe " . GT::Date::date_get() , +0); } binmode STDOUT; print $im->png;

        For colors other than black, I use a simple utility sub to convert rgb triples to their integer representation:

        sub rgb2n{ unpack 'N', pack 'CCCC', 0, @_ } rgb2n( 255, 0, 0 ); ## Red rgb2n( 0, 255, 0 ); ## Green rgb2n( 0, 0, 255 ); ## Blue

        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.