- 69 -

Graphics Tools in Linux

by Kamran Husain

IN THIS CHAPTER


This chapter will introduce you to the following graphics tools and libraries available under Linux:

The pbm Toolkit

The Portable Bitmap Toolkit (pbm toolkit), developed in 1991, is a very powerful toolkit for converting graphics images from one format to another. The toolkit consists of a set of programs that convert data images in a graphics format to or from a PBM format.

The pbm toolkit has no graphical user interface, and all the commands operate on images via the command-line interface. The toolkit programs all work by utilizing the standard input and output features of programs. Each program in the toolkit reads image data from its standard input and writes back to standard output.

The pbm toolkit is available from Linux FTP sites in both binary and source forms. At the ftp://sunsite.unc.edu site, the files can be found in the pub/Linux/apps/graphics/convert subdirectory. The file used for this chapter was the binary archive for Linux: pbmplus-10dec91-bin.tar. Untar the files in a directory, and you then see a README file and man and bin directories under the pbmplus10dec91 directory. Point your PATH to the bin directory. If you cannot get the binary files to work in your installation, you can download the source code in the file pbmplus-10dec91_tar.Z. Uncompress and untar the file to a subdirectory, and follow the instructions in the README file to build the pbmplus executables.

The man directory contains a well-documented set of man pages for the utilities in the toolkit. You can view the contents with the command

nroff -man filename



where filename is the name of the man file you want to look at. The complete list of binary files extracted from this tar archive is shown in Listing 69.1.

Listing 69.1. The files from the pbmplus toolkit.

$ ls pbmplus10dec91/bin



-rwxr-xr-x   1 root     root         3568 Oct 21  1996 atktopbm



-rwxr-xr-x   1 root     root         2112 Oct 21  1996 brushtopbm



-rwxr-xr-x   1 root     root         2136 Oct 21  1996 cmuwmtopbm



-rwxr-xr-x   1 root     root         3864 Oct 21  1996 fitstopgm



-rwxr-xr-x   1 root     root         2628 Oct 21  1996 fstopgm



-rwxr-xr-x   1 root     root         6532 Oct 21  1996 g3topbm



-rwxr-xr-x   1 root     root         2844 Oct 21  1996 gemtopbm



-rwxr-xr-x   1 root     root         6184 Oct 21  1996 giftoppm



-rwxr-xr-x   1 root     root         2320 Oct 21  1996 gouldtoppm



-rwxr-xr-x   1 root     root         2320 Oct 21  1996 hipstopgm



-rwxr-xr-x   1 root     root         2504 Oct 21  1996 icontopbm



-rwxr-xr-x   1 root     root         6108 Oct 21  1996 ilbmtoppm



-rwxr-xr-x   1 root     root         2804 Oct 21  1996 imgtoppm



-rwxr-xr-x   1 root     root         2540 Oct 21  1996 lispmtopgm



-rwxr-xr-x   1 root     root         2248 Oct 21  1996 macptopbm



-rwxr-xr-x   1 root     root         2144 Oct 21  1996 mgrtopbm



-rwxr-xr-x   1 root     root         1884 Oct 21  1996 mtvtoppm



-rwxr-xr-x   1 root     root         1844 Oct 21  1996 pbmlife



-rwxr-xr-x   1 root     root         1836 Oct 21  1996 pbmmake



-rwxr-xr-x   1 root     root         3104 Oct 21  1996 pbmmask



-rwxr-xr-x   1 root     root         2996 Oct 21  1996 pbmreduce



-rwxr-xr-x   1 root     root         3116 Oct 21  1996 pbmtext



-rwxr-xr-x   1 root     root         2768 Oct 21  1996 pbmto10x



-rwxr-xr-x   1 root     root         1796 Oct 21  1996 pbmtoascii



-rwxr-xr-x   1 root     root         2424 Oct 21  1996 pbmtoatk



-rwxr-xr-x   1 root     root         1964 Oct 21  1996 pbmtobbnbg



-rwxr-xr-x   1 root     root         1988 Oct 21  1996 pbmtocmuwm



-rwxr-xr-x   1 root     root         1956 Oct 21  1996 pbmtoepson



-rwxr-xr-x   1 root     root         5552 Oct 21  1996 pbmtog3



-rwxr-xr-x   1 root     root         2124 Oct 21  1996 pbmtogem



-rwxr-xr-x   1 root     root         2988 Oct 21  1996 pbmtogo



-rwxr-xr-x   1 root     root         2548 Oct 21  1996 pbmtoicon



-rwxr-xr-x   1 root     root         2164 Oct 21  1996 pbmtolj



-rwxr-xr-x   1 root     root         3020 Oct 21  1996 pbmtomacp



-rwxr-xr-x   1 root     root         1916 Oct 21  1996 pbmtomgr



-rwxr-xr-x   1 root     root         1884 Oct 21  1996 pbmtopi3



-rwxr-xr-x   1 root     root         1876 Oct 21  1996 pbmtoplot



-rwxr-xr-x   1 root     root         1876 Oct 21  1996 pbmtoptx



-rwxr-xr-x   1 root     root         3596 Oct 21  1996 pbmtox10bm



-rwxr-xr-x   1 root     root         3180 Oct 21  1996 pbmtoxbm



-rwxr-xr-x   1 root     root         1836 Oct 21  1996 pbmtoybm



-rwxr-xr-x   1 root     root         3556 Oct 21  1996 pbmtozinc



-rwxr-xr-x   1 root     root         7288 Oct 21  1996 pbmupc



-rwxr-xr-x   1 root     root         3532 Oct 21  1996 pcxtoppm



-rwxr-xr-x   1 root     root         1572 Oct 21  1996 pgmbentley



-rwxr-xr-x   1 root     root         5644 Oct 21  1996 pgmcrater



-rwxr-xr-x   1 root     root         2140 Oct 21  1996 pgmedge



-rwxr-xr-x   1 root     root         2164 Oct 21  1996 pgmenhance



-rwxr-xr-x   1 root     root         1916 Oct 21  1996 pgmhist



-rwxr-xr-x   1 root     root         3556 Oct 21  1996 pgmnorm



-rwxr-xr-x   1 root     root         1868 Oct 21  1996 pgmoil



-rwxr-xr-x   1 root     root         2372 Oct 21  1996 pgmramp



-rwxr-xr-x   1 root     root        12404 Oct 21  1996 pgmtexture



-rwxr-xr-x   1 root     root         2992 Oct 21  1996 pgmtofits



-rwxr-xr-x   1 root     root         2468 Oct 21  1996 pgmtofs



-rwxr-xr-x   1 root     root         2204 Oct 21  1996 pgmtolispm



-rwxr-xr-x   1 root     root         6972 Oct 21  1996 pgmtopbm



-rwxr-xr-x   1 root     root         2412 Oct 21  1996 pgmtoppm



-rwxr-xr-x   1 root     root         1844 Oct 21  1996 pi1toppm



-rwxr-xr-x   1 root     root         1844 Oct 21  1996 pi3topbm



-rwxr-xr-x   1 root     root        16752 Oct 21  1996 picttoppm



-rwxr-xr-x   1 root     root         4556 Oct 21  1996 pjtoppm



-rwxr-xr-x   1 root     root         4316 Oct 21  1996 pnmarith



-rwxr-xr-x   1 root     root         4684 Oct 21  1996 pnmcat



-rwxr-xr-x   1 root     root         5524 Oct 21  1996 pnmconvol



-rwxr-xr-x   1 root     root         2556 Oct 21  1996 pnmcrop



-rwxr-xr-x   1 root     root         2268 Oct 21  1996 pnmcut



-rwxr-xr-x   1 root     root         2188 Oct 21  1996 pnmdepth



-rwxr-xr-x   1 root     root         1804 Oct 21  1996 pnmenlarge



-rwxr-xr-x   1 root     root         1892 Oct 21  1996 pnmfile



-rwxr-xr-x   1 root     root         3772 Oct 21  1996 pnmflip



-rwxr-xr-x   1 root     root         2712 Oct 21  1996 pnmgamma



-rwxr-xr-x   1 root     root         1604 Oct 21  1996 pnminvert



-rwxr-xr-x   1 root     root         1556 Oct 21  1996 pnmnoraw



-rwxr-xr-x   1 root     root         3308 Oct 21  1996 pnmpaste



-rwxr-xr-x   1 root     root         5916 Oct 21  1996 pnmrotate



-rwxr-xr-x   1 root     root         6508 Oct 21  1996 pnmscale



-rwxr-xr-x   1 root     root         3228 Oct 21  1996 pnmshear



-rwxr-xr-x   1 root     root         1804 Oct 21  1996 pnmtile



-rwxr-xr-x   1 root     root         8072 Oct 21  1996 pnmtops



-rwxr-xr-x   1 root     root         4224 Oct 21  1996 pnmtorast



-rwxr-xr-x   1 root     root         4836 Oct 21  1996 pnmtoxwd



-rwxr-xr-x   1 root     root         3404 Oct 21  1996 ppmdither



-rwxr-xr-x   1 root     root        13204 Oct 21  1996 ppmforge



-rwxr-xr-x   1 root     root         1836 Oct 21  1996 ppmhist



-rwxr-xr-x   1 root     root         1652 Oct 21  1996 ppmmake



-rwxr-xr-x   1 root     root        12620 Oct 21  1996 ppmpat



-rwxr-xr-x   1 root     root         6876 Oct 21  1996 ppmquant



-rwxr-xr-x   1 root     root         1972 Oct 21  1996 ppmrelief



-rwxr-xr-x   1 root     root         5956 Oct 21  1996 ppmtoacad



-rwxr-xr-x   1 root     root         4852 Oct 21  1996 ppmtogif



-rwxr-xr-x   1 root     root         4412 Oct 21  1996 ppmtoicr



-rwxr-xr-x   1 root     root         4136 Oct 21  1996 ppmtoilbm



-rwxr-xr-x   1 root     root         4116 Oct 21  1996 ppmtopcx



-rwxr-xr-x   1 root     root         4740 Oct 21  1996 ppmtopgm



-rwxr-xr-x   1 root     root         2444 Oct 21  1996 ppmtopi1



-rwxr-xr-x   1 root     root         3680 Oct 21  1996 ppmtopict



-rwxr-xr-x   1 root     root         3652 Oct 21  1996 ppmtopj



-rwxr-xr-x   1 root     root         2228 Oct 21  1996 ppmtopuzz



-rwxr-xr-x   1 root     root         1956 Oct 21  1996 ppmtorgb3



-rwxr-xr-x   1 root     root         2964 Oct 21  1996 ppmtosixel



-rwxr-xr-x   1 root     root         6312 Oct 21  1996 ppmtotga



-rwxr-xr-x   1 root     root         3644 Oct 21  1996 ppmtouil



-rwxr-xr-x   1 root     root         3160 Oct 21  1996 ppmtoxpm



-rwxr-xr-x   1 root     root         2148 Oct 21  1996 ppmtoyuv



-rwxr-xr-x   1 root     root         2276 Oct 21  1996 psidtopgm



-rwxr-xr-x   1 root     root         2004 Oct 21  1996 qrttoppm



-rwxr-xr-x   1 root     root         3484 Oct 21  1996 rasttopnm



-rwxr-xr-x   1 root     root         2244 Oct 21  1996 rawtopgm



-rwxr-xr-x   1 root     root         3764 Oct 21  1996 rawtoppm



-rwxr-xr-x   1 root     root         2132 Oct 21  1996 rgb3toppm



-rwxr-xr-x   1 root     root         7836 Oct 21  1996 sldtoppm



-rwxr-xr-x   1 root     root         2636 Oct 21  1996 spctoppm



-rwxr-xr-x   1 root     root         2052 Oct 21  1996 sputoppm



-rwxr-xr-x   1 root     root         4776 Oct 21  1996 tgatoppm



-rwxr-xr-x   1 root     root         3492 Oct 21  1996 xbmtopbm



-rwxr-xr-x   1 root     root         4588 Oct 21  1996 ximtoppm



-rwxr-xr-x   1 root     root         4084 Oct 21  1996 xpmtoppm



-rwxr-xr-x   1 root     root         6684 Oct 21  1996 xwdtopnm



-rwxr-xr-x   1 root     root         2120 Oct 21  1996 ybmtopbm



-rwxr-xr-x   1 root     root         2220 Oct 21  1996 yuvtoppm



Four types of base formats are supported in the pbm toolkit:

You usually convert from a format to either PPM or PNM. Programs that work with PPM files can write only PPM files. Programs that process PNM files can write PBM, PPM, or PGM files.

This powerful toolkit is surprisingly easy to use. Let's say you want to convert a GIF image into a PCX image. This is the command you would use on the file myfile.gif to get myfile.pcx:

$ giftoppm < myfile.gif | ppmtopcx > myfile.pcx



The pnm* functions let you manipulate the contents of images. You can rotate or scale an image with these functions. For example, to scale the original GIF image down by a factor of two, you would use the following command:

$ giftoppm < myfile.gif | pnmscale 3 | ppmtopcx > myfile.pcx



Particularly interesting is the pbmtext program, which converts text files into PPM files. You can therefore take text lines and convert them into images for use in World Wide Web server applications for generating non-editable messages using a fixed font. This would be a typical usage of pbmtext:

$ pbmtext  < /etc/motd | pnmscale 4 |  ppmtogif > motd.gif



The scale factor would have to be adjusted to fit the particular GIF image size you want. To get rotated text at a 45-degree angle (0 degrees is a horizontal line going from left to right), try the following command:

$ pbmtext  < /etc/motd | pnmrotate 45 |  ppmtogif > motd.gif



The angle parameter should be between -90 and 90 degrees. For angles greater than that, try flipping the image with pnmflip to get that extra 180-degree rotation.

The best use for the pbm toolkit is from within shell scripts where you do not want to have any user interaction, especially if you are doing only basic scalar operations on images or converting data from one graphical format to another.

Of course, the major thing lacking with the pbm toolkit is the capability to graphically show the data. Let's see how to display the data we create with the pbm toolkit by using the xv toolkit.

xv

The xv program in Linux is written by John Bradley. The version number of the program on the CD-ROM is 3.10 and is dated 12/16/94. To see an image, issue the following command:

$ xv filename &



It's a good idea to run xv in the background to free up the terminal on which you are working. For example, to see the motd.gif image we just created with the pbm toolkit, we would issue this command:

$ xv motd.gif &



You can bring up the main menu for the screen by clicking the right mouse button anywhere on the display window. You are presented with the menu shown in Figure 69.1.

FIGURE 69.1. The xv main menu screen.

The menu lets you load and save graphics files in several formats, and load and save programs in different formats. Several files can be loaded at one time, but only one can be viewed at a time. Using this graphical program is helpful if you want to work within an interactive environment.

Several filtering algorithms are available. You can rotate images at an angle, as shown in Fig-ure 69.2. An image can also be embossed, as shown in Figure 69.3. An embossed image can be a bit hard to read at times, so you might want to edit the colors with the color editor in the 24/8 Bit menu option. Embossing looks better for graphical images, as shown in Figure 69.4, than for text.

FIGURE 69.2. An image rotated at a 12-degree angle.

FIGURE 69.3. An embossed image with text.

FIGURE 69.4. An embossed image without text.

The xv program provides you with the power of the pbm toolkit and the capability to show the results right away. It is an interactive program, however, and if you want to do something within a shell script, you would want to do it with the pbm toolkit. It's an excellent package for manipulating 2D images.

Geomview

The Geomview toolkit is another freeware tool that works great for displaying 3D images. You can get the software for Linux from the Web site at

http://www.geom.umn.edu/software/download/geomview.html



Geomview is available in source form or in binary form for Linux. (Unless you are the adventurous kind or are impatient, get the binary form. The source files took forever to build on my Linux box, and I wished I had downloaded the ELF binary image instead.) The Web site is from University of Minnesota's Geometry Center, where Geomview was developed.

You need to be aware of certain requirements for visualizing 3D images on Linux machines:

If you attempt to view Geomview images on a 640x480 screen, you really will not be able to appreciate the power of this toolkit.

After you untar the file, change to the Geomview directory that tar creates for you. Then you can issue the following command in bash to set the environment variable GEOMVIEW to this current directory:

$ GEOMVIEW=`pwd`; export GEOMVIEW



The INSTALL file provides more details about how and where to store the executable if the current directory is not suitable for you. If you want to make Geomview available to you all the time, be sure to set GEOMVIEW in your .profile file. Then make sure that Geomview is in the PATH, and enter the following command at the prompt:

$ geomview



When you start Geomview, you are presented with the main screen, as shown in Figure 69.5. Use the File menu to go to the ./data/geom directory, and open a file with the oogl extension. (See Figure 69.6.) These files are good demo files to work with. You can load more than one file at a time.

FIGURE 69.5. The main menu for Geomview.

FIGURE 69.6. The object selection menu for Geomview.


TIP: You can find several other great 3D imaging tools for many operating systems and workstations at http://www.geom.umn.edu. Check them out while you are there.

The Geomview software is great for visualizing 3D images, and it includes the option to do "fly-bys" on images. You can literally walk around a 3D object you have created and can even "step into" it. Several tools are available with the buttons in the Tools menu, shown in Fig- ure 69.7. The buttons in the menu enable you to rotate and translate objects with the mouse button. Press the left mouse button and move the image by holding down the button and moving the mouse. The movement is based on the inertia of the object. Releasing the mouse does not stop the object from rotating! This is a bit hard to master at first because the speed of motion is somehow proportional to the speed your mouse is moving when the button is released. To get static movement, you must stop the mouse movement before you release the mouse button.

FIGURE 69.7. The Tools menu for Geomview.

The speed of the mouse is also a factor when you select the "fly" option. Press the fly button in the menu. Hold down the left mouse button in the view area. Move the mouse at the speed at which you want to do the fly-by, and then release the mouse button. Remember that the rendering is slow on a 486 system and that you might have to work slowly to get just the right effect. The Geomview application uses a command language called the Graphical Command Language (GCL). Using GCL, you can create your animation sequences by sending commands via pipes directly to Geomview. The work of rendering and deciphering images is performed with the Object Oriented Graphics Library (OOGL), also developed at the University of Minnesota. The full documentation for the OOGL is available at the umn site at

http://www.geom.umn.edu/software/geomview/geomview_toc.html



The documentation includes a great tutorial with lots of examples and code to work with.

The Mesa/OpenGL Toolkit

The OpenGL standard is a software interface and libraries designed for 3D graphics on high-end machines such as Iris, Silicon Graphics, IBM, and Sun workstations. Yes, OpenGL libraries also exist for Windows NT products. The OpenGL libraries are generally optimized for the hardware they are designed for, whereas the software interface to their functions remains constant.

The Mesa toolkit was written primarily by Brian Paul as a software-only solution running on top of X Window. The primary motivation for this design is to enable OpenGL programs to run on all platforms that run X Window. This means you can run Mesa on Linux too!

The cost of abstracting this software from the hardware via the layer of X Window is loss of performance. Programs running with Mesa will almost certainly run slower on X than on library code designed for OpenGL. The Mesa toolkit library can be called directly from within C and FORTRAN programs. The Mesa library offers an almost complete set of OpenGL functions. More functions are being added to the library as we go to print. The latest version of the software and documentation can be downloaded from the HTML page at

http://www.ssec.wisc.edu/~brianp/Mesa.html



The files are found in zipped, tar archives. The latest version is 2.0, and the source file is called Mesa-2.0.tar.gz. At the rate versions were changing while I was writing this chapter, you will see a later version of the library.

Untar and unzip the archive, and change directories into the Mesa source tree. Then run the following command:

$ make linux



The make program takes a very long time to complete. So be patient.

After the make program terminates, you are left with the library directory ./lib. As root, link these libraries to /usr/local/lib because the make program does not move these for you. The header files should be linked under /usr/local/include.

The makefile I used for my system and setup is shown in Listing 69.2.

Listing 69.2. The makefile for sample programs.

INCPATH=/home/khusain/mesa/Mesa-2.0/include



LIBPATH=/home/khusain/mesa/Mesa-2.0/lib



LIBX= /usr/X11/lib



LIBS= -lMesaaux -lMesatk -lMesaGL -lMesaGLU -lXext -lX11 -lm







s1: s1.c



    gcc -o s1 s1.c -I$(INCPATH) -L$(LIBPATH) -L$(LIBX) $(LIBS)



Note that in Listing 69.2 I used the /home/khusain/mesa directory rather than /usr/local/lib. This is simply for my convenience and pure laziness while I write this book. You should really just create a link from the /usr/local/lib directory to the files in the Mesa package. I just have too many software packages on my Linux machine that are cluttering my /usr/local/lib source tree. It's ironic that even my /usr/local tree, which is intended for use with custom packages, is too cluttered up with weird links because I have installed and removed so many different versions of different packages. Oh, well; I will do a spring cleanup...real soon now. ;-)

Four libraries must be linked in with this program. All of these libraries are located in the lib subdirectory. If you are going to port this code to non-Linux machines, you might not have to link in the MesaGLU library because this provides the layered interface for the underlying graphics libraries.


TIP: If you stick with the OpenGL standard when writing your programs, your code can be ported to other systems with OpenGL installed in their file systems. These systems include Windows NT, UNIX, and Silicon Graphics workstations.

The test program I tried was the one based on the samples provided in the Mesa package. I actually prefer to write simpler stuff because it's easier to explain some of the examples. See Listing 69.3 for a simple OpenGL program.

Listing 69.3. A simple test program.

 1



 2 #include <stdlib.h>



 3 #include <GL/gl.h>



 4 #include <glaux.h>



 5



 6 float x,y;



 7



 8 void moveUp() { y += 10.0; }



 9 void moveDown() { y -= 10.0; }



10 void moveRight() { x += 10.0; }



11 void moveLeft() { x -= 10.0; }



12



13 void forever()



14 {



15 glClearColor(1.0,1.0,1.0,0.0);



16 glClear(GL_COLOR_BUFFER_BIT);



17 glColor3f(0.0,0.3,0.0);



18 glMatrixMode(GL_PROJECTION);



19 glLoadIdentity();



20 glOrtho(-1.0,1.0,-1.0,1.0,-1.0,1.0);



21 glRotatef(x,1.0,0.0,0.0);



22 glRotatef(y,0.0,1.0,0.0);



23 auxWireCube(1.0);



24 auxWireCube(0.5);



25 glFlush();



26 }



27



28



29 void main(int argc, char *argv[])



30 {



31 x = 0.0;



32 y = 0.0;



33 auxInitDisplayMode(AUX_SINGLE | AUX_RGB);



34 auxInitPosition(0,0,400,400);



35 auxInitWindow(argv[0]); /* program name */



36 auxKeyFunc(AUX_UP,moveUp);



37 auxKeyFunc(AUX_DOWN,moveDown);



38 auxKeyFunc(AUX_RIGHT,moveRight);



39 auxKeyFunc(AUX_LEFT,moveLeft);



40 auxMainLoop(forever);



41 }



Two include files are required for building an application using the Mesa-enabled program. Two global variables are declared at line 6 for the x and y angle of rotation. Lines 8 through 11 define four callback functions that increment and decrement the value of x and y by 10. Each of these functions is designed to be called when a key is pressed. We will be tying these functions to presses of the arrow keys on the keyboard. The values of the keys are defined in OpenGL as AUX_UP, AUX_DOWN, AUX_LEFT, and AUX_RIGHT. (Only the arrow keys worked with this program. The numeric keys with the NumLock key off did not work with these definitions.)

The forever() function is called whenever the window area for the application has to be refreshed. (See line 13.) There are several function calls to each of the libraries in Mesa. The gl functions call the Mesa libraries, whereas the aux functions call the Mesaaux (auxiliary) library functions. The glClearColor() function clears the buffer and color display memory. If you are going to use surfaces and lighting in your program, you must also clear the bit buffer with a call to glClear like this:

16 glClear(GL_COLOR_BUFFER_BIT | GL_COLOR_DEPTH_BUFFER);



All these constants are defined in the header files for Mesa. All functions that end in the letter f take floating-point numbers as arguments. (You should use the decimal point when specifying numbers as arguments to functions, or the gcc compiler will complain.) The function that takes integers as arguments is defined without the f prefix; that is, glColor(int, int, int). Instead, we used the floating format version in line 17 like this:

17 glColor3f(0.0,0.3,0.0);



The next lines (18-22) define the mode of display as GL_PROJECTION and set up the orthogonal projection for the viewing angle. The rotations are done from the origin (0,0,0) and are performed along the line drawn from the point specified in the arguments to the glRotate call. For example, glRotatef(x,1.0,0.0,0.0) rotates about the line from (0,0,0) to (1,0,0). The next two auxiliary functions (lines 23 and 24) are used to draw a wire cube of scale 0.5 and 1.0, respectively. After the drawing commands are sent, we simply flush the buffers and we are done.

The main program does the initialization of the (x,y) coordinates and the initial starting position for the viewing angle. It also initializes the color model (AUX_RGB) and the windows with the program name (lines 33-35). The numeric keys are assigned to handler functions in lines 36-39. Finally, the message loop to process events that in turn call the function to handle user input and render the graphics is done with the call to auxMainLoop in line 40. The function auxMainLoop never returns, and the program must be terminated with an exit() call in one of the handler functions.

This is a very simple introduction to OpenGL. A lot of the information simply cannot be covered in one chapter. Each function I have shown has many variants and options. The OpenGL library itself has many functions for coloring, shading, and three-dimensional graphics tricks that will certainly make programming a joy. Unfortunately, you need a fast Linux box to really take advantage of some the advanced features. Speaking of advanced features, forgive me for not discussing what you can do with OpenGL programming, but lack of time and space in a Linux book simply makes it impossible to deviate into this arena. A topic for this type of programming would take at least a book (or two) on its own.

For more information on the OpenGL standard libraries, check out the files at the Web site at

http://www.sgi.com/Technology/OpenGL



You'll find a FAQ and lots of sample code. The sample programs within the Mesa package run quite slowly with a 486 processor running at 100MHz. The capability to write portable OpenGL code on a Linux machine, however, makes the slow speed a minor inconvenience when you consider the price of a Sun or Iris workstation.

Summary

There you have it. We covered four programs and packages that are available on Linux for performing graphical image processing. The pbm toolkit is useful when you want to manipulate images from within programs. For interactive image editing, try using the xv program. Three-dimensional viewing and creating of models is possible with the Geomview program. Finally, you can use the Mesa libraries for writing OpenGL code that is portable for other UNIX and Windows NT systems with installed OpenGL libraries.