GIF Images on the Fly
The next example uses a few more of the functions supplied with the GD interface. We draw the arrow rather than read it from a file. By drawing the arrow, we can control the angle of the arrow which is drawn on the main image. Listing 2 shows the source code for this example.
Lines 1-8 should look familiar from the previous example. We simply define variables for the main GIF image and the position/angle of the arrow. Just for simplicity, I did not include the ReadParse routine, so no user input is allowed. As in the first example, we read the main image into the variable $im in Lines 10-12.
Line 15 is new. This line simply allocates a color based on RGB values which range from 0 to 255. The color blue has a RGB value of (0,0,255). We can then use the color later when drawing the arrow.
Lines 17 calls the function for creating the arrow. This routine starts on Line 26. In this routine we create a new polygon (an arrow) and then spend most of the time finding the points for the polygon. After we find an x,y position for a corner of the polygon, we put it in the polygon object, $poly.
As mentioned earlier, our polygon is an arrow. Line 37 creates the polygon variable. Then Lines 38-44 find points for the polygon. Here is how that section works. Lines 33-34 define the x,y positions for an arrow that points north. Since we may want to rotate this arrow, Lines 38-44 come into play. These lines figure out the new x,y positions of each point taking the rotation angle into consideration. Line 43 adds the point to the polygon taking into consideration the size of the image (subtracting 75) and the x,y position where the arrow will be placed ($xpos and $ypos). Rather than spending all day trying to explain this section of the code, take a look at an old CGA graphics book. In fact, I got the formulas for this section from a CGA graphics manual.
At last, we have a polygon stored as the variable $poly which is returned to the main program. Line 19 is another GD interface call to fill the arrow with our color and place it on the main image. Finally, the image is displayed and the script exits.
Like the first example, you can call this CGI script both directly and via an IMG tag as shown here:
<IMG SRC= "http://bodock.vislab.olemiss.edu/cgi-bin/example2.cgi" ALT="">
If you want to dynamically control the angle of the arrow, you would need to modify this example to include the cgi-lib.pl library, read in the data with ReadParse and then define $angle appropriately.
We now know how to create a GIF image on the fly and view it both directly and from an IMG tag within an HTML file. What if you need to save the image?
Of course, first of all you need a directory where the images will be created. Depending on your web-server configuration, the ownership and write permissions of that directory will need to be modified so that the CGI program can save the image. Discuss this matter with your webmaster.
Once that issue is resolved, your CGI script can output the image to a file using a unique, file-naming scheme. To recall this file name, you can use a database or simply inform the client of the name of the file. For example, if you develop a CGI program to create virtual postcards, the only person who needs the name of the image is the sender and/or the recipient of the postcard. This could be displayed within the web browser once the postcard has been created or e-mailed to the recipient. In other situations, several people may need to view the image. In this case, a database for storing the file name with the associated options is the best choice in my opinion.
In either case, storing the image can be done in addition to displaying it. That is, just use regular Perl I/O statements to print the image to a file. Pick up any Perl programming book and check out the File I/O section.
Last, you might have to keep a watch on the directory where the images are stored. If the file names are unique and the images are large, consider deleting old files periodically to avoid buying a new disk each month. Then again, you might want to use that as an excuse to obtain more disk space.
Of course, the documentation that comes with GD.pm can fill in any gaps that you might have. In addition, here are two URLs that show some of my programming work in creating GIF images on the fly. The first is a campus map for the University of Mississippi (UM). The second example highlights a few interesting sites about my home state.
For the UM campus map, the original GIF creation programs are written in C and use the gd C library. You can visit that page at the URL http://www.olemiss.edu/hospitality/maps/. The Find option at the top of the page will take you to other web pages. From there, you can select a site of interest. With a simple mouse click, an image is displayed of the campus with an arrow to highlight your selection. In addition, all the information on each building is listed in a database, so the CGI program has to first get this information before the image is created.
A more elaborate example of GIF images created on the fly can be found at the URL http://bodock.vislab.olemiss.edu/onthefly.html. This combines several options such as text, a choice of colors, a variety of pointers, etc. Be sure to follow the “More Practical Example” link at the bottom of the left-most frame. That section shows examples of adding several text and highlighters at the same time. In addition, the map is clickable thanks to some HTML code for a a client-side image map. The CGI programs for this application were developed with Perl and the other packages mentioned earlier.
Editorial Advisory Panel
Thank you to our 2014 Editorial Advisors!
- Jeff Parent
- Brad Baillio
- Nick Baronian
- Steve Case
- Chadalavada Kalyana
- Caleb Cullen
- Keir Davis
- Michael Eager
- Nick Faltys
- Dennis Frey
- Philip Jacob
- Jay Kruizenga
- Steve Marquez
- Dave McAllister
- Craig Oda
- Mike Roberts
- Chris Stark
- Patrick Swartz
- David Lynch
- Alicia Gibb
- Thomas Quinlan
- Carson McDonald
- Kristen Shoemaker
- Charnell Luchich
- James Walker
- Victor Gregorio
- Hari Boukis
- Brian Conner
- David Lane