15.10. Program: Generating Bar Charts from Poll Results

When displaying the
results of a poll, it can be more effective to generate a colorful
bar chart instead of just printing the results as text. The function
shown in Example 15-4 uses GD to create an image that
displays the cumulative responses to a poll question.

To call this program, create an array holding two parallel arrays:
$answers['answer'] and
$answer['votes']. Element $i of
each array holds the answer text and the total number of votes for
answer $i. Figure 15-10 shows this
sample output.

Figure 15-10. Graphical bar chart of poll results

Here the answers are manually assigned, but for a real poll, this
data could be pulled from a database instead.

This program is a good start, but
because it uses the built-in GD fonts, there are a lot of magic
numbers embedded in the program corresponding to the font height and
width. Also, the amount of space between each answer is hardcoded. If
you modify this to handle more advanced fonts, such as PostScript or
TrueType, you'll need to update the algorithms that
control those numbers.

At the top of the function, a bunch of
RGB combinations are defined; they are
used as the colors to draw the bars. A variety of constants are
broken out, such as $line_width, which is the
maximum number of characters per line. The
$bar_height variable determines how high the bars
should be, and $scale scales the length of the bar
as a function of the longest possible line.
$padding is used to push the results five pixels
away from the edge of the canvas.

We then make a very large canvas to draw the chart; later, we will
crop the canvas down to size, but it can be difficult to know ahead
of time how large our total size will be. The default background
color of the bar chart is (224, 224, 224), or a light gray.

In order to restrict the width of the chart to a reasonable size, we
use wordwrap( ) to break our $question
down to size and explode(
) it on
\n. This gives us an array of correctly-sized
lines, which we loop on to print out one line at a time.

After printing the question, we move on to the answers. First, we
format the results numbers with sprintf(
). To format the total percentage of
votes for an answer as a floating-point number with one
decimal point, we use %1.1f. To find the length of
the bar corresponding to that number, you compute a similar number,
but instead of multiplying it by 100, we multiply by a magic number,
$scale, and return an integer.

The text color is pulled from the $colors array of
RGB triplets. Then, we call ImageFilledRectangle(
) to
draw the bar and ImageString( ) to draw the
percentage text to the right of the bar. After adding some padding,
we print the answer using the same algorithm used to print the
question.

When all the answers have been printed, the total size of bar chart
is stored in $y. Now we can correctly crop the
graphic to size, but there's no ImageCrop(
) function. To work around this, we make a new canvas of
the appropriate size and ImageCopy( ) over the
part of the original canvas you want to keep. Then we serve the
correctly sized image as a PNG usingImagePNG( ) and clean up with two calls to
ImageDestroy( ).

As we mentioned at the beginning of this section, this is just a
quick-and-dirty function to print bar charts. It works, and solves
some problems, such a wrapped lines, but isn't 100%
perfect. For instance, it's not very customizable.
Many settings are baked directly into the code. Still, it shows how
to put together a variety of GD's functions to
create a useful graphical application.