9.8
Color
Handling
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.
Example 9-11. A simple 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).
9.8.1 Using the Alpha Channel
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.
Example 9-12. A gray rectangle with a 50% alpha channel overlaid
<?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.
9.8.2 Identifying Colors
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"
.
9.8.3 True Color Color Indexes
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.
9.8.4 Text Representation of an Image
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.
Example 9-13. Converting an image to text
<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.
|