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.
ZIP FILE CONTAINING FINAL CODE AND IMAGES:
(You will need to remove the .txt extension from the files with that extension.)
LINKS TO FUNCTIONS THAT I USED IN THE VIDEO:
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:
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:
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.
- 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:
$im = imagecreatefrompng("reunion.png");
$im = imagecreatefromjpeg("vacation.jpg");
$im = imagecreatefromgif("myPicture.gif");
Or, to create a new, blank image resource, just use imagecreate()
X & Y Coordinates
$im = imagecreate(300,150); // Create a 300 x 150 image
- 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.
- 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).
- 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()
Resizing / Resampling
$white = imagecolorallocate($im, 255, 255, 255);
- 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()
To copy using resizing, use imagecopyresized()
To copy with resampling, use imagecopyresampled():
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.
- 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.
- 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.
- 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()
$boundingBox = imagettfbbox($fontSize, 0, "myFont.ttf", "How big is this text?");
$textWidth = $boundingBox; // 4 is the X coordinate for a right corner of the bounding box
To actually write text onto an image, use imagettftext()
Fonts and Y Coordinates
imagettftext($im, $size, 0, $X, $Y, $blue, $font, "Some text");
- 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:
You can do some pretty cool things with PHP and GD, so make good use of your new tools!