788 lines
56 KiB
HTML
788 lines
56 KiB
HTML
<!--startcut ==============================================-->
|
|
<!-- *** BEGIN HTML header *** -->
|
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
|
|
<HTML><HEAD>
|
|
<title>Exploring Perl Modules - Part 1: On-The-Fly Graphics with GD LG #81</title>
|
|
</HEAD>
|
|
<BODY BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#0000FF" VLINK="#0000AF"
|
|
ALINK="#FF0000">
|
|
<!-- *** END HTML header *** -->
|
|
|
|
<CENTER>
|
|
<A HREF="http://www.linuxgazette.com/">
|
|
<IMG ALT="LINUX GAZETTE" SRC="../gx/lglogo.png"
|
|
WIDTH="600" HEIGHT="124" border="0"></A>
|
|
<BR>
|
|
|
|
<!-- *** BEGIN navbar *** -->
|
|
<IMG ALT="" SRC="../gx/navbar/left.jpg" WIDTH="14" HEIGHT="45" BORDER="0" ALIGN="bottom"><A HREF="kurup.html"><IMG ALT="[ Prev ]" SRC="../gx/navbar/prev.jpg" WIDTH="16" HEIGHT="45" BORDER="0" ALIGN="bottom"></A><A HREF="index.html"><IMG ALT="[ Table of Contents ]" SRC="../gx/navbar/toc.jpg" WIDTH="220" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A><A HREF="../index.html"><IMG ALT="[ Front Page ]" SRC="../gx/navbar/frontpage.jpg" WIDTH="137" HEIGHT="45" BORDER="0" ALIGN="bottom"></A><A HREF="http://www.linuxgazette.com/cgi-bin/talkback/all.py?site=LG&article=http://www.linuxgazette.com/issue81/padala.html"><IMG ALT="[ Talkback ]" SRC="../gx/navbar/talkback.jpg" WIDTH="121" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A><A HREF="../lg_faq.html"><IMG ALT="[ FAQ ]" SRC="./../gx/navbar/faq.jpg"WIDTH="62" HEIGHT="45" BORDER="0" ALIGN="bottom"></A><A HREF="ramankutty.html"><IMG ALT="[ Next ]" SRC="../gx/navbar/next.jpg" WIDTH="15" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A><IMG ALT="" SRC="../gx/navbar/right.jpg" WIDTH="15" HEIGHT="45" ALIGN="bottom">
|
|
<!-- *** END navbar *** -->
|
|
<P>
|
|
</CENTER>
|
|
|
|
<!--endcut ============================================================-->
|
|
|
|
<H4 ALIGN="center">
|
|
"Linux Gazette...<I>making Linux just a little more fun!</I>"
|
|
</H4>
|
|
|
|
<P> <HR> <P>
|
|
<!--===================================================================-->
|
|
|
|
<center>
|
|
<H1><font color="maroon">Exploring Perl Modules - Part 1: On-The-Fly Graphics with GD</font></H1>
|
|
<H4>By <a href="mailto:p_padala@yahoo.com">Pradeep Padala</a></H4>
|
|
</center>
|
|
<P> <HR> <P>
|
|
|
|
<!-- END header -->
|
|
|
|
|
|
|
|
|
|
<h3 name="intro"> Welcome To "Exploring Perl Modules" !!!</h3>
|
|
<p>
|
|
Perl modules are considered to be one of the strongest points for perl's
|
|
success. They contain a lot of re-usable code and of course are free.
|
|
This is an attempt to trap the treasure trove. There are lot
|
|
of tutorials and even books written on popular modules like CGI, DBI etc..
|
|
For less popular modules, users are left with documentation which is cryptic
|
|
and sometimes incomplete.
|
|
<p>
|
|
I am starting a series of articles that will attempt to explain some of the less popular but
|
|
useful modules.
|
|
During the last year, I came across and programmed with
|
|
numerous perl modules. I will explain the modules with numerous
|
|
useful examples from my experience. We will take one module at a time
|
|
and explore its various uses.
|
|
<h3 name="whoread"> Who should be reading these</h3>
|
|
<p>
|
|
Well, you should know perl. We won't be delving much into the basics of perl.
|
|
There are plenty of documentation, articles and books on perl.
|
|
<a href=http://www.oreilly.com/catalog/lperl3/>Learning Perl</a> is
|
|
often recommended for beginners. Once you gain experience, you can try
|
|
<a href=http://www.oreilly.com/catalog/pperl3/>Programming Perl</a>.
|
|
<p>
|
|
If you are an average perl programmer and haven't used lot of modules, this
|
|
is the right place. Modules provide a great way to re-use code and write
|
|
efficient and compact applications. In each article we will graduate from
|
|
simple examples to complex examples ending in a real-world application,
|
|
if appropriate.
|
|
|
|
<h3 name="intromodules"> Introduction to Modules </h3>
|
|
Modules provide an effective mechanism to import code and use it. The
|
|
following line imports a module and makes its functions accessible.
|
|
<pre>
|
|
use module;
|
|
</pre>
|
|
For example if you want to use GD, you would write
|
|
<pre>
|
|
use GD;
|
|
</pre>
|
|
|
|
<h3> Finding and Installing Modules </h3>
|
|
<p>
|
|
Before we plunge into the details of programming, here are some instructions
|
|
for finding and installing modules. We will be using various modules, and most
|
|
of them are not installed by default. Some modules require libraries which
|
|
may or may not have been installed. I will mention the things
|
|
required whenever appropriate. Here are generic instructions for downloading
|
|
and installing modules.
|
|
<p>
|
|
An easy way to install the module is by using the CPAN module. Run CPAN in
|
|
interactive mode as
|
|
<pre>
|
|
perl -MCPAN -e shell
|
|
</pre>
|
|
<p>
|
|
Then you can do various tasks like downloading, decompressing and installing
|
|
modules. For example, for installing GD you can use
|
|
<pre>
|
|
install GD
|
|
</pre>
|
|
<p>
|
|
If you are like me and and are accustomed to configure, make, make install method,
|
|
here are the steps to install a module.
|
|
<ul>
|
|
<li> Find the module in CPAN's
|
|
<a href=http://www.cpan.org/modules/00modlist.long.html>list</a> of all modules.
|
|
<li> Download the latest version of the module. For example, the latest GD
|
|
module can be downloaded from
|
|
<a href=http://www.cpan.org/authors/id/LDS/GD-1.40.tar.gz>http://www.cpan.org/authors/id/LDS/GD-1.40.tar.gz</a>
|
|
<li> Unzip the module
|
|
<pre>
|
|
tar zxvf GD-1.40.tar.gz
|
|
</pre>
|
|
<li> Build the module
|
|
<pre>
|
|
perl Makefile.PL
|
|
(or)
|
|
perl Makefile.PL PREFIX=/my/perl/directory
|
|
(if you want to install in /my/perl/directory)
|
|
make
|
|
make test (optional)
|
|
</pre>
|
|
<li> Install the module
|
|
<pre>
|
|
make install
|
|
</pre>
|
|
</ul>
|
|
|
|
<h3> Ready to Go ... </h3>
|
|
<p>
|
|
So you have installed your favourite module and are raring to learn. In this article we
|
|
will explore the perl GD module, which provides an interface to <a href="http://www.boutell.com/gd/">GD library</a>. We will also be using the CGI module
|
|
for the web interface. You don't need to know a great deal of CGI to understand
|
|
this article. I will explain things where necessary.
|
|
|
|
<h3> Graphics with GD </h3>
|
|
<p>
|
|
Let's start the wheels with a simple and effective example
|
|
<pre>
|
|
Text version of the file can be found <a href=misc/padala/simple.pl.txt>here</a>.
|
|
<font color="#a020f0">#!/usr/local/bin/perl -w</font>
|
|
<font color="#0000ff"># Change above line to path to your perl binary</font>
|
|
|
|
<font color="#a52a2a"><b>use </b></font>GD;
|
|
|
|
<font color="#0000ff"># Create a new image</font>
|
|
<font color="#008b8b">$im</font> = <font color="#a52a2a"><b>new</b></font> GD::Image(<font color="#ff00ff">100</font>,<font color="#ff00ff">100</font>);
|
|
|
|
<font color="#0000ff"># Allocate some colors</font>
|
|
<font color="#008b8b">$white</font> = <font color="#008b8b">$im</font>->colorAllocate(<font color="#ff00ff">255</font>,<font color="#ff00ff">255</font>,<font color="#ff00ff">255</font>);
|
|
<font color="#008b8b">$black</font> = <font color="#008b8b">$im</font>->colorAllocate(<font color="#ff00ff">0</font>,<font color="#ff00ff">0</font>,<font color="#ff00ff">0</font>);
|
|
<font color="#008b8b">$red</font> = <font color="#008b8b">$im</font>->colorAllocate(<font color="#ff00ff">255</font>,<font color="#ff00ff">0</font>,<font color="#ff00ff">0</font>);
|
|
<font color="#008b8b">$blue</font> = <font color="#008b8b">$im</font>->colorAllocate(<font color="#ff00ff">0</font>,<font color="#ff00ff">0</font>,<font color="#ff00ff">255</font>);
|
|
|
|
<font color="#0000ff"># Make the background transparent and interlaced</font>
|
|
<font color="#008b8b">$im</font>->transparent(<font color="#008b8b">$white</font>);
|
|
<font color="#008b8b">$im</font>->interlaced(<font color="#ff00ff">'</font><font color="#ff00ff">true</font><font color="#ff00ff">'</font>);
|
|
|
|
<font color="#0000ff"># Put a black frame around the picture</font>
|
|
<font color="#008b8b">$im</font>->rectangle(<font color="#ff00ff">0</font>,<font color="#ff00ff">0</font>,<font color="#ff00ff">99</font>,<font color="#ff00ff">99</font>,<font color="#008b8b">$black</font>);
|
|
|
|
<font color="#0000ff"># Draw a blue oval</font>
|
|
<font color="#008b8b">$im</font>->arc(<font color="#ff00ff">50</font>,<font color="#ff00ff">50</font>,<font color="#ff00ff">95</font>,<font color="#ff00ff">75</font>,<font color="#ff00ff">0</font>,<font color="#ff00ff">360</font>,<font color="#008b8b">$blue</font>);
|
|
|
|
<font color="#0000ff"># And fill it with red</font>
|
|
<font color="#008b8b">$im</font>->fill(<font color="#ff00ff">50</font>,<font color="#ff00ff">50</font>,<font color="#008b8b">$red</font>);
|
|
|
|
<font color="#0000ff"># Open a file for writing </font>
|
|
<font color="#a52a2a"><b>open</b></font>(<font color="#008b8b">PICTURE</font>, <font color="#ff00ff">"</font><font color="#ff00ff">>picture.png</font><font color="#ff00ff">"</font>) <font color="#a52a2a"><b>or</b></font> <font color="#a52a2a"><b>die</b></font>(<font color="#ff00ff">"</font><font color="#ff00ff">Cannot open file for writing</font><font color="#ff00ff">"</font>);
|
|
|
|
<font color="#0000ff"># Make sure we are writing to a binary stream</font>
|
|
<font color="#a52a2a"><b>binmode</b></font> <font color="#008b8b">PICTURE</font>;
|
|
|
|
<font color="#0000ff"># Convert the image to PNG and print it to the file PICTURE</font>
|
|
<font color="#a52a2a"><b>print</b></font> <font color="#008b8b">PICTURE</font> <font color="#008b8b">$im</font>->png;
|
|
<font color="#a52a2a"><b>close</b></font> <font color="#008b8b">PICTURE</font>;
|
|
</pre>
|
|
<p>
|
|
This is the example given in the
|
|
<a href= http://stein.cshl.org/WWW/software/GD/>GD man page</a>
|
|
with little modifications. This produces a small rectangle
|
|
with a red oval with blue border. Let's dissect the program.
|
|
<p>
|
|
One of the first things you do with GD library, is create an image handle to
|
|
work with. The line
|
|
<pre>
|
|
$im = new GD::Image($width, $height)
|
|
</pre>
|
|
<p>
|
|
creates and image with the specified width and height. You can also create
|
|
an image from an existing image as well. It is useful for manipulating existing
|
|
images. We will see an example on this in the later part of the article.
|
|
<p>
|
|
Next we need to allocate some colors. As you can guess, the RGB intensities
|
|
need to be specified for initializing colors. Since we will be using lots of
|
|
colors, let's write a small function which will initialize a bunch of colors
|
|
for use.
|
|
<pre>
|
|
Text version of the file can be found <a href=misc/padala/init_colors.pl.txt>here</a>.
|
|
<font color="#0000ff"># Save this as init_colors.pl </font>
|
|
<font color="#0000ff"># Other scripts call this function</font>
|
|
</font>
|
|
<font color="#a52a2a"><b>sub</b></font><font color="#008b8b"> </font><font color="#008b8b">InitColors</font><font color="#008b8b"> </font>{
|
|
<font color="#a52a2a"><b>my</b></font>(<font color="#008b8b">$im</font>) = <font color="#008b8b">$_</font>[<font color="#ff00ff">0</font>];
|
|
<font color="#0000ff"># Allocate colors</font>
|
|
<font color="#008b8b">$white</font> = <font color="#008b8b">$im</font>->colorAllocate(<font color="#ff00ff">255</font>,<font color="#ff00ff">255</font>,<font color="#ff00ff">255</font>);
|
|
<font color="#008b8b">$black</font> = <font color="#008b8b">$im</font>->colorAllocate(<font color="#ff00ff">0</font>,<font color="#ff00ff">0</font>,<font color="#ff00ff">0</font>);
|
|
<font color="#008b8b">$red</font> = <font color="#008b8b">$im</font>->colorAllocate(<font color="#ff00ff">255</font>,<font color="#ff00ff">0</font>,<font color="#ff00ff">0</font>);
|
|
<font color="#008b8b">$blue</font> = <font color="#008b8b">$im</font>->colorAllocate(<font color="#ff00ff">0</font>,<font color="#ff00ff">0</font>,<font color="#ff00ff">255</font>);
|
|
<font color="#008b8b">$green</font> = <font color="#008b8b">$im</font>->colorAllocate(<font color="#ff00ff">0</font>, <font color="#ff00ff">255</font>, <font color="#ff00ff">0</font>);
|
|
|
|
<font color="#008b8b">$brown</font> = <font color="#008b8b">$im</font>->colorAllocate(<font color="#ff00ff">255</font>, <font color="#ff00ff">0x99</font>, <font color="#ff00ff">0</font>);
|
|
<font color="#008b8b">$violet</font> = <font color="#008b8b">$im</font>->colorAllocate(<font color="#ff00ff">255</font>, <font color="#ff00ff">0</font>, <font color="#ff00ff">255</font>);
|
|
<font color="#008b8b">$yellow</font> = <font color="#008b8b">$im</font>->colorAllocate(<font color="#ff00ff">255</font>, <font color="#ff00ff">255</font>, <font color="#ff00ff">0</font>);
|
|
}
|
|
</pre>
|
|
<p>
|
|
I often refer to this <a href=http://www.hypersolutions.org/pages/rgbhex.html>
|
|
page</a> for some nice rgb combinations.
|
|
<p>
|
|
The next few lines are straightforward and pretty much self-explanatory.
|
|
The last lines regarding the file creation require special mention.
|
|
Since we will be writing an image to a file, we need to put the file handle
|
|
in binary mode with
|
|
<pre>
|
|
binmode MYFILEHANDLE;
|
|
</pre>
|
|
<p> This actually is a no-op on most UNIX-like systems.
|
|
<p>
|
|
Then we write to the file with the usual print command. GD can print the image
|
|
in various formats. For example if you want to print a jpeg image instead of
|
|
png, all you need to do is
|
|
<pre>
|
|
print MYFILEHANDLE $im->jpeg;
|
|
</pre>
|
|
|
|
<h3> Simple Drawing </h3>
|
|
<p>
|
|
GD offers some simple drawing primitives which can be combined to generate complex
|
|
graphics. Examine the following script that gives a whirlwind tour of all the
|
|
simple primitives.
|
|
<pre>
|
|
Text version of the file can be found <a href=misc/padala/drawing.pl.txt>here</a>.
|
|
<font color="#a020f0">#!/usr/local/bin/perl</font>
|
|
<font color="#0000ff"># Change above line to path to your perl binary</font>
|
|
|
|
<font color="#a52a2a"><b>use </b></font>GD;
|
|
<font color="#a52a2a"><b>do</b></font> <font color="#ff00ff">"</font><font color="#ff00ff">init_colors.pl</font><font color="#ff00ff">"</font>;
|
|
|
|
<font color="#0000ff"># Create a new image</font>
|
|
<font color="#008b8b">$im</font> = <font color="#a52a2a"><b>new</b></font> GD::Image(<font color="#ff00ff">640</font>,<font color="#ff00ff">400</font>);
|
|
|
|
<font color="#0000ff"># Allocate some colors</font>
|
|
<font color="#008b8b">&InitColors</font>(<font color="#008b8b">$im</font>);
|
|
|
|
<font color="#0000ff"># Make the background transparent and interlaced</font>
|
|
<font color="#008b8b">$im</font>->transparent(<font color="#008b8b">$white</font>);
|
|
<font color="#008b8b">$im</font>->interlaced(<font color="#ff00ff">'</font><font color="#ff00ff">true</font><font color="#ff00ff">'</font>);
|
|
|
|
<font color="#008b8b">$x1</font> = <font color="#ff00ff">10</font>;
|
|
<font color="#008b8b">$y1</font> = <font color="#ff00ff">10</font>;
|
|
<font color="#008b8b">$x2</font> = <font color="#ff00ff">200</font>;
|
|
<font color="#008b8b">$y2</font> = <font color="#ff00ff">200</font>;
|
|
|
|
<font color="#0000ff"># Draw a border</font>
|
|
<font color="#008b8b">$im</font>->rectangle(<font color="#ff00ff">0</font>, <font color="#ff00ff">0</font>, <font color="#ff00ff">639</font>, <font color="#ff00ff">399</font>, <font color="#008b8b">$black</font>);
|
|
<font color="#0000ff"># A line</font>
|
|
<font color="#008b8b">$im</font>->line(<font color="#008b8b">$x1</font>,<font color="#008b8b">$y1</font>,<font color="#008b8b">$x2</font>,<font color="#008b8b">$y2</font>,<font color="#008b8b">$red</font>);
|
|
<font color="#0000ff"># A Dashed Line</font>
|
|
<font color="#008b8b">$im</font>->dashedLine(<font color="#008b8b">$x1</font> + <font color="#ff00ff">100</font>, <font color="#008b8b">$y1</font>, <font color="#008b8b">$x2</font>, <font color="#008b8b">$y2</font>, <font color="#008b8b">$blue</font>);
|
|
<font color="#0000ff"># Draw a rectangle</font>
|
|
<font color="#008b8b">$im</font>->rectangle(<font color="#008b8b">$x1</font> + <font color="#ff00ff">200</font>, <font color="#008b8b">$y1</font>, <font color="#008b8b">$x2</font> + <font color="#ff00ff">200</font>, <font color="#008b8b">$y2</font>, <font color="#008b8b">$green</font>);
|
|
<font color="#0000ff"># A filled rectangle</font>
|
|
<font color="#008b8b">$im</font>->filledRectangle(<font color="#008b8b">$x1</font> + <font color="#ff00ff">400</font>, <font color="#008b8b">$y1</font>, <font color="#008b8b">$x2</font> + <font color="#ff00ff">400</font>, <font color="#008b8b">$y2</font>, <font color="#008b8b">$brown</font>);
|
|
<font color="#0000ff"># A circle</font>
|
|
<font color="#008b8b">$im</font>->arc(<font color="#008b8b">$x1</font> + <font color="#ff00ff">100</font>, <font color="#008b8b">$y1</font> + <font color="#ff00ff">200</font> + <font color="#ff00ff">100</font>, <font color="#ff00ff">50</font>, <font color="#ff00ff">50</font>, <font color="#ff00ff">0</font>, <font color="#ff00ff">360</font>, <font color="#008b8b">$violet</font>);
|
|
|
|
<font color="#0000ff"># A polygon</font>
|
|
<font color="#0000ff"># Make the polygon</font>
|
|
<font color="#008b8b">$poly</font> = <font color="#a52a2a"><b>new</b></font> GD::Polygon;
|
|
<font color="#008b8b">$poly</font>->addPt(<font color="#008b8b">$x1</font> + <font color="#ff00ff">200</font>, <font color="#008b8b">$y1</font> + <font color="#ff00ff">200</font>);
|
|
<font color="#008b8b">$poly</font>->addPt(<font color="#008b8b">$x1</font> + <font color="#ff00ff">250</font>, <font color="#008b8b">$y1</font> + <font color="#ff00ff">230</font>);
|
|
<font color="#008b8b">$poly</font>->addPt(<font color="#008b8b">$x1</font> + <font color="#ff00ff">300</font>, <font color="#008b8b">$y1</font> + <font color="#ff00ff">310</font>);
|
|
<font color="#008b8b">$poly</font>->addPt(<font color="#008b8b">$x1</font> + <font color="#ff00ff">400</font>, <font color="#008b8b">$y1</font> + <font color="#ff00ff">300</font>);
|
|
<font color="#0000ff"># Draw it</font>
|
|
<font color="#008b8b">$im</font>->polygon(<font color="#008b8b">$poly</font>, <font color="#008b8b">$yellow</font>);
|
|
|
|
<font color="#0000ff"># Open a file for writing </font>
|
|
<font color="#a52a2a"><b>open</b></font>(<font color="#008b8b">PICTURE</font>, <font color="#ff00ff">"</font><font color="#ff00ff">>picture.png</font><font color="#ff00ff">"</font>) <font color="#a52a2a"><b>or</b></font> <font color="#a52a2a"><b>die</b></font>(<font color="#ff00ff">"</font><font color="#ff00ff">Cannot open file for writing</font><font color="#ff00ff">"</font>);
|
|
|
|
<font color="#0000ff"># Make sure we are writing to a binary stream</font>
|
|
<font color="#a52a2a"><b>binmode</b></font> <font color="#008b8b">PICTURE</font>;
|
|
|
|
<font color="#0000ff"># Convert the image to PNG and print it to the file PICTURE</font>
|
|
<font color="#a52a2a"><b>print</b></font> <font color="#008b8b">PICTURE</font> <font color="#008b8b">$im</font>->png;
|
|
<font color="#a52a2a"><b>close</b></font> <font color="#008b8b">PICTURE</font>;
|
|
</pre>
|
|
<p>
|
|
The output looks like
|
|
<a href="misc/padala/picture1.png">this</a>.
|
|
<p>
|
|
The above script is self-explanatory. The polygon needs a little bit
|
|
of explanation. In order to draw a polygon, you first have to make the polygon and then
|
|
draw it. Of course, a polygon must have at least three vertices.
|
|
|
|
<h3> Drawing Text </h3>
|
|
<p>
|
|
So what about text? You can draw text in some of the simple fonts
|
|
provided by GD or use a True Type font available on your system.
|
|
There are two simple functions available to draw text.
|
|
|
|
<pre>
|
|
|
|
# Draw the text
|
|
$im->string($font, $x, $y, $string, $color);
|
|
|
|
# Print text rotated 90 degrees
|
|
$im->stringUp($font, $x, $y, $string, $color);
|
|
|
|
</pre>
|
|
|
|
The following script shows various simple fonts provided by GD.
|
|
<pre>
|
|
Text version of the file can be found <a href=misc/padala/text.pl.txt>here</a>.
|
|
<font color="#a020f0">#!/usr/local/bin/perl</font>
|
|
<font color="#0000ff"># Change above line to path to your perl binary</font>
|
|
|
|
<font color="#a52a2a"><b>use </b></font>GD;
|
|
<font color="#a52a2a"><b>do</b></font> <font color="#ff00ff">"</font><font color="#ff00ff">init_colors.pl</font><font color="#ff00ff">"</font>;
|
|
|
|
<font color="#0000ff"># Create a new image</font>
|
|
<font color="#008b8b">$im</font> = <font color="#a52a2a"><b>new</b></font> GD::Image(<font color="#ff00ff">200</font>, <font color="#ff00ff">80</font>);
|
|
|
|
<font color="#0000ff"># Allocate some colors</font>
|
|
<font color="#008b8b">&InitColors</font>(<font color="#008b8b">$im</font>);
|
|
|
|
<font color="#0000ff"># Make the background transparent and interlaced</font>
|
|
<font color="#008b8b">$im</font>->transparent(<font color="#008b8b">$white</font>);
|
|
<font color="#008b8b">$im</font>->interlaced(<font color="#ff00ff">'</font><font color="#ff00ff">true</font><font color="#ff00ff">'</font>);
|
|
|
|
<font color="#0000ff"># Create a Border around the image</font>
|
|
<font color="#008b8b">$im</font>->rectangle(<font color="#ff00ff">0</font>, <font color="#ff00ff">0</font>, <font color="#ff00ff">199</font>, <font color="#ff00ff">79</font>, <font color="#008b8b">$black</font>);
|
|
<font color="#008b8b">$x1</font> = <font color="#ff00ff">2</font>;
|
|
<font color="#008b8b">$y1</font> = <font color="#ff00ff">2</font>;
|
|
|
|
<font color="#0000ff"># Draw text in small font</font>
|
|
<font color="#008b8b">$im</font>->string(gdSmallFont, <font color="#008b8b">$x1</font>, <font color="#008b8b">$y1</font>, <font color="#ff00ff">"</font><font color="#ff00ff">Small font</font><font color="#ff00ff">"</font>, <font color="#008b8b">$blue</font>);
|
|
<font color="#008b8b">$im</font>->string(gdMediumBoldFont, <font color="#008b8b">$x1</font>, <font color="#008b8b">$y1</font> + <font color="#ff00ff">20</font>, <font color="#ff00ff">"</font><font color="#ff00ff">Medium Bold Font</font><font color="#ff00ff">"</font>, <font color="#008b8b">$green</font>);
|
|
<font color="#008b8b">$im</font>->string(gdLargeFont, <font color="#008b8b">$x1</font>, <font color="#008b8b">$y1</font> + <font color="#ff00ff">40</font>, <font color="#ff00ff">"</font><font color="#ff00ff">Large font</font><font color="#ff00ff">"</font>, <font color="#008b8b">$red</font>);
|
|
<font color="#008b8b">$im</font>->string(gdGiantFont, <font color="#008b8b">$x1</font>, <font color="#008b8b">$y1</font> + <font color="#ff00ff">60</font>, <font color="#ff00ff">"</font><font color="#ff00ff">Giant font</font><font color="#ff00ff">"</font>, <font color="#008b8b">$black</font>);
|
|
|
|
<font color="#0000ff"># Open a file for writing </font>
|
|
<font color="#a52a2a"><b>open</b></font>(<font color="#008b8b">PICTURE</font>, <font color="#ff00ff">"</font><font color="#ff00ff">>picture.png</font><font color="#ff00ff">"</font>) <font color="#a52a2a"><b>or</b></font> <font color="#a52a2a"><b>die</b></font>(<font color="#ff00ff">"</font><font color="#ff00ff">Cannot open file for writing</font><font color="#ff00ff">"</font>);
|
|
|
|
<font color="#0000ff"># Make sure we are writing to a binary stream</font>
|
|
<font color="#a52a2a"><b>binmode</b></font> <font color="#008b8b">PICTURE</font>;
|
|
|
|
<font color="#0000ff"># Convert the image to PNG and print it to the file PICTURE</font>
|
|
<font color="#a52a2a"><b>print</b></font> <font color="#008b8b">PICTURE</font> <font color="#008b8b">$im</font>->png;
|
|
<font color="#a52a2a"><b>close</b></font> <font color="#008b8b">PICTURE</font>;
|
|
</pre>
|
|
<p>
|
|
The output picture looks like this.<br>
|
|
<img alt="Output image of above script" src=misc/padala/picture2.png width=200 height=80>
|
|
<p>
|
|
As you can see, these fonts are quite limited and not so attractive. The
|
|
following section shows the usage of True Type Fonts with GD
|
|
|
|
<h3> True Type Fonts </h3>
|
|
<p>
|
|
You can use the true type fonts available on your system to draw some nice
|
|
text. The function <code>stringFT</code> is used to draw in TTF font.
|
|
<pre>
|
|
# $fontname is an absolute or relative path to a TrueType font.
|
|
stringFT($fgcolor,$fgcolor,$fontname,$ptsize,$angle,$x,$y,$string);
|
|
</pre>
|
|
<p>
|
|
Here's an example showing the usage
|
|
<pre>
|
|
Text version of the file can be found <a href=misc/padala/ttf.pl.txt>here</a>.
|
|
<font color="#a020f0">#!/usr/local/bin/perl</font>
|
|
<font color="#0000ff"># Change above line to path to your perl binary</font>
|
|
|
|
<font color="#a52a2a"><b>use </b></font>GD;
|
|
<font color="#a52a2a"><b>do</b></font> <font color="#ff00ff">"</font><font color="#ff00ff">init_colors.pl</font><font color="#ff00ff">"</font>;
|
|
|
|
<font color="#0000ff"># Create a new image</font>
|
|
<font color="#008b8b">$im</font> = <font color="#a52a2a"><b>new</b></font> GD::Image(<font color="#ff00ff">270</font>, <font color="#ff00ff">80</font>);
|
|
|
|
<font color="#0000ff"># Allocate some colors</font>
|
|
<font color="#008b8b">&InitColors</font>(<font color="#008b8b">$im</font>);
|
|
|
|
<font color="#0000ff"># Make the background transparent and interlaced</font>
|
|
<font color="#008b8b">$im</font>->transparent(<font color="#008b8b">$white</font>);
|
|
<font color="#008b8b">$im</font>->interlaced(<font color="#ff00ff">'</font><font color="#ff00ff">true</font><font color="#ff00ff">'</font>);
|
|
|
|
<font color="#008b8b">$im</font>->rectangle(<font color="#ff00ff">0</font>, <font color="#ff00ff">0</font>, <font color="#ff00ff">269</font>, <font color="#ff00ff">79</font>, <font color="#008b8b">$black</font>);
|
|
|
|
<font color="#008b8b">$x1</font> = <font color="#ff00ff">10</font>;
|
|
<font color="#008b8b">$y1</font> = <font color="#ff00ff">20</font>;
|
|
|
|
<font color="#0000ff"># Draw text in a TTF font</font>
|
|
<font color="#008b8b">$font</font> = <font color="#ff00ff">"</font><font color="#ff00ff">/usr/X11R6/lib/X11/fonts/TTF/luxisri.ttf</font><font color="#ff00ff">"</font>;
|
|
<font color="#008b8b">$im</font>->stringFT(<font color="#008b8b">$red</font>, <font color="#008b8b">$font</font>, <font color="#ff00ff">15</font>, <font color="#ff00ff">0</font>, <font color="#008b8b">$x1</font>, <font color="#008b8b">$y1</font>, <font color="#ff00ff">"</font><font color="#ff00ff">A TTF font</font><font color="#ff00ff">"</font>);
|
|
|
|
<font color="#008b8b">$anotherfont</font> = <font color="#ff00ff">"</font><font color="#ff00ff">/usr/share/fonts/default/TrueType/starbats.ttf</font><font color="#ff00ff">"</font>;
|
|
<font color="#008b8b">$im</font>->stringFT(<font color="#008b8b">$blue</font>, <font color="#008b8b">$font</font>, <font color="#ff00ff">20</font>, <font color="#ff00ff">0</font>, <font color="#008b8b">$x1</font>, <font color="#008b8b">$y1</font> + <font color="#ff00ff">40</font>, <font color="#ff00ff">"</font><font color="#ff00ff">Another one here !!!</font><font color="#ff00ff">"</font>);
|
|
|
|
<font color="#0000ff"># Open a file for writing </font>
|
|
<font color="#a52a2a"><b>open</b></font>(<font color="#008b8b">PICTURE</font>, <font color="#ff00ff">"</font><font color="#ff00ff">>picture.png</font><font color="#ff00ff">"</font>) <font color="#a52a2a"><b>or</b></font> <font color="#a52a2a"><b>die</b></font>(<font color="#ff00ff">"</font><font color="#ff00ff">Cannot open file for writing</font><font color="#ff00ff">"</font>);
|
|
|
|
<font color="#0000ff"># Make sure we are writing to a binary stream</font>
|
|
<font color="#a52a2a"><b>binmode</b></font> <font color="#008b8b">PICTURE</font>;
|
|
|
|
<font color="#0000ff"># Convert the image to PNG and print it to the file PICTURE</font>
|
|
<font color="#a52a2a"><b>print</b></font> <font color="#008b8b">PICTURE</font> <font color="#008b8b">$im</font>->png;
|
|
<font color="#a52a2a"><b>close</b></font> <font color="#008b8b">PICTURE</font>;
|
|
</pre>
|
|
<p>
|
|
The output looks like this.<br>
|
|
<img alt="Output image for above script" src=misc/padala/picture3.png width=270 height=80>
|
|
|
|
<h3> Let's go Online </h3>
|
|
<p>
|
|
Now that we have seen some basic uses of GD, let's turn our attention to
|
|
web graphics. So how do you output an image through CGI? Simple. Add the
|
|
following lines to the scripts instead of printing to a file.
|
|
<pre>
|
|
# To disable buffering of image content.
|
|
select(STDOUT);
|
|
$| = 1;
|
|
undef $/;
|
|
|
|
print "Content-type: image/jpeg\n\n";
|
|
print $im->jpeg(100);
|
|
</pre>
|
|
<p>
|
|
This is all you need to know about CGI for now. If you already know CGI,
|
|
you can enhance your code for handling complex web interaction. Let's write a small program which
|
|
reads an image and displays a resized version of it. It might be useful
|
|
for showing thumbnails.
|
|
<pre>
|
|
Text version of the file can be found <a href=misc/padala/resize.cgi.txt>here</a>.
|
|
<font color="#a020f0">#!/usr/local/bin/perl -wT</font>
|
|
<font color="#0000ff"># Change above line to path to your perl binary</font>
|
|
|
|
<font color="#a52a2a"><b>use </b></font>CGI <font color="#ff00ff">'</font><font color="#ff00ff">:standard</font><font color="#ff00ff">'</font>;
|
|
<font color="#a52a2a"><b>use </b></font>GD;
|
|
|
|
<font color="#0000ff"># create a new image</font>
|
|
<font color="#008b8b">$image_file</font> = <font color="#ff00ff">"</font><font color="#ff00ff">images/surfing.jpg</font><font color="#ff00ff">"</font>;
|
|
<font color="#008b8b">$im</font> = GD::Image->newFromJpeg(<font color="#008b8b">$image_file</font>);
|
|
(<font color="#008b8b">$width</font>, <font color="#008b8b">$height</font>) = <font color="#008b8b">$im</font>->getBounds();
|
|
<font color="#008b8b">$newwidth</font> = <font color="#008b8b">$width</font> / <font color="#ff00ff">3</font>;
|
|
<font color="#008b8b">$newheight</font> = <font color="#008b8b">$height</font> / <font color="#ff00ff">3</font>;
|
|
<font color="#008b8b">$outim</font> = <font color="#a52a2a"><b>new</b></font> GD::Image(<font color="#008b8b">$newwidth</font>, <font color="#008b8b">$newheight</font>);
|
|
|
|
<font color="#0000ff"># make the background transparent and interlaced</font>
|
|
<font color="#008b8b">$outim</font>->copyResized(<font color="#008b8b">$im</font>, <font color="#ff00ff">0</font>, <font color="#ff00ff">0</font>, <font color="#ff00ff">0</font>, <font color="#ff00ff">0</font>, <font color="#008b8b">$newwidth</font>, <font color="#008b8b">$newheight</font>, <font color="#008b8b">$width</font>, <font color="#008b8b">$height</font>);
|
|
|
|
<font color="#0000ff"># make sure we are writing to a binary stream</font>
|
|
<font color="#a52a2a"><b>binmode</b></font> <font color="#008b8b">STDOUT</font>;
|
|
<font color="#a52a2a"><b>select</b></font>(STDOUT);
|
|
<font color="#008b8b">$|</font> = <font color="#ff00ff">1</font>;
|
|
<font color="#a52a2a"><b>undef</b></font> <font color="#008b8b">$/</font>;
|
|
<font color="#a52a2a"><b>print</b></font> <font color="#ff00ff">"</font><font color="#ff00ff">Content-type: image/jpeg</font><font color="#6a5acd">\n\n</font><font color="#ff00ff">"</font>;
|
|
<font color="#a52a2a"><b>print</b></font> <font color="#008b8b">$outim</font>->jpeg();
|
|
</pre>
|
|
<p>
|
|
In this example, the function newFromJpeg() reads a jpeg file. Then we
|
|
then calculated the boundaries and resized it accordingly. A demo of the resizing
|
|
can be found <a href=http://www.cise.ufl.edu/~ppadala/perl/exploring/cgi-bin/resize.cgi>here</a>
|
|
|
|
<h3> A Photo Album </h3>
|
|
<p>
|
|
With this resizing knowledge we can create a small online photo album. In this
|
|
we use resizing to show
|
|
smaller images and display the original image when the user clicks on the smaller images.
|
|
<pre>
|
|
Text version of the file can be found <a href=misc/padala/album.cgi.txt>here</a>.
|
|
<font color="#a020f0">#!/usr/local/bin/perl -wT</font>
|
|
<font color="#0000ff"># Change above line to path to your perl binary</font>
|
|
|
|
<font color="#a52a2a"><b>use </b></font>CGI <font color="#ff00ff">'</font><font color="#ff00ff">:standard</font><font color="#ff00ff">'</font>;
|
|
<font color="#a52a2a"><b>use </b></font>GD;
|
|
|
|
<font color="#008b8b">$imnum</font> = param(<font color="#ff00ff">'</font><font color="#ff00ff">imnum</font><font color="#ff00ff">'</font>);
|
|
<font color="#a52a2a"><b>if</b></font>(!<font color="#a52a2a"><b>defined</b></font>(<font color="#008b8b">$imnum</font>)) {
|
|
<font color="#008b8b">$imnum</font> = <font color="#ff00ff">0</font>;
|
|
}
|
|
|
|
<font color="#008b8b">$orig</font> = param(<font color="#ff00ff">'</font><font color="#ff00ff">orig</font><font color="#ff00ff">'</font>);
|
|
<font color="#a52a2a"><b>if</b></font>(!<font color="#a52a2a"><b>defined</b></font>(<font color="#008b8b">$imnum</font>)) {
|
|
<font color="#008b8b">$orig</font> = <font color="#ff00ff">0</font>;
|
|
}
|
|
|
|
<font color="#a52a2a"><b>select</b></font>(STDOUT);
|
|
<font color="#008b8b">$|</font> = <font color="#ff00ff">1</font>;
|
|
|
|
<font color="#008b8b">@images</font> = (<font color="#ff00ff">"</font><font color="#ff00ff">surfing.jpg</font><font color="#ff00ff">"</font>, <font color="#ff00ff">"</font><font color="#ff00ff">boat.jpg</font><font color="#ff00ff">"</font>, <font color="#ff00ff">"</font><font color="#ff00ff">boston-view.jpg</font><font color="#ff00ff">"</font>, <font color="#ff00ff">"</font><font color="#ff00ff">seashore.jpg</font><font color="#ff00ff">"</font>);
|
|
|
|
<font color="#a52a2a"><b>print</b></font> <font color="#ff00ff">"</font><font color="#ff00ff">Content-type: text/html</font><font color="#6a5acd">\n\n</font><font color="#ff00ff">"</font>;
|
|
<font color="#a52a2a"><b>print</b></font> <font color="#ff00ff">"</font><font color="#ff00ff"><font color=green>Click on the image to make it bigger or smaller<br></font>
|
|
<font color="#ff00ff">You can browse through the small images using the buttons or by clicking</font>
|
|
<font color="#ff00ff">on the numbers </font></font><font color="#6a5acd">\n</font><font color="#ff00ff">"</font>;
|
|
<font color="#a52a2a"><b>print</b></font> <font color="#ff00ff">"</font><font color="#ff00ff"><table><tr></font><font color="#6a5acd">\n</font><font color="#ff00ff">"</font>;
|
|
|
|
<font color="#a52a2a"><b>if</b></font>(<font color="#008b8b">$imnum</font> > <font color="#ff00ff">0</font> && <font color="#008b8b">$imnum</font> < <font color="#008b8b">@images</font>) {
|
|
<font color="#a52a2a"><b>printf</b></font> <font color="#ff00ff">"</font><font color="#ff00ff"><td><a href=album.cgi?imnum=</font><font color="#008b8b">%d</font><font color="#ff00ff">><img src=images/prev.gif border=0></a></font><font color="#6a5acd">\n</font><font color="#ff00ff">"</font>, <font color="#008b8b">$imnum</font><font color="#ff00ff">-1</font>;
|
|
}
|
|
|
|
<font color="#a52a2a"><b>if</b></font>(<font color="#008b8b">$imnum</font> >= <font color="#ff00ff">0</font> && <font color="#008b8b">$imnum</font> < <font color="#008b8b">@images</font> - <font color="#ff00ff">1</font>) {
|
|
<font color="#a52a2a"><b>printf</b></font> <font color="#ff00ff">"</font><font color="#ff00ff"><td><a href=album.cgi?imnum=</font><font color="#008b8b">%d</font><font color="#ff00ff">><img src=images/next.gif border=0></a></font><font color="#6a5acd">\n</font><font color="#ff00ff">"</font>, <font color="#008b8b">$imnum</font><font color="#ff00ff">+1</font>;
|
|
}
|
|
|
|
<font color="#a52a2a"><b>print</b></font> <font color="#ff00ff">"</font><font color="#ff00ff"><td></font><font color="#ff00ff">"</font>;
|
|
<font color="#a52a2a"><b>for</b></font>(<font color="#008b8b">$i</font> = <font color="#ff00ff">0</font>; <font color="#008b8b">$i</font> < <font color="#008b8b">@images</font>; ++<font color="#008b8b">$i</font>) {
|
|
<font color="#a52a2a"><b>print</b></font> <font color="#ff00ff">"</font><font color="#ff00ff"><a href=album.cgi?imnum=</font><font color="#008b8b">$i</font><font color="#ff00ff">></font><font color="#008b8b">$i</font><font color="#ff00ff">|</a></font><font color="#6a5acd">\n</font><font color="#ff00ff">"</font>;
|
|
}
|
|
<font color="#a52a2a"><b>print</b></font> <font color="#ff00ff">"</font><font color="#ff00ff"></tr></table></font><font color="#6a5acd">\n</font><font color="#ff00ff">"</font>;
|
|
<font color="#a52a2a"><b>if</b></font>(<font color="#008b8b">$imnum</font> < <font color="#ff00ff">0</font> || <font color="#008b8b">$imnum</font> >= <font color="#008b8b">@images</font>) {
|
|
<font color="#a52a2a"><b>print</b></font> <font color="#ff00ff">"</font><font color="#ff00ff"><b>No such image</b></font><font color="#ff00ff">"</font>;
|
|
<font color="#a52a2a"><b>exit</b></font>;
|
|
}
|
|
|
|
<font color="#a52a2a"><b>if</b></font>(<font color="#008b8b">$orig</font>) {
|
|
<font color="#a52a2a"><b>print</b></font> <font color="#ff00ff">"</font><font color="#ff00ff"><a href=album.cgi?imnum=</font><font color="#008b8b">$imnum</font><font color="#ff00ff">><img src=images/</font><font color="#008b8b">$images</font><font color="#ff00ff">[</font><font color="#008b8b">$imnum</font><font color="#ff00ff">] border=0></img></a></font><font color="#6a5acd">\n</font><font color="#ff00ff">"</font>;
|
|
}
|
|
<font color="#a52a2a"><b>else</b></font> {
|
|
<font color="#008b8b">$im</font> = GD::Image->newFromJpeg(<font color="#ff00ff">"</font><font color="#ff00ff">images/</font><font color="#008b8b">$images</font><font color="#ff00ff">[</font><font color="#008b8b">$imnum</font><font color="#ff00ff">]</font><font color="#ff00ff">"</font>);
|
|
<font color="#0000ff"># create a new image</font>
|
|
(<font color="#008b8b">$width</font>, <font color="#008b8b">$height</font>) = <font color="#008b8b">$im</font>->getBounds();
|
|
<font color="#008b8b">$newwidth</font> = <font color="#ff00ff">200</font>;
|
|
<font color="#008b8b">$newheight</font> = <font color="#ff00ff">200</font>;
|
|
<font color="#008b8b">$outim</font> = <font color="#a52a2a"><b>new</b></font> GD::Image(<font color="#008b8b">$newwidth</font>, <font color="#008b8b">$newheight</font>);
|
|
|
|
<font color="#008b8b">$outim</font>->copyResized(<font color="#008b8b">$im</font>, <font color="#ff00ff">0</font>, <font color="#ff00ff">0</font>, <font color="#ff00ff">0</font>, <font color="#ff00ff">0</font>, <font color="#008b8b">$newwidth</font>, <font color="#008b8b">$newheight</font>, <font color="#008b8b">$width</font>, <font color="#008b8b">$height</font>);
|
|
<font color="#008b8b">$tmpfile</font> = <font color="#ff00ff">"</font><font color="#ff00ff">images/tmp</font><font color="#008b8b">$imnum</font><font color="#ff00ff">.jpg</font><font color="#ff00ff">"</font>;
|
|
<font color="#a52a2a"><b>if</b></font> (<font color="#008b8b">$tmpfile</font> =~<font color="#a52a2a"><b> /</b></font><font color="#ff00ff">^</font><font color="#6a5acd">(</font><font color="#ff00ff">[-</font><font color="#6a5acd">\@\w</font><font color="#6a5acd">.</font><font color="#6a5acd">\/</font><font color="#ff00ff">]</font><font color="#6a5acd">+)</font><font color="#ff00ff">$</font><font color="#a52a2a"><b>/</b></font>) { <font color="#0000ff"># For the tainting stuff</font>
|
|
<font color="#008b8b">$tmpfile</font> = <font color="#008b8b">$1</font>;
|
|
}
|
|
<font color="#a52a2a"><b>else</b></font> {
|
|
<font color="#a52a2a"><b>print</b></font> <font color="#ff00ff">"</font><font color="#ff00ff">Should never happen</font><font color="#ff00ff">"</font>;
|
|
<font color="#a52a2a"><b>exit</b></font>; <font color="#0000ff"># Should never happen</font>
|
|
}
|
|
<font color="#a52a2a"><b>open</b></font>(<font color="#008b8b">TMP</font>, <font color="#ff00ff">"</font><font color="#ff00ff">></font><font color="#008b8b">$tmpfile</font><font color="#ff00ff">"</font>) || <font color="#a52a2a"><b>die</b></font>(<font color="#ff00ff">"</font><font color="#ff00ff">Cannot open file</font><font color="#ff00ff">"</font>);
|
|
<font color="#a52a2a"><b>binmode</b></font>(TMP);
|
|
<font color="#a52a2a"><b>print</b></font> <font color="#008b8b">TMP</font> <font color="#008b8b">$outim</font>->jpeg(<font color="#ff00ff">100</font>);
|
|
<font color="#a52a2a"><b>close</b></font>(TMP);
|
|
<font color="#a52a2a"><b>chmod</b></font>(<font color="#ff00ff">0644</font>, <font color="#008b8b">$tmpfile</font>);
|
|
<font color="#a52a2a"><b>print</b></font> <font color="#ff00ff">"</font><font color="#ff00ff"><a href=album.cgi?imnum=</font><font color="#008b8b">$imnum</font><font color="#ff00ff">&orig=1><img src=</font><font color="#008b8b">$tmpfile</font><font color="#ff00ff"> border=0></a></font><font color="#ff00ff">"</font>;
|
|
}
|
|
</pre>
|
|
<p>
|
|
This script uses a few CGI features. The function param returns the parameter
|
|
value, if supplied. This value is used to display the proper image. If
|
|
the user wants to see an original image, it is displayed. Otherwise a
|
|
temporary resized image is created and displayed.
|
|
<p>
|
|
A <a href=http://www.cise.ufl.edu/~ppadala/perl/exploring/cgi-bin/album.cgi>demo</a>
|
|
of the album is
|
|
<a href=http://www.cise.ufl.edu/~ppadala/perl/exploring/cgi-bin/album.cgi>here</a>
|
|
|
|
<h3> A Graphical Hit Counter </h3>
|
|
<p>
|
|
Now let us turn our attention to another popular web application "A Hit Counter".
|
|
There are many counter scripts available on web. Here's our attempt to
|
|
write one.
|
|
<p>
|
|
The counter works like this. Every time a web-page is accessed, the cgi script
|
|
records the hit count and creates an image on-the-fly. So why wait? Let's
|
|
write it.
|
|
<pre>
|
|
Text version of the file can be found <a href=misc/padala/counter.cgi.txt>here</a>.
|
|
<font color="#a020f0">#!/usr/local/bin/perl -wT</font>
|
|
<font color="#a52a2a"><b>use </b></font>CGI <font color="#ff00ff">'</font><font color="#ff00ff">:standard</font><font color="#ff00ff">'</font>;
|
|
<font color="#a52a2a"><b>use </b></font>GD;
|
|
<font color="#a52a2a"><b>use strict</b></font>;
|
|
|
|
<font color="#a52a2a"><b>my</b></font>(<font color="#008b8b">$LOCK_SH</font>, <font color="#008b8b">$LOCK_EX</font>, <font color="#008b8b">$LOCK_NB</font>, <font color="#008b8b">$LOCK_UN</font>);
|
|
|
|
<font color="#008b8b">$LOCK_SH</font> = <font color="#ff00ff">1</font>;
|
|
<font color="#008b8b">$LOCK_EX</font> = <font color="#ff00ff">2</font>;
|
|
<font color="#008b8b">$LOCK_NB</font> = <font color="#ff00ff">4</font>;
|
|
<font color="#008b8b">$LOCK_UN</font> = <font color="#ff00ff">8</font>;
|
|
|
|
<font color="#a52a2a"><b>select</b></font>(STDOUT);
|
|
<font color="#008b8b">$|</font> = <font color="#ff00ff">1</font>;
|
|
|
|
<font color="#008b8b">&main</font>;
|
|
|
|
<font color="#a52a2a"><b>sub</b></font><font color="#008b8b"> </font><font color="#008b8b">main</font><font color="#008b8b"> </font>{
|
|
<font color="#a52a2a"><b>my</b></font>(<font color="#008b8b">$id</font>, <font color="#008b8b">$iformat</font>, <font color="#008b8b">$show</font>);
|
|
|
|
<font color="#008b8b">$id</font> = param(<font color="#ff00ff">"</font><font color="#ff00ff">id</font><font color="#ff00ff">"</font>);
|
|
<font color="#008b8b">$iformat</font> = param(<font color="#ff00ff">"</font><font color="#ff00ff">iformat</font><font color="#ff00ff">"</font>);
|
|
|
|
<font color="#a52a2a"><b>my</b></font>(<font color="#008b8b">$counter_value</font>);
|
|
<font color="#008b8b">$counter_value</font> = <font color="#008b8b">&update_counter_value</font>(<font color="#008b8b">$id</font>);
|
|
|
|
<font color="#a52a2a"><b>chomp</b></font>(<font color="#008b8b">$counter_value</font>);
|
|
<font color="#a52a2a"><b>if</b></font>(<font color="#008b8b">$iformat</font> <font color="#a52a2a"><b>eq</b></font> <font color="#ff00ff">"</font><font color="#ff00ff">jpg</font><font color="#ff00ff">"</font> || <font color="#008b8b">$iformat</font> <font color="#a52a2a"><b>eq</b></font> <font color="#ff00ff">"</font><font color="#ff00ff">png</font><font color="#ff00ff">"</font>) {
|
|
<font color="#008b8b">&print_counter</font>(<font color="#008b8b">$iformat</font>, <font color="#008b8b">$counter_value</font>);
|
|
}
|
|
<font color="#a52a2a"><b>else</b></font> {
|
|
<font color="#008b8b">&print_error_image</font>(<font color="#ff00ff">"</font><font color="#ff00ff">Image format </font><font color="#008b8b">$iformat</font><font color="#ff00ff"> not supported</font><font color="#ff00ff">"</font>);
|
|
}
|
|
}
|
|
|
|
<font color="#a52a2a"><b>sub</b></font><font color="#008b8b"> </font><font color="#008b8b">print_counter</font><font color="#008b8b"> </font>{
|
|
<font color="#a52a2a"><b>my</b></font>(<font color="#008b8b">$iformat</font>, <font color="#008b8b">$counter_value</font>) = <font color="#008b8b">@_</font>;
|
|
<font color="#a52a2a"><b>my</b></font>(<font color="#008b8b">$COUNTER_SIZE</font>) = <font color="#ff00ff">4</font>;
|
|
|
|
<font color="#a52a2a"><b>my</b></font>(<font color="#008b8b">$im</font>) = GD::Image-><font color="#a52a2a"><b>new</b></font>(<font color="#ff00ff">"</font><font color="#ff00ff">${iformat}s/0.${iformat}</font><font color="#ff00ff">"</font>);
|
|
<font color="#a52a2a"><b>if</b></font>(!<font color="#a52a2a"><b>defined</b></font>(<font color="#008b8b">$im</font>)) {
|
|
<font color="#008b8b">&print_error_image</font>(<font color="#ff00ff">"</font><font color="#6a5acd">\$</font><font color="#ff00ff">im couldn't be initialized</font><font color="#ff00ff">"</font>);
|
|
<font color="#a52a2a"><b>exit</b></font>;
|
|
}
|
|
|
|
<font color="#a52a2a"><b>my</b></font>(<font color="#008b8b">$w</font>, <font color="#008b8b">$h</font>) = <font color="#008b8b">$im</font>->getBounds();
|
|
<font color="#a52a2a"><b>undef</b></font> <font color="#008b8b">$im</font>;
|
|
|
|
<font color="#a52a2a"><b>my</b></font>(<font color="#008b8b">$printim</font>) = GD::Image-><font color="#a52a2a"><b>new</b></font>(<font color="#008b8b">$w</font> * <font color="#008b8b">$COUNTER_SIZE</font>, <font color="#008b8b">$h</font>);
|
|
<font color="#008b8b">$printim</font>->colorAllocate(<font color="#ff00ff">255</font>, <font color="#ff00ff">255</font>, <font color="#ff00ff">255</font>);
|
|
|
|
<font color="#a52a2a"><b>my</b></font>(<font color="#008b8b">$pos</font>, <font color="#008b8b">$l</font>, <font color="#008b8b">$temp</font>, <font color="#008b8b">$digit</font>, <font color="#008b8b">$x</font>, <font color="#008b8b">$srcim</font>);
|
|
<font color="#008b8b">$x</font> = <font color="#ff00ff">0</font>;
|
|
<font color="#a52a2a"><b>for</b></font>(<font color="#008b8b">$pos</font> = <font color="#008b8b">$COUNTER_SIZE</font> - <font color="#ff00ff">1</font>; <font color="#008b8b">$pos</font> >= <font color="#ff00ff">0</font>; <font color="#008b8b">$pos</font>--) {
|
|
<font color="#a52a2a"><b>if</b></font>(<font color="#008b8b">$pos</font> > <font color="#a52a2a"><b>length</b></font>(<font color="#008b8b">$counter_value</font>) - <font color="#ff00ff">1</font>) {
|
|
<font color="#008b8b">$digit</font> = <font color="#ff00ff">0</font>;
|
|
}
|
|
<font color="#a52a2a"><b>else</b></font> {
|
|
<font color="#008b8b">$l</font> = <font color="#a52a2a"><b>length</b></font>(<font color="#008b8b">$counter_value</font>);
|
|
<font color="#008b8b">$temp</font> = <font color="#008b8b">$l</font> - <font color="#008b8b">$pos</font> - <font color="#ff00ff">1</font>;
|
|
<font color="#008b8b">$digit</font> = <font color="#a52a2a"><b>substr</b></font>(<font color="#008b8b">$counter_value</font>, <font color="#008b8b">$temp</font>, <font color="#ff00ff">1</font>);
|
|
}
|
|
<font color="#008b8b">$srcim</font> = GD::Image-><font color="#a52a2a"><b>new</b></font>(<font color="#ff00ff">"</font><font color="#ff00ff">${iformat}s/${digit}.${iformat}</font><font color="#ff00ff">"</font>);
|
|
<font color="#008b8b">$printim</font>->copy(<font color="#008b8b">$srcim</font>, <font color="#008b8b">$x</font>, <font color="#ff00ff">0</font>, <font color="#ff00ff">0</font>, <font color="#ff00ff">0</font>, <font color="#008b8b">$w</font>, <font color="#008b8b">$h</font>);
|
|
<font color="#008b8b">$x</font> += <font color="#008b8b">$w</font>;
|
|
<font color="#a52a2a"><b>undef</b></font> <font color="#008b8b">$srcim</font>;
|
|
}
|
|
<font color="#a52a2a"><b>if</b></font>(<font color="#008b8b">$iformat</font> <font color="#a52a2a"><b>eq</b></font> <font color="#ff00ff">"</font><font color="#ff00ff">jpg</font><font color="#ff00ff">"</font>) {
|
|
<font color="#a52a2a"><b>print</b></font> <font color="#ff00ff">"</font><font color="#ff00ff">Content-type: image/jpeg</font><font color="#6a5acd">\n\n</font><font color="#ff00ff">"</font>;
|
|
<font color="#a52a2a"><b>print</b></font> <font color="#008b8b">$printim</font>->jpeg(<font color="#ff00ff">100</font>);
|
|
}
|
|
<font color="#a52a2a"><b>else</b></font> {
|
|
<font color="#a52a2a"><b>print</b></font> <font color="#ff00ff">"</font><font color="#ff00ff">Content-type: image/png</font><font color="#6a5acd">\n\n</font><font color="#ff00ff">"</font>;
|
|
<font color="#a52a2a"><b>print</b></font> <font color="#008b8b">$printim</font>->png;
|
|
}
|
|
}
|
|
|
|
<font color="#a52a2a"><b>sub</b></font><font color="#008b8b"> </font><font color="#008b8b">print_error_image</font><font color="#008b8b"> </font>{
|
|
|
|
<font color="#a52a2a"><b>my</b></font> <font color="#008b8b">$error_string</font> = <font color="#008b8b">$_</font>[<font color="#ff00ff">0</font>];
|
|
<font color="#a52a2a"><b>my</b></font> <font color="#008b8b">$im</font> = <font color="#a52a2a"><b>new</b></font> GD::Image(
|
|
gdMediumBoldFont->width * <font color="#a52a2a"><b>length</b></font>(<font color="#008b8b">$error_string</font>),
|
|
gdMediumBoldFont->height);
|
|
|
|
<font color="#008b8b">$im</font>->colorAllocate(<font color="#ff00ff">255</font>, <font color="#ff00ff">255</font>, <font color="#ff00ff">255</font>);
|
|
<font color="#a52a2a"><b>my</b></font> <font color="#008b8b">$red</font> = <font color="#008b8b">$im</font>->colorAllocate(<font color="#ff00ff">255</font>, <font color="#ff00ff">0</font>, <font color="#ff00ff">0</font>);
|
|
<font color="#008b8b">$im</font>->string(gdMediumBoldFont, <font color="#ff00ff">0</font>, <font color="#ff00ff">0</font>, <font color="#008b8b">$error_string</font>, <font color="#008b8b">$red</font>);
|
|
<font color="#a52a2a"><b>print</b></font> <font color="#ff00ff">"</font><font color="#ff00ff">Content-type: image/jpeg</font><font color="#6a5acd">\n\n</font><font color="#ff00ff">"</font>;
|
|
<font color="#a52a2a"><b>print</b></font> <font color="#008b8b">$im</font>->jpeg(<font color="#ff00ff">100</font>);
|
|
<font color="#a52a2a"><b>exit</b></font>;
|
|
}
|
|
|
|
<font color="#a52a2a"><b>sub</b></font><font color="#008b8b"> </font><font color="#008b8b">update_counter_value</font><font color="#008b8b"> </font>{
|
|
<font color="#a52a2a"><b>my</b></font>(<font color="#008b8b">$file_name</font>, <font color="#008b8b">$counter_value</font>);
|
|
|
|
<font color="#008b8b">$file_name</font> = <font color="#ff00ff">"</font><font color="#008b8b">$_</font><font color="#ff00ff">[0].counter</font><font color="#ff00ff">"</font>;
|
|
<font color="#a52a2a"><b>if</b></font> (<font color="#008b8b">$file_name</font> =~<font color="#a52a2a"><b> /</b></font><font color="#ff00ff">^</font><font color="#6a5acd">(</font><font color="#ff00ff">[-</font><font color="#6a5acd">\@\w</font><font color="#6a5acd">.</font><font color="#ff00ff">]</font><font color="#6a5acd">+)</font><font color="#ff00ff">$</font><font color="#a52a2a"><b>/</b></font>) { <font color="#0000ff"># For the tainting stuff</font>
|
|
<font color="#008b8b">$file_name</font> = <font color="#008b8b">$1</font>;
|
|
}
|
|
<font color="#a52a2a"><b>else</b></font> {
|
|
<font color="#a52a2a"><b>exit</b></font>; <font color="#0000ff"># Should never happen</font>
|
|
}
|
|
<font color="#a52a2a"><b>if</b></font>(<font color="#a52a2a"><b>open</b></font>(<font color="#008b8b">COUNTERFILE</font>, <font color="#ff00ff">"</font><font color="#ff00ff">+<</font><font color="#008b8b">$file_name</font><font color="#ff00ff">"</font>) == <font color="#ff00ff">0</font>) {
|
|
<font color="#0000ff"># Getting accessed for the first time</font>
|
|
<font color="#a52a2a"><b>open</b></font>(<font color="#008b8b">COUNTERFILE</font>, <font color="#ff00ff">"</font><font color="#ff00ff">></font><font color="#008b8b">$file_name</font><font color="#ff00ff">"</font>);
|
|
<font color="#a52a2a"><b>print</b></font> <font color="#008b8b">COUNTERFILE</font> <font color="#ff00ff">"</font><font color="#ff00ff">1</font><font color="#ff00ff">"</font>;
|
|
<font color="#a52a2a"><b>close</b></font>(COUNTERFILE);
|
|
<font color="#a52a2a"><b>return</b></font> <font color="#ff00ff">1</font>;
|
|
}
|
|
|
|
<font color="#a52a2a"><b>flock</b></font>(<font color="#008b8b">COUNTERFILE</font>, <font color="#008b8b">$LOCK_EX</font>);
|
|
<font color="#008b8b">$counter_value</font> = <font color="#008b8b"><COUNTERFILE></font>;
|
|
<font color="#a52a2a"><b>seek</b></font>(<font color="#008b8b">COUNTERFILE</font>, <font color="#ff00ff">0</font>, <font color="#ff00ff">0</font>);
|
|
++<font color="#008b8b">$counter_value</font>;
|
|
<font color="#a52a2a"><b>print</b></font> <font color="#008b8b">COUNTERFILE</font> <font color="#008b8b">$counter_value</font>;
|
|
<font color="#a52a2a"><b>flock</b></font>(<font color="#008b8b">COUNTERFILE</font>, <font color="#008b8b">$LOCK_UN</font>);
|
|
|
|
<font color="#a52a2a"><b>close</b></font>(COUNTERFILE);
|
|
<font color="#a52a2a"><b>return</b></font>(<font color="#008b8b">$counter_value</font> - <font color="#ff00ff">1</font>);
|
|
}
|
|
</pre>
|
|
<p>
|
|
This script can be used by adding a line like this in your web page.
|
|
<pre>
|
|
<img src=counter.cgi?id=my_html_file.html&iformat=jpg>
|
|
</pre>
|
|
<p>
|
|
The id needs to be unique. A sample counter can be seen on my
|
|
<a href=http://www.cise.ufl.edu/~ppadala>home page</a>.
|
|
<p>
|
|
Now to the innards of the script. The counter script has three important
|
|
functions.
|
|
<pre>
|
|
update_counter_value: This function reads the hit count from a file named
|
|
html_file.counter and increments it. It creates the
|
|
counter file, if one already doesn't exist. It also
|
|
locks the file to avoid conflicts due to multiple
|
|
simultaneous accesses.
|
|
|
|
print_counter: Prints the counter by attaching the counter digits in a new
|
|
image. The digits are read from an appropriate directory.
|
|
|
|
print_error_image: This is a useful function to show error images. You
|
|
can use it in your programs, for reporting errors
|
|
through GD.
|
|
</pre>
|
|
<p>
|
|
You need to have the digits (0-9) in jpg or png format. Sites like
|
|
<a href="http://www.counterart.com/">Counter Art dot Com</a> provide free
|
|
counter digits. In my next article, I'll discuss how to generate digits on
|
|
the fly.
|
|
<p>
|
|
I developed a <a href=http://pstats.sourceforge.net>personal website statistics</a>
|
|
package woven around this counter concept. It provides much more than a simple
|
|
counter. It logs the accesses, shows visitor statistics and much more. Check
|
|
it out at <a href=http://pstats.sourceforge.net>pstats</a> page.
|
|
|
|
<p>
|
|
You can also use the <a href=http://search.cpan.org/doc/GAAS/File-CounterFile-0.12/CounterFile.pm>File::CounterFile</a>
|
|
module for managing the counter file.
|
|
|
|
<h3> Coming Up.. </h3>
|
|
<p>
|
|
I hope you enjoyed reading this article. In the coming months, we will look at
|
|
GD::Graph and PerlMagick modules. Send me comments at
|
|
<a href="mailto:p_padala@yahoo.com">this address</a>.
|
|
<p>
|
|
Have Fun !!!</a>
|
|
|
|
<h3> Acknowledgements </h3>
|
|
<p>
|
|
My best friend <a href=http://www.ece.arizona.edu/~parimi>ravi</a> has become
|
|
the official editor for all my writings. I am indebted to him for looking
|
|
through all the gibberish I write and make sense out of it. Thanks ravi :-)
|
|
<p>
|
|
I thank <a href=mailto:ben-fuzzybear@yahoo.com>Benjamin A. Okopnik</a> for
|
|
reviewing the article and pointing out some nice perl hacks.
|
|
|
|
|
|
|
|
|
|
<!-- *** BEGIN bio *** -->
|
|
<SPACER TYPE="vertical" SIZE="30">
|
|
<P>
|
|
<H4><IMG ALIGN=BOTTOM ALT="" SRC="../gx/note.gif">Pradeep Padala</H4>
|
|
<EM>I am a master's student at University of Florida. I love hacking and
|
|
adore Linux. My interests include solving puzzles and playing board
|
|
games. I can be reached through
|
|
<a href="mailto:p_padala@yahoo.com">p_padala@yahoo.com</a> or <a
|
|
href="http://www.cise.ufl.edu/~ppadala">my web site</a>.</EM>
|
|
|
|
<!-- *** END bio *** -->
|
|
|
|
<!-- *** BEGIN copyright *** -->
|
|
<P> <hr> <!-- P -->
|
|
<H5 ALIGN=center>
|
|
|
|
Copyright © 2002, Pradeep Padala.<BR>
|
|
Copying license <A HREF="../copying.html">http://www.linuxgazette.com/copying.html</A><BR>
|
|
Published in Issue 81 of <i>Linux Gazette</i>, August 2002</H5>
|
|
<!-- *** END copyright *** -->
|
|
|
|
<!--startcut ==========================================================-->
|
|
<HR><P>
|
|
<CENTER>
|
|
<!-- *** BEGIN navbar *** -->
|
|
<IMG ALT="" SRC="../gx/navbar/left.jpg" WIDTH="14" HEIGHT="45" BORDER="0" ALIGN="bottom"><A HREF="kurup.html"><IMG ALT="[ Prev ]" SRC="../gx/navbar/prev.jpg" WIDTH="16" HEIGHT="45" BORDER="0" ALIGN="bottom"></A><A HREF="index.html"><IMG ALT="[ Table of Contents ]" SRC="../gx/navbar/toc.jpg" WIDTH="220" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A><A HREF="../index.html"><IMG ALT="[ Front Page ]" SRC="../gx/navbar/frontpage.jpg" WIDTH="137" HEIGHT="45" BORDER="0" ALIGN="bottom"></A><A HREF="http://www.linuxgazette.com/cgi-bin/talkback/all.py?site=LG&article=http://www.linuxgazette.com/issue81/padala.html"><IMG ALT="[ Talkback ]" SRC="../gx/navbar/talkback.jpg" WIDTH="121" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A><A HREF="../lg_faq.html"><IMG ALT="[ FAQ ]" SRC="./../gx/navbar/faq.jpg"WIDTH="62" HEIGHT="45" BORDER="0" ALIGN="bottom"></A><A HREF="ramankutty.html"><IMG ALT="[ Next ]" SRC="../gx/navbar/next.jpg" WIDTH="15" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A><IMG ALT="" SRC="../gx/navbar/right.jpg" WIDTH="15" HEIGHT="45" ALIGN="bottom">
|
|
<!-- *** END navbar *** -->
|
|
</CENTER>
|
|
</BODY></HTML>
|
|
<!--endcut ============================================================-->
|