问题
Similar to this question I would like to both blend colors, and bitmaps (png or bmp, but in my case I'm using a png) while preserving transparency.
As with the linked question, I would like to (a) not use third party libraries, (b) use VCL built in techniques where possible but with recourse to the Win32 GDI APIs where needed, and (c) not use GDI+.
This simple code, based on the code in the linked question I see that the color blending works but the PNG file's transparency is not preserved, when I do this:
Things I tried: - Different pixel formats (pf32bit,pf24bit) - Different values for TBitmap.Transparent.
I tried this in Delphi XE5 and XE6, in this case, but I suspect that the same thing will work for XE2 and up.
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 the unblended but correctly transparent image on the right, and a blended, but no longer transparent image on the left:
Note: I think that pre-blending the background and the foreground with a Win32 API call to AlphaBlend MAY be the only way to go, in which case the VCL does NOT contain any built in transparency support worth mentioning. (Someone on StackOverflow told me that he thought that third party libraries to this purpose were not worthwhile since this is built into the VCL, and I wondered if he's right, so I'm trying to do this with the VCL only.)
来源:https://stackoverflow.com/questions/23702868/how-do-you-do-both-blending-and-transparency-using-just-pure-vcl-on-bitmapped-im