Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery

Adding text to an image for printing

by tel2 (Pilgrim)
on Nov 29, 2014 at 01:12 UTC ( [id://1108685]=perlquestion: print w/replies, xml ) Need Help??

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

Hi Monks,

I'm wanting to write a Perl script to:
- take user input (text),
- somehow merge that with a background image (maybe a TIFF), and
- save the result as a file for users to download and print.
(This is to replace a more manual (and easy to get wrong) method of doing an MS Word mail merge.)

To achieve this, I was thinking I'd use Perl's PDF::API2 module to create a PDF from the image and text.
I may be able to work out how to do that, but the main stumbling block I can see is, the font I need to use is "MT Script Bold", and it doesn't look as if that comes with PDF::API2, so any ideas how to make that font available to PDF::API2?  I've been searching the web for 30+ mins, including looking at the module docs, but I haven't got anywhere with it yet.

Apart from the font issue, do you see any issues with the above approach or can you suggest a better method of achieving my goals?


Replies are listed 'Best First'.
Re: Adding text to an image for printing
by james28909 (Deacon) on Nov 29, 2014 at 03:34 UTC
    After a 2 sec google search, it looks like Image::Magick is what you may want to use. I am in the process of looking for some documentation.
    EDIT: This is the best documentation i can find so far. Hope it helps :)

    Also, at PDF::API2 it specifically tells you:
    # Add an external TTF font to the PDF $font = $pdf->ttfont('/path/to/font.ttf');
    So.. make a PDF, use the image, and then write whatever text on it you want on it after importing your font with the above method.
    Also take a look at this link.

    EDIT2: Would it not be just as easy (or easier) to just create an html page with the image as a background, and then align the user text input and format it however you want?

    EDIT3: also GD looks to do this as well without needing to convert to PDF.
      Awesome selection of answers, James!
      Thanks heaps for all that!
Re: Adding text to an image for printing
by pme (Monsignor) on Nov 29, 2014 at 09:09 UTC
    Hi tel2,

    As james28909 said the GD module can do what you need.

    You can create a GD object from the file:

    $image = GD::Image->new($filename);
    and then add the text
    and save as png
    $png_data = $image->png; open (OUTFILE,"imagewithtext.png"); binmode OUTFILE; print OUTFILE $png_data; close OUTFILE;
      That's great, pme, thanks!

      It's good to have that (rather concise) code, which I might use for something else someday, but I'm not sure I can use it in my exact scenario, because of some requirements that I didn't think to explain before, i.e. the users might be printing say 20 course certificates for students, (which are always 2 per A4 page).  So, if I put all 20 in a 10 page PDF, the users can just download that single PDF, open it, and print it.

      Would there be a quick & easy way to achieve the same thing using PNGs which were created by GD?

        Hi tel2,

        Check out this:

        Using GD one can create empty canvas and then draw what you want and save in many different formats when ready.

        Using GD even you can insert a small marker image to a given position into a big picture.

        $myImage = new GD::Image(100,100); ... various drawing stuff ... $srcImage = new GD::Image(50,50); ... more drawing stuff ... # copy a 25x25 pixel region from $srcImage to # the rectangle starting at (10,10) in $myImage $myImage->copy($srcImage,10,10,0,0,25,25);


        Image::Magick can write PDFs. It looks like you could convert a series of PNGs (or whatever) into a PDF. Also, you might be to skip GD and add the text to the image in Image::Magick.

        Disclaimer: I have not tried this. YMMV.

Re: Adding text to an image for printing
by jmlynesjr (Deacon) on Jan 15, 2015 at 15:57 UTC

    Needed to do this to be able to post to another forum with very limited file type support. Thanks to all above for the hints. Wanted to share my proof of concept code for the next one needing to do this.

    Update: Added Wx GUI version below.

    #! /usr/bin/perl # - Convert a text file into a png format image # James M. Lynes, Jr. - January 15, 2015 # Proof of concept. File names hard coded. Expand to read command line + arguments # or move to Wx gui app. # Tab expansion regex from The Perl Cookbook use strict; use warnings; use GD; open INFILE, "<", "" || die; my $image = GD::Image->new(700, 700) || die; my $white = $image->colorAllocate(230,230,230); # backgroun +d color - Lt Gray my $black = $image->colorAllocate(0,0,0); # text color - Bl +ack my $x = 5; my $y = 0; while(<INFILE>) { chomp; 1 while s/\t+/' ' x (($+[0] - $-[0]) * 8 - $-[0] % 8)/e; # do t +ab expansion regex here $image->string(gdMediumBoldFont, $x, $y, $_, $black); $y += 14; } my $png_data = $image->png; open OUTFILE, ">", "text_to_image.png" || die; binmode OUTFILE; print OUTFILE $png_data; close OUTFILE;

    Wx Version

    #! /usr/bin/perl # Name: # Author: James M. Lynes, Jr. # Created: February 11, 2015 # Modified By: James M. Lynes, Jr. # Last Modified: February 11, 2015 # Change Log: 2/11/2015 - Program Created - Wx version using + sizers # and filepicker control. # Based on structur +e. # Description: Convert a single page text file into a png for +mat image. # Allows conversion of multiple files. # Tab expansion regex from The Perl Cookbook. package main; use strict; use warnings; my $app = App->new(); $app->MainLoop; package App; use strict; use warnings; use base 'Wx::App'; sub OnInit { my $frame = Frame->new(); $frame->Show(1); } package Frame; use strict; use warnings; use Wx qw(:everything); use base qw(Wx::Frame); use GD; use Data::Dumper; sub new { my ($class, $parent) = @_; my $frame = $class->SUPER::new($parent, -1, "Text File to png File + Converter", wxDefaultPosition, wxDefaultSize); #Create controls # Fields my $pdfLabel=Wx::StaticText->new($frame, wxID_ANY,"Select a Text F +ile to Convert to png", wxDefaultPosition, wxDefaultSize); my $pdfFilePicker=Wx::FilePickerCtrl->new($frame, wxID_ANY, "", "S +elect an Input File","*.*", wxDefaultPosition, [400,-1], wxDIRP_DIR_MUST +_EXIST| wxDIRP_CHANGE_DIR|wxDIRP_USE_TEXTCTRL); $pdfFilePicker->SetPath("~/"); $frame->{inpath} = "default"; # Buttons my $okButton = Wx::Button->new($frame, wxID_OK, "", wxDefaultPosit +ion, wxDefaultSize); my $exitButton = Wx::Button->new($frame, wxID_EXIT, "", wxDefaultP +osition, wxDefaultSize); # Create sizers. my $verticalSizerFrame = Wx::BoxSizer->new(wxVERTICAL); $frame->SetSizer($verticalSizerFrame); my $verticalSizerControls = Wx::BoxSizer->new(wxVERTICAL); my $horizontalSizerButtons = Wx::BoxSizer->new(wxHORIZONTAL); # Lay 'em out. $verticalSizerFrame->Add($verticalSizerControls,0,0,0); $verticalSizerFrame->Add($horizontalSizerButtons,0,0,0); $verticalSizerControls->AddSpacer(15); # Spacer $verticalSizerControls->Add($pdfLabel,0,0,0); $verticalSizerControls->Add($pdfFilePicker,0,0,0); $verticalSizerControls->AddSpacer(15); # Spacer $horizontalSizerButtons->Add($okButton,0,0,0); $horizontalSizerButtons->Add($exitButton,0,0,0); # Event handlers Wx::Event::EVT_BUTTON($frame, $okButton, sub { my ($self, $event) = @_; #print "\nOK Button\n"; open INFILE, "<", $self->{inpath} || die; my $image = GD::Image->new(700, 700) || die; my $white = $image->colorAllocate(230,230,23 +0); # background color - Lt Gray my $black = $image->colorAllocate(0,0,0); + # text color - Black my $x = 5; my $y = 0; while(<INFILE>) { chomp; 1 while s/\t+/' ' x (($+[0] - $-[0]) * 8 + - $-[0] % 8)/e; # do tab expansion regex here $image->string(gdMediumBoldFont, $x, $y, + $_, $black); $y += 14; } my $png_data = $image->png; open OUTFILE, ">", $self->{inpath}.".png" || + die; binmode OUTFILE; print OUTFILE $png_data; close INFILE; close OUTFILE; }); Wx::Event::EVT_BUTTON($frame, $exitButton, sub { my ($self, $event) = @_; #print "\nEXIT Button\n"; $self->Close; }); Wx::Event::EVT_FILEPICKER_CHANGED($frame, $pdfFilePicker, sub { my ($self, $event) = @_; $self->{inpath} = $pdfFilePicker->GetPath; }); $verticalSizerFrame->Layout(); return $frame; } 1;


    There's never enough time to do it right, but always enough time to do it over...

      Months later...
      Thanks James. I just noticed your post now.

Log In?

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1108685]
Approved by Eily
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others pondering the Monastery: (5)
As of 2024-04-12 11:13 GMT
Find Nodes?
    Voting Booth?

    No recent polls found