Delphi, GR32 + PngObject: converting to Bitmap32 doesn't work as expected

后端 未结 2 1302
南方客
南方客 2021-01-03 02:25

I\'m using GR32 for drawing multiple semi-transparent PNG images. So far I\'ve been using the following method:

  png:= TPNGObject.Create;
  png.LoadFromFile         


        
2条回答
  •  抹茶落季
    2021-01-03 02:54

    The reason seems to be that the transparency is applied two times to the image when loaded with LoadPNGintoBitmap32, giving it a more transparent and greyish look (more on this later).

    First the transparency:

    This is code from the original LoadPNGintoBitmap32, the critical parts are marked with comments:

     PNGObject := TPngObject.Create;
     PNGObject.LoadFromStream(srcStream);
    
     destBitmap.Assign(PNGObject);  // <--- paint to destBitmap's canvas with transparency (!)
     destBitmap.ResetAlpha;         
    
     case PNGObject.TransparencyMode of  // <--- the following code sets the transparency again for the TBitmap32
     { ... }
    

    The destBitmap.Assign internally does the same as you in your previous approach: it let's the PNG image paint itself to its canvas. This operation respects the alpha channel of the PNG. But this is not necessary, since the alpha channel is assigned to TBitmap32's pixels in a second step!

    Now change the code as follows, critical parts are again marked with comments:

     PNGObject := TPngObject.Create;
     PNGObject.LoadFromStream(srcStream);
    
     PNGObject.RemoveTransparency;  // <--- paint PNG without any transparency...
     destBitmap.Assign(PNGObject);  // <--- ...here
     destBitmap.ResetAlpha;
    
     srcStream.Position:=0;
     PNGObject.LoadFromStream(srcStream); // <--- read the image again to get the alpha channel back
    
     case PNGObject.TransparencyMode of   // <--- this is ok now, the alpha channel now only exists in the TBitmap32
     { ... }
    

    The above solution is inefficient because it reads the image twice. But it shows why your second approach produces a more transparent image.

    And for the greyishness: There is one more problem in the original code: destBitmap.Assign first fills the background with clWhite32, then paints the image transparently onto it. And then LoadPNGintoBitmap32 comes and adds another layer of transparency on top of it.

提交回复
热议问题