|
Using a Union for Packed Color Values
Submitted by |
I rarely find good uses for unions, but this is one. Often color values are
stored and supplied as packed, 4-byte ARGB values. This is a compact and
efficient storage format, but sometimes it is not that convenient. For
example, in many cases you may have a fixed color value that needs to have
only its alpha component changed based on some calculation. Code for this
operation often looks like this:
typedef unsigned int COLOR4B;
COLOR4B color;
float alpha;
color = 0xFFFF0000;
alpha = resultOfSomeCalculation;
// now, update color's alpha component
// keep rgb components
color &= 0x00FFFFFF;
// or in the alpha value
color |= (COLOR4B)(alpha * 255.0f) << 24;
|
By using a union, you can provide the compiler with two different
_representations_ of the same memory, which can make access to individual
color components easier, and sometimes faster. Let_s change our COLOR4B
type to a union:
typedef union color4bTag
{
unsigned int c; // packed representation
struct argbTag // component-wise representation
{
unsigned char b; // (reversed for intel storage order)
unsigned char g;
unsigned char r;
unsigned char a;
} argb;
} COLOR4B;
|
Now, to set the alpha component of a packed 4-byte color, all we need to do
is:
color.argb.a = (unsigned char)(alpha * 255.0f);
But we still have the flexibility of setting the entire color value at once:
color.c = 0xFF00FF00
This C implementation shows the principle in its simplest form, but it can
easily be wrapped up in a C++ class to take advantage of automatic type
conversion and other syntactic niceties. Beware that on other platforms the
ordering of the argb members in the structure may need to be reversed.
There is also a chance that in some instances a partial register stall may
be incurred if the color value is used immediately after being updated, but
this is rare.
|
The zip file viewer built into the Developer Toolbox made use
of the zlib library, as well as the zlibdll source additions.
|