Как вы делаете смешивание и прозрачность, используя только чистый VCL для растровых изображений?

Подобно этому вопросу, я хотел бы смешивать цвета и растровые изображения (png или bmp, но в моем случае я использую png), сохраняя прозрачность.

Как и в случае со связанным вопросом, я хотел бы (а) не использовать сторонние библиотеки, (б) использовать встроенные методы VCL, где это возможно, но при необходимости прибегать к API-интерфейсам Win32 GDI, и (в) не использовать GDI+.

Этот простой код, основанный на коде в связанном вопросе, я вижу, что смешивание цветов работает, но прозрачность файла PNG не сохраняется, когда я делаю это:

Вещи, которые я пробовал: - Различные форматы пикселей (pf32bit,pf24bit) - Различные значения для TBitmap.Transparent.

Я попробовал это в Delphi XE5 и XE6, в этом случае, но я подозреваю, что то же самое будет работать для XE2 и выше.

Демо-код:

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.

Снимок экрана, на котором справа показано несложное, но правильно прозрачное изображение, а слева - смешанное, но уже не прозрачное изображение:

Примечание: я думаю, что предварительное смешивание фона и переднего плана с вызовом Win32 API к AlphaBlend МОЖЕТ быть единственным путем, и в этом случае VCL НЕ содержит встроенной поддержки прозрачности, о которой стоит упомянуть. (Кто-то в Stackru сказал мне, что он считает, что сторонние библиотеки для этой цели не годятся, так как это встроено в VCL, и я подумал, прав ли он, поэтому я пытаюсь сделать это только с VCL.)

0 ответов

Другие вопросы по тегам