Like this question, I would like to mix colors as well as bitmap images (png or bmp, but in my case I use png) while maintaining transparency.
Like a related question, I would like (a) not to use third-party libraries, (b) use VCL built into methods where possible, but if necessary use the Win32 GDI API where necessary, and (c) not use GDI + .
This simple code, based on the code in the related question, I see that color mixing works, but the transparency of the PNG file is not preserved when I do this:
Things I tried: - Different pixel formats (pf32bit, pf24bit) - Different values for TBitmap.Transparent.
I tried this on Delphi XE5 and XE6, in this case, but I suspect the same will work for XE2 and higher.
Demo code:
unit BlendUnit2;
{ Investigating VCL alpha blending GDI capability }
interface
uses
Winapi.Windows,
Winapi.Messages,
System.SysUtils,
System.Variants,
System.Classes,
Vcl.Graphics,
Vcl.Controls,
Vcl.Forms,
Vcl.Dialogs,
Vcl.ExtCtrls,
Vcl.Imaging.pngimage,
Vcl.StdCtrls;
type
TForm2 = class(TForm)
BackgroundImage: TImage;
TransparentImageInDFM: TImage;
GeneratedImage: TImage;
Label1: TLabel;
Shape1: TShape;
Shape2: TShape;
Label2: TLabel;
Label3: TLabel;
procedure FormDestroy(Sender: TObject);
procedure FormCreate(Sender: TObject);
public
{ Public declarations }
procedure Blend(ACanvas:TCanvas);
end;
var
Form2: TForm2;
implementation
{$R *.dfm}
procedure ColorBlend(const ACanvas: TCanvas; const ARect: TRect;
const ABlendColor: TColor; const ABlendValue: Integer);
var
bmp: TBitmap;
begin
bmp := TBitmap.Create;
// bmp.PixelFormat := pf32bit;
// bmp.AlphaFormat := afPremultiplied;
// bmp.Transparent := True;
try
bmp.Canvas.Brush.Color := ABlendColor;
bmp.Width := ARect.Right - ARect.Left;
bmp.Height := ARect.Bottom - ARect.Top;
bmp.Canvas.FillRect(Rect(0,0,bmp.Width, bmp.Height));
ACanvas.Draw(ARect.Left, ARect.Top, bmp, ABlendValue);
finally
bmp.Free;
end;
end;
procedure TForm2.Blend(ACanvas:TCanvas);
var
Image: TPNGImage;
begin
Image := TPNGImage.Create;
try
Image.LoadFromFile('..\..\AppIcon2013.png');
ColorBlend(Image.Canvas, Image.Canvas.ClipRect, $00CCFF80, 85);
ACanvas.Draw(0, 0, Image);
finally
Image.Free;
end;
end;
procedure TForm2.FormDestroy(Sender: TObject);
begin
//
end;
procedure TForm2.FormCreate(Sender: TObject);
begin
// GeneratedImage.Picture.Bitmap.Transparent := false;
// GeneratedImage.Picture.Bitmap.PixelFormat := pf32bit;
GeneratedImage.Picture.Bitmap.SetSize(280,280);
Blend( GeneratedImage.Picture.Bitmap.Canvas );
end;
end.
Screenshot showing indelible, but correctly transparent image on the right, and mixed, but no more transparent image on the left:

Note. I think pre-blending the background and foreground with a call to the Win32 API for AlphaBlend MAY be the only way, in which case the VCL does NOT contain the built-in transparency support that is worth mentioning. (Someone from StackOverflow told me that he thought that third-party libraries weren’t worth it because it is built into VCL, and I wondered if it was right, so I only try to do it with VCL.)