What is the channel order in bitmap pixels? Does the R channel occupy the least- or most- significant byte?
Ah, the answer to this simple question held me back for nearly a day while debugging some image processing code. MSDN, while being excruciatingly verbose on obsolete legacies of bitmaps (device-dependent bitmaps, anyone?) is remarkably mysterious here.
First, they note that:
The system and applications use parameters and variables having the COLORREF type to pass and store color values … Applications can create a color value from individual component values by using the RGB macro.
Which says that R is the least-significant (as in COLORREF). This drove the original design of my code, but external viewers kept showing the colors wrong in images I produced.
Reversing the buffer contents from RGB to BGR solved the problem – the cleanest way is just using RGBQUAD instead of COLORREF. Still, to this moment I cannot find an explicit mention of this being the expected channel order in bitmap storage. There’s this quote:
When creating or examining a logical palette, an application uses the RGBQUAD structure to define color values and to examine individual component values.
And this:
The RGBQUAD structures specify the RGB intensity values for each of the colors in the device’s palette.
Both docs indicate that RGBQUAD is the expected channel order for indexed bitmaps: those where pixel colors are not stored explicitly, but as indices into a central color-table (or palette). This hasn’t really been useful since devices started to show more than 256 colors, but it feels like the docs still consider it more important than non-indexed bitmaps.
Turns out that that for regular, non-indexed bitmaps – i.e., biBitcount equals 16, 24 or 32 – the expected channel order is the same as for the palette: R being the most significant byte.
Extra Chatter
If you insisted you could force a different channel ordering on the stored bitmap, using color masks (it’s a wikipedia link – by far more readable than MSDN). You’d have to –
- use either BITMAPV4HEADER or BITMAPV5HEADER.
- Set the bV4V4Compression (historical typo?) or bV5Compression fields to BI_BITFIELDS.
- Set the bVxRedMask/bVxGreenMask/ bVxBlueMask to indicate your desired channel masks (x being 4 or 5).
- Expect the rest of the world to have massive trouble using your images.
Thank you. Nice to have some facts behind the behavior!
it confuses me for 3 days. Thank you very much! Really Appreciate!