Delphi 在另一张图片上绘制 png 文件的一部分
Posted
技术标签:
【中文标题】Delphi 在另一张图片上绘制 png 文件的一部分【英文标题】:Delphi drawing part of png file on another image 【发布时间】:2021-05-17 03:26:39 【问题描述】:我正在使用此函数在特定位置的 TImage 上绘制 png:
procedure TForm1.PlacePNG(nam: string; px, py: Integer);
var
vPic: TPicture;
vSrc: TGraphic;
begin
vPic := TPicture.Create;
try
vPic.LoadFromFile(Nam);
vSrc := vPic.Graphic;
Image1.Canvas.Draw(px, py, vSrc);
finally
vPic.Free;
end;
end;
我的问题:使用 png 文件的 部分 做到这一点的最佳方法是什么,同时又不会失去其透明度?
【问题讨论】:
【参考方案1】:这是一个有趣的问题!
当然,绘制整个 PNG 很简单:
procedure TForm1.FormCreate(Sender: TObject);
var
bg, fg: TPngImage;
begin
bg := TPngImage.Create;
try
bg.LoadFromFile('K:\bg.png');
fg := TPngImage.Create;
try
fg.LoadFromFile('K:\fg.png');
Image1.Picture.Graphic := bg;
Image2.Picture.Graphic := fg;
fg.Draw(bg.Canvas, Rect(0, 0, fg.Width, fg.Height));
Image3.Picture.Graphic := bg;
finally
fg.Free;
end;
finally
bg.Free;
end;
end;
要仅绘制一部分,一个可能的解决方案是获取图像为 32-bpp RGBA 位图,然后使用 Windows API,具体而言,AlphaBlend
函数:
procedure TForm1.FormCreate(Sender: TObject);
var
bg, fg: TPngImage;
bgbm, fgbm: TBitmap;
BlendFunction: TBlendFunction;
begin
// Load background PNG
bg := TPngImage.Create;
try
bg.LoadFromFile('K:\bg.png');
// Load foreground PNG
fg := TPngImage.Create;
try
fg.LoadFromFile('K:\fg.png');
// Preview background and foreground
Image1.Picture.Graphic := bg;
Image2.Picture.Graphic := fg;
// Create background BMP
bgbm := TBitmap.Create;
try
bgbm.Assign(bg);
// Create foreground BMP
fgbm := TBitmap.Create;
try
fgbm.Assign(fg);
// Blend PART OF foreground BMP onto background BMP
BlendFunction.BlendOp := AC_SRC_OVER;
BlendFunction.BlendFlags := 0;
BlendFunction.SourceConstantAlpha := 255;
BlendFunction.AlphaFormat := AC_SRC_ALPHA;
if not Winapi.Windows.AlphaBlend(
bgbm.Canvas.Handle,
100,
100,
200,
200,
fgbm.Canvas.Handle,
200,
200,
200,
200,
BlendFunction
) then
RaiseLastOSError;
// Preview result
Image3.Picture.Graphic := bgbm;
finally
fgbm.Free;
end;
finally
bgbm.Free;
end;
finally
fg.Free;
end;
finally
bg.Free;
end;
end;
【讨论】:
它对我不起作用。系统错误。代码:87。参数不正确。 @OferLeshem:你确定你将 PNG 转换为位图吗?如果您尝试将AlphaBlend
与MyPng.Canvas.Handle
一起使用,您将收到该错误消息。
我目前没有安装 Delphi 来测试这个,但是 TCanvas.CopyRect()
在这种情况下可以工作吗?
@RemyLebeau:不,这不适用于 Alpha 通道。在内部,它使用StretchBlt
。
@AndreasRejbrand 我用 D7 将它调整为 PngImage 2.0's TPngObject
(使用 ZLib 1.2.8),还得到了 $00000087
,甚至确保两个矩形都在范围内并且不重叠。我猜我的TBitmap
版本太旧了,不支持/期待 RGBA。以上是关于Delphi 在另一张图片上绘制 png 文件的一部分的主要内容,如果未能解决你的问题,请参考以下文章