15.1. Introduction
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:
ImagePng($image, '/path/to/your/new/image.png');
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.