SDA India is an online resource for Software, Development,IT, Architecture, Open Source, Mobile, Security, Databases, Delphi, C, OS, Asp, .Net, Php, Xml, Java

Building graphs with Imlib2


Current Issue

Christopher Kunz
Christopher Kunz is a student and freelance PHP developer based in Hannover, Germany. He is a regular speaker at PHP conferences and an active member of the PHP community..


PHP features numerous possibilities for multimedial web content and graphics creation.The most obvious choice is using the GD graphics library by Tom Boutell, which is currently in widespread use and will be a part of the PHP source distribution from PHP 4.3.0 on. GD enables the web programmer to quickly create graphics and include true type fonts, but currently lacks in regards of image quality and advanced features.

Luckily, there are alternatives. While the popular graphics manipulation package, ImageMagick, is in no way ready for use in a PHP production environment, there is already a quite stable PHP extension for Imlib2.
This library, written by Rasterman, is part of the Gnome window manager "Enlightenment" and its API has been ported into a PHP extension. This extension, however, is currently not part of the PHP source distribution and must be installed and configured separately. See the box (Installing the PHP Imlib2 Extension) for details.

The basics – building graphs manually

The C-like approach to I/O functions, file and resource handles, is used for Imlib2, too. Image manipulation is performed on



image handles. The following examples will illustrate the creation of a bar graph, including a legend, from a two-dimensional array as the data source.

Before you start, it is a good idea to predefine some variables – you will need them throughout the script.

$width = 300; # width of the image
$height = 300; # height of the image
$distance = 5; # distance between bars
$border = 20; # left / lower border


The data source for your graph can be database output, values provided from another script or almost anything else as long as it is stored in an associative array of the form “description” => “value“ and the values are numeric.

The first “real” step, of course, will be the creation of an image handle. Imlib2 provides several functions for image creation – most of them are more appropriate for manipulation of an already existent image than for drawing a new image from scratch. The correct function for creating a blank image handle (and “flood filling” it with white color) is

$handle = imlib_create_image($width, $height);
imlib_image_fill_rectangle($handle, 0,0,$width, $height,
255,255,255,255);

This function returns a valid image handle on execution – this handle will be subject to all operations from now on –like the function imlib_image_fill_rectangle, which is called immediately after imlib_create_image and fills the image handle with white color.

Borders and axes

If a border value greater than 0 is defined, the real drawable area is smaller than then original image proportions. The coordinates of this rectangle are stored in an array in the following order: X value of upper right corner, Y value of upper right corner, X value of lower right corner, Y value of lower right corner. Instead of using $width and $height to position the bar graphics, you can now use the appropriate
coordinates from this array.

$drawable_area = array($border + 1,0,$width, $height -
$border -1);


A bar graph needs a scale – the X and Y axis should be drawn at the perimeters of the drawable area: from top left to bottom left for the Y axis and from bottom left to bottom right for the X axis.


To draw a line, use the function imlib_image_draw_line and provide the following arguments:

•$handle – the image handle
•$x1 / $y1 – coordinates of the line start
•$x2 / $y2 – coordinates of the line end
•$red, $green, $blue for red, green and
blue values of the line color
•$alpha for the line’s transparency value

The axis lines are drawn with the following function calls:

imlib_image_draw_line($handle, 0,$height - $border,
$width, $height - $border, 0,0,0,255);
imlib_image_draw_line($handle, , 0, $border,
$height, 0,0,0,255);


Drawing the Bars

Some additional calculations are needed to provide correct positioning and bar width. In this example, a fixed margin between the bars ($distance) and flexible bar width are used. You could as well fix the bar width and calculate the margins respectively, but that could break your script if the number of bars exceeded the width of the drawable area.

$width_of_bars = (($drawable_area[2] - [0])
- (count(array_keys($datasource))-1) -
((count(array_keys($datasource)) -
1)*$distance))/count(array_keys($datasource));




To properly determine the relation between the data value and its pixel size, you need to divide the drawable area by the biggest value in the data set.


$scale_factor = floor(($drawable_area[3]-
$drawable_area[0])/max(array_values()));


At last, set the initial horizontal position to the left corner of the drawable area.


$xpos = $drawable_area[0];


Now, you can start to loop through the available data set, and draw a bar for each array element.



Fig. 1: Imlib support in phpinfo()

foreach ($datasource as $legend => $data) {
$data = round($data, 1);
imlib_image_fill_rectangle( $handle, $xpos, $drawable_
area[3] - $scale_factor*$data, $width_of_bars,
ceil($scale_factor*$data), 0,255,0,255);
$xpos += $width_of_bars + $distance;
}


Using the function imlib_image_fill_rectancle with the usual arguments (image handle, initial X and Y coordinates, X and Y coordinates for the rectangle’s end point, as well as red, green, blue and transparency values for the rectangle color), a filled rectangle is drawn onto the image handle for each bar of the graph.


After drawing the bar, the X position is set in accordance with the next bar and the loop is re-executed.

Saving and Output

Of course, the finished image must somehow be made available to the viewer. This can be accomplished in two ways: either by streaming it to the client or by storing it on the server for later use. Either possibility
has a special function.

Prior to saving or streaming, you need to set the image format of the image, with the function imlib_image_set_format (, ), where can be jpeg or png. Unfortunately (and probably due to the known license issues inflicted by UniSys), GIF support is not available in ext/imlib and trying to set the image format to gif yields very weird errors. So, you will have to resort to PNG if you need transparency information.

It is essential to use imlib_image- _set_format before saving the image because otherwise, the image would always be sent in PNG format, no matter what image headers were sent by the script. This can lead to some confusion for browsers, image viewers, and other client programs.

If you decide to stream the image back to the client, you need to set the appropriate headers with the header() function. After that, imlib_dump_image() sends the image at optimum quality settings.

If, however, you want to save the image for later use, you do not need any headers – just call imlib_save-
_image($handle, „/var/www/html/images/image.jpg“) to save the image to disk.

Both functions take two optional arguments, $error and $quality. The former is a variable to save any occurring errors, the latter is the quality level used for saving (or displaying) images. It ranges from 0 –100 (quality in percent) for JPEG and from 0-9 (compression rate) for PNG images.

After you do not need the image handle any more, you should free the allocated memory by using imlib_free_
image($handle). This concludes the image operation and the first part of this article.

Building graphs with Vagrant

Instead of programming each graph type manually, using a pre-programmed charting engine is a much easier solution. The only charting class for Imlib2 that I know of is Vagrant (see [3] for more information and


Fig. 2: Simple bar graph
download). With this class collection, you can create graphs in Imlib2 as well as GD2.
Vagrant’s installation is fairly straightforward, just unpack the archive and put the .class files somewhere where they can easily be included (your PHP library path may be a good place). After that, you can immediately start creating images.
Currently, Vagrant supports the following graph styles:
•Line Graphs
•Vertical Bar Graphs (similar to the ones
created in the first part)
•Dashed Line Graphs
•Filled Line Graphs
•Scatter Graphs
•Pie Charts


Unfortunately, the development of Vagrant seems to be stalling. The current CVS version, Vagrant 2.5, has not been touched for over a year.

Creating a graph

To use the functions provided by Vagrant, you need to include the imlib base class. If you want to use Imlib2 for the graphics output, just perform include(“Graph.imlib. class”), if you prefer GD, the class to use is named Graph.gd.class.

First, you will again need to provide an array of input values. You can reuse the array of random values from the last script or use your own data source.

You will need a second array with exactly the same number of elements that is used for the X axis tickmarks. For example, if your first Y value has the X value of “0”, this would be the first element for the X value array. Unfortunately, Vagrant does not support literal X axis descriptions yet – you must use numerical values. Normally, counting from 1 to the number of values in the Y value array is sufficient.

$y = array(1.2345, 4.5689, 8.9877, 10.2322, 17.009);
$x = array();
while ($i = 1; $i = count($y); $i++)
{
array_push($x, $i);
}


As Vagrant is completely object oriented, initializing the graph is actually creating an instance of the class Graph. The following lines of code are used for initialisation of a 500*500 pixel graph titled Vagrant Example Graph:


$graph = new Graph;
$graph->InitGraph(500,500);
$graph->SetTitle('Vagrant Example Graph');


Note: The initialisation is the same for all graph types!


You can also set a subtitle for the graph, as well as X and Y axis descriptions. The appropriate methods are

$graph->SetSubTitle();
$graph->SetxTitle();
$graph->SetyTitle();


After these parameters are set to your convenience, you can add your dataset to the graph. The method AddData() does that. It has three arguments:


•Array $x – X axis values – prepared in aloop
•Array $y – the actual bar values; provided by your data source of choice
•String $description – Description of the graph for the image legend

Therefore, the method call is $data = $graph->AddData($x,$y,"Data Set 1").It returns an object.

The decision which type of graph is to be used for the final visualization is made at this point of the script – all earlier functions and methods are interchangeable for most graph types. To see the differences between creating a graph manually and having a library do the dirty work for you, we will start with a bar graph, with the same data source that has been used in the former part of the article.

Adding a Bar Graph

The support for bar graphs in Vagrat is quite limited and the results will probably not be satisfactory in comparison to what you can accomplish on your own with a few more lines of code.

To add a vertical bar graph, simply call

$graph->VBarGraph($data, $color);

The argument $data is the object that was returned by the call to AddData() and $color is one of the colors supported by Vagrant (see the box for a complete list). That is it – you have just added a bar graph to your image.

Using Line plots

There are currently four types of line plots in Vagrant: generic line plots, plots that draw a dashed line, the so-called “scatter plots” and filled line plots. The four types only differ in the method call used to draw them; taken that aside, their behaviour is identical to each other.

The method calls for the different line plot types are

$graph->LineGraph($data, $color);
$graph->DashedLineGraph($data,$color);
$graph->FilledLineGraph($data, $color);


The fourth line plot type, a scatter graph, needs an additional argument, the type of the scatter polygon. Currently, this is either a circle, a box or a triangle. The complete method call I

$graph->ScatterGraph($data,”box”, $color);

Pie charts

Pie charts are handled somewhat differently than bar and line graphs. They are definitely the best-looking graphs Vagrant can create, as they are rendered in a semitransparent look and an isometric threedimensional look. Creating a pie chart with vagrant is the easiest task with this free charting library. You will need two single-dimensional arrays, one with the values and a second one with their literal description. These two arrays are passed to the PieChart() method call, along with a title for the complete graph. The final method call could look like this:

$graph->PieChart($x, $y, ”An example pie chart”);

where $x is the array of descriptions and contains the actual values.

Yes, it is really that easy to create a good-looking pie chart! However, you cannot impose multiple pie charts onto each other.

A legend is automatically rendered, so you do not need to use the DrawAxis() method to create it.

Multiple Graphs in one image

It is possible to add multiple graphs to one image and superimpose them onto each other. Just call the respective methods one after another to add more than one graph to the image. To add a line graph, a bar graph and a dashed line graph, you would use this code:

/* Bar graph */
$graph->VBarGraph($data, $color);
/* Line graph */
$graph->LineGraph($data, );
/* Dashed line graph */
$graph->DashedLineGraph($data,$color);


Displaying the image

After every graph has been added, your image can be shown. The method Show- Graph() prints all necessary headers and outputs the finished image.

Unfortunately, Vagrant does not currently support saving of images to a file. Instead, every image resource is streamed back to the browser. If you want to save an image instead, you will need to use output buffering functions prior to displaying the image. This is a bit of a nuisance, especially because saving images to files can be regarded as a basic function for any graphing class.

To draw the axes and the legend and output the graphic, the following methods are used:

$graph->DrawAxis();
$graph->ShowGraph();

That is it. The image is streamed to the browser.

Summary

Creating good-looking graphs is an easy task with PHP and Imlib2. However, you need to evaluate carefully if a pre-programmed graphing class meets your needs or if you might be better off by creating all necessary code by hand. In either case, Imlib2 is a great alternative to the established solutions like GD.

Resources and References

  Related Links
  prdownloads.sourceforge.net/enlightenment/
  www.christopher-kunz.de/imlib/php_imlib--
  vagrant.sourceforge.net/#
Post a Comment
Name
Title
Comment
Menu
News Desk
Feature Stories
Articles
Interviews
Case Studies
White Paper
Analyst Corner
Planet SDA-India
SDA Events
INDIA IT Event Calender
IT Jobs
Advertise