Creating a graph using the GD library. Drawing graphs in PHP What we changed

To identify the uses of graphics tools in web scenarios, consider the following range of possible graphics use cases:

  • Static images, created independently or borrowed from somewhere, can be embedded into an HTML page.
  • Programmatically generated images (HTML + CSS) can be used.
  • You can use the gd library to pre-create static graphics for all possible situations that may arise during a script's execution, save them in files, and display them conditionally.

We will not consider the option of introducing graphics using static images due to its simplicity, so first we will consider a simple option (HTML + CSS graphics), and then we will consider using the gd library in PHP.

Graphics HTML + CSS

Website visitors are familiar with horizontal bar graphs with colored sides, which are especially often used to illustrate survey results. At first glance, it seems like some kind of graphical tools are used to create such diagrams, but in reality, it is enough to use a few simple scripts:

Working with graphics in PHP, HTML, CSS /* CSS styles that form the design */ body div ( height: 1em; display: inline-block; vertical-align: middle ) span ( display: inline-block; width: 120px ) .orange ( background: orange ) .apple ( background: #33CC66 ) .banana ( background: yellow ) .tomato ( background: red ) .cucumber ( background: green ) .potato ( background: gray ) Order form Fruits Oranges Apples Bananas Vegetables Tomatoes Cucumbers Potatoes

This example does not demonstrate any new features of PHP, but simply shows a simple way to create graphics using HTML and CSS (in this case bar charts):

gd library

The graphics tools described in the previous section practically exhaust the capabilities of standard HTML code (though it is worth noting that we did not cover the fairly powerful HTML5 Canvas graphics creation tool). Now let's move on to describing methods for creating truly arbitrary graphics using the gd library.

General description of the gd library

Generally speaking, the gd toolkit is a library of C code for creating and manipulating images. This library was originally developed and made available to the public by the talented and generous employees of Boutell.com.

The gd library itself is not a graphics or drawing program, nor does it constitute a standalone application or graphical user interface. Instead, the gd library provides functions that can be called by any program to perform the desired image manipulation. This means that the gd library can be linked to any C program in which it is necessary to use the code of this library. This is exactly the problem that the developers of the PHP system solved.

In fact, a set of interface functions have been written for this purpose that make it easy to call gd procedures from a PHP script. But the gd library itself does not contain any PHP-specific code, and interfaces have been developed to allow the library to be accessed from several other programming languages ​​and programming environments, including Perl, Pascal, Haskell, and REXX.

The gd library allows you to call functions to create source images (initially blank, resembling a blank sheet of paper), draw and paint within those source images in a variety of ways, and ultimately convert the image from gd's internal image format to a standard image format and then send it to final destination (output in a browser window or save in a file or database). And since all these operations are performed under the control of the program, and not carried out manually, the created images can become as complex as desired and depend on any situations during the execution of the program on which it is desirable to make them dependent.

Image formats

The gd library basically allows you to import and export images using a wide variety of formats. The most popular image formats are GIF, JPEG, and PNG, although the examples used primarily use the latter.

The GIF and PNG formats are intended to describe a grid of colored elements corresponding to pixels, with some additions. The first addition is that cells can contain actual color numbers or indexes into a table of color numbers. (The first option allows you to create more expressive images, since it allows you to provide any number of different colors, and the last option helps you create more compact images.)

The second addition is as follows. Of course, the conceptual representation of the GIF and PNG formats is quite simple, but in practice, reading, writing and transmitting images in these formats is always done in a compressed form. Compression is necessary because storing data represented as a grid of cells requires a large amount of memory. A simple 500x400 pixel image contains 200,000 pixels, and if each pixel requires three bytes, the amount of memory required is already over half a megabyte.

The topic of compression is a broad and complex one, but most compression algorithms are based on reducing image redundancy in order to reduce its size. (For example, it will take less memory space to specify that every pixel in an image is green than to specify the green value for each pixel individually.) Unfortunately, compression algorithms don't rely on using these properties because they have to decide such complex problems that the methods for solving these problems, implemented in the compression algorithm used to generate images in the GIF format, have even been patented.

Installing the library

Frankly, the task of installing the gd library and making it work successfully in conjunction with a PHP system is quite complex. This is not due to any deficiencies in the PHP or gd software, but is entirely due to configuration issues; in particular, you need to understand where the gd libraries should be and actually are, and ensure that the compilation and linking steps of all executables are completed correctly. Therefore, the best possible situation is that the user discovers that the gd library is already installed and gd support is already enabled in the PHP system (either courtesy of the web hosting company or because it is included in installed PHP system).

Therefore, the installation of the gd library must begin from step zero - by checking whether this library has already been installed. First, enter the following code into your script file and view the results of running it in your browser, whether your scripts are run by your web hosting company or run entirely by your own installation:

After displaying this page on the screen, simply search for the text string "gd" in the browser window. This should reveal a subsection describing the extent to which your PHP installation allows support for the gd library. If you only intend to prepare certain types of images (for example, PNG), and the results of the phpinfo() function indicate that support for that type of image is enabled, you can get started right away. And if the gd version information includes the word "bundled", then the gd library that comes with PHP is used.

If an attempt to find a mention of the gd library ends in failure, and you are installing PHP yourself, then you can install and configure the gd library configuration. (On the other hand, if your PHP installation is handled by your hosting company, your only options are to ask that company to provide support for the gd library, or use another web hosting company.)

Using the gd library that comes with PHP eliminates many of the hassles associated with installing gd, but not all. The fact is that using the version itself included in the distribution kit allows you to get the gd library, but not necessarily all the libraries necessary for gd to work. The gd library itself depends on several other libraries: libpng (for manipulating PNG images), zlib (for compression), and jpeg-6b or later (for manipulating JPEG images if needed). These libraries are already present in many Linux installations, in which case it may be sufficient to include the required with option (such as --with-zlib) in the options without specifying the installation directory. If you do the PHP configuration yourself, you can simply add the --with-gd option to ensure that the included version of gd is included in the executable. And if you want to point to a different version, use the --with-gd=path option instead.

If you find that one or more required libraries are missing, this means that those libraries will have to be built separately. For information on where to find current versions, you can start by reviewing the documentation located at www.libgd.org.

Basic principles of working with the gd library

When an image is created or manipulated using the gd toolkit, the image is represented in a special gd format that has no correspondence to any conventional image type. It is theoretically possible to export images in this gd format, but such an operation is rarely used because the resulting image is not compressed and cannot be displayed in a browser or simple graphics program.

An image processed using the gd toolkit is characterized by information about the width, height and color of all pixels, the number of which is equal to the product of width and height. Typically, a program begins its interaction with the gd library by either creating a new empty image (on which to draw and draw), or by importing an image from a file. The following steps are usually performed: first, the distribution of colors in the image, second, drawing and painting or manipulating the image using some other operations, third, converting the image into a generally accepted format (for example, PNG or JPEG ) and transfer it to its destination.

Representation of colors

There are two ways to represent colors in gd images: a palette-based representation, which is limited to 256 colors, and a true-color representation, which allows you to specify an arbitrary number of different RBG color numbers. In gd 1.x, the only option was to use palette-based colors, but in gd 2.x and the version of this library included with PHP, it is possible to create both palette-based images and images in realistic colors. One thing to keep in mind is that any given gd image must be either palette-based or have true-to-life colors (RGB); this means there is no option to introduce realistic colors into images based on a palette.

To get the original blank image based on the palette, you need to call the ImageCreate() function, and to get the image in true colors, use the ImageCreateTrueColor() function.

Palette-based images

Colors are specified in the Red-Green-Blue (RGB) format, using three numbers from 0 to 255. For example, the color specified by the numbers (255, 0, 0) is bright red, the color ( 0, 255, 0) - green, color (0, 0, 255) - blue, color (0, 0, 0) - black, color (255, 255, 255) - white and color (127, 127, 127) - grey. By creating more and more new colors, you can choose the values ​​of the three color components arbitrarily.

Any drawing on an image must be done with a specific color, and the colors must be distributed in the image before they are used. Additionally, the first color distributed in the image automatically becomes the background color. So, in no case should you assume that you can do without specifying colors, and usually the operation of distributing colors is the first operation after creating a new empty image.

Colors in palette-based images are created using the imagecolorallocate() function, which takes as parameters an image (created previously) and three integers specifying the proportion of red, green, and blue. The return value is an integer that specifies the index of the new color in the image's internal palette. This return value must be assigned to a variable because the specified index value is needed to perform all future operations using this color.

Palette-based images can have a maximum number of colors of 256. (The reader may or may not be interested in what such images are actually based on, but each pixel in a palette-based image is actually a single byte that stores the index of one element in the palette of 256 colors.)

Note that the index returned when distributing one of the colors in an image is only meaningful for that image. For example, if a PHP script assigns $black to a color distributed in one image, then it makes no sense to use that variable as color input to a drawing command called to process another image.

Images with realistic colors

gd 2.0 and later also provides the ability to create non-palette-based images in which each pixel stores an arbitrary RGB color number. In this so-called true-color format, the number of possible colors is extremely large. Not only does this feature limitlessly expand the scope of artistic expression, but it also allows you to faithfully reproduce PNG and JPEG images with true-to-life colors loaded into memory using the gd toolkit.

Except that a different function is used to create the initial image and there are no restrictions on selecting different colors, the principles of working with true-color images are similar to those of palette-based images.

In particular, you can still call ImageColorAllocate() to create new colors and assign a variable the return value for later use in drawing commands. The only difference is that the return value is the RGB color number, not the index of the element in the palette. Additionally, in images with true-to-life colors, there is no concept of a background color created as a side effect of the ImageColorAllocate() function; As a result of initialization, all pixels are assigned the designation black (0, 0, 0).

Transparency

Versions of gd 2.x support the concept of transparency. This uses an alpha channel (in addition to the red, green, and blue values) to indicate how transparent the color is. This allows, for example, one shape to be superimposed on another so that the first shape remains partially visible rather than completely overlapping the second.

In PHP, many functions for working with images have an analogue containing the word "alpha" in the name, which indicates that in these functions color is represented by four values ​​(R, G, B, A). For example, the imageColorAllocate() function takes three parameters, and when calling the ImageColorAllocateAlpha() function, you must specify a fourth parameter with a value between 0 and 127. A value of zero indicates that the color is completely opaque, and a value of 127 indicates that the color is completely opaque. transparent

Coordinates and drawing commands

After creating an image using the gd toolkit, a coordinate system is implicitly created that allows you to specify drawing commands within it. The limiting coordinate values ​​in this system are determined by the specified parameters of the image width and height.

The origin of coordinates in this system, corresponding to coordinates (0, 0), is located in the upper left corner of the image. The positive direction for X values ​​is from left to right, and for Y values ​​it is from top to bottom. (In computer graphics coordinate systems, this location of the origin is common, but those who have studied analytical geometry seem to be accustomed to the origin being in the lower left corner of the diagram.)

The number of drawing commands is very large. These commands include, but are not limited to, commands for drawing line segments, rectangles, and arcs, as well as commands for setting specific pixel values. But keep in mind that the end result of all these drawing and plotting commands is to set pixel values. After executing commands that change pixel values, there is no trace left in memory (other than the changed values ​​themselves), so there is no way to override drawing and plotting commands or to present the results of different commands separately.

There is nothing to prevent drawing commands that extend beyond the specified image, but such drawing has no visible effect. For example, a rectangle will not be visible in the image if all coordinate values ​​are negative.

Format conversion

All drawing and image manipulation operations are performed on the image represented in the internal gd format. And after these operations are completed, the script can call one of the conversion and output commands (imagepng, imagetjpeg, etc.) to convert this image into the required graphic format and output it to the user's browser window (or to a file).

Freeing up resources

Once the result of converting the completed gd image is transferred to the user, we can consider that work with the internal version is completed. This means that this version must be destroyed. The correct way to do this is to call imagedestroy() with an image as a parameter.

gd library functions

We are not going to separately list and describe in this article all the functions provided in the gd interface of the PHP interpreter. To familiarize yourself with this information, we recommend using the “Image Processing and Generation” section of the php.net manual. Most gd functions fall into one of the categories shown in the table below. Note that the function names listed in this table are capitalized to make the first letter of each word easier to read, but this condition is not always observed in the code examples because PHP function names are not case sensitive:

Classification of gd functions Type Example Note
Image creation functions ImageCreate(), ImageCreateTruecolor(), ImageCreateFromGd(), ImageCreateFromJpeg() Return a new gd image. The ImageCreate() function takes as parameters the width and height of the image, and the parameters of other functions are a file path, URL, or a string containing a previously created image that should be loaded and converted to gd format
Functions that perform color distribution operations ImageColorAllocate(), ImageColorAllocateAlpha(), ImageColorDeallocate() The ImageColorAllocate() function takes an image handle and the required values ​​of red, green, and blue as parameters, and then returns a color number for later use in drawing and plotting operations. The ImageColorAllocateAlpha function accepts an additional parameter - transparency coefficient (0-127)
Functions that perform color matching operations ImageColorClosest(), ImageColorClosestAlpha(), ImageColorExact(), ImageColorExactAlpha() Return the index of the matching color in the paletted image. Functions containing the word "Closest" in their name return the most closely matched color (matching accuracy is measured as the distance between points in RGB value space); functions with the designation "Exact" return the color number only if it is identical to the searched one, otherwise they return the value -1, functions with the name "Alpha" operate on colors, which are determined using four values ​​(with transparent colors)
Line drawing functions ImageLine(), ImageDashedLine(), ImageRectangle(), ImagePolygon(), ImageEllipse(), ImageArc() They are used to draw straight segments or curves of the specified shape. Typically, the first parameter of each of these functions is the image, the last parameter is the color, and the intermediate parameters are the X and Y coordinates.
Line drawing pen settings ImageSetStyle(), ImageSetThickness() Change settings that affect the characteristics of the lines produced by subsequent line-drawing commands (some of these functions are only applicable to gd 2.0.1 or later versions)
Drawing and filling functions ImageFilledRectangle(), ImageFilledEllipse(), ImageFilledPolygon(), ImageFilledArc(), ImageFill() As a rule, they are similar to the corresponding functions for drawing lines, but they provide not only for drawing the contours of areas, but also for filling the created areas with color. The special function ImageFill() performs a fill operation using a specified fill color. Filling is done in all directions starting from the specified XY coordinates (some of these features require gd 2.0.1 or later)
Functions for working with text ImageString(), ImageLoadFont() The ImageString function takes as parameters an image handle, font number, X and Y coordinates, a text string, and a color. If the font number is between 1 and 5, then one of the five built-in fonts is used to display the line in this color. On the other hand, a font number greater than 5 indicates the result of loading a specialized font using the ImageLoadFont() function
Export functions ImagePng(), ImageJpeg() Convert the internal gd image to an image of the appropriate format, and then send this image to the output stream. If only one parameter is specified (the image handle), then the image is echoed to the user, and if an additional parameter is used, which is a file path, the destination of the output stream becomes the file
Image destruction function ImageDestroy() Takes an image handle as a parameter and releases all resources associated with the image
HTTP image support

In order for an image to be presented properly in the user's browser, it is necessary to specify where the image should come from and what its format is. Therefore, unfortunately, it is not possible to simply implement, for example, a call to the imageToPng() function in the generated HTML file and thereby solve the problem of displaying the image. Essentially, you have to alternate the image output code with the HTML code generated in the PHP script, and for this you can use one of the three options described below.

Creating Full Page Images

The entire generated page can be formatted as an image. In this case, you need to pass an HTTP header preceding the image data, thereby declaring that what follows is an image of a certain type. For example, the following lines might be provided at the end of the script:

// ... code that creates an image and assigns it // to the variable $image header("Content-type: image/png"); // Display the title in the browser imagepng($image); // Pass the data of the image itself, converted to PNG format imagedestroy($image); // Release resources

The advantage of this approach is that any information, including POST parameters, can be used to convey instructions about the composition of the future image. The downside is that the resulting page cannot contain any regular HTML code. In fact, you even have to be careful not to send any text output before the title and image in your scripts, as this is tantamount to sending the content prematurely. In this case, the error message "Headers already sent..." appears.

Embedding images stored in files

First of all, note that HTML supports the descriptor , which allows you to embed an image by specifying the image file path or URL, as in the following example:

This design applies to static image files, but there is no reason why it couldn't enable embedding of a newly created image. Therefore, you can prepare a script in which an image is first created, then the image data is written to a local file, and then the HTML code with the corresponding descriptor is generated , pointing to the newly created file.

The only disadvantages of this approach are that, first, the page creation process must include file writes, which can be time consuming, and, second, you must determine what to do with the files when you are done using them.

But in a certain situation this approach is ideal. It's about creating and caching images that represent a finite set of choices. In this case, there is a specific way to associate a particular situation with the name of the image file. When some of these situations arise that require an image to be output, it is checked to see if a corresponding file already exists. If the answer is positive, a link to this file is simply applied, formatted as a descriptor , and if the answer is no, then an image is created, written to a file, and then a link to this image is again applied. Ultimately, creating new files will simply not be necessary.

Embedding images generated in scripts

Finally, there is no reason why you couldn't provide a standalone image script and then embed the resulting image in a dynamic page generated by another script by specifying in the descriptor URL of this script. The only difficulty is choosing how to transfer the necessary data to the dependent page. For example, a handle indicating an embedded image might look like this:

In this case, the ballpage.php script returns PNG images of colored balls located at various positions in the picture.

But using this approach can cause problems because web servers and browsers sometimes check the suffixes of the files being processed and, when they receive the results of the check, react to them differently. For example, the ballpage rendering script may need to be given a .php extension so that the Apache server can determine that the server code should be interpreted as PHP code (although the required processing mode can also be specified through configuration files).

However, there are also non-standard versions of browsers that do not take into account the possibility that a file with a .php extension produces an image, even though the header passed indicates that an image follows. Therefore, when using this method, you need to test the scripts in different browsers and make sure that the intended circle of users will receive the pages in the form you intended.

Below are examples of using the gd library to create images.

An example of using the gd library: creating simple shapes

In the following example we will show how to use the gd library to generate a drawing containing simple geometric shapes:

Replace the settings with your own and save this file under the name connect-to-database.php in the fcdemo folder.

Let's insert random data

If this were a real project, the users table would grow over time, but for the sake of demonstration, we need to insert some data. Let's write a small script that will insert random data into the table. Don't worry if you don't understand the following code - it's not important for this tutorial.

Save this file called generate-random-data.php all in the same folder.

First we include the database connection file. Then we set a time frame from which the time for user registration will be randomly selected. You can change the number of rows to be inserted. To do this, you need to adjust the $RecordsToInsert variable.

Then we run the script for inserting the generated records into the database. In order to start this process, go to this address - http://localhost/fcdemo/generate-random-data.php.

Eventually you should see the message: "Inserted ($RecordsToInsert) records"

Step 2. Prepare the website skeleton

We need to create a very simple page to display our chart. Something like this:

FusionCharts v3.2 - LinkedCharts PHP Demo