Codular

HomeWriters RSS

PHP GD Introduction

Introduction

As part of this multi-part tutorial we're going to look at how we can write a basic graphing library using the PHP GD library. While a lot of graphing libraries exist in JavaScript, there have been situations where I've required a PHP graphing library, but failed to find one that has done what I needed. For example when including graphs in a server-side generated PDF, or if you want to give users the option to download/export graphs as images from a web application.

We'll be doing a very simple bar graph, however we will learn quite a few basic GD lessons throughout:

We'll begin with a non-dynamic graph with 4 columns, which have varying values. The below data is what we'll use, it's a survey of 25 people highlighting what animal is their favourite.

Create a simple filled rectangle

We'll do this gradually, starting with a simple rectangle, filled in a nice red colour. This will eventually be the code that we use for each bar on our graph.

Create an empty image

$img = imagecreatetruecolor(200, 150);

Here we're defining it with a width of 200px, and height of 150px.

Define some colours

We'll just define black, white, and the red colour for now.

$black = imagecolorallocate($img, 0, 0, 0);
$white = imagecolorallocate($img, 255, 255, 255);
$red = imagecolorallocate($img, 255, 153, 153);

It is worth noting here that the first parameter is the image that we created earlier, and then the subsequent are Red, Green & Blue values for the colour.

Set the image to have a white background

We need to set the image to have a white background as standard, this requires us to use the PHP command imagefill:

imagefill($img, 0, 0, $white);

Draw a filled rectangle

Next we're going to draw a red rectangle that is 100px wide, and 50px tall, which starts at the x co-ordinate of 10, and the y co-ordinate of 15 also:

imagefilledrectangle($img, 10, 15, 100, 50, $red);

Output the image

We're going to output the image as a PNG, to do this it's a 3 step process:

  1. Set the header to be PNG

header('Content-Type: image/png');

  1. Output as a PNG image
imagepng($img);
  1. Destroy the GD image

imagedestroy($img);

Add a border

We'll just add a quick border around the rectangle also, to do this, we'll just define an unfilled rectangle at the same co-ordinates. Make sure you place this just after the section of code that adds the filled in rectangle.

imagerectangle($img, 10, 15, 100, 50, $black);

Result

By combining all of that code you should end up with something along the lines of this:

http://codular.com/a/i/graph-1.png

Multiple Rectangles

To add multiple rectangles, we need to just duplicate the two lines for each rectangle.

For our graph we need to come up with a scale, let's go ahead and make some changes:

  1. The graph will be 400px wide
  2. The graph will be 350px high
  3. For each value of 1 we'll add 35px. (value of 8 = 280, etc.)
  4. All graphs will be 50px wide
  5. We'll put 20px between each vertical bar.

With these things in mind, we'll quickly create graphs of the correct dimensions:

Cats:

imagefilledrectangle($img, 10, 15, 60, 635, $red);
imagerectangle($img, 10, 15, 50, 635, $black);

Dogs:

imagefilledrectangle($img, 80, 15, 130, 835, $red);
imagerectangle($img, 80, 15, 130, 835, $black);

Sheep:

imagefilledrectangle($img, 150, 15, 200, 335, $red);
imagerectangle($img, 150, 15, 200, 335, $black);

Whales:

imagefilledrectangle($img, 220, 15, 270, 835, $red);
imagerectangle($img, 220, 15, 270, 835, $black);

A few things to note: 1. All of the initial x-values increment by 70px. 2. The y-value is calculated by simply multiplying 3. The graphs sit at the top of the image:

http://codular.com/a/i/graph-2.png

What we need to do is push these down to the bottom to be aligned correctly. To do this, we must add a set amount to each y-value.

First we must define a y-value that we want to be the baseline, we'll make this 320px down. What we'll do is set the first y-value to be 320px, and then the second to be 320px minus the calculated height. e.g.:

Cats

imagefilledrectangle($img, 10, 320, 60, 320-(635), $red);
imagerectangle($img, 10, 320, 60, 320-(635), $black);

Dogs:

imagefilledrectangle($img, 80, 320, 130, 320-(835), $red);
imagerectangle($img, 80, 320, 130, 320-(835), $black);

Sheep:

imagefilledrectangle($img, 150, 320, 200, 320-(335), $red);
imagerectangle($img, 150, 320, 200, 320-(335), $black);

Whales:

imagefilledrectangle($img, 220, 320, 270, 320-(835), $red);
imagerectangle($img, 220, 320, 270, 320-(835), $black);

If you run this successfully, you should end up with the following:

http://codular.com/a/i/graph-3.png

Add some Axes

Next we need to add the x-axis and the y-axis to the graph, to do this we may need to shift the x co-ordinates of all of the graph bars over to the right a bit. But let's look at how we draw each of the axis:

The x-axis

This is simple, we know that this is at the y-position of 320, and we just need to work out where it starts and ends. To do this we need to look at where the first bar starts, and where the last bar ends. This is 10px, and 270px respectively. We will want to add 20px padding to each side of the bar as per our standards, so we'll be looking to run the bar from -10 to 290.

This won't work out completely due to -10 being off the left hand side, so we'll shift the left hand side of the bar to start at +20. Meaning we'll need to shift all of the bars over to the right by 30px.

To draw a line, we need to use the imageline method, which takes 6 parameters. The image, starting x and y co-ordinates, final x and y co-ordinates, and then the colour. If we shift all of the bars, and draw the x-axis using the following code (note that we've altered the x co-ordinates of this also):

imageline($img, 20, 320, 320, 320, $black);

We should end up with something looking like this:

http://codular.com/a/i/graph-4.png

The y-axis

The y-axis needs to run from the same initial co-ordinates as the x-axis, and run to the maximum y-coordinate from the bars, with an additional 20px to add our standard padding.

To do so, we'd use the following line:

imageline($img, 20, 320, 20, 320-(8*35)-20, $black);

Thing to note is that we are (again) calculating the final y co-ordinate. This is the y-offset, minus the maximum height, minus the 20px padding. If this all runs successfully, we'd end up with:

http://codular.com/a/i/graph-5.png

Complete Code

Below is the completed code for this section, including comments:

<?php
// Create GD Image
$img = imagecreatetruecolor(400, 350);

// Assign some 
$black = imagecolorallocate($img, 0, 0, 0);
$white = imagecolorallocate($img, 255, 255, 255);
$red = imagecolorallocate($img, 255, 153, 153);

// Set background colour to white
imagefill($img, 0, 0, $white);

// Cats: 6
imagefilledrectangle($img, 40, 320, 90, 320-(6*35), $red);
imagerectangle($img, 40, 320, 90, 320-(6*35), $black);

// Dogs: 8
imagefilledrectangle($img, 110, 320, 160, 320-(8*35), $red);
imagerectangle($img, 110, 320, 160, 320-(8*35), $black);

// Sheep: 3
imagefilledrectangle($img, 180, 320, 230, 320-(3*35), $red);
imagerectangle($img, 180, 320, 230, 320-(3*35), $black);

// Whales: 8
imagefilledrectangle($img, 250, 320, 300, 320-(8*35), $red);
imagerectangle($img, 250, 320, 300, 320-(8*35), $black);

// Draw x-axis
imageline($img, 20, 320, 320, 320, $black);

// Draw y-axis
imageline($img, 20, 320, 20, 320-(8*35)-20, $black);

// Define output header
header('Content-Type: image/png');

// Output the png image
imagepng($img);

// Destroy GD image
imagedestroy($img);

Conclusion

For now it's a working example of how to draw a few things with PHP GD, and form them together into a graph.

Next tutorial we'll look at how we can automate this with an array of data, as well as the adding of labels, and a few extra features.

Tag: PHP