24-bit Colors and Bitwise Operators

24-Bit Colors in AS3

A 24-bit color in AS3 is internally represented by a sequence of 24 zeros and ones; that is, by 24 bits. For example:

ourColor: 00000001 00100000 11111111

(We are leaving a space between groups of eight bits for a reason explained later.) There are 224=16,777,216 of such sequences. Thus, there are 16,777,216 different 24-bit colors. A sequence of 24 zeros and ones represents a binary expansion of a number - binary means in terms of powers of 2. (Similarly as the decimal expansion that represents a number in terms of powers of 10.) For example, the sequence above gives the number:

1*20+1*21+1*22+1*23+1*24+1*25+1*26+1*27+
0*28+0*29+0*210+0*211+0*212+1*213+0*214+0*215+
1*216+0*217+0*218+0*219+0*220+0*221+0*222+0*223=73,983

We are going from right to left, from lower powers of 2 to higher powers. (Also, for any number a0=1.)

The unsigned integer 73,983 is the number of our color or its numerical value. Those values range from 0 to 16,777,215.

The eight-bit groups in a 24-bit sequence represent the red, green, and blue (RGB) components of a color. Each group is interpreted as a binary number on its own. A binary number with eight digits may take values from 0 to 255. Thus the RGB components are unsigned integers between 0 and 255. For example, the RGB components of ourColor are:

Red is the binary number 00000001. Thus, its decimal value is:

R: 1*20+0*21+0*22+0*23+0*24+0*25+0*26+0*27=1

Green is the binary number 00100000. Thus, its decimal value is:

G: 0*20+0*21+0*22+0*23+0*24+1*25+0*26+0*27=32

Green is the binary number 11111111. Thus, its decimal value is:

B: 1*20+1*21+1*22+1*23+1*24+1*25+1*26+1*27=255

Two questions come to mind right away. How to represent an RGB color in a way more readable than its binary form? Given the value of a color, how to extract the values of its red, green and blue components? For example, how to extract RGB components from the color 73,983 (if we did't know them already)?

Hexadecimal Form of a Number

Hexadecimal representation of a number is its expansion in terms of powers of 16. Not 10 not 2 but 16. The only problem are hexadecimal digits. Binary digits are 0, 1; decimal digits are 0, 1, 2, 3, 4, 5, 6, 7, 8, 9. 'Digits' for a given base or 'radix' are possible remainders of division by the radix. So hexadecimal digits are: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15. However, we do not want digits that occupy more than one character. So we denote hexadecimal digits by 0, 1 , 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F:

Hexadecimal digits:
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A=10, B=11, C=12, D=13, E=14, F=15.

Why use powers of 16? Bacause powers of 2 and the powers of 16 have a particular relationship. 4 bits translate into one hexadecimal digit. Every 24-bit binary number can be represented as a six-digit hexadecimal number (perhaps with leading zeros). Moreover, pairs of two consecutive haxadecimal digits in this expansion have the same values as the groups of eight bits in 24-bit form. So consecutive pairs in hexadecimal form represent the RGB components of a 24-bit color. For example, take ourColor=73,783. In AS3 the hexadecimal form is indicated by '0x' at the beginning. We have:

ourColor = 73,783 = 0x0120FF

Indeed:

0x0120FF = 15*160+15*161+0*162+2*163+1*164+0*165 = 73,783

Moreover, RGB components of ourColor can be read easily from the haxadecimal form. Each pair in 0x0120FF as an independent hexadecimal number has value:

0x01 = 1*160+0*161 = 1

0x20 = 0*160+2*161 = 32

0xFF = 15*160+15*161 = 255

You can have Flash calculate for you all kinds of expansions by using aGivenNumber.toString(16) for hexadecimal or aGivenNumber.toString(2) for the binary expansion. The only disadvantage of this method is the fact that leading zeros are omitted. Mathematically it makes sense, but it is not good for our purposes. Try for example:

trace((73983).toString(16));

The Output window shows: 120ff. Since we want six digits, we add a leading zero 0120ff and this is our hxadecimal representation.

Bitwise Operators and RGB Extraction Formulas

In the extraction formulas on the first page, we use the right bitwise shift operator, >>. For example, in extractGeen we have:

( (c >> 8) & 0xFF )

The right bitwise shift operator shifts all bits of an unsigned integer c to the right by the number of spaces specified, in the case above by 8 spaces. Bits that shift off to the right are discarded. Thus, after (c >> 8) the eight bits representing the green component of c are now the eight right-most bits. How do we get rid of the possible nonzero bits to the left of the right-most eight bits? By using the bitwise AND operator, &. This operator compares two binary sequences and returns a sequence in which a bit is 1 if and only if the bits at the same position are 1 in both sequences. Since 0xFF corresponds to the binary sequence 11111111, the operation (c >> 8) & 0xFF returns a sequence in which the eight righ-most bits are the same as in (c >> 8) and the rest are zero. In short, (c >> 8) shifts green bits to the eight right-most bits, and & 0xFF gets rid of all but the right-most eight bits. So the green component is extracted. Similarly, for other extraction functions.

In combineRGB function, we use the left bitwise shit, << and the bitwise operator OR, |:

( ( r << 16 ) | ( g << 8 ) | b )

The left bitwise shift << shifts bits to the right by the number of places specified by the second operand (16 and 8 in our case). Bits that shift off to the left are discarded, emptied spaces are filled with zeros. The bitwise OR, |, assigns 1 to each bit for which at least one of the operands has value 1 otherwise it assgins 0. So we get a 24-bit color with its red, green, and blue bits in the right places in the 24-bit sequence.

For a detailed description of bitwise operators we refer to AS3 Language Reference under Languange Elements - Operators.

32-Bit Colors

In Bitmap programming the alpha information about each pixel is important. For example, BitmapData.getPixel32(x,y) method returns a number which holds information about the red, green, blue, and alpha components of the pixel at the position (x,y). That number is between 0 and 4,294,967,295 and corresponds to a 32-bit binary sequence. In binary form the Alpha information is stored in the additional 8 bits to the left of the RGB bits. For example, the sequence:

ourColorWithAlpha: 11111111 00000001 00100000 11111111

represents our color from the example above, 0x0120FF, completely opaque. Its hexadecimal form including Alpha is: 0xFF0120FF - the first two haxadecimal digits hold the Alpha information.

Here is the function that extracts the Alpha channel value from the 32-bit color:

function extractAlpha(c:uint):uint {

return (( c >> 24 ) & 0xFF);

}

A function that combines ARGB data into a color value looks as follows:

combineARGB(a:uint,r:uint,g:uint,b:uint):uint {

return ( (a << 24) | ( r << 16 ) | ( g << 8 ) | b );

}

The displayInHex function can easily be adjusted, too.

Download

  • Download all files corresponding to this tutorial: rgbs.zip

References:

You will find much information about manipulating colors on the binary level in our two favorite books: Essential ActionScript 3.0 by Colin Moock (O'Reilly, 2007) and ActionScript 3.0 Image Effects by Todd Yard (friendsofED, 2009).

Back Intermediate Tutorials              Back to Flash and Math Home

We welcome your comments, suggestions, and contributions. Click the Contact Us link below and email one of us.

Adobe®, Flash®, ActionScript®, Flex® are registered trademarks of Adobe Systems Incorporated.