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.
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.
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.