gpt4 book ai didi

delphi - 从资源文件加载的透明 PNG 图像,使用 Grapics32 调整大小并在 Canvas 上绘制

转载 作者:行者123 更新时间:2023-12-03 15:34:34 28 4
gpt4 key购买 nike

我需要一点帮助...

我的应用程序资源中有一个透明的 PNG 图像。到目前为止,我将其加载到 TPngImage 中,并使用 Canvas.Draw(X, Y, PngImage); 将其绘制在屏幕上。而且是透明绘制的。现在,我将应用程序更新为 DpiAware,并且需要缩放所有图像。我需要一个高质量的重采样器,因此我选择使用 Graphics32。我设法进行了重新采样,但我不知道如何保持透明度...我尝试了所有我能想到的...以下代码的结果是在透明区域中用黑色绘制的图像.. .

Foto32, Buff: TBitmap32;
FotoPng: TPngImage;

constructor TForm.Create(AOwner: TComponent);
const BkgHeight = 380;
var Res: TKernelResampler;
SRect, DRect: TRect;
ImgWidth: Integer;
begin
inherited;
Buff:= TBitmap32.Create;
Res:= TKernelResampler.Create;
Res.Kernel:= TLanczosKernel.Create;

FotoPng:= TPngImage.Create;
FotoPng.Transparent:= True;
FotoPng.TransparentColor:= clBlack;
FotoPng.LoadFromResourceName(HInstance, 'BKG_FOTO');
Foto32:= TBitmap32.Create;
Foto32.DrawMode:= dmBlend;
Foto32.CombineMode:= cmMerge;
Foto32.OuterColor:= clBlack;
Foto32.Canvas.Brush.Style:= bsClear;
Foto32.SetSize(FotoPng.Width, FotoPng.Height);
FotoPng.Draw(Foto32.Canvas, Rect(0, 0, FotoPng.Width, FotoPng.Height));

ImgWidth:= Round(Real(Foto32.Width / Foto32.Height) * BkgHeight);
SRect:= Rect(0, 0, Foto32.Width, Foto32.Height);
Buff.DrawMode:= dmBlend;
Buff.CombineMode:= cmMerge;
Buff.OuterColor:= clBlack;
Buff.Canvas.Brush.Style:= bsClear;
Buff.SetSize(Scale(ImgWidth), Scale(BkgHeight));
DRect:= Rect(0, 0, Buff.Width, Buff.Height);
Res.Resample(Buff, DRect, DRect, Foto32, SRect, dmTransparent {dmBlend}, nil);
end;

procedure TForm.Paint;
begin
// ....
Buff.DrawTo(Canvas.Handle, X, Y);
end;

这是我编译成资源的透明 PNG 图像: https://postimg.cc/3yy3wrJB

我在这里找到了similar question ,但我不将图像与 TImage 一起使用,而是直接将其绘制在 Canvas 上。大卫在一个答案中说:

Anyway, if that is so, I would combine the transparency support of TImage with the re-sampling ability of TBitmap32 to build a solution that way. Keep the original image in a TBitmap32 instance. Whenever you need to load it into the TImage component, for example when re-sizing, use TBitmap32 to perform an in-memory re-size and load that re-sized image.

这正是我想要做的,但我不知道为什么透明度不起作用。有任何想法吗 ?

最佳答案

您的问题似乎是将缓冲区绘制到屏幕上的问题。 Bitmap32 使用 StretchDIBits 进行绘制,忽略 Alpha channel 。

您可以使用 AlphaBlend 函数来绘制图像:

procedure TForm1.FormPaint(Sender: TObject);
var
BF: TBlendFunction;
begin
BF.BlendOp := AC_SRC_OVER;
BF.BlendFlags := 0;
BF.SourceConstantAlpha := 255;
BF.AlphaFormat := AC_SRC_ALPHA;

Winapi.Windows.AlphaBlend(Canvas.Handle, 0, 0, Buff.Width, Buff.Height,
Buff.Canvas.Handle, 0, 0, Buff.Width, Buff.Height, BF);
end;

或者将 TBitmap32 转换为 Delphi TBitmap 并使用 VCL 进行绘制:

procedure TForm1.FormPaint(Sender: TObject);
var
Bmp: TBitmap;
I: Integer;
begin
Bmp := TBitmap.Create;
try
Bmp.PixelFormat := pf32bit;
Bmp.AlphaFormat := afDefined;
Bmp.SetSize(Buff.Width, Buff.Height);
for I := 0 to Buff.Height - 1 do
Move(Buff.ScanLine[I]^, Bmp.ScanLine[I]^, Buff.Width * 4);
Canvas.Draw(0, 0, Bmp);
finally
Bmp.Free;
end;
end;

关于delphi - 从资源文件加载的透明 PNG 图像,使用 Grapics32 调整大小并在 Canvas 上绘制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59904761/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com