Programming Web Graphics
Using Perl and GNU Software

by Shawn Wallace
Published March 1999
by O'Reilly & Associates

Visit Shawn's Home Page

In 1998 I wrote a book about using Perl to generate graphics for the web. This page has been set up as a service for the readers of this book, to help ensure that the first and future editions are as accurate as humanly possible. You can also download the code examples here, some of which may be slightly different or improved from those in the book.

Where to get it

Here are a few places online where you can order Programming Web Graphics:

Are you boycotting Amazon? Well, then try: (At right is the original book cover, which was changed from a pair of Guinea fowl to a Collared Titi.)

Errata

There are two places to check for updated information and corrections to mistakes:

  • My errata page. This should be the most up-to-date, if, for some reason, the two pages are out of sync, which they shouldn't be.
  • O'Reilly's Errata page. The canonical page, if not (necessarily) the most up-to-date.
Have you noticed a mistake in the book? If so, please submit an error report below. You can also use this form to submit general comments to me. All changes will be incorporated into future editions of the book (and credited if you give me your name). Or you can mail me directly.

Your name: Your e-mail:

What Chapter? What Page?

A brief description of the error (or your comment):

How severe would you say this problem is?

Reviews

ACCU review, December 5, 2000.
UK Unix Users Group review.
On slashdot, August 20, 1999.
On NL.Linux.org in Dutch.
In Issue 64 of the Linux Journal, by Michael Hammel.
In Issue 42 of the Linux Gazette, by Jack Coats.
By the Association of C and C++ Users
On the Perl Monger's site by brian d. foy.
In the Norwegian Linux Community by Andreas-Johann Ulvestad.
Oh, it also got a mention on christmas-baking.com.

Example Code

Here's the example code, broken down by chapter:

Chapter 1: Image File Formats
Chapter 2: Serving Graphics on the Web
Chapter 3: A Litany of Libraries
Chapter 4: On-the-Fly Graphics with GD
Chapter 5: Industrial-Strength Graphics Scripting with PerlMagick
Chapter 6: Charts and Graphs with GIFgraph
Chapter 7: Web Graphics with the Gimp
Chapter 8: Image Maps
Chapter 9: Programming GIF Animation
Chapter 10: Web Graphics Cookbook
Chapter 11: Printing and the Web
Get the Postscript module at http://cpan.org/modules/by-module/PostScript/SHAWNPW/.
Appendix A

Figures

These may not be 100% up-to-date (some may be from an earlier revision of the book). All of the figures are zipped up by the chapter. If you need an unzipper, try here.

Chapter 1 Figures
Chapter 2 Figures
Chapter 3 Figures
Chapter 4 Figures
Chapter 5 Figures
Chapter 6 Figures
Chapter 7 Figures
Chapter 8 Figures
Chapter 9 Figures
Chapter 10 Figures
Chapter 11 Figures

References
Chapter 1

The Encyclopedia of Graphics File Formats, 2nd Edition Murray, James D, and William vanRyper, , O'Reilly and Associates, Cambridge, 1996

License Information on GIF and Other LZW-based Technologies
http://corp2.unisys.com/LeadStory/lzwfaq.html

The PNG Specification
ftp://ftp.uu.net/graphics/png/documents/png-1.0-w3c-single.html.gz

An explanation of compositing partially transparent pixels from the PNG specification
ftp://ftp.uu.net:/graphics/png/documents/ png-1.0-w3c-single.html.gz
#D.Alpha-channel-processing

FIXMEThe Deflate algorithm which PNG uses as its compression method
ftp://ds.internic.net/rfc/rfc1951.txt

Some Information on the CRC Algorithm (ISO 3309)
http://bbs-koi.uniinc.msk.ru/tech1/1994/er_cont/crc.htm

MNG Home Page
http://www.cdrom.com/pub/mng/

JPEG Home Page
http://www.jpeg.org/

JPEG FAQ
http://www.faqs.org/faqs/jpeg-faq/

JPEG:Still Image Data Compression Standard (a book containing the complete ISO JPEG standards) Pennebaker, William B. and Joan L. Mitchell, , Van Nostrand Reinhold, New York, 1993.

The comp.compression FAQ
http://www.faqs.org/faqs/compression-faq/

Greg Roelofs' PNG Page with current comparisons of PNG support by different browsers
http://www.cdrom.com/pub/png/

The description of the Image Library for the Mozilla web browser (an instructive look at how an actual "real world" web browser deals with file formats, with some discussion about the tradeoffs in features vs. performance)
http://www.mozilla.org/docs/tplist/catCode/imagdesc.htm

Chapter 2
The Official Guide to Programming with CGI.pm
Stein, Lincoln D., John Wiley & Sons, 1998.

Online CGI.pm documentation
http://www.genome.wi.mit.edu/ftp/pub/software/WWW/

The Idiot's Guide to Solving Perl CGI Problems
http://www.perl.com/CPAN-local/doc/FAQs/cgi/idiots-guide.html

The Perl-Apache Integration Project
http://perl.apache.org

mod_perl performance tuning guide
http://perl.apache.org/tuning

HTML: The Definitive Guide
Musciano, Chuck and Bill Kennedy, , O'Reilly & Associates, 3rd Edition, 1998

Chapter 3
The Comprehensive Perl Archive Network (CPAN)
http://www.cpan.org

The GIF Controversy: A Software Developer's Perspective
http://www.cloanto.com/users/mcb/19950127giflzw.html

The Open Source Definition
http://www.opensource.org/osd.html

The GNU General Public License
http://www.gnu.org/copyleft/gpl.html

The BSD License
http://www.opensource.org/bsd-license.html

Textmode Quake, a version of the popular Quake game that renders its graphics in ASCII using AA-lib
http://webpages.mr.net/bobz/ttyquake/

Chapter 4
Get GD.pm from the Comprehensive Perl Archive Network (CPAN)
http://www.cpan.org

The latest version of GD.pm should also be available at
http://stein.cshl.org/WWW/software/GD/GD.html

Thomas Boutell's original C-language version of the libgd library can be found at
http://www.boutell.com/gd/gd.html

Chapter 5
The official web page for ImageMagick is
http://www.wizards.dupont.com/cristy/ImageMagick.html

The PerlMagick page is at
http://www.wizards.dupont.com/cristy/www/perl.html

PerlMagick is also available via CPAN at
http://www.perl.com/CPAN-local/modules/by-module/Image/

Several ftp mirrors for the source and precompiled binaries are available at
http://www.wizards.dupont.com/cristy/www/archives.html

The mailing list is archived periodically at
ftp://ftp.wizards.dupont.com/pub/ImageMagick/mailing-list/

Chapter 10
The Connectix Quick Cam Third Party Driver Page
http://www.crynwr.com/qcpc/

The Genericam "webcam templates" Page
http://occonnect.com/johnqpublic/index.html

Chapter 11
PostScript Language Tutorial and Cookbook
The so-called "Blue Book," with many examples and recipes, Adobe Systems, Inc., Addison-Wesley, 1985

PostScript Language Reference Manual 2nd edition
The so-called "Red Book," the official language reference, Adobe Systems, Inc., , Addison-Wesley, 1990

PostScript by Example
A good introduction to PostScript, similar in purpose to the Blue Book, McGilton, Henry, and Mary Campione, Addison-Wesley Publishing Company, 1992

The Ghostscript Home Page
http://www.cs.wisc.edu/~ghost

Adobe's Technical Resources Page
http://partners.adobe.com/supportservice/devrelations/technotes.html

The html2ps HTML-to-PostScript converter
http://www.tdb.uu.se/~jan/html2ps.html

The PostScript Module

Get the Postscript module at http://cpan.org/modules/by-module/PostScript/SHAWNPW/.

Some notes on the PostScript module described in Chapter 11.

Font::AFM

Parses the AFM files of fonts. (I used this to create the hashes in the PostScript::Metrics module).

Johan Vromans has created:

PostScript::Font

loads a font into perl memory
can convert from .pfa to .pfb and vice versa
extracts essential info (like FontName, FontType, FontFamily)
can extract the encoding vector
can extract the list of glyphs (slow)
A trivial .pfb to .pfa conversion program would look like:
        my $font = new PostScript::Font (shift(@ARGV),
                                   format => "ascii");
        print STDOUT ($font->data);

PostScript::FontMetrics

loads an Adobe font metrics (AFM) file into perl memory extracts essential info (like FontName, FontFamily)

PostScript::FontInfo

loads a font info (INF) file into perl memory extracts essential info (like FontName, PCPrefix)

Simon Twigger has created PostScript::Basic module, documented online at http://legba.ifrc.mcw.edu/~simont/pub/ps.html

PostScript::Basic v. 0.2

Essentially this is a collection of macros to simplify the generation of basic PostScript and PDF images. It is modelled roughly on the GD.pm module. It is procedure-oriented; you create a new PostScript page (it doesn't look like multi-page docs are supported...?) with the ps_start function, and print the PostScript code with the ps_finish fuction.

Some features of note:

  • transforms (translation, rotation, scale)
  • bezier curves (with 'debugging mode' showing tangents)
  • save/restore graphics state supported
  • pdf features supported

Shawn Wallace started the PostScript::TextBlock, PostScript::Metrics, PostScript::Document, and PostScript::Elements modules.

PostScript::TextBlock v 0.05

All of the modules in this suite are ment to be used in an o.o. manner. A TextBlock is a rectangle of left-justified text. Font sizes, styles, and leading may be intermingled. The visual metaphor is similar to that of page layout programs such as PageMaker; the TextBlock is of arbitrary length and may be fit to an area by specifying the area with the Write() method. This will return the PS code to draw the text within a given rectangle, and will also return the portion of the TextBlock that did not fit within the rectangle.

Dan Smeltz added functionality to PostScript::TextBlock:

  • the ability to use standard PS fontnames via an alias mechanism.
  • a function that will automatically size the font so the text you give it fits in the given box.

PostScript::Metrics

Kind of a hack that supports the PostScript::TextBlock module. This defines a hash containing the character metrics for each font.

PostScript::Document

Allows for the easy creation of multi-page PostScript documents with optional headers, footers and page numbers. TextBlocks and Elements may be intermingled. (Embedded EPS support to follow).

PostScript::Elements

An object representing lines, arcs, or boxes of various line widths and tints. Elements are defined in terms of absolute points on a page (relative definition to follow).

Some thoughts:

  • There are inconsistencies in the way that methods are named in the PostScript::Basic and PostScript::TextBlock et. al. modules. The underscore convention follows the example set by GIFgraph and GD. The more general naming scheme in the latter modules ($ps->Write(), for example) is justified by the fact that it makes the integration of different PostScript-code- generating objects more transparent. We could do the following, for example:
       my $tb  = PostScript::TextBlock;
       my $eps = PostScript::EPS;       # Note: doesn't exist yet...
       my $ps  = PostScript::Elements;
    
       # Generate the PS code for a list of objects
       #
       foreach $object ($ps, $eps, $ps) {
           print $object->Write();
       }
    

    (Of course, TextBlock returns a list of two elements, so this doesn't really work. I will have to add another layer of abstraction in there somewhere...)

    I think it would be valuable to have a consistent interface for this last part of the code generation process.

  • In PostScript::Basic, I think it would be best to return the code rather than print it to STDOUT.

  • (From Johan) In PostScript::Metrics module This only has the metrics for the ASCII part of the fonts, and does not take font encoding into account. The correct way of calculating a glyph width should be:
      # encoding->[NN] holds the glyph name corresponding with character NN
      $fonts{$fontname}->glyphtable->{$fonts{$fontname}->encoding->[$char]}->width
    
    Alternatively, an encoding could be pre-set:
      $fonts{$fontname}->encoding = [ (0) x 256 ];
      my $i = 0;
      foreach $glyph ( @encoding ) {
        $fonts{$fontname}->encoding->[$i] =
           $fonts{$fontname}->glyphtable->{$glyph}->width;
        $i++;
      }
      # now encoding->[NN] holds the width for character NN
    
    It's the encoding issues that makes things problematic.

    I think PostScript::Metrics should be replaced by Johan's PostScript:: FontMetrics module.