私は通常:を使用し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];
浮動小数点値として扱う必要がある場合:
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;
編集:
以下のコメントで述べられているように、この使用union
は未定義動作(UB)です。LuchianGrigoreからのこの質問を参照してください。
編集2:
DWORD
したがって、を回避してコンポーネントに分割する別の方法union
は、ビット単位の魔法を使用することです。
#define GET_COMPONENT(color, index) (((0xFF << (index * 8)) & color) >> (index * 8))
しかし、私はマクロソリューションをアドバイスしません。関数を使用する方が良いと思います。
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;
}
使い方?私たちが呼ぶとしましょうget_component(0xAABBCCFF, 0)
:
shift = 0 * 8
shift = 0
mask = 0xFF << 0
mask = 0x000000FF
0x000000FF &
0xAABBCCFF
----------
0x000000FF
0x000000FF >> 0 = 0xFF
私たちが呼ぶとしましょうget_component(0xAABBCCFF, 2)
:
shift = 2 * 8
shift = 16
mask = 0xFF << 16
mask = 0x00FF0000
0x00FF0000 &
0xAABBCCFF
----------
0x00BB0000
0x00BB0000 >> 16 = 0xBB
警告!すべてのカラーフォーマットがそのパターンに一致するわけではありません!
しかし、IMHO、より適切な解決策は、インデックスの値の限られたパックで作業しているため、関数を列挙型と組み合わせることです。
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;
}
最後のアプローチでは、入力パラメーターが有効な場合にのみビット演算が実行されるようにします。これは使用例です。
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';
そして、これがライブデモです。