2

Here is some minimal code to show an issue:

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 result I'm getting image filled by RGB values equals to 10. It seems GDI+ uses the conventional algorithm:

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

But I'm expecting that premultiplied algorithm will be used (because foreground image has the premultiplied PixelFormat32bppPARGB format):

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

So my question, why GDI+ uses conventional formula when image is in premultiplied alpha format? And is there any workaround to make GDI+ to use the premultiplied alpha algorithm?

Ian Boyd
  • 246,734
  • 253
  • 869
  • 1,219
iendgame
  • 153
  • 7
  • Both the source and the destination bitmaps are PARGB. So no need to change the pixel, you'll get an exact copy of foregroundImg. – Hans Passant Nov 06 '13 at 10:34
  • no, I'm not getting copy of foregroung image. I'm getting image filled with ARGB(255,10,10,10), which exactly what conventional algo is produced. BTW, I've tried with various formats for background, but result is always the same – iendgame Nov 06 '13 at 10:36

1 Answers1

1

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

You might be able to do what you intend by setting the source image bits directly, or you might not. Components with values greater than 100% aren't really valid in gdiplus's rendering model, so I'd not be surprised if it caps them during rendering. If you really want this level of control over the rendering, you'll have to lock the bitmap bits and do it yourself.

Esme Povirk
  • 3,004
  • 16
  • 24