Winapi 使用其他32位位图的alpha通道合成新的32位位图

Winapi 使用其他32位位图的alpha通道合成新的32位位图,winapi,gdi,alphablending,Winapi,Gdi,Alphablending,我有几个32位的Alpha通道位图 我需要组成一个新的位图,它又有一个alpha通道。因此,最终的位图稍后将与AlphaBlend一起使用 没有必要拉伸。如果没有alpha通道,我将使用BitBlt创建新位图 我没有使用托管代码,我只是想用标准GDI/WinAPI函数来实现这一点。我还对一个解决方案感兴趣,它不需要一些特殊的库 短暂性脑缺血发作 注意:我知道我可以使用几个AphaBlend函数在最终输出中完成相同的合成。但为了便于在我的程序中使用,我更愿意一次性合成这样的位图。您可以遍历每个像素

我有几个32位的Alpha通道位图

我需要组成一个新的位图,它又有一个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;
        }
    }
void ComposeBitmaps(位图*位图、int位图计数、位图和输出位图)
{

对于(int y=0;y,我找到了以下最适合我的解决方案

  • 我使用CreateDIBSection创建了一个新的目标位图
  • 我用完全透明的像素预先填充新位图。(FillMemory/ZeroMemory)
  • 我接收需要用GetDIBits复制的像素。如果可能,从宽度开始,我直接将行复制到我之前创建的缓冲区中。否则,我将逐行将数据复制到步骤中创建的缓冲区中
  • 生成的位图可用于AlphaBlend和CImageList对象

  • 因为位图不重叠,我不需要关心目标数据。

    有帮助吗?或者?这是GDI+,必须有一种方法,只使用GDI。或者它链接的文章来解释alpha混合GDI,非常详细,包括将多个位图相互组合成最终位图,然后可以混合一次。它有一个Delphi类,您可以使用也可以使用(您没有提到您使用的语言。)具体来说,您在流程的哪一部分遇到困难:从文件加载位图、合成、使用结果、将结果保存到文件中,等等?当然最好使用AlphaBlend将所有位图合成在一起,然后在需要时绘制一幅合成图像?AlphaBlend将比大多数手动操作更快代码。@David M:AlphaBlend保持Alpha通道吗?如何保持?@David M:AlphaBlend可能更快,但是:1)如果位图尚未进行alpha预乘,则在调用AlphaBlend之前仍必须手动执行预乘。2)只有一种混合方法;例如,它无法独立混合位图顺序。3)最重要的是,它存在兼容性问题。请参阅:
        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;
        }