FAQ Content

1. Installations

The simple answer is: Anywhere You like! Since the necessary library files are included in Your own script with an "include" statement it doesn't matter where You put the library as long as Your scripts can access it. A common place is to store the library is in a directory where PHP searches for include files (as specified in Your php.ini file), for example in "/usr/share/php" or perhaps "/usr/local/php" depending on Your PHP configuration.
An even simpler way is to just store the library in a directory where Your scripts are executed from.

Yes. The library itself is OS-agnostic. As long as you have a WEB server which supports PHP 4.3.x (or above) and have the GD library. Please note though that the behavior of PHP/Apache on Unix and Windows seems to have some subtle differences which might affect things like path specification using '/' or '\'.

1-3 My webadmin does not allow PHP any write permissions and hence I can't use the cache feature of JpGraph. Is there any way to completely turn off the caching feature?

Yes, set the constant "USE_CACHE" to FALSE in jpg-config.php. This way will skip writing file even if a filename has been submitted in the Graph() creation call. You can also accomplish this by not having any file name at all in the call to Graph().

1-4 After installation all I get is an empty page when I try any of the examples?

If the HTTP server respons is truly absolutely empty (verify that by looking at the source of the page that gets returned to the browser) then the only answer is that the HTTP server has crashed. Most likely it is the PHP process within the server that has crashed. Even though PHP is fairly stable there are still ways of crashing it. To investigate this further You might try to:

* ... investigate the system log for traces of a server crash.

* ... try increase the maximum allowed memory for PHP in php.ini. As a rule it should be a minimum of 16MB (and preferable 32MB).

* ... upgrade PHP to the latest stable version (and use the compile options shown further down in this FAQ.

* ... enable all errors and warning for PHP (in php.ini) to help track down the problem.

* ... disable output buffering to get errors send back to the browser as soon as possible (in php.ini).

2. General

2-1 How can I send the generated graph to both the browser and a file at the same time?

This is not directly supported by means of any particular option or setting in the library but with small "trick" this is easy enough to accomplish.
The idea is to use the _IMG_HANDLER option that forces the Graph::Stroke() to just return the image handler and then stop. We can then manually first send the image to the chosen file and then stream it back to the browser using some internal methods in the library.

The following code snippet shows how this is done

$graph = new Graph(400,300);
// Get the handler to prevent the library from sending the
// image to the browser
$gdImgHandler = $graph->Stroke(_IMG_HANDLER);
// Stroke image to a file and browser
// Default is PNG so use ".png" as suffix
$fileName = "/tmp/imagefile.png";
$graph->img->Stream($fileName);
// Send it back to browser
$graph->img->Headers();
$graph->img->Stream();

2-2 What is this 'auto' I see in all the Graph() creating in the Examples directory? Do I need it?

No. The third argument in the graph call is an optional cache file name and is not necessary unless You want to use the caching feature of JpGraph. By specifying 'auto' the filename is automatically created based on the name of the script file.

In order to run the examples the code generates HTML to read the image from the cache directory as Apache sees it. You must adjust the image tag to have the correct path to your cache directory.

2-4 When I run 'testsuit_jpgraph.php' I get a warning "Due to insufficient permission the source files can't be automatically created"

This is not a serious problem. When the testsuit is run it tries to create a symbolic link with the same base name as the individual testfile but with extension ".phps". This is just so it is possible to click on an image and then view the source syntax colored. If Apache doesn't have write permissions to the directory where 'testsuit_jpgraph.php' is executed from you will get this warning.

If you want to use this feature just change the permissions so Apache may write to the directory.

This method is not suitable for large data sets since there is an upper bound to the length of an URL specification (around 255 characters)

* A fourth way might be to use session variables to pass the data between different scripts. For large data sets the only practical way is to read the data from a file or from a DB to construct the data vectors.

Export the data from Excel as a CSV (Comma separated Values) file to be able to easily read the file. Then either write your own routine to read and parse the data from that file or use the utility class "ReadCSV" in "jpgraph_utils.php".

A basic example on how to do this for a line graph assuming the name of the data file is "data.csv".

2-7 How do I pass data from a Database (e.g. MySQL) to a script to produce a graph?

By adding some SQL statments in Your graph scripts that creates the data arrays from the DB.

Watch out for empty values and strings. JpGraph doesn't know how to plot strings. Any value passed into JpGraph should be only valid numeric data. See the online discussions on populating from a DB Populating DB or the discussion on how to read data from file Reading from file.

See How to populate arrays from mySQL

2-8 I change my data but my image does not get updated? The old image is still send back to the browser?

What you are seeing is a cached version of Your image. Depending on your setup it could either be that the browser has a cached image or You are using the builtin cache system in the library by accident.
Fixing the browser cache

Since the script from the browser point of view is the same it just displays the old image. To fix this you need to turn of the browser image caching.

Another "trick" that can be used since normally it is impossible to control the browser for the end user is ot add a "dummy" URL argument which changes. This way the brower will always see a new URL and then alwyas reload that file. This could be done for example as:

echo ('<img src="graphscript.php?' .microtime(). '"&rt;');

Fixing the library cache

The other reason might be that You have enabled the built-in cache feature in JpGraph. To turn it of You can either

* Not specify a cache name in the call to Graph(). Just call new Graph(200,200) for example.

* Turn off the reading from the cache by setting READ_CACHE to false (in jpg-config.inc)

* Turn off the reading and writing from the cache by setting USE_CACHE to false (in jpg-config.php)

* Use the cache but with a timeout so that the image will be re-generated if the cached image is older then the specified timeout value in the call to Graph().

2-9 Can I run JpGraph in batch-mode just outputting an image directly to a file and not streamed back to the browser?

Yes. Just specify an absolute file name in the call to Graph::Stroke(). To store the image in the local temp directory use:

$myGraph->Stroke("/tmp/myimage.png")

Note: You must match the file ending Yourself to the format you have chosen to generate the image in.

2-10 Do you offer a commercial version of JpGraph with full support and no QPL?

Yes, For commercial (non-open-source) you will need to get the "JpGraph Professional License". This allows you you deploy JpGraph in a commercial context. Further details upon contact.

2-11 Some of my script just return a blank image and no error messages?

This could potentially be a lot of things depending on which browser you are using. One thing you might want to check is that your script doesn't take to long time. In that case they might hit the time limit for running a PHP script as specified in php.ini. You can adjust that time limit with a call to set_time_limit().

2-12 I can see the generated image fine in the browser but I can't print it?

This is again browser dependent. Some browser does not like to print an image which is generated on-line and does exist as a *.jpg, *.png etc file. No good workaround has been identified short of changing browser. Some browsers (and versions) can print others not. The only real safe way (if you need printing) is to generate the image on disk and then have the browser read the image from there.

2-13 How can I generate an image directly to disk without streaming it back to the browser?

Two ways: (Preferred way) If you supply a filename in the call to $graph->Stroke() the image will be written to that file and not be streamed back to the browser. If you prefer to have the image going to the cache directory but not streamed back then you could just set the '$aInlineFlag' in the initial call to Graph() (fifth argument) to false as in

$mygraph = new Graph(200,200,"auto",0,false)

The "auto" argument makes an automatic file name in the cache based on the script name. The 0 indicates that we have no timeout. The advantage with this method is that you can specify a timeout to avoid having the image generated to often.

2-14 When I try to plot graphs with many 1000:s of data points I only get a blank page. Is there a limit in JpGraph to the number of data points you can plot?

No, there is no such limit. The problem is most likely that your script takes so long time that the PHP execution limit (as specified in php.ini) aborts the script. If you have more than 10,000 data points JpGraph will work but doing this kind of heavy data analysis on a WEB-server extension is probably not a good idea to start with.

The other reason could be that the script exhausts the allowed memory limit for PHP as specified in the "php.ini" file. By default this is often set to 8Mb which is to low for a complex JpGraph script. Try increasing the memory limit to a minimum of 16Mb. For very complex graphs with 1000s of data points there might be a need to increase the memory even further.

You can do this in two ways, you can either stroke the image created with the library directly to a file where it can be used with Your PDF library of choice. For example, using FPDF (www.fpdf.org) the Image() functoin would have to be used to read an image from the filesystem.

If You are using the PDF library (APIs included in the PHP distribution but the library itself might require a license depending on Your usage.) you can avoid the storage of the file by getting the image handler for the image directly and use it with PDF.

With the PDF library you must first open the in memory image with a call to pdf_open_memory_image($pdf, $im). The following script places an image from JpGraph directly into a PDF page that is returned when running this script.

A html link, which directs to the php page (assuming the filename is chart.php): Download Then, if you click on the link, a download dialog appears and you can download the "chart.png". Note: If you directly open chart.php, the image is directly streamed to the browser and the download dialog will not open.

To open a target CSIM (drill down) in a separate window some javascript in the target link is necessary since this action must be performed in the browser. The target URL needs top be in the form of an action to open up a window (with any optional URL argument that might be needed). For example, assume we have a bar graph and that theb user can click on each bar to get more details. When the user clicks on a bar we open up the detaails witha call to the helper script "bar_details.php" and send the parameter "id" to the script to separate the individual bars. We would then use the following URL link (with javascript)

It should be noted that in the above Javascript code we have used the special window name '_new' which means that a new window will be opened each time a user clicks on a bar. By giving the window a specific name the same window would be re-used every time.

The above script when run should produce an image with a black text string on a white background. If this doesn't work then there is a setup problem with PHP + TTF.

As a first step to resolve this recompile Your PHP4 setup using the following basic configuration (depending on the local conditions some options/path might have to be changed). The critical options are marked in bold.

You have a old buggy version of the FreeType library, most likely the old FreeType I library is being used. Please upgrade to the latest version of FreeType II.

3-3 I get an error "This PHP build has not been configured with TTF support. You need to recompile your PHP installation with FreeType support."

This error is reported if the built-in PHP/GD function "imagettfbbox()" is not available. This is a crucial method to make TTF fonts work with JpGraph. The most likely reason for this problem is that the PHP configuration is faulty and does not have correct support for TTF fonts. Please recompile PHP as shown above and make sure that the built-in version of GD is being used and not the stand-alone library.

You have either not specified a correct path where your fonts are stored (see top of jpg-config.inc) or you have tried to use a font you do not have installed.

3-5 I get the error "Can't find font file FONT_PATHarial.ttf" (or some other font)

You are most likely running on Windows. This seems to be caused by a bug in PHP/Apache (or PHP/IIS) specifically on Windows. The problem seems to be that PHP doesn't remember a DEFINE() setting across two or more include directive. A simple workaround is to hard-code the font path in class TTF in file jpgraph.php. Note: If you have this problem you will most likely also have a problem with the path to the cache directory.

This error is caused by the inability of PHP/JpGraph to read the font file. This could have several reasons:

1. The file path or name is wrong and the file really doesn't exist. Please check that the file and path (as shown in the error message) really exists.

2. If the file exists it might still not be possible for PHP to read the file due to permission problem. Please make sure that PHP can read a file in the TTF directory. This can be verified with the following short script

3-9 When I put a text object on a graph and use Set90AndMargin() it doesn't show?

The main casue for this behaviour is that the text object position is rotated 90 degrees.

For example, putting a text object at Pos(0,0) it will become "invisible". The reason for this behaviour is that the texts position (not the text itself) is rotated around the center of the image 90 degrees clockwise.

For example, assuming the image is WxH in size. Rotating position (0,0) which is the top left corner of the image gives the rotated position:

(0,0) => rotate 90 degrees => (W,0)

Now, if a string was put at position (W,0) it will be drawn outside the image and hence become invisible.

If You need to position text with rotated images just keep this in mind and swap the meaning of the X and Y posiiont since the X-position will become the Y position and vice versa after a 90 degree rotation. Some experiements will soon allow You to get the hang of it.

Tip: Start with an image that is equal in W and H since this makes it easier to understand the rotation.

4. Error Messages

First, this is not a problem with JpGraph per se. What has happened is that your PHP file which produces the image has already returned some data to the browser before the image has been sent. This is most often caused by one or more spaces before the first "
When later JpGraph tries to send the correct image header the browser gets confused since it has already received a header for the current document. (Each document can only have one and only one type). Check your files for any output (even a single space) before the call to Graph::Graph() (or Graph::Stroke())

If you are running on Windows this problem could be caused by a blank line at the end of any of the jpgraph_*.php files. All files in jpgraph ends in a newline which some configurations on Windows doesn't like. Remove the newline so that the file ends just after the final "?>"

Also remember that when you include external file using include/include_once and so on Php include the whole content of the file; this content of the file also include any potential carriage return/line feed or "blank" space before "" These "dirty characters" will stop the JpGraph being properly sent back because they are included in the image streaming.

You have not compiled PHP with support for the GD graphic library. See PHP documentation for details. Note that you also need to configure PHP to use GD and/or TTF fonts to get JpGraph full functionality

You have not compiled PHP with support for the JPG format. See PHP documentation for details

4-4 I get an error "Warning: MkDir failed (Permission denied) in jpgraph.php on line XXXX"

This is a permission problem. To use the cache Apache/PHP must have write permission to the cache directory. Make sure that Apache/PHP have sufficient permissions to write to the specified cache directory.

4-5 I get an error "Fatal error: Undefined class name "parent" in jpgraph.php on line xxxx"

You are using an older version of PHP. JpGraph requires at least PHP 4.3

Most likely Your data really contains non-numeric data which You need to further investigate (for example by printing out the array with a var_dump(). One additional thing to watch out for is if the data looks like ".56" (or "-.56") which is a shortform of "0.56". The problem is that the number starts with an "." (dot) which is non-numeric. The solution is to replace the single dot with a "0."

4-7 I get an error "Date is outside specified scale range" trying to create a Gantt chart

As the error says, you start or end date for a activity is larger/smaller than the max/min value in the scale. If you get this error and you are using automatic scale then you are probably using a null value (empty string "") as start or end date. Check your data.

This is a permission problem. Check that your cache directory has the right permissions to let JpGraph access and write to it.

4-9 I get an error "Fatal error: Call to undefined function: getcsimareas() ..."

You have enabled the DEFINE("JPG_DEBUG",true) in jpgraph.php. This is an internal debug flag which should always be left untouched.

4-10 I get an error "Fatal error: Call to undefined function: imagetypes()"

You have not installed the core GD library correct. imagetypes() is a standard GD function. Please refer to the installation section in the manual for more information on how to verify You setup.

4-11 I get an error saying something like "Error: 'parent::' not valid in context..."

You are most likely using the Zend cache. There is a bug with some versions of the Zend cache together with the "parent" meta class. If the referenced parent class is in another file that is included this problem seems to occur. The workaround seems to be to put all classes in the same physical file or upgrade the Zend cache to a more recent version.

4-12 I get an error "Image cannot be displayed because it contains errors.."

First of all this is an error message from the browser and not the library. There could be various reasons for this but the most likely scenario is that Your installation of PHP has both enabled output buffering and enabled strict error checking.

What could now happen is that with output buffering enabled PHP will buffer up any text error messages. This could for example be som "Notice:" warnings if You have forgotten to initialize some variables. When then the library adds the proper image header and the buffered error messages together with the image gets sent back the browser it all falls apart.

The browser tries to interpret both the error messages and the image data as an image and it of course fails and gives this error message. Why? Because the textual error messages that was buffered is interpretated as if they would belong to the image which of course is nonsense.

The solution is to disable output-buffering until You are convinced that Your code is without any problem. On a develpment server it is recommended to always have output buffering disabled.

4-13 When I use PHP5 + JpGraph 2.x I get "A plot has an illegal scale..."

There have been a few reports of this problem and it seems to be due to a faulty PHP 5.x installation. For example a standard SuSE 9.3 PHP5 installation gives this problem. The exact reason for the problem has not been established but it all points to a PHP5 problem since it can be solved by adjusting the PHP installation without any change in the library.

Step 1: First check that Your php.ini file have compatibility mode turned off

zend.ze1_compatibility_mode=off

Step 2: If turning the compatibility mode off still doesn't solve the problem the only remaining solution is to re-compile PHP 5. For example on our development servers we use the following configuration Note: We place "php.ini" in "/etc/php5/apache2" and You might want to change this to suit Your specific setup.

You can set USE_IMAGE_ERROR_HANDLER to false defined in jpg-config.inc.php
to change error message to text-based.
jpg-config.inc.php

// Determine if the error handler should be image based or purely
// text based. Image based makes it easier since the script will
// always return an image even in case of errors.
define('USE_IMAGE_ERROR_HANDLER', false);

5. Formatting Problems

5-1 I try to mix bar and line graphs and the bars doesn't get centered and the labels are not correctly aligned?

This is a known problem. The best way to partly solve this is to make sure you add the bar plot as the last plot to the graph. The reason behind this problem is that plot that gets added to the graph internally makes modification to the alignment of the plot. Since each plot does not know what other plot has been added it will happily overwrite previous plots settings in the graph. Hence the workaround by adding the bar last. conflicting settings.)

There is not any built in support in JpGraph at the moment to do this.

5-3 The auto-scaling algorithm chooses very tight limits around my Y-values. How do I get a more "space" between the end of the scale and the min/max values?

Use the SetGrace() to specify some extra space (as percentage of the scale) between the min/max value and the limits of the scale. For example $graph->yscale->SetGrace(10) gives 10% extra space at the ends.

5-4 I want to use autoscaling to handle the maximum value but I always want the Y-axis to start at 0 regardless?

Hint: If you need to limit the maximum value but auto-scale the minimum value use the SetAutoMax() method.

5-5 I want the position of the X-axis to be at the bottom of the Y-scale and not always at the position Y=0?

To adjust the position of the Axis Use the Axis::SetPos() method. The argument to this method can be either the numerical scale value on the Y-axis where the X-axis should be positioned or it can be one of the two special value "min" or "max". In the latter case the axis will be positioned on either the minimum or the maximum value of the scale. For example

...
$graph->xaxis->SetPos("min");
...

Will put the X-axis at the lowest value of the Y-axis.
Note: The same positioning is possible for the Y-axis.

5-6 I specify color X in the image but the color displayed is not exactly what I specified?

This is a result of a finite color palette for GIF, PNG formats. If you are using anti-aliasing, perhaps a background image or even gradient fill you might exhaust the color palette supported in the GD library. Try set the constant USE_APPROX_COLORS to false and generate the picture again. If you now get an error message saying that no more colors can be allocated this is the problem. There is no good workaround if you are using GD 1.x since for PNG the GD 1.x library does not support "True-color".

The only real solution is to upgrade to GD 2.x to get full true-color support. If you are using a background image try to "degrade" it to have a smaller color palette or turn of anti-aliasing and you might have enough free palette entries to cater for all the colors you want and still use GD 1.x

Note: Internal fonts support 0 and 90 degrees text. If you need to use, say 45 degree (or any other arbitrary angle), you must use TTF fonts.

5-8 How do I invert the Y-scale so that it has the minimum value on top and the largest value at the bottom?

The easiest way to do this is by following a two step process by first a) Negating all Your values and then b) Create a callback function for the Y-axis that negates all the display values.

What will happen now is that after the negative values have been feed into the graph it will create a scale starting at the lowest value, say -8, then go up to the highest, say -1. If these values are then inverted when printed it will in affect achieve the inverted axis appearance. The code snippet below shows a basic example of this technique.

5-11 Line weight does not seem to work in my graphs? I specify a thick line but still get a thin line?

Use the Axis::SetTitleMargin() method. For example to have a 25 pixels margin for the Y-title you could use:

...
$mygraph->yaxis->SetTitleMargin(25);
...

5-13 How can I display both X and Y values above each data point in a line, bar or scatter plot?

You need to use a value formatting callback. The callback function is called for each data point and is passed the Y-value as argument. This means that if You also need to display the x-value it must be available in the callback function,perhaps as a global data array.

5-15 Is there any way to specify a newline in the legend box for a specific legend?

Use XXX; format in your strings where XXXX is the decimal value for the unicode character. You may find a list of Unicode characters and there encodings at www.unicode.org Please observe that the encoding in the lists are given in hexadecimal and these values must be converted to decimal.

Note: If You are working in an UTF-8 environment then the characters may be input directly.

You are using a very old GD version (probably 2.0.1). Background images only work with a truecolor image, (enable the USE_TRUECOLOR constant). Some people have reported that it works as long as the background image is not in PNG format. The drawback with truecolor images is that truefont doesn't work properly in GD versions < 2.0.8

Use the Image::SetImgFormat() method at runtime. You can also change the default value with the DEFAULT_GFORMAT define in jpg-config.php. This is normally set to 'auto' format which means that JpGraph will automatically choose the format depending on what is available.

Red Hat 7.2 has a bug in it's TTF libraries FreeType 2.0.3 that comes with 7.2. Upgrade to FreeType 2.0.9. Read more about this problem here (on Google groups)

5-23 When I rotate a paragraph (multi-line) text the paragraph is always left aligned even though I have specified another alignment. It seems fine for non-rotated paragraphs though. What is the problem?

This is a limitation with the current implementation. (The reason is that GD does not support inter-paragraph alignment so all that logic is done within the libraries string-layout engine.

At the moment the logic only implements this paragraph alignment for non-rotated paragraphs.) For rotated paragraphs left-alignment will always be used regardless of specified paragraph alignment.

5-24 I have a huge number of data points and I only want labels (which I want to specify as text string) and ticks on every x:th data. Can I do this?

Yes. What most users stumble on is the fact that the label array must still contain data for all the data points even though only every x:th data label is displayed.

This means that if your original data array only contains just the display values it is necessary first to augment the label array with padding spaces to fill it out.

It is then possible to use the method Axis::SetTextTickInterval() to specify that only every n:th tick+label should be displyed. Something like:

The easiest way is to use the PHP built-in function "number_format()" as a callback.

For example, to have the line plot display values using this format install the callback as:

...
$lineplot->value->SetFormatCallback("number_format");
...

If you instead want the Y-axis label to use this kind of formatting install the callback using

...
$graph->yaxis->SetLabelFormatCallback("number_format");
...

5-26 The Y2 axis is no longer positioned at the right side of the graph

This will happen after that You have manually specified the sclae and/or the tick spacing. If the user manipulates the default scale the library defaults to setting the position of the Y2 axis to the 0 X-position. It is easy to re-adjust the Y2 axis position by calling SetPos() as the following code snippet demonstrates

This can be solved by a bit of extra GD code since the library by default do not directly support this functionality. The easiest way to solve this is to manually create a big enough empty graph with plain GD commands. Then get the image handles from the Stroke() methods in the graphs that should be included. It is then possible to use these handles together with the GD copy command and copy the individual graphs to the previously created empty large GD image.

This is illustrated in the follwing code snippet. In the example below we assume that graph1 is the same size as the final combined graph we would like to create. This way our combined graph get a background and color as specified in the first graph.

6-3 How can I change between percentage and absolute values for pie slices?

Use PiePlot::SetValueType($aType) where $aType is either PIE_VALUE_ABS or PIE_VALUE_PERCENTAGE. To hide/show values on the pie you access the value property of the plot (just like in line plots) If you want some special format of the string you also need to specify a format string. By default just a number gets printed. If you (for example) want percent with a "%" sign you should use a format string like "%d%%" (assuming you just want to display whole numbers)

6-4 Can I display the actual value as labels on the pie bar instead of the percentage?

7. MS Windows specific issues

7-1 When I use IE v5 or v6 I can only save the generated graph image in the browser as a BMP file even if it was generated as a JPEG or PNG encoded image?

This is a bug in the way IE handles HTTP headers. By default the library sends no-cache headers to instruct the browser to always make a HTTP request to the server. This is necessary since graph scripts normally have the same name but the graphs may change over time and we don't want the browser to be fooled by thinking it has already fetched the graph before.

The only known workaround is to tell the library not to send back any no-cache headers as illustrated below.

...
$graph->img->SetExpired(false);
$graph->Stroke();

The "SetExpired(false)" call instructs the library to not send back any has-expired headers.

About

JpGraph is an Object-Oriented Graph creating library for PHP5 (>=5.1) and PHP7.0 The library is completely written in PHP and ready to be used in any PHP scripts (both CGI/APXS/CLI versions of PHP are supported).