Delphi 为什么';这段D2006代码是不是可以使PNG图像褪色?
这个问题源于前面的一个问题。大部分代码来自于建议的答案,这些答案可能在以后的Delphi版本中有效。在D2006中,我没有得到完整的不透明度范围,图像的透明部分显示为白色 图像来自。Delphi 为什么';这段D2006代码是不是可以使PNG图像褪色?,delphi,png,alphablending,delphi-2006,timage,Delphi,Png,Alphablending,Delphi 2006,Timage,这个问题源于前面的一个问题。大部分代码来自于建议的答案,这些答案可能在以后的Delphi版本中有效。在D2006中,我没有得到完整的不透明度范围,图像的透明部分显示为白色 图像来自。 它在运行时从PNGImageCollection加载到TImage中,因为我发现您必须这样做,因为保存DFM后图像不会保持完整。为了演示这种行为,您可能不需要PNGImageCollection,只需在设计时将PNG图像加载到TImage中,然后从IDE运行它即可 表单上有四个按钮-每个按钮设置不同的不透明度值。不
它在运行时从PNGImageCollection加载到TImage中,因为我发现您必须这样做,因为保存DFM后图像不会保持完整。为了演示这种行为,您可能不需要PNGImageCollection,只需在设计时将PNG图像加载到TImage中,然后从IDE运行它即可 表单上有四个按钮-每个按钮设置不同的不透明度值。不透明度=0可以正常工作(paintbox图像不可见,不透明度=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.
**此代码(使用图形32 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.
**(更新)此代码(使用图形32 TImage32)不起作用**
以下代码在运行时成功地将PNG图像分配给Graphics32.TImage32。带有alpha通道的PNG图像加载到TPNGImageCollection(非常有用的组件,因为它允许任意大小的图像混合)在设计时。在表单创建时,它被写入流,然后使用从流读取到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 ;
正如David对问题的评论,当您将图形分配给位图时,alpha通道信息丢失。因此,在分配后将像素格式设置为
pf32bit
没有任何意义,除了防止AlphaBlend
调用失败外,位图中没有每像素alpha
但是png对象知道如何在画布上绘制透明度信息。因此解决方案将涉及在位图画布上绘制而不是指定图形,然后,由于没有Alpha通道,从BLENDFUNCTION
中删除AC\u SRC\u Alpha
标志
以下是D2007上的工作代码:
procedure TAlphaBlendForm.FormCreate(Sender: TObject);
begin
Image1.Picture.LoadFromFile(
ExtractFilePath(Application.ExeName) + 'Icon_attention_s.png');
FBitmap := TBitmap.Create;
FBitmap.Width := Image1.Picture.Graphic.Width;
FBitmap.Height := Image1.Picture.Graphic.Height;
FBitmap.Canvas.Brush.Color := Color; // background color for the image
FBitmap.Canvas.FillRect(FBitmap.Canvas.ClipRect);
FBitmap.Canvas.Draw(0, 0, Image1.Picture.Graphic);
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 := 0;
Windows.AlphaBlend(
PaintBox1.Canvas.Handle,
0,
0,
PaintBox1.Width,
PaintBox1.Height,
FBitmap.Canvas.Handle,
0,
0,
FBitmap.Width,
FBitmap.Height,
fn
);
end;
或不使用中间TImage
:
procedure TAlphaBlendForm.FormCreate(Sender: TObject);
var
PNG: TPNGObject;
begin
PNG := TPNGObject.Create;
try
PNG.LoadFromFile(ExtractFilePath(Application.ExeName) + 'Icon_attention_s.png');
FBitmap := TBitmap.Create;
FBitmap.Width := PNG.Width;
FBitmap.Height := PNG.Height;
FBitmap.Canvas.Brush.Color := Color;
FBitmap.Canvas.FillRect(FBitmap.Canvas.ClipRect);
PNG.Draw(FBitmap.Canvas, FBitmap.Canvas.ClipRect);
PaintBox1.Width := FBitmap.Width;
PaintBox1.Height := FBitmap.Height;
finally
PNG.Free;
end;
end;
我认为透明度在调用TBitmap.Assign时丢失了。我正在研究如何修复这一问题,这将涉及直接操作Windows API函数。我使用的是D6的副本。实际上,在我在D6中运行的代码中,也使用Gustavo Daud的PNG单元,我认为透明度在PNG级别没有得到正确处理。我将现在尝试另一种方法,使用具有部分透明度的.ico文件,因为我确信它们工作正常!好吧,我放弃。我不相信这些旧版本的Delphi的Graphics.pas正确地支持部分透明度和alpha通道。如果你想用这些工具实现这一点,那么你需要做大量低级别的Win API工作。你的PNG ima据我所知,ge unit也不支持部分透明。我认为是时候升级到XE!+1了。我为旧Delphi提供的PNG代码不支持部分透明,因此avenue注定要失败。我真的很讨厌CodeGear接管此代码时所做的事——试图拒绝旧版本用户使用PNG的能力糟糕的公关@Sertac,@David谢谢你。我明天(凌晨3点)会在D2006下试一试.同时,我编辑了这个问题-使用TImage32似乎可行,除了当我在设计时将PNG加载到TImage32中时,我无法使alpha通道工作-图像的背景是黑色的,不是透明的。我可以通过将相同的图像加载到apha通道中使其工作,但我确实需要创建从图像中删除一个遮罩,这样图像的三角形部分可以有100%的不透明度。如何自动做到这一点?@用户放弃在设计时加载它。使用资源并在运行时执行。@用户注意,您可以向上投票,也可以接受!@Sertac derserves the rep!!;-)谢谢@David:)关于你的第一个评论,我从来不知道是这样的。如果有人需要,它有最新版本(支持部分透明)。