Using Bitwise Operators: Manipulating Color Channels
Manipulating Color Channels
Color channel values are simply integers that range from 0 (0x00) to 255 (0xFF). As such, you can use just about any math operators you want to manipulate them; the important thing is to ensure that when you recombine them, they are still within the range from 0 to 255.
The following example simply adds random, channel-specific “noise” to the color channel values you extracted in the previous section. Although this example affects only a single color value, by looping through all of the pixels (or random pixels) in a BitmapData instance, you could generate noise over an image:
var redNoiseAmount:Number = 255;
var greenNoiseAmount:Number = 0;
var blueNoiseAmount:Number = 128;
// add a random amount to each channel,
// but keep the value within 0-255:
red = Math.min(255,red+random(redNoiseAmount));
green = Math.min(255,green+random(greenNoiseAmount));
blue = Math.min(255,blue+random(blueNoiseAmount));
This is sort of a useless example, considering that the
BitmapData.noise method is available. You could do much more complex and interesting manipulations than this one, but I wanted to keep things very simple (the focus is on the bitwise operations). There is a slightly more useful example in the source files you downloaded previously.
All that remains now is to combine the individual color channels back into a single color value.
Combining Color Channels
Combining separate channels back into a single color value is easier than splitting them apart. All you have to do is left-shift each channel back into its proper position and then use the OR operator (|) to combine them again. Mashed into a single, efficient line of code, it looks like this:
argb = (alpha << 24) | (red << 16) | (green << 8) | blue;
Broken down, you can see the exact process:
// argb starts at 0, which we can look at as 0x00000000
argb = 0;
// take the alpha value (0xFF)
// and shift it 24 bits (6 hex digits) left:
alpha <<= 24;
// alpha now equals 0xFF000000
// combine it with argb using OR.
// This will turn on any bits that are on in alpha:
argb |= alpha;
// argb now equals 0xFF000000
// shift the red value (0xC9) 16 bits (4 hex digits) left:
red <<= 16;
// red now equals 0x00C90000
// combine with argb using OR,
// this will turn on any bits that are on in red,
// while leaving on any bits that were previously on:
argb |= red;
// argb now equals 0xFFC90000
// continue with green and blue.
Using bitwise operators, you can now separate a single RGB or ARGB color into its component channels, manipulate the color values for each channel, and then combine them back into a single color value. To see this all at work in one place, check out the source files you downloaded earlier and then take a look at some other ways you can apply bitwise operators.
Inserting Color Channels
What if you want to manipulate just one color channel? It’s easy enough to extract a single color channel but it might not be so obvious how to insert a single channel into an existing color value without dissembling the whole thing. All you need to do is zero the channel’s original bits by applying an inverted bit mask using AND, and then using the OR operator to set the new bits in the channel.
This example inserts a new value (0xEE) into the green channel of an existing color:
var argb:Number = 0xFFC97B33;
var newGreenValue:Number = 0xEE;
// apply an inverted mask using AND – a one in the mask
// will stay unchanged, a zero in the mask will result in a zero:
argb &= 0xFFFF00FF;
// argb now equals 0xFFC90033
// shift the green value into the right position
// (2 hex digits or 8 bits left),
// then use OR to insert it into the color value:
argb |= (newGreenValue << 8);
// argb now equals 0xFFC9EE33
You could even do this all in a single line:
argb = (argb & 0xFFFF00FF) | (0xFF << 8);
Tip: Another handy use for shift operators is to emulate a
Math.floor operation. Shift operators discard anything after the decimal place, so shifting by zero provides a faster way to floor your numbers (both to type and execute):
trace(1224.215>>0); // 1224