使用来自其他32位位图的alpha通道编写新的32位位图

时间:2014-02-13 11:03:11

标签: winapi gdi alphablending

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

我需要编写一个新的Bitmap,它再次有一个alpha通道。因此,最终的位图稍后将与AlphaBlend一起使用。

无需拉伸。如果没有alpha通道,我只会使用BitBlt来创建新的位图。

我没有使用托管代码,我只想用标准的GDI / WinAPI函数来做这件事。此外,我感兴趣的是一个不需要某些特殊库的解决方案。

TIA

注意:我知道我可以使用几个AphaBlend函数在最终输出中执行相同的组合。但是为了在我的程序中易于使用,我宁愿一次编写这样的位图。

2 个答案:

答案 0 :(得分:0)

您可以浏览每个像素并手动撰写:

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;
    }

答案 1 :(得分:0)

我找到了最适合我的解决方案。

  1. 我使用CreateDIBSection
  2. 创建一个新的目标位图
  3. 我使用完全透明的像素预填充新位图。 (FillMemory / ZeroMemory)
  4. 我收到需要使用GetDIBits复制的Pixel。如果可能形成宽度,我直接将行复制到我先前创建的缓冲区中。否则,我将数据逐行复制到步骤中创建的缓冲区中。
  5. 生成的位图可以与AlphaBlend和CImageList对象一起使用。
  6. 由于位图不重叠,我不需要关注目标数据。