我几个带有 Alpha 通道的 32 位位图。
我需要编写一个新的位图,它再次具有 alpha 通道。因此,最终的位图稍后与AlphaBlend一起使用。
无需拉伸。如果没有 alpha 通道,我将只使用 BitBlt 创建新的位图。
我没有使用托管代码,我只想使用标准GDI/WinAPI函数来执行此操作。我也对不需要一些特殊库的解决方案感兴趣。
蒂亚
注意:我知道我可以使用多个AphaBlend函数在最终输出中执行相同的组合。但是为了在我的程序中易于使用,我更愿意编写一次这样的位图。
您可以遍历每个像素并手动合成它们:
void ComposeBitmaps(BITMAP* bitmaps, int bitmapCount, BITMAP& outputBitmap)
{
for(int y=0; y<outputBitmap.bmHeight; ++y)
{
for(int x=0; x<outputBitmap.bmWidth; ++x)
{
int b = 0;
int g = 0;
int r = 0;
int a = 0;
for(int i=0; i<bitmapCount; ++i)
{
unsigned char* samplePtr = (unsigned char*)bitmaps[i].bmBits+(y*outputBitmap.bmWidth+x)*4;
b += samplePtr[0]*samplePtr[3];
g += samplePtr[1]*samplePtr[3];
r += samplePtr[2]*samplePtr[3];
a += samplePtr[3];
}
unsigned char* outputSamplePtr = (unsigned char*)outputBitmap.bmBits+(y*outputBitmap.bmWidth+x)*4;
if(a>0)
{
outputSamplePtr[0] = b/a;
outputSamplePtr[1] = g/a;
outputSamplePtr[2] = r/a;
outputSamplePtr[3] = a/bitmapCount;
}
else
outputSamplePtr[3] = 0;
}
}
(假设所有位图都是 32 位的,并且具有相同的宽度和高度)
或者,如果要在另一个位图之上绘制位图,而不是按相等的比例混合它们:
unsigned char* outputSamplePtr = (unsigned char*)outputBitmap.bmBits+(y*outputBitmap.bmWidth+x)*4;
outputSamplePtr[3] = 0;
for(int i=0; i<bitmapCount; ++i)
{
unsigned char* samplePtr = (unsigned char*)bitmaps[i].bmBits+(y*outputBitmap.bmWidth+x)*4;
outputSamplePtr[0] = (outputSamplePtr[0]*outputSamplePtr[3]*(255-samplePtr[3])+samplePtr[0]*samplePtr[3]*255)/(255*255);
outputSamplePtr[1] = (outputSamplePtr[1]*outputSamplePtr[3]*(255-samplePtr[3])+samplePtr[1]*samplePtr[3]*255)/(255*255);
outputSamplePtr[2] = (outputSamplePtr[2]*outputSamplePtr[3]*(255-samplePtr[3])+samplePtr[2]*samplePtr[3]*255)/(255*255);
outputSamplePtr[3] = samplePtr[3]+outputSamplePtr[3]*(255-samplePtr[3])/255;
}
我找到了以下最适合我的解决方案。
- 我使用 CreateDIB 服务创建新的目标位图
- 我用完全透明的像素预填充新的位图。(FillMemory/ZeroMemory)
- 我收到了需要使用 GetDIBits 复制的像素。如果可能的话,形成宽度,我直接将行复制到我之前创建的缓冲区中。否则,我将数据逐行复制到步骤中创建的缓冲区中。
- 生成的位图可以与 AlphaBlend 和 CImageList 对象一起使用。
因为位图不重叠,所以我不需要关心目标数据。