Chapter 15. Graphics
With the assistance of the GD library, you can use PHP to create applications that use dynamic images to display stock quotes, reveal poll results, monitor system performance, and even create games. However it's not like using Photoshop or GIMP; you can't draw a line by moving your mouse. Instead, you need to precisely specify a shape's type, size, and position.
GD has an existing API, and PHP tries to follows its syntax and function-naming conventions. So, if you're familiar with GD from other languages, such as C or Perl, you can easily use GD with PHP. If GD is new to you, it may take a few minutes to figure it out, but soon you'll be drawing like Picasso.
The feature set of GD varies greatly depending on which version GD you're running and which features were enabled during configuration. Versions of GD up to 1.6 supported reading and writing GIFs, but this code was removed due to patent problems. Instead, newer versions of GD support JPEGs, PNGs, and WBMPs. Because PNGs are generally smaller than GIFs, allow you to use many more colors, have built-in gamma correction, and are supported by all major web browsers, the lack of GIF support is classified as a feature, not a bug. For more on PNG, go to http://www.libpng.org/pub/png/ or read Chapter 21, "PNG Format," of Web Design in a Nutshell written by Jennifer Niederst (O'Reilly).
Besides supporting multiple file formats, GD lets you draw pixels, lines, rectangles, polygons, arcs, ellipses, and circles in any color you want. Recipe 15.2 covers straight shapes, while Recipe 15.3 covers the curved ones. To fill shapes with a pattern instead of a solid color, see Recipe 15.4.
You can also draw text using a variety of font types, including built-in, TrueType, and PostScript Type 1 fonts. Recipe 15.5 shows the ins and outs of the three main text-drawing functions, and Recipe 15.6 shows how to center text within a canvas. These two recipes form the basis for Recipe 15.7, which combines an image template with real-time data to create dynamic images. GD also lets you make transparent GIFs and PNGs. Setting a color as transparent and using transparencies in patterns are discussed in Recipe 15.8.
Recipe 15.9 moves away from GD and shows how to securely serve images by restricting user access. Last, we provide an example application — taking poll results and producing a dynamic bar graph showing what percentage of users voted for each answer.
All these features work with GD 1.8.4, which is the latest stable version of the library. If you have an earlier version, you should not have a problem. However, if a particular recipe needs a specific version of GD, we note it in the recipe.
PHP also supports GD 2.x, which, as of this writing, is still in beta. Despite its beta status, the new version is relatively stable and has many new features. In particular, Version 2.x allows true-color images, which lets GD read in PNGs and JPEGs with almost no loss in quality. Also, GD 2.x supports PNG alpha channels, which allow you to specify a transparency level for each pixel.
Both versions of GD are available for download from the official GD site at http://www.boutell.com/gd/. The GD section of the online PHP Manual at http://www.php.net/image also lists the location of the additional libraries necessary to provide support for JPEGs and Type 1 fonts.
There are two easy ways to see which version, if any, of GD is installed on your server and how it's configured. One way is to call phpinfo( ) . You should see --with-gd at the top under "Configure Command"; further down the page there is also a section titled "gd" that has more information about which version of GD is installed and what features are enabled. The other option is to check the return value of function_exists('imagecreate'). If it returns true, GD is installed. The imagetypes( ) function returns a bit field indicating which graphics formats are available. See http://www.php.net/imagetypes for more on how to use this function. If you want to use a feature that isn't enabled, you need to rebuild PHP yourself or get your ISP to do so.
The basic image generation process has three steps: creating the image, adding graphics and text to the canvas, and displaying or saving the image. For example:
$image = ImageCreate(200, 50); $background_color = ImageColorAllocate($image, 255, 255, 255); // white $gray = ImageColorAllocate($image, 204, 204, 204); // gray ImageFilledRectangle($image, 50, 10, 150, 40, $gray); header('Content-type: image/png'); ImagePNG($image);
The output of this code, which prints a gray rectangle on a white background, is shown in Figure 15-1.
Figure 15-1. A gray rectangle on a white background
To begin, you create an image canvas. The ImageCreate( ) function doesn't return an actual image. Instead, it provides you with a handle to an image; it's not an actual graphic until you specifically tell PHP to write the image out. Using ImageCreate( ), you can juggle multiple images at the same time.
The parameters passed to ImageCreate( ) are the width and height of the graphic in pixels. In this case, it's 200 pixels across and 50 pixels high. Instead of creating a new image, you can also edit existing images. To open a graphic, call ImageCreateFromPNG( ) or a similarly named function to open a different file format. The filename is the only argument, and files can live locally or on remote servers:
// open a PNG from the local machine $graph = ImageCreateFromPNG('/path/to/graph.png'); // open a JPEG from a remote server $icon = ImageCreateFromJPEG('http://www.example.com/images/icon.jpeg');
Once you have an editable canvas, you get access to drawing colors by calling ImageColorAllocate( ) :
$background_color = ImageColorAllocate($image, 255, 255, 255); // white $gray = ImageColorAllocate($image, 204, 204, 204); // gray
The ImageColorAllocate( ) function takes an image handle to allocate the color to and three integers. The three integers each range from 0 to 255 and specify the red, green, and blue components of the color. This is the same RGB color combination that is used in HTML to set a font or background color. So, white is 255, 255, 255; black is 0, 0, 0, and everything else is somewhere in between.
The first call to ImageAllocateColor( ) sets the background color. Additional calls allocate colors for drawing lines, shapes, or text. Therefore, set the background color to 255, 255, 255 and then grab a gray pen with ImageAllocateColor($image, 204, 204, 204). It may seem odd that the background color is determined by the order ImageAllocateColor() is called and not by a separate function. But, that's how things work in GD, so PHP respects the convention.
Call ImageFilledRectangle( ) to place a box onto the canvas. ImageFilledRectangle( ) takes many parameters: the image to draw on, the x and y coordinates of the upper left corner of the rectangle, the x and y coordinates of the lower right corner of the rectangle, and finally, the color to use to draw the shape. Tell ImageFilledRectangle( ) to draw a rectangle on $image, starting at (50,10) and going to (150,40), in the color gray:
ImageFilledRectangle($image, 50, 10, 150, 40, $gray);
Unlike a Cartesian graph, (0,0) is not in the lower left corner; instead, it's in the upper left corner. So, the vertical coordinate of the spot 10 pixels from the top of a 50 pixel high canvas is 10 because it's 10 pixels down from the top of the canvas. It's not 40, because you measure from the top down, not the bottom up. And it's not -10, because down is considered the positive direction, not the negative one.
Now that the image is all ready to go, you can serve it up. First, send a Content-type header to let the browser know what type of image you're sending. In this case, we display a PNG. Next, have PHP write the PNG image out using ImagePNG( ) . Once the image is sent, your task is over:
header('Content-Type: image/png'); ImagePNG($image);
To write the image to disk instead of sending it to the browser, provide a second argument to ImagePNG( ) with where to save the file:
Since the file isn't going to the browser, there's no need to call header( ). Make sure to specify a path and an image name, and be sure PHP has permission to write to that location.
PHP cleans up the image when the script ends, but, if you wish to manually deallocate the memory used by the image, calling ImageDestroy($image) forces PHP to get rid of the image immediately.
Copyright © 2003 O'Reilly & Associates. All rights reserved.