I have the example :
unsigned int dwColor = 0xAABBCCFF; //Light blue color
And its parameters from left to right are : "alpha, red, green, blue"; each parameter requires two hexadecimal values.
The maximum value of each parameter is 255; lowest : 0
And, how to extract then convert all parameters of a DWORD color to decimals?
I like the value range "0.00 -> 1.00". For example :
float alpha = convert_to_decimal(0xAA); //It gives 0.666f
float red = convert_to_decimal(0xBB); //It gives 0.733f
float green = convert_to_decimal(0xCC); //It gives 0.800f
float blue = convert_to_decimal(0xFF); //It gives 1.000f
EDIT : I've just seen union, but the answerer says it's UB (Undefined Behaviour). Does anyone know the better solution? :)
I usually use an union
:
union color
{
unsigned int value;
unsigned char component[4];
};
color c;
c.value = 0xAABBCCFF;
unsigned char r = c.component[0];
unsigned char g = c.component[1];
unsigned char b = c.component[2];
unsigned char a = c.component[3];
If you need to treat it as a float value:
float fr = c.component[0] / 255.0f;
float fg = c.component[1] / 255.0f;
float fb = c.component[2] / 255.0f;
float fa = c.component[3] / 255.0f;
EDIT:
As mentioned in the comments below, this use of union
is Undefined Behaviour (UB), see this question from Luchian Grigore.
EDIT 2:
So, another way to break a DWORD
into components avoiding the union
is using some bitwise magic:
#define GET_COMPONENT(color, index) (((0xFF << (index * 8)) & color) >> (index * 8))
But I do not advise the macro solution, I think is better to use a function:
unsigned int get_component(unsigned int color, unsigned int index)
{
const unsigned int shift = index * 8;
const unsigned int mask = 0xFF << shift;
return (color & mask) >> shift;
}
How it works? Lets supose we call get_component(0xAABBCCFF, 0)
:
shift = 0 * 8
shift = 0
mask = 0xFF << 0
mask = 0x000000FF
0x000000FF &
0xAABBCCFF
----------
0x000000FF
0x000000FF >> 0 = 0xFF
Lets supose we call get_component(0xAABBCCFF, 2)
:
shift = 2 * 8
shift = 16
mask = 0xFF << 16
mask = 0x00FF0000
0x00FF0000 &
0xAABBCCFF
----------
0x00BB0000
0x00BB0000 >> 16 = 0xBB
Warning! not all color formats will match that pattern!
But IMHO, the neater solution is to combine the function with an enum, since we're working with a limited pack of values for the index:
enum color_component
{
A,B,G,R
};
unsigned int get_component(unsigned int color, color_component component)
{
switch (component)
{
case R:
case G:
case B:
case A:
{
const unsigned int shift = component * 8;
const unsigned int mask = 0xFF << shift;
return (color & mask) >> shift;
}
default:
throw std::invalid_argument("invalid color component");
}
return 0;
}
The last approach ensures that the bitwise operations will only be performed if the input parameters are valid, this would be an example of usage:
std::cout
<< "R: " << get_component(the_color, R) / 255.0f << '\n'
<< "G: " << get_component(the_color, G) / 255.0f << '\n'
<< "B: " << get_component(the_color, B) / 255.0f << '\n'
<< "A: " << get_component(the_color, A) / 255.0f << '\n';
And here is a live demo.