PHP can do graphics, too!

Yeah, I still like PHP. All the drawbacks haven’t really convinced me to stop writing in PHP, as they all will be corrected either in the next updates of PHP 5 or in the forthcoming PHP 6. That’s why, despite many people saying “stp wrting php, u n00b!“, I still want to use this language and I still want to share my knowledge ;) So I decided to write a short tutorial explaining how to generate images using PHP.

Introduction

Among many PHP graphic extensions, two are the most functional: GD and Imlib2. However, only the former will be described here, as Imlib2 actually sucks. And so, you’ll have to check whether your server supports GD. Create a file where you call the function phpinfo(), open it and find the GD section. The table shows if GD is enabled on your server (if it isn’t, go to official GD site and download it or contact your admin) and what file types it supports.

Now that you’re sure that your server can actually do all the things mentioned in this post, let’s continue with it. But before we can get into the image generation, I have to make sure you take one thing into consideration: a site consisting of some text and two images sends three HTTP requests to the server. Each image makes the server process one more request, as it’s content type is other than the site’s (images use e.g. image/png type, whereas the whole pages use text/html or application/xhtml+xml). And so you must remember that you can’t print text and images within the same PHP file, as it will cause errors.

Let’s start with some simple image generation. First, we’ll use some simple GD colouring and drawing functions. ImageCreate(width, height) creates an image. Then, we’ll define some colours and assign them to variables with ImageColorAllocate(image, red, green, blue) and finally we’ll create a red rectangle using the ImageFilledRectangle(image, top_left_x, top_left_y, bottom_right_x, bottom_right_y, colour) function (its arguments are the top left and bottom right points’ coordinates). Next, we’ll have to send the header() to the server to tell it that the file’s an image, not text. Eventually, we’ll use a the ImagePNG(image [, filename]) creating the actual image.

<?php
$image = ImageCreate(150, 150);
$white = ImageColorAllocate($image, 255, 255, 255);
$red = ImageColorAllocate($image, 255, 0, 0);
ImageFilledRectangle($image, 50, 50, 150, 150, $red);
header('Content-Type: image/png');
ImagePNG($image);
?>


The result image

The result should look like image on the right.
This, despite being a very simple and quite meaningless example, showed us the use of the basic drawing functions. Remember that, when not using the ImageCreateTrueColor() function, the first colour you declare will be the background colour of your image.

Of course, you can generate another graphic file type instead of PNG. To do this, you’ll need to change ImagePNG() to ImageJPEG(), ImageGIF() or ImageWBMP and header('Content-Type: image/png') to the particular image content type (image/jpeg, image/gif or image/vnd.wap.wbmp).

Useful functions

To draw a line, you’ll need to use ImageLine(image, start_x, start_y, end_x, end_y, colour) or ImageDashedLine() (using the same parametres).

To draw a rectangle, you’ll either use ImageRectangle(image, top_left_x, top_left_y, bottom_right_x, bottom_right_y, colour) or ImageRectangle() (described above) with the same parametres.

Drawing an ellipse can be acomplished with ImageEllipse(image, centre_x, centre_y, width, height, colour) and ImageFilledEllipse() functions, or with ImageArc(image, centre_x, centre_y, width, height, start, end, colour) function (start and end parametres are degrees, 0° is located at the three-o’clock position, and the arc is drawn clockwise) with start set to 0 and end to 360.

It’s more difficult to draw a polygon. The functions are: ImageCreatePolygon(image, vertices, number, colour) (and ImageCreateFilledPolygon()). The vertices parametre should be an array with all the vertices’ coordinates, and the number is just the number of vertices (so it’ll probably be count($vertices) / 2).

To fill a part of the image with a particular colour, you can use two different functions: ImageFill(image, x, y, colour), which will perform a flood fill starting at the given coordinates and ending when it meets a border of any colour (different than the one it’s filling, of course), or ImageFillToBorder(image, x, y, border_colour, fill_colour) when you choose the border colour yourself.

To make a colour transparent, you’ll need to use the ImageColorTransparent(image) function.

The most senseless function is ImageSetPixel(image, x, y, colour), which will… colour the pixel you choose. Wow.

ImageRotate(image, angle, bg_colour) function will rotate the image to the given angle, applying a particular background colour to it.

One of the most useful functions in the GD library is ImageCreateFromXXX() (XXX can be PNG, JPEG, GIF or some others), which creates an image which doesn’t use a colour as the background (as ImageCreate() does), but it actually includes an image with particular file type. Note that you cannot load .php files using this function, even if they generate a proper image file1.

ImageSx(image) and ImageSy(image) will return, respectively, the width and the height of the given image.

ImageDestroy(image) will destroy the image freeing any memory that it’s taken. It’s useful when you’ve created an image you don’t want to use or work on two images at one time and you can use only one of them.

Now, have a look at some of the functions mentioned above in use, and an image which is the result of the script.

The result image

<?php
$image = ImageCreate(150, 150);

$white = ImageColorAllocate($image, 255, 255, 255);
$blue = ImageColorAllocate($image, 0, 0, 255);
$red = ImageColorAllocate($image, 255, 0, 0);
$black = ImageColorAllocate($image, 0, 0, 0);
$transparent = ImageColorTransparent($image, $white);

ImageFilledRectangle($image, 50, 50, 150, 150, $red);
ImageFilledEllipse($image, 100, 100, 100, 100, $blue);

$rotated = ImageRotate($image, 45, $transparent);

$vertices = array(0, 0, 70, 105, 0, 50);
$number = count($vertices)/2;
ImageFilledPolygon($rotated, $vertices, $number, $black);

header('Content-Type: image/png');
ImagePNG($rotated);
?>

Working with text

Nowadays, the Internet’s full of custom-made graphic banners that show the title of your last blog post. Yeah, it’s usually made with PHP, using GD. How to do that? Of course I won’t explain all the database-related stuff, but I can show you how to put a custom label on an image file.

The easiest way to do this is to use the function ImageString(image, font, x, y, text, colour). The font parametre can be 1, 2, 3, 4 or 5 for built-in fonts (and higher numbers for larger text) or your own font (this feature sucks, though, so I won’t mention it). Look at the example:

The result image

<?php
$image = ImageCreate(150, 150);
$white = ImageColorAllocate($image, 255, 255, 255);
$black = ImageColorAllocate($image, 0, 0, 0);

ImageFilledEllipse($image, 75, 75, 150, 100, $black);

ImageString($image, 5, 56, 68, 'ZOMG', $white);

header('Content-Type: image/png');
ImagePNG($image);
?>

If your server supports FreeType (phpinfo() if you’re not sure), you can load your own fonts saved in the TrueType format (.ttf). If you have a TT font on your server, you can use the ImageTTFText(image, size, angle, x, y, colour, font, text) function. The size parametre must be given in pixels, angle in degrees (0 will make the text horizontal). Keep in mind that the x and y parametres determine the position of the text’s bottom left corner, and that if you don’t enter a full path to the font, the script will look for it in /usr/share/fonts/truetype directory, and if you forget the .ttf at the end of the path, it’ll add it automatically.

The result image

<?php
$image = ImageCreate(150, 150);
$white = ImageColorAllocate($image, 255, 255, 255);
$black = ImageColorAllocate($image, 0, 0, 0);

ImageFilledEllipse($image, 75, 75, 150, 100, $black);

ImageTTFText($image, 20, 0, 30, 88, $white, '/path/to/font.ttf', 'ZOMG');

header('Content-Type: image/png');
ImagePNG($image);
?>

The alpha channel

GD library, since version 2, supports the Truecolor mode with 7-bit alpha channel (0-127). It allows you to use more colours and advanced transparency.

To create a Truecolor image, use the ImageCreateTrueColor(width, height) function. Remember that if you create an image this way, its background will not be automatically set.

Now, let’s do some transparency! To create a partially transparent colour, you’ll need the function ImageColorResolveAlpha(image, red, green, blue, alpha) (remember the alpha parametre is a 7-bit value). ImageAlphaBlending(image, bool) is set to true by default. If you disable it, the alpha channel won’t work. In the example below, I’ve created three orange rectangles on an ellipse. The left one is opaque; the middle one should be transparent, but I’ve turned the alpha blending off; the last one is 40% transparent.

The result image

<?php
$image = ImageCreateTrueColor(150, 150);
$white = ImageColorAllocate($image, 255, 255, 255);
$black = ImageColorAllocate($image, 0, 0, 0);
$orange = ImageColorAllocate($image, 255, 50, 0);
$orange_transparent = ImageColorResolveAlpha($image, 255, 50, 0, 50);

ImageFilledRectangle($image, 0, 0, 150, 150, $white); // background

ImageFilledEllipse($image, 75, 75, 150, 100, $black);
ImageTTFText($image, 20, 0, 30, 88, $white, '/path/to/font', 'ZOMG');

ImageFilledRectangle($image, 0, 0, 30, 150, $orange);
ImageAlphaBlending($image, false);
ImageFilledRectangle($image, 60, 0, 90, 150, $orange_transparent);
ImageAlphaBlending($image, true);
ImageFilledRectangle($image, 150, 0, 120, 150, $orange_transparent);

header('Content-Type: image/png');
ImagePNG($image);
?>

Resizing images

Here’s some simple methods of resizing images. There’s an old function ImageCopyResized() which is supported by all GD versions. However, the way it resizes images totally sucks and thus I don’t recommend using it (although if you’d like to use it, it has the same parametres as ImageCopyResampled()). ImageCopyResampled(destination, source, dst_x, dst_y, src_x, src_y, dst_width, dst_height, src_width, src_height), which uses the pixel interpolation algorithm, is the most efficient way to copy and/or resize images. The destination and source parametres are image link resources (image handlers). All the coordinates refer to the upper left corner of the destination/source image. The example below will make the image three times smaller.

The result image

<?php
$src = ImageCreateFromJPEG('path/to/jpeg/image.jpg');
$width = ImageSx($src);
$height = ImageSy($src);
$dst_width = $width / 3;
$dst_height = $height / 3;

$dst = ImageCreateTrueColor($dst_width, $dst_height);
ImageCopyResampled($dst, $src, 0, 0, 0, 0, $dst_width,
   $dst_height, $width, $height);

header('Content-Type: image/png');
ImageDestroy($src);
ImagePNG($dst);
?>

Simple caching

You’ve probably noticed that the actual time of displaying (and generating) an image using GD is much longer than just showing a static graphic. Thus, if you don’t want your server to go down and your site visitors to wait such a long time, you should use some kind of caching.

Of course, if you have a billion visitors every day or use a super-advanced-PHP-awesome-framework and need to use some advanced caching, there are many scripts on the Net. The method I show below is simple, but it works well for most users.

<?php
$path = 'path/to/the/image.png';
header('Content-Type: image/png');

if (file_exists($path)) {
	readfile($path);
} else {
	$image = ImageCreateTrueColor(150, 150);
	// do all the things you want to do with the image

	ImagePNG($image, $path);
	ImagePNG($image);
	ImageDestroy($image);
}
?>

Goodbye

That’s the end of the article. Hope you’ve enjoyed it and you’ve found something useful in it. I mentioned all the most important GD library functions which are enough to generate your own graphics, banners and images with dynamic content. Here’s an exercise for you, so that you could try GD in use: create a banner like the one below, displaying the last post from your blog / homepage / discussion board.
May the Force be with you!

The banner


  1. 1) Thanks to PiotrLegnica for arguing with me on this topic ;)

posted on Monday, 6th August, 2007 at 01:37 (UTC +1000)
filed under PHP, Tutorial, Web
comments feed

6 Responses to “PHP can do graphics, too!”

Python can do graphics, too!…

regua opisał GD w PHP, to ja opiszę Python Imaging Library.PIL jest biblioteką potężną. Te formaty obsługuje w trybie read-write:GIFPNGPPMBMPIMJPEGMSPPCXTIFFXBMI jeszcze sporo innych w trybie read-only.Instalacja, prosty obrazekInstalacja sprowa…

that was awsome

Great article!

I use often imagemagick for image resizing, adding text(effects) etc. its very fast and easy to use

Hello Thanks

Ciekawa strona, trafilem tu przypadkowo, ale od dzis bede wpadal czesciej, pozdro

Leave a Reply