1

開始色は 0xffff00ff です。これは a:255、r:255、g:0、b:255 です。

目標は、パーセンテージに基づいて、色のアルファ チャネルを不透明度が低くなるように変更することです。つまり、その色の 50% の不透明度は、およそ 0x80ff00ff です。

私が解決策に到達しようとした方法:

DWORD cx = 0xffff00ff;
DWORD cn = .5;

DWORD nc = cx*cn;
4

5 に答える 5

1
typedef union ARGB
{
    std::uint32_t Colour;
    std::uint8_t A, R, G, B;
};


int main()
{
    DWORD cx = 0xffff00ff;
    reinterpret_cast<ARGB*>(&cx)->A = reinterpret_cast<ARGB*>(&cx)->A / 2;

    std::cout<<std::hex<<cx;
}
于 2014-07-06T04:18:53.217 に答える
1

これはテスト済みのコードです (Linux で)。ただし、もっと簡単な答えが見つかるかもしれません。注: これは RGBA であり、質問で参照した ARGB ではありません。

double transparency = 0.500;

unsigned char *current_image_data_iterator = reinterpret_cast<unsigned char*>( const_cast<char *>( this->data.getCString() ) );
unsigned char *new_image_data_iterator = reinterpret_cast<unsigned char*>( const_cast<char *>( new_image_data->data.getCString() ) );

size_t x;

//cout << "transparency: " << transparency << endl;

for( x = 0; x < data_length; x += 4 ){

    //rgb data is the same
    *(new_image_data_iterator + x) = *(current_image_data_iterator + x);
    *(new_image_data_iterator + x + 1) = *(current_image_data_iterator + x + 1);
    *(new_image_data_iterator + x + 2) = *(current_image_data_iterator + x + 2);

    //multiply the current opacity by the applied transparency
    *(new_image_data_iterator + x + 3) = uint8_t( double(*(current_image_data_iterator + x + 3)) * ( transparency / 255.0 ) );

    //cout << "Current Alpha: " << dec << static_cast<int>( *(current_image_data_iterator + x + 3) ) << endl;
    //cout << "New Alpha: " << double(*(current_image_data_iterator + x + 3)) * ( transparency / 255.0 ) << endl;
    //cout << "----" << endl;

}
于 2014-07-06T04:25:21.367 に答える
0

私はあなたの質問を次のように理解しています:全体の透明度を同じに保ちながら、特定のrgbaカラーコンポーネントを特定の要因で変更したいと考えています。

完全なアルファ (1.0 または 255) を持つ色の場合、これは簡単です。他の要素に触れずに要素を乗算するだけです。

//typedef unsigned char uint8
enum COMPONENT {
    RED,
    GREEN,
    BLUE,
    ALPHA
};

struct rgba {
    uint8 components[4];
    // uint8 alpha, blue, green, red; // little endian
    uint8 &operator[](int index){
        return components[index];
    }
};

rgba color;
if (color[ALPHA] == 255)
   color[RED] *= factor;
else
    ComponentFactor(color, RED, factor);

一般的なケースでは、おそらくその質問に対する単一の答えはありません。色はHSL または HSVで代替的にエンコードされる可能性があることを考慮してください。これらのパラメーターの一部を固定したままにし、他のパラメーターを変更できるようにすることができます。

この問題に対する私のアプローチは、最初にソース カラーとターゲット カラーの間の色相距離をフル アルファで見つけてから、実際のソース カラーを HSV に変換し、色相の変更を適用してから RGBA に戻すことです。明らかに、アルファが実際に 1.0 である場合、その 2 番目のステップは必要ありません。

擬似コード:

rgba ComponentFactor(rgba color, int component, double factor){
    rgba fsrc = color, ftgt;
    fsrc.alpha = 1.0; // set full alpha
    ftgt = fsrc;
    ftgt[component] *= factor; // apply factor
    hsv hsrc = fsrc, htgt = ftgt; // convert to hsv color space
    int distance = htgt.hue - hsrc.hue; // find the hue difference
    hsv tmp = color; // convert actual color to hsv
    tmp.hue += distance; // apply change in hue
    rgba res = tmp; // convert back to RGBA space 
    return res;
}

上記がどのように型に依存し、rgba暗黙hsv的な変換コンストラクターを持つかに注意してください。変換のアルゴリズムは、Web 検索で簡単に見つけることができます。[]rgba から hsv の構造体定義を派生させることも、(演算子を使用するのではなく) フィールド メンバーとして個々のコンポーネント アクセスを含めることも簡単です。例えば:

//typedef DWORD uint32;

struct rgba {

    union {
        uint8 components[4];
        struct {
            uint8 alpha,blue,green,red; // little endian plaform
        }
        uint32 raw;
    };

    uint8 &operator[](int index){
        return components[4 - index];
    }
    rgba (uint32 raw_):raw(raw_){}
    rgba (uint8 r, uint8 g, uint8 b, uint8 a):
        red(r), green(g), blue(b),alpha(a){}
};

おそらく、距離ではなく色相係数を見つけるか、他の HSV コンポーネントを微調整して目的の結果を得る必要があります。

于 2014-07-06T04:14:23.700 に答える