How can an 8-bpp bitmap contain 256 values of alpha?

The question was posed to me yesterday (which relates to the entry I wrote about creating a .bmp-with-alpha to use in the panel system of Flight Sim: what IS the deal with the .bmp files that are used by the panel system that have alpha in them?  A great question!

These .bmp files are not of a standard format, so many image editors will not display them correctly.  I have seen paint actually do a pretty good job of displaying them, along with windows explorer.  Visual Studio doesn't do such a great job.  The .bmp format standard is described briefly here.  The .bmps that are genererated by imagetool vary from this standard significantly.

But let's start with how the FS bmp-w-alpha does match the standard.  It DOES start with a standard BITMAPFILEHEADER, followed by a BITMAPINFOHEADER.  In the BITMAPINFOHEADER, the bmp-w-alpha specifies an 8-bit-per-pixel format (256 colors), which sounds very limiting until you realize that you can specify exactly which 256 colors you want in the palette. An array of RGBQUAD's follows the BITMAPINFOHEADER, just like you'll see in standard bitmaps.  (Although if anyone can explain why it's called an "RGBQUAD" instead of a "BGRQUAD", please be my guest).  However, if you followed that link to the definition of RGBQUAD, you'll noticed that rgbReserved is supposed to be zero.  Zilch!  Nada!  However, if you open one of these bitmaps as binary - hexidecimal (take, for example, magnetic_compass_shadow_alpha.bmp that ships as part of the Douglas_DC3.cab), that that is not the case.  OK, well, it won't be entirely obvious unless you can read hex like Neo in The Matrix, but in the palette section (which jumps out as the section with lots of zeros), you'll see lots of RGBQUAD's that look like: "00 00 00 96".  Or if you're like me, you're not sure if it's supposed to be "00 96 00 00" or "96 00 00 00", but then you realize that the RGB should always be black ("00 00 00"), so the reserved bits are clearly used for the alpha channel.  And since there are 8 reserved bits, that gives us the 256 different values of alpha we were wondering about.

This explains why MS Paint, for example, makes this image look completely black instead of, well, like a 3D shadow... because the RGB is really just black, with varying levels of alpha around the bitmap.  And MS Paint doesn't expect any alpha values to be present in that palette!

Moving right along through the binary representation of our sample .bmp file, we see a bunch of consecutive zeros.  That's the unused part of the palette.  (We don't need all 256 entries!)  And then the cool part: right around byte 0x436, we see "FS70".  Hm, you think this might be Flight Sim-specific?   (I suppose it's not so obvious if you just see the hex sequence "46 53 37 30", unless you're Neo.)  Indeed, this is the start of the FS-specific header info.  Fortunately for us, this header has nothing to do with the images used by the panel system (remember that imagetool is used for textures and whatnot that have nothing to do with the panels) so I won't bother going into that.  So the rest of the file is just standard 8-bits-per-pixel data, each byte (8 bits) representing an index into that nonstandard palette that we looked at before.

One thing that's somewhat unfortunate about this system is that instead of limiting us to 256 colors, it limits us to 256 combinations of color+alpha value.  So if our image had 256 colors in it and then we added two different alpha values (let's say 50% transparent and opaque) for each possible color, we'd be up to 512 possible combinations, and we'd probably have some banding as a result of the rounding that would ensue. 

However, these bmps-with-alpha have been used in our gauges almost entirely (maybe I can leave out 'almost') for shadows and highlights, which use only a small number of RGB values (usually plain white or black), so this palette limitation doesn't see to be a problem.  Let me know if you think otherwise!

I hope you have learned something from this entry, because I know I have!