開始色は 0xffff00ff です。これは a:255、r:255、g:0、b:255 です。
目標は、パーセンテージに基づいて、色のアルファ チャネルを不透明度が低くなるように変更することです。つまり、その色の 50% の不透明度は、およそ 0x80ff00ff です。
私が解決策に到達しようとした方法:
DWORD cx = 0xffff00ff;
DWORD cn = .5;
DWORD nc = cx*cn;
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;
}
これはテスト済みのコードです (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;
}
私はあなたの質問を次のように理解しています:全体の透明度を同じに保ちながら、特定の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 コンポーネントを微調整して目的の結果を得る必要があります。