Drawing PixelFormat32bppPARGB images with GDI + uses regular formula instead of pre-multiplied

Here are some minimal codes to show the problem:

static const int MAX_WIDTH = 320;
static const int MAX_HEIGHT = 320;

Gdiplus::Bitmap foregroundImg(MAX_WIDTH,MAX_HEIGHT,PixelFormat32bppPARGB);
{
    Gdiplus::Graphics g(&foregroundImg);
    g.Clear(Gdiplus::Color(10,255,255,255));
}

Gdiplus::Bitmap softwareBitmap(MAX_WIDTH,MAX_HEIGHT,PixelFormat32bppPARGB);
Gdiplus::Graphics g(&softwareBitmap);
g.SetCompositingMode(Gdiplus::CompositingModeSourceOver);
g.SetCompositingQuality(Gdiplus::CompositingQualityDefault);

g.Clear(Gdiplus::Color(255,0,0,0));

g.DrawImage(foregroundImg,0,0);

CLSID encoder;
GetEncoderClsid(L"image/png",&encoder);
softwareBitmap.Save(L"d:\\image.png",&encoder);

      

As a result, I get an image filled with RGB values ​​equal to 10

. GDI + seems to use the usual algorithm:

255 * (10/255) + 0 * (1-10 / 255) == 10.

But I expect a premultiplexing algorithm to be used (because the foreground is in a premultiplexed format PixelFormat32bppPARGB

):

255 + 0 * (1-10 / 255) == 255

So my question is, why does GDI + use the normal formula when the image is in pre-multiplied alpha format? And is there any workaround to get GDI + to use the premultiplexed alpha algorithm?

+2


source to share


1 answer


The format of your foreground image doesn't matter (given that it has alpha) because you are setting it to Gdiplus :: Color. Color values ​​are defined as non-pre-multiplex, so gdiplus multiplies the components by the alpha value when it clears the foreground image. An alternative would be for the color values ​​to have a different meaning depending on the format of the render target, and therein lies the madness.



You may be able to do what you intend by directly setting the original bits of the image, or you may not. Components with values ​​greater than 100% are not really valid in the gdiplus render model, so I wouldn't be surprised if it closes them during rendering. If you really want that level of control over rendering, you'll have to lock the bitmap bits and do it yourself.

+1


source







All Articles