How do you do both blending and transparency using just pure VCL on bitmapped images?

做~自己de王妃 提交于 2020-01-16 04:31:38

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!