RGB vs. BGR in Bitmaps

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 –

  1. use either BITMAPV4HEADER or BITMAPV5HEADER.
  2. Set the bV4V4Compression (historical typo?) or bV5Compression fields to BI_BITFIELDS.
  3. Set the bVxRedMask/bVxGreenMask/ bVxBlueMask to indicate your desired channel masks (x being 4 or 5).
  4. Expect the rest of the world to have massive trouble using your images.
Advertisements
This entry was posted in Win32 and tagged , . Bookmark the permalink.

One Response to RGB vs. BGR in Bitmaps

  1. Anonymous says:

    Thank you. Nice to have some facts behind the behavior!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s