TBitmap32.Assign() abnormal behavior

664 Views Asked by At

What's wrong with Graphics32 TBitmap32.Assign()? Why is the transparency of the original image not preserved for TBitmap32, while for TBitmap everything is fine? Here is a sample code:

procedure TForm1.Button8Click(Sender: TObject);
var
  bmp32: TBitmap32;
  bmp: TBitmap;
  wic: TWICImage;
begin
  bmp32 := TBitmap32.Create(TMemoryBackend);
  bmp := TBitmap.Create;
  wic := TWICImage.Create;
  try
    wic.LoadFromFile('overlay.png'); // transparent
    bmp32.Assign(wic);
    bmp32.SaveToFile('BMP32.bmp'); // !!! nontransparent .bmp
    img1.Bitmap.Assign(bmp32);
    bmp.Assign(wic);
    bmp.SaveToFile('BMP.bmp'); // transparent .bmp
    img2.Bitmap.Assign(bmp);
  finally
    wic.Free;
    bmp32.Free;
    bmp.Free;
  end;
end;

Here is a screenshot of the result:
enter image description here

Is this a Graphics32 library (version is the latest from github) bug? Or TWICImage bug? Or Delphi 10.2.3 bug? Or am I doing something wrong? How to fix this?

The original overlay.png file:
enter image description here

1

There are 1 best solutions below

1
LuFang On BEST ANSWER

I think I've found a solution. I added a couple of lines to GR32 module to nested procedure AssignFromGraphic of TCustomBitmap32.Assign procedure:

  procedure AssignFromGraphic(TargetBitmap: TCustomBitmap32; SrcGraphic: TGraphic);
  begin
    if SrcGraphic is TBitmap then
      AssignFromBitmap(TargetBitmap, TBitmap(SrcGraphic))
    else if SrcGraphic is TIcon then
      AssignFromIcon(TargetBitmap, TIcon(SrcGraphic))
{$IFNDEF PLATFORM_INDEPENDENT}
    else if SrcGraphic is TMetaFile then
      AssignFromGraphicMasked(TargetBitmap, SrcGraphic)
{$ENDIF}
//--- start fix
    else if (SrcGraphic is TWICImage) and (TWICImage(SrcGraphic).ImageFormat = wifPng) then
      AssignFromGraphicPlain(TargetBitmap, SrcGraphic, $00FFFFFF, False)
//--- end fix
    else
      AssignFromGraphicPlain(TargetBitmap, SrcGraphic, clWhite32, True);
  end;

I've added some extra checks and changed two parameters of the procedure AssignFromGraphicPlain(TargetBitmap: TCustomBitmap32; Src Graphic: TGraphic; FillColor: TColor32; ResetAlphaAfterDrawing: Boolean);
With FillColor = $00FFFFFF (clWhite32 with alpha channel = 0) and ResetAlphaAfterDrawing = False the transparency of the original PNG image is now preserved. It looks like a dirty trick, but it works!
Of course, I would like to hear a more authoritative opinion, so I will not accept my answer yet. There may be another way without changing the source code of the Graphics32 library.