Question

I several a 32bit bitmap with Alpha channel.

I need to compose a new Bitmap that has again an alpha channel. So the final bitmap is later used with AlphaBlend.

There is no need for stretching. If there would be no alpha channel, I would just use BitBlt to create the new bitmap.

I am not using managed code, I just want to do this with standard GDI / WinAPI functions. Also I am interested in a solution that there is no need for some special libraries.

TIA

Note: I know that I can use several AphaBlend functions to do the same composition in the final output. But for the ease of use in my program I would prefer to compose such a bitmap once.

Was it helpful?

Solution 2

I found the following solution that fits best for me.

  1. I Create a new target bitmap with CreateDIBSection
  2. I prefill the new bitmap with fully transparent pixels. (FillMemory/ZeroMemory)
  3. I Receive the Pixel that needs to be copied with GetDIBits. If possible form the width I directly copy the rows into the buffer I previously created. Otherwise I copy the data row by row into the buffer created in step.
  4. The resulting bitmap can be used with AlphaBlend and in CImageList objects.

Because the bitmaps don't overlap I don't need take care about the target data.

OTHER TIPS

You can go through every pixel and compose them manually:

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

(Assuming all bitmaps are 32-bit and have the same width and height)

Or, if you want to draw bitmaps one on top of another, rather than mix them in equal proportions:

    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;
    }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top