《ibm-generatedynamicbitmapgraphicswithphpandgd》
Dynamic bitmap graphics with PHP and gd Presented by developerWorks, your source for great tutorials ibm.com/developerWorks Table of Contents If you re viewing this document online, you can click any of the topics below to link directly to that section. 1. Introduction2 2. Before you start.3 3. Rolling your own: First steps .7 4. gd drawing primitives 10 5. Basic data visualization .12 6. Before you send your masterpiece to the visitor19 7. Embedding in HTML documents 20 8. What s next and resources .21 Dynamic bitmap graphics with PHP and gdPage 1 of 23 Section 1. Introduction What this tutorial is about A picture is worth a thousand words, especially when it is used to illustrate business, financial, or scientific data. It is worth even more if it can be generated on demand, so it can serve the latest information in the visual format. If your job requires writing such applications in PHP, then this tutorial will teach you how to generate bitmap images using PHP and the gd library. (All source files from this tutorial are available on-line .) About the author Jacek Artymiak works as a freelance consultant, developer, and writer. Since 1991 he s been developing software for many commercial and free variants of the Unix and BSD operating systems (AIX, HP-UX, IRIX, Solaris, Linux, FreeBSD, NetBSD, OpenBSD, and others), as well as for the MS-DOS, Microsoft Windows, Mac OS, and Mac OS X operating systems. Jacek specializes in business and financial application development, Web design, network security, computer graphics, animation, and multimedia. He s a prolific writer on technology subjects and the coauthor of Install, Configure, and Customize Slackware Linux (Prima Tech, 2000) and StarOffice for Linux Bible (IDG Books, 2000). Many of Jacek s software projects can be found at SourceForge.net. Jacek s site is located at http://www.artymiak.com; you can contact the author there. ibm.com/developerWorksPresented by developerWorks, your source for great tutorials Page 2 of 23Dynamic bitmap graphics with PHP and gd Section 2. Before you start Required tools The basic requirements for this tutorial are : ? Access to a good operating system. I consider the following good operating systems: ? Linux ? Free/Net/OpenBSD ? Microsoft Windows NT/2000 ? Mac OS X Other Unix-like operating systems are also acceptable as long as they can run Apache (http://httpd.apache.org/docs/install.html), PHP (http://www.php.net/manual/en/installation.php), and gd 1.8.x (http://www.boutell.com/gd/manual1.8.4.html) or gd2.x (http://www.boutell.com/gd/manual2.0.1.html). ? A machine with a CPU clocked at 100 MHz or more ? A machine with 32 MB of RAM or more ? A 500-MB hard disk Also, you can use a different HTTP server as long as it is supported by PHP (http://www.php.net/manual/en/installation.php). On top of that, the gd library will need the following additional support libraries: freetype2, zlib, libpng, and libjpeg6. Tips for the easiest way to assemble a working PHP system The easiest way to put together a working PHP setup for the purposes of this tutorial (and in many cases, for production use) is to use pre-compiled Apache, PHP, gd, and any additional libraries that gd may require. Following is a list of such tips for some of the most popular operating systems: ? FreeBSD. Use the ports system (http://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/ports.html) to install the latest software, but make sure that you install Apache 1.3.x not Apache 2.x, unless PHP is ported to Apache 2.x by the time you read this tutorial. Then, install gd and other required libraries. ? Linux. This varies from distribution to distribution. Users of Red Hat and other RPM-based distributions should install apache-1.3.26, php4, php4-gd, and any additional RPMs that will be required. Users of Debian-based distributions should follow the same route, but use DEBs. Similarly, users of Slackware and other TGZ-based distributions should use appropriate TGZ archives. Presented by developerWorks, your source for great tutorialsibm.com/developerWorks Dynamic bitmap graphics with PHP and gdPage 3 of 23 ? Apple Mac OS X. Apache is a part of the default installation, so you only need to start it and add PHP and the rest of the software. Apple offers a nice page with instructions (http://developer.apple.com/internet/macosx/php.html). ? NetBSD. Use the packages system ()http://www.mclink.it/personal/MG2508/nbsdeng/chap-pack.html to install required software. (See notes for FreeBSD.) ? OpenBSD. Apache is a part of the default installation, so you only have to download PHP and the rest of the software, which you can do with pkg_add php4-version-gd.tgz. If you are new to OpenBSD packages, read “The Ports and Packages collection“ (http://www.openbsd.org/ports.html). Then, start Apache with apachectl start (must be done by the superuser) and you re set. ? Microsoft Windows. You only need to install Apache binaries (http://www.apache.org/dist/httpd/binaries/win32/) if you do not have IIS installed. PHP, gd and the rest of the necessary libraries are also available as a binary distribution with a GUI installer (http://www.php.net/downloads.php). ? Other operating systems. Either use pre-compiled packages or build software from sources. Building required tools from sources If you cannot find ready-made binaries for your system, you will have to build them from sources using an ANSI C/C++ compiler like GCC. As for the sources of particular packages, you can find them here: ? Apache: http://www.apache.org/dist/httpd/ ? PHP: http://www.php.net/downloads.php ? gd: http://www.boutell.com/gd/ ? libpng: http://www.libpng.org/pub/png/libpng.html ? zlib: http://www.gzip.org/zlib/ ? libjpeg: http://www.ijg.org/ ? freetype2 (optional, required for rendering TrueType fonts): http://www.freetype.org/ ? t1lib (optional, required for rendering Type 1 fonts): http://freshmeat.net/projects/t1lib/ For details on building every package, see README or INSTALL files found in each package. You should build in the following order: 1. zlib 2. libpng 3. libjpeg 4. freetype2 5. t1lib 6. gd ibm.com/developerWorksPresented by developerWorks, your source for great tutorials Page 4 of 23Dynamic bitmap graphics with PHP and gd 7. Apache 8. PHP Most of these tools can be built by following the standard Unix routine: $ ./configure $ ./make $ sudo ./make install Additional tools Additional software required to test your scripts includes a graphical Web browser. Ideally, it ought to be running on a machine other than the one generating graphics, so you can check whether your scripts are accessible to the outside world. All major browsers (Mozilla, Internet Explorer, Opera, and others) are able to handle such tasks. You will also need a plain text editor. In this case vi, emacs, TextPad, or BBEdit work equally well. Testing your PHP/gd installation When you have all required components installed, you can check if the support for gd is working. This is done with two simple scripts. First, you create a general PHP test script: Save the script as test.php (remember to save it in the document directory), change file access modes to read-only for all users with chmod 0444 test.php and request the script using the browser (for example, http://localhost/test.php). You should see a long table listing various PHP options. Do a search for gd and check for the --with-gd option and the gd section (support for gd ought to be enabled). If the browser reports errors, check the configuration of your HTTP server, PHP, and gd and try again. Next, create a gd test script: Again, you need to make this script readable by all users, and request it using your browser. The result should be identical to the following: ibm.com/developerWorksPresented by developerWorks, your source for great tutorials Page 6 of 23Dynamic bitmap graphics with PHP and gd Section 3. Rolling your own: First steps Start with the right header Once you complete the initial tests, it is time to write your own gd scripts. To do that, you need to learn about the general structure of a gd script. I ll start with the basics. Every script that generates graphics must start with this command: header(“Content-Type: image/jpeg“); Using the header() function, you can set the value of the HTTP headers sent by the HTTP server to the HTTP client (your Web browser). One of these headers is Content-Type, which informs the HTTP client what kind of data it will receive. The client uses that information to decide how it should process the data it receives. It may decide to use external converters or display information that it is unable to handle on its own. For example, image/jpeg informs the client that it will receive a bitmap image in the JPEG format. The client can now decide what to do with this image -- decode it, use an external viewer, or give up and tell the user that it is unable to display this particular type of image. After the Content-Type header is sent to the browser, your script can do whatever job you designed it for. Remember, however, that the only output your script can produce is the bytestream that makes up the image. This rules out the use of commands like echo or print to generate HTML code within the same script. But what if you want to generate an HTML document that contains a dynamically generated image? You ll learn how you can do it later in this tutorial, but before I get to that, you need to learn how to generate a bitmap image. Prepare your canvas Before you begin drawing anything, prepare your canvas, just like a real painter. This is done with a call to the ImageCreate() function: # Set the dimensions of the canvas $cw = 500; $ch = 300; # Create canvas $c = ImageCreate($cw, $ch); The numeric ID returned by ImageCreate() is used by all commands that modify the image. This creates an interesting possibility to create two or more separate images in Presented by developerWorks, your source for great tutorialsibm.com/developerWorks Dynamic bitmap graphics with PHP and gdPage 7 of 23 the same script. However, the practical use of this feature is limited because the script can only send a single image to the HTTP client that invokes it. On the other hand, as you will see later on, it is possible to combine two or more images or save images to the local disk (on the server). Note that the dimensions of the canvas ought to match the dimensions of the image specified in the height and width attributes of the tag. If you use different values, the image still displays in the browser s window, but it is distorted. It is not a particularly good design trick, so it is best to avoid it. Compose your palette Now it is time to mix some paint. Although gd 2.x can work with a palette of millions of colors, you will limit the size of the palette to 256 colors because that is the number of colors both the 1.8.4 and the 2.x releases of gd can work with. Every color in the palette is created with a call to the ImageColorAllocate() function, which takes four arguments: the position of the given color in the palette and the values of the red, green, and blue components (their values are integers in the 0255 range). For example, the following piece of code creates a gray-scale palette: # Generate color palette for ($n = 0; $n The above script generates a random pixel map, shown in the following image. ibm.com/developerWorksPresented by developerWorks, your source for great tutorials Page 10 of 23Dynamic bitmap graphics with PHP and gd Presented by developerWorks, your source for great tutorialsibm.com/developerWorks Dynamic bitmap graphics with PHP and gdPage 11 of 23 Section 5. Basic data visualization Make a clock with arcs and lines While random pixel maps are cute to look at, they re not very useful (except for the Computer Graphics people, who like to use them as “bump maps“ for generating rough 3D surfaces). A much more interesting example would be one that shows how to use gd for visualization of numeric real-time data. I ll use the current time (you cannot get more real-time than this) to create a clock which shows the time it was generated on the server. This clock is a very good starting point for showing how to use ImageArc(), ImageLine(), and Image DashedLine() functions. 11) { $th -= 11; } ibm.com/developerWorksPresented by developerWorks, your source for great tutorials Page 12 of 23Dynamic bitmap graphics with PHP and gd # Prepare some constants $hi = deg2rad(30); $mi = deg2rad(6); $adj = deg2rad(90); # Compute coordinates of the hour, minute, # and second hands # Compute angles $th = $hi * $th - $adj; $tm = $mi * $tm - $adj; $ts = $mi * $ts - $adj; # Compute the length and the coordinates of # the hour hand $hhl = $cw * .6; $hhx = $hhl * cos($th); $hhy = $hhl * sin($th); # Compute the length and the coordinates of # the minute hand $mhl = $cw * .7; $mhx = $mhl * cos($tm); $mhy = $mhl * sin($tm); # Compute the length and the coordinates of # the second hand $shl = $cw * .8; $shx = $shl * cos($ts); $shy = $shl * sin($ts); # Draw the hour hand ImageLine($c, $x, $y, $x + $hhx, $y + $hhy, $cols[2]); # Draw the minute hand ImageLine($c, $x, $y, $x + $mhx, $y + $mhy, $cols[3]); # Draw the second hand ImageDashedLine($c, $x, $y, $x + $shx, $y + $shy, $cols[4]); # Generate image ImageJPEG($c); ? The results of running the clock script can be seen in the following figure. Now, every time you reload the script, you see an analog clock showing the local server time. Making changes required to display local time at the visitor s place is left as an exercise to the reader. Presented by developerWorks, your source for great tutorialsibm.com/developerWorks Dynamic bitmap graphics with PHP and gdPage 13 of 23 Visualizing numeric data The clock example in Make a clock with arcs and lines on page 12 was an interesting introduction to the subject of data visualization, but its business or scientific use is a bit limited. A more useful example of data visualization could be a plot of results of surveys conducted in different geographic locations. For the purposes of this example, I ll assume that I asked developers in California, Texas, and New York to tell me what desktop manager they use, and I want to present the results on a map of the USA. This is exactly what the following script does. The result looks like the following image. Presented by developerWorks, your source for great tutorialsibm.com/developerWorks Dynamic bitmap graphics with PHP and gdPage 15 of 23 Note that in this script, I wrote a simple function for drawing charts, drawChart(), to make my life easier. You should do the same when you are performing a similar type of visualization. This way, over time you build a library of handy functions for drawing various types of charts. The map of the USA shown in this example is a very rough approximation and does not include Alaska or Hawaii. Making it look better is left as an exercise to the reader. The map is drawn using ImagePolygon() and ImageFilledPolygon(), wh