pd->Blue = pd->Blue * 255 / pd->Alpha;
pd->Green = pd->Green * 255 / pd->Alpha;
pd->Red = pd->Red * 255 / pd->Alpha;
}
}
}
}
//---------------------------------------------------------------------------
// source alpha = true, dest alpha = true, alpha = 255
static VOID Mixer7(PImageCpyData cpyData, INT alpha)
{
PARGBQuad pd = cpyData->dstScan0;
PARGBQuad ps = cpyData->srcScan0;
for (INT y = 0; y < cpyData->height; y ++, pd += cpyData->dstOffset, ps += cpyData->srcOffset)
{
for (INT x = 0; x < cpyData->width; x ++, pd ++, ps ++)
{
if (ps->Alpha)
{
pd->Blue = (pd->Blue * pd->Alpha + 127) / 255;
pd->Green = (pd->Green * pd->Alpha + 127) / 255;
pd->Red = (pd->Red * pd->Alpha + 127) / 255;
pd->Blue += (((ps->Blue - pd->Blue) * ps->Alpha + 127) / 255);
pd->Green += (((ps->Green - pd->Green) * ps->Alpha + 127) / 255);
pd->Red += (((ps->Red - pd->Red) * ps->Alpha + 127) / 255);
pd->Alpha += (ps->Alpha - (pd->Alpha * ps->Alpha + 127) / 255);
pd->Blue = pd->Blue * 255 / pd->Alpha;
pd->Green = pd->Green * 255 / pd->Alpha;
pd->Red = pd->Red * 255 / pd->Alpha;
}
}
}
}
//---------------------------------------------------------------------------
VOID ImageMixer(BitmapData *dest, CONST BitmapData *source, INT alpha)
{
if (alpha <= 0) return;
if (alpha > 255) alpha = 255;
ImageCpyData data;
data.width = (INT)(dest->Width < source->Width dest->Width : source->Width);
data.height = (INT)(dest->Height < source->Height dest->Height : source->Height);
data.dstOffset = (dest->Stride >> 2) - data.width;
data.srcOffset = (source->Stride >> 2) - data.width;
data.dstScan0 = (PARGBQuad)dest->Scan0;
data.srcScan0 = (PARGBQuad)source->Scan0;
MixerProc proc[] = {Mixer0, Mixer1, Mixer2, Mixer1, Mixer4, Mixer5, Mixer6, Mixer7};
INT index = (alpha / 255) | ((dest->Reserved >> 16) << 1) | ((source->Reserved >> 16) << 2);
proc[index](&data, alpha);
}
//---------------------------------------------------------------------------
函数ImageMixer有三个参数,分别为目标图数据结构(借用GDI+的BitmapData结构)指针、源图数据结构指针和源图像素混合比例(不透明度,取值范围为0 - 255,前面的公式中的取值范围0 - 1是方便描述)。函数体中的proc数组包括了图像混合的全部8种情况的子函数,而index则按混合比例、目标图Alpha信息和源图Alpha信息组合成子函数调用下标值(Alpha信息在BitmapData结构的保留字段中)。
当然,在实际的运用中,全部8种情况似乎是多了点,可根据情况进行适当合并取舍,以兼顾代码的复杂度和执行效率。下面是我认为比较合理的精简版ImageMixer函数:
VOID ImageMixer(BitmapData *dest, CONST BitmapData *source, INT alpha)
{
if (alpha <= 0) return;
if (alpha > 255) alpha = 255;
ImageCpyData data;
data.width = (INT)(dest->Width < source->Width dest->Width : source->Width);
data.height = (INT)(dest->Height < source->Height dest->Height : source->Height);
data.dstOffset = (dest->Stride >> 2) - data.width;
data.srcOffset = (source->Stride >> 2) - data.width;
data.dstScan0 = (PARGBQuad)dest->Scan0;
data.srcScan0 = (PARGBQuad)source->Scan0;
if (alpha == 255 && !(source->Reserved & PixelAlphaFlag))
Mixer1(&data, alpha);
else if (dest->Reserved & PixelAlphaFlag)
Mixer6(&data, alpha);
else
Mixer4(&data, alpha);
}
//----------------------------------------- |