Closed koow520530 closed 1 year ago
这是个好问题,很抱歉这么晚才回复你。 实际上,src 和 dst 的颜色分量不应该互斥,因为这个函数的作用是将 dst 叠加到 src 上,所以 src 的颜色分量不应该被改变。但如果 alpha 参数不为 255(不透明),则 dst 和 src 都会被再次叠上一层透明度,然后再混合到一起。
如果你觉得没问题,可以关闭这个 issue,或者我会在几个星期后把它关闭。
fRatioAlpha 0.5 fRatioSrc 0.5 fRatioSrcAlpha 0.25 fRatioDst 0.75 fRatioSrc 0.5 按照原始的,src+dst超过1了,两个颜色(192,96,150)和(250,0,170)紫红混合成了(19,72,197)蓝色,而且dst的alpha如果是1的话,那就没有透明效果,就是蓝色了。你可以测试一下。我是因为显示出错了,才查到这个地方可能有问题。
因为我一直在学校,所以回复很迟,抱歉。
我重新检查了我的代码,确实存在你所说的问题。由于之前 cSrc 和 cDst 的颜色分量相加可能大于 1,所以导致混合后的色值中,rgb 分量可能大于 255,造成溢出。
下面是我重新写的 MixAlphaColor 函数,你可以先用它替换你的项目中旧的 MixAlphaColor 函数,测试问题是否解决,如果没有问题,我会把这个函数更新到下一个版本中。
/**
* @brief 根据透明度混合颜色
* @param[in] cDst 原位置像素
* @param[in] cSrc 待绘制像素(根据其透明度混合颜色)
* @param[in] isCalculated 待绘制像素点是否已经乘以它的透明度 <p>
* 例如,透明 png 图像中的像素就是已经乘过透明度的。<p>
* 但是一般在程序中创建的颜色是没用乘过的。<p>
* @param[in] alpha 叠加在 src 上的透明度(默认为 255,即不叠加)
* @return 混合后的颜色(不含透明信息)
*/
COLORREF MixAlphaColor(COLORREF cDst, COLORREF cSrc, bool isCalculated, BYTE alpha = 255);
COLORREF MixAlphaColor(COLORREF cDst, COLORREF cSrc, bool isCalculated, BYTE alpha)
{
float fSrc = GetAValue(cSrc) / 255.0f; // 待绘制像素的透明度
if (alpha != 255) // 叠加透明度
fSrc *= alpha / 255.0f;
if (fSrc == 0.0f) // 绘制透明度为 0 时不做任何处理
return cDst;
float fDst = 1 - fSrc; // 原位置像素应乘透明度
if (isCalculated)
{
return RGB(
GetRValue(cSrc) + GetRValue(cDst) * fDst,
GetGValue(cSrc) + GetGValue(cDst) * fDst,
GetBValue(cSrc) + GetBValue(cDst) * fDst
);
}
else
{
return RGB(
GetRValue(cSrc) * fSrc + GetRValue(cDst) * fDst,
GetGValue(cSrc) * fSrc + GetGValue(cDst) * fDst,
GetBValue(cSrc) * fSrc + GetBValue(cDst) * fDst
);
}
}
另附一份测试代码(可直接编译运行)
#include "HiEasyX.h"
#include <conio.h>
int main()
{
hiex::Window wnd(640, 480);
hiex::AutoExit();
hiex::Canvas canvas;
wnd.BindCanvas(&canvas);
canvas.Clear(true, WHITE);
canvas.SolidRectangle(100, 100, 300, 300, true, PURPLE);
for (byte i = 0; i < 255; i++)
{
canvas.SolidRectangle(200, 200, 400, 400, true, hiex::MixAlphaColor(WHITE, SET_ALPHA(RED, i), false));
canvas.SolidRectangle(200, 200, 300, 300, true, hiex::MixAlphaColor(PURPLE, SET_ALPHA(RED, i), false));
wnd.Redraw();
Sleep(10);
}
_getch();
wnd.CloseWindow();
return 0;
}
不知道能不能解决你的问题,期待你的回复!
此问题已在 Ver0.2.2 中修复,详见 https://github.com/zouhuidong/HiEasyX/releases/tag/Ver0.2.2