この質問は以前の質問から生まれました。ほとんどのコードは、Delphi の以降のバージョンでおそらく機能する、提案された回答からのものです。D2006 では、不透明度の全範囲を取得できず、画像の透明部分が白く表示されます。
画像はhttp://upload.wikimedia.org/wikipedia/commons/6/61/Icon_attention_s.pngからのものです。
DFM が保存された後、画像がそのまま残らないため、実行時に PNGImageCollection から TImage に読み込まれます。動作を説明する目的では、おそらく PNGImageCollection は必要なく、設計時に PNG 画像を TImage にロードし、IDE から実行するだけで済みます。
フォームには 4 つのボタンがあり、それぞれが異なる不透明度の値を設定します。不透明度 = 0 で問題なく動作します (ペイントボックスの画像は表示されません。不透明度 = 16 は白い背景を除いて問題ないように見えます。不透明度 = 64、255 も同様です。不透明度は約 10% で飽和しているようです。
何が起きているかについてのアイデアはありますか?
unit Unit18;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, pngimage, StdCtrls, Spin, PngImageList;
type
TAlphaBlendForm = class(TForm)
PaintBox1: TPaintBox;
Image1: TImage;
PngImageCollection1: TPngImageCollection;
Button1: TButton;
Button2: TButton;
Button3: TButton;
Button4: TButton;
procedure PaintBox1Paint(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure Button4Click(Sender: TObject);
private
FOpacity : Integer ;
FBitmap : TBitmap ;
{ Private declarations }
public
{ Public declarations }
end;
var
AlphaBlendForm: TAlphaBlendForm;
implementation
{$R *.dfm}
procedure TAlphaBlendForm.Button1Click(Sender: TObject);
begin
FOpacity:= 0 ;
PaintBox1.Invalidate;
end;
procedure TAlphaBlendForm.Button2Click(Sender: TObject);
begin
FOpacity:= 16 ;
PaintBox1.Invalidate;
end;
procedure TAlphaBlendForm.Button3Click(Sender: TObject);
begin
FOpacity:= 64 ;
PaintBox1.Invalidate;
end;
procedure TAlphaBlendForm.Button4Click(Sender: TObject);
begin
FOpacity:= 255 ;
PaintBox1.Invalidate;
end;
procedure TAlphaBlendForm.FormCreate(Sender: TObject);
begin
Image1.Picture.Assign (PngImageCollection1.Items [0].PNGImage) ;
FBitmap := TBitmap.Create;
FBitmap.Assign(Image1.Picture.Graphic);//Image1 contains a transparent PNG
FBitmap.PixelFormat := pf32bit ;
PaintBox1.Width := FBitmap.Width;
PaintBox1.Height := FBitmap.Height;
end;
procedure TAlphaBlendForm.PaintBox1Paint(Sender: TObject);
var
fn: TBlendFunction;
begin
fn.BlendOp := AC_SRC_OVER;
fn.BlendFlags := 0;
fn.SourceConstantAlpha := FOpacity;
fn.AlphaFormat := AC_SRC_ALPHA;
Windows.AlphaBlend(
PaintBox1.Canvas.Handle,
0,
0,
PaintBox1.Width,
PaintBox1.Height,
FBitmap.Canvas.Handle,
0,
0,
FBitmap.Width,
FBitmap.Height,
fn
);
end;
end.
** このコード (graphics32 TImage32 を使用) はほぼ動作します **
unit Unit18;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, pngimage, StdCtrls, Spin, PngImageList, GR32_Image;
type
TAlphaBlendForm = class(TForm)
Button1: TButton;
Button2: TButton;
Button3: TButton;
Button4: TButton;
Image321: TImage32;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure Button4Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
AlphaBlendForm: TAlphaBlendForm;
implementation
{$R *.dfm}
procedure TAlphaBlendForm.Button1Click(Sender: TObject);
begin
Image321.Bitmap.MasterAlpha := 0 ;
end;
procedure TAlphaBlendForm.Button2Click(Sender: TObject);
begin
Image321.Bitmap.MasterAlpha := 16 ;
end;
procedure TAlphaBlendForm.Button3Click(Sender: TObject);
begin
Image321.Bitmap.MasterAlpha := 64 ;
end;
procedure TAlphaBlendForm.Button4Click(Sender: TObject);
begin
Image321.Bitmap.MasterAlpha := 255 ;
end;
end.
** (UPDATE) このコード (graphics32 TImage32 を使用) は動作します **
次のコードは、実行時に PNG 画像を Graphics32.TImage32 に割り当てることに成功しています。アルファ チャネルを持つ PNG 画像は、設計時に TPNGImageCollection (任意のサイズの画像を混在させることができるため、非常に便利なコンポーネント) に読み込まれます。フォームの作成時にストリームに書き込まれ、 LoadPNGintoBitmap32 を使用してストリームから Image32 に読み込まれます。これが完了したら、TImage32.Bitmap.MasterAlpha に割り当てることで不透明度を制御できます。OnPaint ハンドラを気にする必要はありません。
procedure TAlphaBlendForm.FormCreate(Sender: TObject);
var
FStream : TMemoryStream ;
AlphaChannelUsed : boolean ;
begin
FStream := TMemoryStream.Create ;
try
PngImageCollection1.Items [0].PngImage.SaveToStream (FStream) ;
FStream.Position := 0 ;
LoadPNGintoBitmap32 (Image321.Bitmap, FStream, AlphaChannelUsed) ;
finally
FStream.Free ;
end;
end ;