[Video] Create Dynamic Images with PHP and GD

AID: 1898
  • Status: Published

14726 points

  • Bygr8gonzo
  • TypeTutorial
  • Posted on2009-11-03 at 10:26:09
Awards
  • Community Pick
  • Experts Exchange Approved
  • Editor's Choice
Creating your own images on-the-fly isn't hard at all, especially with the help of PHP and GD.

GD is a graphics library (http://www.boutell.com/gd/) , and PHP has an extension that gives easy access to the major GD functions, giving you the ability to use GD to generate images (JPEGs, GIFs, PNGs, etc) on-the-fly. This tutorial is aimed at people who come across the need for dynamic images, discover that PHP can do it with GD, but have a hard time understanding how to use it.

The tutorial is offered in two versions, a video version, and a text-only version (although it may be helpful to see both).

1

Video Version


This detailed video will take you through every step of the process, and will create a dynamic, reusable "folder tab" image using a TrueType font.

It will also cover some common mistakes and misunderstandings that many people face when working with dynamic images for the first time.

VIDEO:
http://www.screencast.com/t/wnXwbVRV

ZIP FILE CONTAINING FINAL CODE AND IMAGES:
gdarticle.zip
  • 54 KB
  • All the files I used in the video, with the final code.
gdarticle.zip


(You will need to remove the .txt extension from the files with that extension.)

LINKS TO FUNCTIONS THAT I USED IN THE VIDEO:
http://www.php.net/manual/en/function.imagettfbbox.php
http://www.php.net/manual/en/function.imagettftext.php
http://www.php.net/manual/en/function.imagecopy.php
http://www.php.net/manual/en/function.imagecopyresized.php
http://www.php.net/manual/en/function.imagecreate.php
http://www.php.net/manual/en/function.imagecreatefrompng.php
http://www.php.net/manual/en/function.imagecolorallocate.php


NOTES:
1. In Part 1,  I use Photoshop to create some smaller images that I later use to make a nicer-looking tab. You don't need Photoshop - any image editor will do, and there are some good free ones out there, like Paint.NET and GIMP.

2. I used a random font from my font library, but you can use ANY TrueType (.TTF) font file.

3. I use PNG files throughout the tutorial, but you can also use GIF, BMP, or JPEG formats, too (anything GD can support).

4. I only used a small handful of GD functions. There are LOTS of things you can do with GD:
http://www.php.net/manual/en/ref.image.php

5. GD -is- required to be installed on your server, and is usually found on most hosting providers that support PHP. On Windows servers, enabling GD is as simple as uncommenting the:
extension=php_gd2.dll
line in your php.ini file. On Linux, you may need to either recompile PHP with the right options, or use a package manager to install GD support (it depends on how PHP was installed).

6. If your image looks broken, try accessing the image directly by its URL (instead of through an HTML document like I do in the video). Sometimes there are PHP errors that will show up in the image data that can help you figure out what's wrong.




2

Text Version


The GD library is very easy to use once you understand a some basic concepts, and I'll explain each one:


What GD Can Do - Using GD, you can open an existing photo or image and change any part of it, whether it's changing the color of a single pixel, drawing a black square over the face of someone you don't like, or even adding a blur effect to the photo. You can also create a new image from scratch, and put whatever you want inside it, as if you were an artist painting onto a blank canvas.


What GD Cannot Do - GD is mostly limited by the amount of effort you want to put into it, but there ARE some things that GD is not really designed to do, so they're simply extremely difficult (or slow) to do. For example, you COULD write a million lines of code that reproduces a photo of someone pixel-by-pixel, but that's like painting a portrait by dipping a needle into paint and poking at the canvas. It CAN be done, but it's just not really GD's strength. However, with a little ingenuity, you'd be surprised at what you CAN pull off with GD.


Image Resources - Whenever you look at an image on your computer, the viewing program opens up that image file, sucks in all the image data (so it knows what to show on your screen), and then closes the image file again. GD has to do the same thing in order to work with an image file. However, instead of just displaying the image data to you and closing, it copies the picture onto a virtual painting canvas so you can play with it. That virtual canvas is referred to as an image resource. So if you want to add a square onto the existing image, you tell GD to open the image file and give you the image resource. Then you tell it to paint a square onto the image resource / virtual canvas. When you're done, GD can save or display the results.

To create an image resource from an existing image, use the imagecreatefrom... functions, like:

imagecreatefrompng()
http://www.php.net/manual/en/function.imagecreatefrompng.php
$im = imagecreatefrompng("reunion.png");
                                    
1:

Select allOpen in new window

$im = imagecreatefromjpeg("vacation.jpg");
                                    
1:

Select allOpen in new window

$im = imagecreatefromgif("myPicture.gif");
                                    
1:

Select allOpen in new window



Or, to create a new, blank image resource, just use imagecreate():
http://www.php.net/manual/en/function.imagecreate.php
$im = imagecreate(300,150); // Create a 300 x 150 image
                                    
1:

Select allOpen in new window




X & Y Coordinates - In real life, if someone told you to paint a sun at the top of your picture, you would know generally where to put it. Computers, as with most things, are far more precise. You can't tell GD to just paint a yellow circle at the top of your picture - you have to tell it the EXACT location where you want the yellow circle to go. This is done with coordinates. A set of coordinates is simply two numbers, referred to as X and Y, and might look like: 54, 23. In that example, 54 is the X coordinate, and 23 is the Y coordinate, and they indicate an exact location on our virtual canvas.

If you imagine your virtual painting canvas and put a giant grid of squares on it, you would probably say that the very first square is the one in the top-left corner. This is exactly how coordinates work in GD. Coordinates start at 0 and go up the size of your image. So if you had an image that was 300 pixels wide and 150 pixels tall, then your X coordinate could be any number between 0 and 299 (not 300, because we start at 0). Likewise, the Y coordinate could be anything from 0 to 149. If you haven't guessed already, the coordinates 0, 0 always refer to the top-left corner of your image. In our example image, the coordinates 299, 149 would refer to the bottom-right corner.


Color Allocation - Let's talk about the painting canvas again. If you've ever seen an old picture of a classic painter, then you've probably seen them holding a thin, circular wooden board called a palette (if you're not sure what I'm talking about, use Google Images to search for "painting palette"). The palette holds the different colors of paint that the artist uses. All computer images have a palette, as well, and it works the same way (which is why they named it a palette). After all, every image is just a bunch of pixels of different colors. The palette of a computer image is just a giant, virtual version of that wooden board, and holds anywhere from 2 colors to millions of them.

When you want to paint something onto a virtual canvas, you almost always need to specify a color. This is done by first allocating a color to our palette, giving you a color resource. When it comes time to paint, we just provide that color resource to the "painting" function (whichever one you're using).


Color Combinations - Your basic color is made up of a certain amount of Red, an amount of Green, and an amount of Blue (hence the acronym RGB). Each amount can be a number from 0 to 255. White is made up of the maximum value of all three, so it is 255 Red, 255 Green, and 255 Blue. Black, on the other hands, is 0 of everything. You can get a bright green color with 0 Red, 255 Green, and 0 Blue. From there, you can figure out that you have access to quite a few combinations of colors (16,581,375 to be exact).

To allocate a color with a specific color combination, use imagecolorallocate():
http://www.php.net/manual/en/function.imagecolorallocate.php
$white = imagecolorallocate($im, 255, 255, 255);
                                    
1:

Select allOpen in new window




Resizing / Resampling - One of GD's strengths is taking an existing image and changing it's size. This might just be a simple enlargement of a photo or a reduction, or maybe you're stretching out an image. You can do it in one of two ways - with resizing or resampling. Resizing is pretty self-explanatory - GD takes an image and stretches it out to the size you want. Resampling does the same thing but goes a bit further and tries to "smooth out" parts of the image so you don't end up with blocky, pixelated results. Resampling usually works better when you're resizing photos with lots of colors (although it is slower than resizing), while resizing usually works best when you're dealing with either a few colors or else you don't want the "smoothing out" effect. (You can also just copy different parts from different pictures and put them all together into one new image without resizing.)

If you want to copy an image (or part of an image) without resizing or resampling, use imagecopy():
http://www.php.net/manual/en/function.imagecopy.php

To copy using resizing, use imagecopyresized():
http://www.php.net/manual/en/function.imagecopyresized.php

To copy with resampling, use imagecopyresampled():
http://www.php.net/manual/en/function.imagecopyresampled.php

NOTE: Check out the code in the attached ZIP file at the end of this article for examples on how to use the copy and copyresized functions.


Content-Type: - Let's say you've created a dynamic image and you're now ready to display it to the user. These dynamic images are almost always viewed through an internet browser like Firefox or Internet Explorer. Some browsers can look at all the binary data gibberish and make a guess at what it is (is it a JPEG or a GIF? Or maybe a PNG?), but not all of them have that ability. Imagine trying to read a Spanish book as if all the words were supposed to be English - none of the words would make sense! But if you were told to read it in Spanish (and if you knew Spanish), then you could read and understand the book. So before we start spewing out all of our image data to the browser, we can tell the browser what kind of image we're about to send. That way, all browsers can be prepared to take the data and make sense of all of it.
header("Content-type: image/png");
                                    
1:

Select allOpen in new window




Fonts - One of the most frequently-used features of GD is the ability to write text onto an image, using any TrueType font (fonts that end in the .TTF extension) that you have on your system. The most common problem people face here is simply not putting the font file into a place where GD can get to it. During development, I usually copy the font file into the same folder as my dynamic image. Once I get it working, I can move the font file into its final location and adjust my script to look for it in that new location.


Bounding Boxes - The other most common problem people face with working with text is dealing with sizes. If you create an image that is 300 pixels wide, and then you try to write a really long sentence in a big font, then the text is going to disappear off the canvas / image, and you're not going to be able to see it. The image does not magically expand to hold everything - that is something you are responsible for doing, and that is why you are giving the bounding box tool. For simplicity's sake, I like to call it the boundary box instead, since it feels a little more accurate. To explain the bounding box, look for any word on this page that is in a nice, big font, and just remember what it looks like. Now imagine you could stretch a rubber band around the word, and after you did that, the rubber band suddenly spoke to you and said, "This word is 50 pixels wide and 20 pixels tall." That is what a bounding/boundary box is, except instead of a rubber band, it's an invisible rectangle.

You can give GD a font name, a font size, and a word (or words), and tell it to create a bounding box. In return, GD gives you an array of coordinates, but 99% of the time, you'll just want two coordinates - the X and the Y coordinate of the bottom-right corner (which would also tell you how wide/tall the box is). Using a bounding box, you can increase the size of your new image to fit all of the text (if that's what you want to do).

The PHP function for creating a bounding box is imagettfbbox():
http://www.php.net/manual/en/function.imagettfbbox.php
//
$boundingBox = imagettfbbox($fontSize, 0, "myFont.ttf", "How big is this text?");
$textWidth = $boundingBox[4]; // 4 is the X coordinate for a right corner of the bounding box
//
                                    
1:
2:
3:
4:

Select allOpen in new window



To actually write text onto an image, use imagettftext():
http://www.php.net/manual/en/function.imagettftext.php
imagettftext($im, $size, 0, $X, $Y, $blue, $font, "Some text");
                                    
1:

Select allOpen in new window




Fonts and Y Coordinates - The third (and last) most common text-relaed problem occurs when people test out their fonted, text-writing code and use the coordinates 0, 0 for the position of their text (and they don't see anything happening). However, writing text onto an image is like writing on a lined piece of notebook paper. You write just above that thin little line. So when you're writing text on an image, the X coordinate still acts normal, but the Y coordinate represents the line UNDERNEATH your text. So coordinates 0, 0 will still work, but you won't see anything because the BOTTOM of the text is at the 0 Y coordinate.

Adjusting is pretty simple. When you're writing text, you also specify a font size. This font size is simply how tall the font can be in pixels (easiest seen with upper-case letters). So with a font size of 12, your upper-case letter M will be 12 pixels tall. That said, if you want the text to appear at the very top of your image, all you need to do is start at your font size value (e.g. 12) instead of 0 for your Y coordinate. If you're trying to do any math to calculate a Y coordinate, just keep that little offset in mind, and you'll be in the clear.

The video tutorial tries to illustrate many of these concepts and take you through the coding of them, but now that you know the basic concepts, you should be able to take my attached example and figure out what it's doing (and play around with it).

ZIP FILE CONTAINING EXAMPLE CODE AND IMAGES:
gdarticle.zip
  • 54 KB
  • All the files I used in the video, with the final code.
gdarticle.zip


You can do some pretty cool things with PHP and GD, so make good use of your new tools!
Asked On
2009-11-03 at 10:26:09ID1898
Tags

php

,

gd

,

video

,

truetype

Topic

PHP Scripting Language

Views
4213

Comments

Expert Comment

by: lherrou on 2009-11-04 at 06:01:23ID: 5121

Superb work. I have given it my YES vote above, and am linking to it from my own article, Fonts, Web Design, and the Holy Grail (http://www.experts-exchange.com/A_1599.html)

Add your Comment

Please Sign up or Log in to comment on this article.

Join Experts Exchange Today

Gain Access to all our Tech Resources

Get personalized answers

Ask unlimited questions

Access Proven Solutions

Search 3.2 million solutions

Read In-Depth How-To Guides

1000+ articles, demos, & tips

Watch Step by Step Tutorials

Learn direct from top tech pros

And Much More!

Your complete tech resource

See Plans and Pricing

30-day free trial. Register in 60 seconds.

Loading Advertisement...

Top PHP Experts

  1. Ray_Paseur

    1,354,218

    Genius

    3,734 points yesterday

    Profile
    Rank: Savant
  2. DaveBaldwin

    284,951

    Guru

    4,300 points yesterday

    Profile
    Rank: Genius
  3. StingRaY

    144,754

    Master

    4,000 points yesterday

    Profile
    Rank: Wizard
  4. jason1178

    143,172

    Master

    1,000 points yesterday

    Profile
    Rank: Genius
  5. bportlock

    123,643

    Master

    1,600 points yesterday

    Profile
    Rank: Genius
  6. ChrisStanyon

    111,336

    Master

    0 points yesterday

    Profile
    Rank: Sage
  7. Roads_Roads

    106,350

    Master

    0 points yesterday

    Profile
    Rank: Genius
  8. maeltar

    95,247

    Master

    0 points yesterday

    Profile
    Rank: Guru
  9. gr8gonzo

    95,168

    Master

    0 points yesterday

    Profile
    Rank: Sage
  10. smadeira

    82,088

    Master

    0 points yesterday

    Profile
    Rank: Wizard
  11. Slick812

    77,062

    Master

    0 points yesterday

    Profile
    Rank: Sage
  12. johanntagle

    74,700

    Master

    2,000 points yesterday

    Profile
    Rank: Sage
  13. logudotcom

    67,088

    Master

    0 points yesterday

    Profile
    Rank: Genius
  14. COBOLdinosaur

    65,841

    Master

    0 points yesterday

    Profile
    Rank: Genius
  15. leakim971

    63,819

    Master

    0 points yesterday

    Profile
    Rank: Genius
  16. un1x86

    56,406

    Master

    0 points yesterday

    Profile
    Rank: Master
  17. Derokorian

    46,763

    10 points yesterday

    Profile
    Rank: Guru
  18. marqusG

    44,475

    10 points yesterday

    Profile
    Rank: Sage
  19. DrDamnit

    42,892

    0 points yesterday

    Profile
    Rank: Genius
  20. ahoffmann

    40,068

    0 points yesterday

    Profile
    Rank: Genius
  21. designatedinitializer

    37,800

    0 points yesterday

    Profile
    Rank: Master
  22. maestropsm

    37,678

    0 points yesterday

    Profile
    Rank: Guru
  23. TerryAtOpus

    34,800

    0 points yesterday

    Profile
    Rank: Genius
  24. xterm

    32,850

    0 points yesterday

    Profile
    Rank: Sage
  25. kaufmed

    31,808

    0 points yesterday

    Profile
    Rank: Genius

Hall Of Fame