Color support improved markedly between GD 1.x and GD 2.x. In GD 1.x there was no notion of the alpha channel, color handling was rather simple, and the library supported only 8-bit palette images (256 colors). When creating GD 1.x 8-bit palette images, you use the ImageCreate( ) function, and the first color you allocate using the ImageColorAllocate( ) function becomes the background color.
In GD 2.x there is support for true color images complete with an alpha channel. GD 2.x has a 7-bit (0-127) alpha channel.
To create a true color image, use the ImageCreateTrueColor( ) function:
$image = ImageCreateTrueColor(width, height);
Use ImageColorResolveAlpha( ) to create a color index that includes transparency:
$color = ImageColorResolveAlpha(image, red, green, blue, alpha);
The alpha value is between 0 (opaque) and 127 (transparent).
While most people are used to an 8-bit (0-255) alpha channel, it is actually quite handy that GD's is 7-bit (0-127). Each pixel is represented by a 32-bit signed integer, with the four 8-bit bytes arranged like this:
High Byte Low Byte {Alpha Channel} {Red} {Green} {Blue}
For a signed integer, the leftmost bit, or the highest bit, is used to indicate whether the value is negative, thus leaving only 31 bits of actual information. PHP's default integer value is a signed long into which we can store a single GD palette entry. Whether that integer is positive or negative tells us whether antialiasing is enabled for that palette entry.
Unlike with palette images, with GD 2.x true color images the first color you allocate does not automatically become your background color. Call ImageFilledRectangle( ) to fill the image with any background color you want.
Example 9-11 creates a true color image and draws a semitransparent orange ellipse on a white background.
<?php $im = ImageCreateTrueColor(150,150); $white = ImageColorAllocate($im,255,255,255); ImageAlphaBlending($im, false); ImageFilledRectangle($im,0,0,150,150,$white); $red = ImageColorResolveAlpha($im,255,50,0,50); ImageFilledEllipse($im,75,75,80,63,$red); header('Content-Type: image/png'); ImagePNG($im); ?>
Figure 9-11 shows the output of Example 9-11.
You can use the ImageTrueColorToPalette( ) function to convert a true color image to one with a color index (also known as a paletted image).
In Example 9-11, we turned off alpha blending before drawing our background and our ellipse. Alpha blending is a toggle that determines whether the alpha channel, if present, should be applied when drawing. If alpha blending is off, the old pixel is replaced with the new pixel. If an alpha channel exists for the new pixel, it is maintained, but all pixel information for the original pixel being overwritten is lost.
Example 9-12 illustrates alpha blending by drawing a gray rectangle with a 50% alpha channel over an orange ellipse.
<?php $im = ImageCreateTrueColor(150,150); $white = ImageColorAllocate($im,255,255,255); ImageAlphaBlending($im, false); ImageFilledRectangle($im,0,0,150,150,$white); $red = ImageColorResolveAlpha($im,255,50,0,63); ImageFilledEllipse($im,75,75,80,50,$red); $gray = ImageColorResolveAlpha($im,70,70,70,63); ImageAlphaBlending($im, false); ImageFilledRectangle($im,60,60,120,120,$gray); header('Content-Type: image/png'); ImagePNG($im); ?>
Figure 9-12 shows the output of Example 9-12 (alpha blending is still turned off).
If we change Example 9-12 to enable alpha blending just before the call to ImageFilledRectangle( ), we get the image shown in Figure 9-13.
To check the color index for a specific pixel in an image, use ImageColorAt( ) :
$color = ImageColorAt(image, x, y);
For images with an 8-bit color palette, the function returns a color index that you then pass to ImageColorsForIndex( ) to get the actual RGB values:
$values = ImageColorsForIndex(image, index);
The array returned by ImageColorsForIndex( ) has keys "red", "green", and "blue". If you call ImageColorsForIndex( ) on a color from a true color image, the returned array has an extra key, "alpha".
The color index returned by ImageColorResolveAlpha( ) is really a 32-bit signed long, with the first three 8-bit bytes holding the red, green, and blue values, respectively. The next bit indicates whether antialiasing is enabled for this color, and the remaining seven bits hold the transparency value.
For example:
$green = ImageColorResolveAlpha($im,0,0,255,127);
This code sets $green to 2130771712, which in hex is 0x7F00FF00 and in binary is 01111111000000001111111100000000.
This is equivalent to the following ImageColorResolveAlpha( ) call:
$green = 127<<24 | 0<<16 | 255<<8 | 0;
You can also drop the two 0 entries in this example and just make it:
$green = 127<<24 | 255<<8;
To deconstruct this value, you can use something like this:
$a = ($col & 0x7F000000) >> 24; $r = ($col & 0x00FF0000) >> 16; $g = ($col & 0x0000FF00) >> 8; $b = ($col & 0x000000FF);
Direct manipulation of true color color values like this is rarely necessary. One application is to generate a color-testing image that shows the pure shades of red, green, and blue. For example:
$im = ImageCreateTrueColor(256,60); for($x=0; $x<256; $x++) { ImageLine($im, $x, 0, $x, 19, $x); ImageLine($im, 255-$x, 20, 255-$x, 39, $x<<8); ImageLine($im, $x, 40, $x, 59, $x<<16); } ImagePNG($im);
Figure 9-14 shows the output of the color-testing program.
Obviously it will be much more colorful than what we can show you here in black and white, so try this example for yourself. In this particular example it is much easier to simply calculate the pixel color than to call ImageColorResolveAlpha( ) for every color.
An interesting use of the ImageColorAt( ) function is to loop through each pixel in an image and check the color, and then do something with that color data. Example 9-13 displays a # character in the appropriate color for each pixel.
<html><body bgcolor=#000000><tt> <?php $im = imagecreatefromjpeg('php-tiny.jpg'); $dx = imagesx($im); $dy = imagesy($im); for($y = 0; $y < $dy; $y++) { for($x=0; $x < $dx; $x++) { $col = imagecolorat($im, $x, $y); $rgb = imagecolorsforindex($im,$col); printf('<font color=#%02x%02x%02x>#</font>', $rgb['red'],$rgb['green'],$rgb['blue']); } echo "<br>\n"; } imagedestroy($im); ?> </tt></body></html>
The result is an ASCII representation of the image, as shown in Figure 9-15.
Copyright © 2003 O'Reilly & Associates. All rights reserved.