May 4th, 2008
Learn How to Generate Graphics in PHP - Part II
How to Add Dimensions
In the previous part of this tutorial we learnt how to draw lines with a spoon feeding library and in this part we will enhance our PHP graphics library and learn How to Add Dimensions, Group Class and How to Develop a Viewport and more… so lets start.
With the first requirement: the ability to have graphic objects out of the way, it’s time to move on to the second requirement: the ability to position objects above and below each other using a z dimension.
Think of each z level being like a plane the size of the original image. The drawing elements are drawn in order from lowest to highest. For example, let’s draw two graphics elements: a red circle and a black box. Begin with the circle at 100 and the box at 200. That puts the circle behind the box, as shown below
Flip the values around, and show the red circle popping above the black rectangle with only a change to the z values. To do this, you need each GraphicsObject to have a z() method that returns a numeric z value. Because you’ll create different graphics objects (Line, Oval, and Rectangle), you’ll also create a base class called BoxObject used by all three to maintain the starting and ending coordinates, the z value, and the color of the object. The UML is shown below:

The code for which graphics library handle z information is below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 | <?php class GraphicsEnvironment { public $width; public $height; public $gdo; public $colors = array(); public function __construct( $width, $height ) { $this->width = $width; $this->height = $height; $this->gdo = imagecreatetruecolor( $width, $height ); $this->addColor( "white", 255, 255, 255 ); imagefilledrectangle( $this->gdo, 0, 0, $width, $height, $this->getColor( "white" ) ); } public function width() { return $this->width; } public function height() { return $this->height; } public function addColor( $name, $r, $g, $b ) { $this->colors[ $name ] = imagecolorallocate( $this->gdo, $r, $g, $b ); } public function getGraphicObject() { return $this->gdo; } public function getColor( $name ) { return $this->colors[ $name ]; } public function saveAsPng( $filename ) { imagepng( $this->gdo, $filename ); } } abstract class GraphicsObject { abstract public function render( $ge ); abstract public function z(); } abstract class BoxObject extends GraphicsObject { protected $color; protected $sx; protected $sy; protected $ex; protected $ey; protected $z; public function __construct( $z, $color, $sx, $sy, $ex, $ey ) { $this->z = $z; $this->color = $color; $this->sx = $sx; $this->sy = $sy; $this->ex = $ex; $this->ey = $ey; } public function z() { return $this->z; } } class Line extends BoxObject { public function render( $ge ) { imageline( $ge->getGraphicObject(), $this->sx, $this->sy, $this->ex, $this->ey, $ge->getColor( $this->color ) ); } } class Rectangle extends BoxObject { public function render( $ge ) { imagefilledrectangle( $ge->getGraphicObject(), $this->sx, $this->sy, $this->ex, $this->ey, $ge->getColor( $this->color ) ); } } class Oval extends BoxObject { public function render( $ge ) { $w = $this->ex - $this->sx; $h = $this->ey - $this->sy; imagefilledellipse( $ge->getGraphicObject(), $this->sx + ( $w / 2 ), $this->sy + ( $h / 2 ), $w, $h, $ge->getColor( $this->color ) ); } } ?> |
Now we can implement it in php_graphics_1.php and here it is:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | <?php require_once("php_graphics_lib.php"); function zsort( $a, $b ) { if ( $a->z() < $b->z() ) return -1; if ( $a->z() > $b->z() ) return 1; return 0; } $ge = new GraphicsEnvironment( 400, 400 ); $ge->addColor( "black", 0, 0, 0 ); $ge->addColor( "red", 255, 0, 0 ); $ge->addColor( "green", 0, 255, 0 ); $ge->addColor( "blue", 0, 0, 255 ); $gobjs = array(); $gobjs []= new Oval( 100, "red", 50, 50, 150, 150 ); $gobjs []= new Rectangle( 200, "black", 100, 100, 300, 300 ); usort( $gobjs, "zsort" ); foreach( $gobjs as $gobj ) { $gobj->render( $ge ); } $ge->saveAsPng( "test.png" ); ?> |
There are two things to notice here. First is the addition of the creation of the Oval and Rectangle objects, where the first parameter is the z value. Second is the call to usort, which uses the zsort function to sort the graphics objects by the z value.
The output is below:

Now, make make the following changes in the code:
1 2 | $gobjs []= new Oval( 200, "red", 50, 50, 150, 150 ); $gobjs []= new Rectangle( 100, "black", 100, 100, 300, 300 ); |
Run the code again, and suddenly the oval pops up above the rectangle as shown below:

The red circle appears above the rectangle, even though it’s created first and added to the array first. That is the real value of the z dimension: You can create objects in any order you choose and position them relative to each other by adjusting the z value on each object.
In this code, the z-order sorting is done outside the library. Let’s fix that by creating a new container object called a Group that can hold a bunch of GraphicsObjects. The Group object will then handle the sorting.
The code for the Group class is shown below:
The Group class
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | function zsort( $a, $b ) { if ( $a->z() < $b->z() ) return -1; if ( $a->z() > $b->z() ) return 1; return 0; } class Group extends GraphicsObject { private $z; protected $members = array(); public function __construct( $z ) { $this->z = $z; } public function add( $member ) { $this->members []= $member; } public function render( $ge ) { usort( $this->members, "zsort" ); foreach( $this->members as $gobj ) { $gobj->render( $ge ); } } public function z() { return $this->z; } } |
The Group object’s job is to hold an array of objects and then, when it’s rendered, do the sort and render the objects one by one.
Now we can update it in php_graphics_1.php and here it is:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | <?php require_once("php_graphics_lib.php"); $ge = new GraphicsEnvironment( 400, 400 ); $ge->addColor( "black", 0, 0, 0 ); $ge->addColor( "red", 255, 0, 0 ); $ge->addColor( "green", 0, 255, 0 ); $ge->addColor( "blue", 0, 0, 255 ); $g1 = new Group( 0 ); $g1->add( new Oval( 200, "red", 50, 50, 150, 150 ) ); $g1->add( new Rectangle( 100, "black", 100, 100, 300, 300 ) ); $g1->render( $ge ); $ge->saveAsPng( "test.png" ); ?> |
Now all the clients has to do is create one Group object. It will handle ordering and rendering everything else.
Pages : 1 2


May 4th, 2008 at 2:36 am
[…] Chris Channing wrote an interesting post today onHere’s a quick excerptHow to Add Dimensions In the previous part of this tutorial we learnt how to draw lines with a spoon feeding library and in this part we will enhance our PHP graphics library and learn How to Add Dimensions, Group Class and How to … […]