Master the bit masks used to isolate, extract, and modify individual color channels in packed RGB and ARGB values. Practical examples for image processing and graphics programming.
A bit mask is a value used with the AND operation to isolate a specific set of bits from a larger value. In the context of color, a channel mask is a pattern where the bits you want to keep are set to 1 and the bits you want to discard are set to 0. When I first learned this concept, the lightbulb moment was realizing that the AND operation acts like a stencil — it lets only the masked bits through.
For example, to isolate the red channel of an RGB color, you AND with 0xFF0000 — a mask that has 1s only in the red byte position. Everything outside the red byte gets zeroed out. The same principle applies to any packed data format, from network packets to file headers.
I used channel masking in a photo editing plugin I wrote to apply a sepia tone. By masking out the red, green, and blue channels individually, I could adjust each color contribution independently without affecting the others.
I use masks constantly in my image processing work. Whether I am isolating a channel for a histogram, zeroing out a channel for a color filter, or extracting raw bytes for a custom image format, the pattern is always the same: pick the right mask, AND it with the color, and optionally shift the result into the low byte position.
The three fundamental masks for RGB color are 0xFF0000 (red), 0x00FF00 (green), and 0x0000FF (blue). Each mask has exactly one byte of 1s at the position of its channel and zeros everywhere else. These masks work for both 24-bit values stored in 32-bit integers and for 32-bit ARGB values where the alpha byte should be ignored.
To extract a channel value as a number from 0-255, you combine masking with a right shift. The mask isolates the byte, and the shift moves it to the least significant position:
Notice that the blue extraction does not technically need a shift — color & 0x0000FF already gives the correct value. But I always include the >> 0 for consistency. It makes the code easier to scan and eliminates the temptation to leave off the shift for one channel but not the others.
// JavaScript: mask-based extraction (defensive version)
function getRed(color) { return (color & 0xFF0000) >> 16; }
function getGreen(color) { return (color & 0x00FF00) >> 8; }
function getBlue(color) { return (color & 0x0000FF); }
console.log(getRed(0xAABBCC), getGreen(0xAABBCC), getBlue(0xAABBCC));
// Output: 170 187 204
For 32-bit ARGB colors, the masks are shifted one byte higher to accommodate the alpha channel. The same masking-and-shifting pattern works, just with an extra mask for the alpha byte.
I find the ARGB masks particularly useful when debugging pixel data from a canvas or image decoder. When I dump raw pixel buffer values to the console, I can quickly compute which mask to apply by looking at the byte position of the channel I care about. The naming convention (A = byte 3, R = byte 2, G = byte 1, B = byte 0) maps directly to the mask hex digits.
// JavaScript: ARGB extraction using masks
function getAlpha(color) { return (color & 0xFF000000) >>> 24; }
function getRed(color) { return (color & 0x00FF0000) >> 16; }
function getGreen(color) { return (color & 0x0000FF00) >> 8; }
function getBlue(color) { return (color & 0x000000FF); }
// Using >>> for alpha to avoid sign extension issues
Sometimes you need to zero out a specific channel without affecting the others — for example, removing the green channel from an image to create a red-blue tint effect. The technique combines AND with the complement of a channel mask (the NOT of the mask, which has 0s where the mask has 1s and vice versa).
This complement masking pattern is also how you prepare a color value for ORing in a new channel value. First you clear the old channel with color & ~mask, then you OR in the new channel shifted to the right position: newColor = (color & ~0x00FF00) | (newGreen << 8).
// JavaScript: set green to a specific value while preserving R and B
function setGreenChannel(color, newGreen) {
// Clear the green byte, then OR in the new green shifted into place
return (color & ~0x00FF00) | ((newGreen & 0xFF) << 8);
}
I use these complement masks so often that I have them memorized: ~0xFF0000 = 0x00FFFF (clear red), ~0x00FF00 = 0xFF00FF (clear green), ~0x0000FF = 0xFFFF00 (clear blue). Each is simply the original mask's byte position replaced with zeros and everything else set to 0xFF.
Channel swapping — exchanging the red and blue channels, for example — is a common operation when converting between color formats. Different image formats and APIs use different byte orders (RGB vs BGR), and swapping channels is the fix.
Channel swapping comes up constantly in real-world graphics work. A few common scenarios where I have needed it:
// Fast BGR to RGB conversion using bitwise operations
function bgrToRgb(bgr) {
let r = (bgr & 0x0000FF) << 16; // blue byte -> red position
let g = (bgr & 0x00FF00); // green stays
let b = (bgr & 0xFF0000) >> 16; // red byte -> blue position
return r | g | b;
}
// Process an entire pixel buffer
function convertBgrBuffer(buffer) {
for (let i = 0; i < buffer.length; i++) {
buffer[i] = bgrToRgb(buffer[i]);
}
}
Masking is the foundation. See how these techniques apply to ARGB, pixel format conversion, and low-level bitmap manipulation.
A color channel mask is a bit pattern used with the AND operation to isolate a specific color channel from a packed RGB or ARGB value. For example, the red mask 0xFF0000 isolates the red byte by zeroing out the green and blue bytes. Common masks are: Red = 0xFF0000, Green = 0x00FF00, Blue = 0x0000FF.
To extract the red channel from a packed 24-bit RGB value, AND with the red mask 0xFF0000 to isolate the red byte, then shift right 16 bits: R = (color & 0xFF0000) >> 16. For green: G = (color & 0x00FF00) >> 8. For blue: B = color & 0x0000FF (no shift needed).
For ARGB 32-bit format: Alpha mask = 0xFF000000, Red mask = 0x00FF0000, Green mask = 0x0000FF00, Blue mask = 0x000000FF. Each mask isolates one byte, and the corresponding shift amounts are 24, 16, 8, and 0 bits respectively.
To clear the green channel in an RGB value while preserving red and blue, AND with the complement of the green mask: color & ~0x00FF00. This keeps the red byte (0xFF0000) and blue byte (0x0000FF) while zeroing the green byte. The complement ~0x00FF00 equals 0xFF00FF.
0x00FF00 is the green channel mask for RGB. In binary, it is 00000000 11111111 00000000. When ANDed with an RGB value, it preserves only the green byte (bits 15-8) and zeros out everything else. After masking, shifting right by 8 bits gives the raw green value.