Generating Dynamic Images with PHP

You've seen many Web 2.0 sites, or just Web applications generating dynamic images such as graphs, texts, labels, annotations and more. How did they do that? This tutorial teaches you how.

Does your server support PHP GD?

Your server must support PHP GD in order to generate images from PHP scripts. Many free/paid Web hosts is pre-installed with PHP GD, and personal Web servers will probably do not have it. Here is a way to check if PHP GD is installed:

<?php
if (function_exists('gd_info')){
 echo "GD is installed.";
 var_dump(gd_info());
} else {
 echo "GD is not installed.";
}
?>

Copy and paste that code to a new PHP file, and see what happens. If it said "GD is not installed." try to install it(if you can install software on that server). If your web host does not support GD, then too bad, you cannot install programs on others server.

To install GD on Linux, open your command line, and enter root mode:

$ su
Password:
# 

Then install the php-gd package. On Red Hat distributions, type yum install php-gd on Debian/Ubuntu, type apt-get install php-gd. If the above steps did not work, you can search Google to find a way to do it, you may need to compile the library from source code of PHP and/or GD. Don't ask me about how to install GD, Google before asking questions.

Your First Image

Let's make your first image, first, you must tell the browser that you are making an image: header('Content-Type: image/png'), replace image/png with the type of the image, such as image/gif for GIF, image/jpg, image/jpeg and so on. image_type_to_mime_type() can help you.
Then, allocate a new image in the memory: $image = imagecreate(100, 30)
The function imagecreate() takes two parameters: $width and $height. I recommend you to use imagecreatetruecolor() if photos, renders and complex images are involved. Now the variable $image will become a pointer to the memory location of the image. (you don't need to care about memory allocation in PHP, the memory pointers are resource types).
Let's choose a background color, the function imagecolorallocate takes three arguments: $image, $r, $g and $b. The first argument $image is the image resource that is imagecreate()'ed.
The following 3 arguments are red, green and blue values. Use your Photoshop or Paint color picker to get the red/green/blue values. The color grey will be 128, 128, 128, (or hex notation for each parameter: 0x88, 0x88, 0x88) pink will be 255, 128, 255 (or 0xFF, 0x88, 0xFF). Choose a background color and move on: $bg = imagecolorallocate($image, 0xFF, 0x88, 0xFF). The hex color #FF88FF will became 0xFF, 0x88, 0xFF on PHP GD. If you are interested in hex notation in PHP, here is a grammar for hexadecimal(hex) notations and oct(octal) notations:

Hex → '0x' ['0'-'9', 'a'-'f', 'A'-'F']+
Oct → '0' ['0'-'7']+

That means a hex notation begins with "0x" and follows one or more valid hex characters: from 0 to 9, a to f and A to F, and oct notation begins with 0 and follows numbers from 0 to 7.

OK, no more off-topics, you imagecolorallocate()'ed $bg, and $bg stores hex color 0xFF88FF. The first call of imagecolorallocate() for $image will give $image the background color. Let's allocate another color: $fg = imagecolorallocate($image, 0, 0, 0). Now $fg became integer 0(zero), which is black.

Let's write something on the image, the function imagestring() draws a string on the image. It takes the following parameters:

boolean imagestring(
 resource $image, //The image resource that you previously created
 int $font, //The font ID, can be 1 to 5 or a custom font
 int $x, //The X coordinate of the text
 int $y, //The Y coordinate of the text
 string $string, //The text to be drawn
 int $color //The color of the text
)

Let's write "Hello, world!" in top-left of the image: imagestring($image, 0, 0, 0, 'Hello, world!', $fg). The first parameters is the image you've created, the second one is the font ID, choose 0 for the smallest (default) font and 5 for largest (default) font. Then the 3rd and 4th parameters are X and Y. The 4th parameter is the text to be drawn, and the 5th one is the color of the text. There is also an alternative way to draw text(with a better font): imageloadfont(), imagettftext(). I'm not covering that function this time. It requires you to upload your own fonts and set some environment variables.

Now, let's output the image, there are several functions to do it: imagepng(), imagegif(), imagejpeg() and more. They all take at least one argument: the image resource. You can specify the filename, quality and filters in other arguments. imagepng($image, 'out.png') writes the image to file out.png, and imagepng($image, 'out.png', 9) increases compression level to 9(and writes out.png). For more details, visit PHP.net's official site: http://us.php.net/imagepng Finally, de-allocate the memory: use imagedestroy($image)

Here is the finished code:

<?php

///READ THE COMMENTS

//tell the browser you are making PNG image,
// MUST BE CALLED BEFORE ANY OUTPUT such as echo and inline HTML
//Can be called before image(png|gif|jpeg|etc.)
header('Content-Type: image/png');
//Create the image: width=100, height=30
//we can also use imagecreatetruecolor() to
// create true color images such as photos, PNGs, JPGs
$image = imagecreate(100, 30);
//you can do some error handling:
//if ($image === false) { die ("Unable to generate image"); }


//background color: pink(#FF88FF)
$bg = imagecolorallocate($image, 0xFF, 0x88, 0xFF);
//text color: black(#000000)
$fg = imagecolorallocate($image, 0, 0, 0);
//now, draw text
imagestring($image, 0, 0, 0, 'Hello, world!', $fg);

//For a larger font size
// imagestring($image, 5, 0, 0, 'Hello, world!', $fg);

//For something useful:
// imagestring($image, 0, 0, 0, $_GET['text'], $fg);

//output the image as PNG
imagepng($image);

//de-allocate the memory to prevent memory leak
imagedestory($image);

//now you see 'Hello, world!' on the image.

//Some functions returns false on error,
// so you can handle error by using
// if ($result === false) { die ("ERROR"); }
?>

Here is the resulting image:
Hello, world![pink background]

Questions and Exercises

  1. How to create a new 50x50 PNG image to be drawn on?
  2. What does header('Content-Type: image/png') do?
  3. Convert the hex color #2277FF to imagecolorallocate() arguments, assuming $image is the image to be drawn.
  4. Which is the correct hexadecimal notation in PHP? 0FB FB 0hFB 0xFB
  5. Fix the following code:
    <?php
    $image = imagecreate(100, 200);
    $background = imagecolorallocate($image, 0xFF, 0xFF, 0xFF);
    $foreground = imagecolorallocate($image, 0x00, 0x00, 0x00);
    
    imagestring($image, 5, 0, 0, 'Hello, world!', $foreground);
    
    imagepng($image);
    
    header('Content-Type: image/png');
    ?>
    
  6. Write a script that shows the today's date, browser's information and client's IP address.

Answers

  1. imagecreate(50, 50), or imagecreatetruecolor(50, 50) if photos and external images are involved.
  2. It tells the browser the server is sending a PNG image, so the browser will render image instead of HTML.
  3. imagecolorallocate($image, 0x22, 0x77, 0xFF). The first invocation of imagecolorallocate() for $image will be the background color of $image.
  4. 0xFB. A hex notation must start with 0x, and hex notations are case-insensitive, 0xfb and 0xFb are same value.
  5. <?php
    $image = imagecreate(100, 200);
    $background = imagecolorallocate($image, 0xFF, 0xFF, 0xFF);
    $foreground = imagecolorallocate($image, 0x00, 0x00, 0x00);
    
    imagestring($image, 5, 0, 0, 'Hello, world!', $foreground);
    
    header('Content-Type: image/png'); //must be called before output
    imagepng($image); //this function writes output
    imagedestroy($image); //free up memory
    ?>
    
  6. <?php
    //the main image
    $image = imagecreate(600, 50);
    
    //background color: white
    $bg = imagecolorallocate($image, 0xFF, 0xFF, 0xFF);
    //text color: black
    $fg = imagecolorallocate($image, 0, 0, 0);
    
    imagestring($image, 5, 0, 0, 'Date: ' . date('r'), $fg);
    imagestring($image, 5, 0, 15, 'Your Browser: ' . $_SERVER['HTTP_USER_AGENT'], $fg);
    imagestring($image, 5, 0, 30, 'Your IP Address: ' . $_SERVER['REMOTE_ADDR'], $fg);
    
    
    header('Content-Type: image/png');
    //output image
    imagepng($image);
    //Free up memory
    imagedestroy($image);
    
    ?>
    
    

Using Images

You can create a new image from an existing image or add an existing image to your image. imagecreatefrompng(), imagecreatefromgif() and so on. They take one argument: the image filename or the URI to the image. It returns the image resource on success and false(as boolean type) on failure. An example is imagecreatefromgif('http://www.google.com/intl/en_ALL/images/logo.gif') or die('Unable to load image.').

To show an existing image to your newly created image resource, use imagecopy(). This function is very complex.

boolean imagecopy(
 resource $dest_img, //The destination image resource
 resource $src_img, //the source image resource, NOT URL
 int dest_x, //X coordinate of the destination image
 int dest_y, //Y coordinate of the destination image
 int src_x, //X coordinate of the source image(to be cropped)
 int src_y, //Y coordinate of the source image's crop rectangle
 int src_w, //width of the source image's crop rectangle
 int src_h, //height of the source image's crop rectangle
)

If it's hard for you to understand, I made a diagram.
imagecopy() diagram.

The following code shows a cropped Google logo and string 'Google Logo':

<?php

//disable all error messages
error_reporting(0);

//the main image, IMPORTANT: if you use imagecreate, you will get ugly 256 color image
//Use imagecreatetruecolor if external images are involved.
$image = imagecreatetruecolor(275, 65);

//load the Google logo image. Some web-hosts disabled external URL file loading, so you must save
//the Google logo locally if image could not be loaded.
$google = imagecreatefromgif('http://www.google.com/intl/en_ALL/images/logo.gif')
	or die('Unable to load image, make sure your server can connect to other servers');

//background color: white
$bg = imagecolorallocate($image, 0xFF, 0xFF, 0xFF);
//text color: black
$fg = imagecolorallocate($image, 0, 0, 0);
//write text on the top
imagestring($image, 5, 0, 0, 'Google Logo', $fg);
//add Google logo
imagecopy($image, $google,
	0, 15, //destination coordinates
	10, 33, //source crop rectangle's coordinates
	273, 54 //source crop rectangle's size
);

header('Content-Type: image/png');
//output image
imagepng($image);
//Free up memory
imagedestroy($image);
imagedestroy($google);

?>

Getting Image Size

The imagesx() gets width of an image resource, imagesy() gets height of an image resource, they all take one argument: The image resource. $image = imagecreatefrompng('test.png');imagesx($image); will return 50 if $image's width is 50. For more detail and other functions, visit PHP.net's official function page: http://us.php.net/manual/en/function.imagesx.php

Questions and Exercises

  1. How to load a PNG image from example.png (beside the script)?
  2. How to get the height of image resource $load?
  3. By using imagesx() and imagesy() and imagecopy(), copy $from to $to, and the size of the copied image should be the size of $from.

Answers

  1. $image = imagecreatefrompng('example.png')
  2. imagesy($load)
  3. imagecopy($to, $from, 0, 0, 0, 0, imagesx($from), imagesy($from))

Coming Soon

This tutorial is not finished yet! Next time, I will teach you how draw shapes.



Comments

Great job!

User: Thunda | Date: May 12th, 2009 5:10:49 am | Link: http://tob.pkmnnation.com/

Ooh, I've always wanted to know about this. Thanks for the tutorial!


Add Comment