1

私は例を持っています:

unsigned int dwColor = 0xAABBCCFF; //Light blue color
  • パラメータは左から順に「アルファ、赤、緑、青」です。各パラメーターには 2 つの 16 進数値が必要です。

  • 各パラメーターの最大値は255です。最低: 0

また、DWORD カラーのすべてのパラメーターを抽出してから 10 進数に変換する方法を教えてください。

値の範囲"0.00 -> 1.00"が好きです。例えば ​​:

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

編集:ユニオンを見たばかりですが、回答者はそれがUB(未定義の動作)だと言っています。誰もがより良い解決策を知っていますか? :)

4

1 に答える 1

1

私は通常:を使用し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';

そして、これがライブデモです。

于 2013-01-28T07:12:28.800 に答える