C++ 更改DWORD颜色alpha通道值
我有一个起始颜色:0xffff00ff,它是a:255,r:255,g:0,b:255 目标是基于百分比将颜色的alpha通道更改为不太不透明。i、 e.该颜色的50%不透明度约为0x80ff00ff 我如何尝试达成解决方案:C++ 更改DWORD颜色alpha通道值,c++,winapi,dword,C++,Winapi,Dword,我有一个起始颜色:0xffff00ff,它是a:255,r:255,g:0,b:255 目标是基于百分比将颜色的alpha通道更改为不太不透明。i、 e.该颜色的50%不透明度约为0x80ff00ff 我如何尝试达成解决方案: DWORD cx = 0xffff00ff; DWORD cn = .5; DWORD nc = cx*cn; 这应该能奏效。我在这里所做的就是用or(以“|”符号表示)将DWORD的前8位设置为1,然后用希望的正确值(即alpha掩码乘以cn)对这些位进行andin
DWORD cx = 0xffff00ff;
DWORD cn = .5;
DWORD nc = cx*cn;
这应该能奏效。我在这里所做的就是用or(以“|”符号表示)将DWORD的前8位设置为1,然后用希望的正确值(即alpha掩码乘以cn)对这些位进行anding。当然,我将乘法的结果再次转换为双字
这应该能奏效。我在这里所做的就是用or(以“|”符号表示)将DWORD的前8位设置为1,然后用希望的正确值(即alpha掩码乘以cn)对这些位进行anding。当然,我将乘法的结果再次转换为双字 我对你的问题的理解是:我希望在保持相同的整体透明度的同时,以一定的因子更改给定的rgba颜色分量 对于具有完整alpha(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);
在一般情况下,这个问题可能没有一个单一的答案。考虑颜色可以交替编码。您可能希望固定其中一些参数,并允许更改其他参数
我解决这个问题的方法是首先尝试找到源颜色和目标颜色之间在全alpha下的色调距离,然后将真实源颜色转换为HSV,应用色调的变化,然后转换回RGBA。显然,如果alpha实际上是1.0,那么第二步是不必要的
在伪代码中:
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
来使用隐式转换构造函数的。通过网络搜索可以很容易地找到转换算法。从rgba one派生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组件以达到所需的结果。我将您的问题理解为:我希望通过某个因子更改给定的rgba颜色组件,同时保持相同的整体透明度
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;
}
对于具有完整alpha(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);
在一般情况下,这个问题可能没有一个单一的答案。考虑颜色可以交替编码。您可能希望固定其中一些参数,并允许更改其他参数
我解决这个问题的方法是首先尝试找到源颜色和目标颜色之间在全alpha下的色调距离,然后将真实源颜色转换为HSV,应用色调的变化,然后转换回RGBA。显然,如果alpha实际上是1.0,那么第二步是不必要的
在伪代码中:
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
来使用隐式转换构造函数的。通过网络搜索可以很容易地找到转换算法。从rgba one派生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组件以获得所需的结果。typedef union ARGB
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;
}
{
标准:uint32色;
标准:uint8_t A、R、G、B;
};
int main()
{
DWORD cx=0xffff00ff;
重新解释强制转换(&cx)->A=重新解释强制转换(&cx)->A/2;
std::couttypedef联合ARGB
{
标准:uint32色;
标准:uint8_t A、R、G、B;
};
int main()
{
DWORD cx=0xffff00ff;
重新解释强制转换(&cx)->A=重新解释强制转换(&cx)->A/2;
std::cout这是经过测试的代码(在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;
}
双透明度=0.500;
unsigned char*current_image_data_iterator=reinterpret_cast(const_cast(this->data.getCString());
unsigned char*new_image_data_iterator=reinterpret_cast(const_cast(new_image_data->data.getCString());
尺寸x;
//cout这是经过测试的代码(在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;
}
双透明度=0.500;
unsigned char*current_image_data_iterator=reinterpret_cast(const_cast(this->data.getCString());
unsigned char*new_image_data_iterator=reinterpret_cast(const_cast(new_image_data->data.getCString());
尺寸x;
//我选择的解决方案是:
DWORD changeOpacity(DWORD color, float opacity) {
int alpha = (color >> 24) & 0xff;
int r = (color >> 16) & 0xff;
int g = (color >> 8) & 0xff;
int b = color & 0xff;
int newAlpha = ceil(alpha * opacity);
UINT newColor = r << 16;
newColor += g << 8;
newColor += b;
newColor += (newAlpha << 24);
return (DWORD)newColor;
}
DWORD更改不透明度(DWORD颜色、浮点不透明度){
int alpha=(颜色>>24)&0xff;
int r=(颜色>>16)&0xff;
int g=(颜色>>8)&0xff;
int b=颜色&0xff;
int newAlpha=ceil(alpha*不透明度);
UINT newColor=r我选择的解决方案:
DWORD changeOpacity(DWORD color, float opacity) {
int alpha = (color >> 24) & 0xff;
int r = (color >> 16) & 0xff;
int g = (color >> 8) & 0xff;
int b = color & 0xff;
int newAlpha = ceil(alpha * opacity);
UINT newColor = r << 16;
newColor += g << 8;
newColor += b;
newColor += (newAlpha << 24);
return (DWORD)newColor;
}
DWORD更改不透明度(DWORD颜色、浮点不透明度){
int alpha=(颜色>>24)&0xff;
int r=(颜色>>16)&0xff;
int g=(颜色>>8)&0xff;
int b=颜色&0xff;
int newAlpha=ceil(alpha*不透明度);
UINT newColor=r您研究过任何按位运算吗?是的,但我不确定/不知道我将使用什么作为另一个操作数(?)。即0xffff00ff | 0xee或什么。没有任何结果。使用逐位运算提取R G和B值。根据从第一步获得的整数执行调整。然后将其打包回原始字节结构。例如,要提取a
的位,您需要使用逐位和e> 操作cx&ff000000
。然后要将其作为一个int,必须将其转换为