delphi - 从资源文件加载的透明 PNG 图像,使用 Grapics32 调整大小并在 Canvas 上绘制
问题描述
我需要一点帮助...
我的应用程序资源中有一个透明的 PNG 图像。到目前为止,我将它加载到 a 中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
我在这里找到了一个类似的问题,但我不使用带有 a 的图像TImage
,我直接在画布上绘制它。在唯一的答案中,大卫说:
无论如何,如果是这样,我会将 TImage 的透明度支持与 TBitmap32 的重新采样能力结合起来,以这种方式构建解决方案。将原始图像保存在 TBitmap32 实例中。每当您需要将其加载到 TImage 组件中时,例如在重新调整大小时,请使用 TBitmap32 执行内存中重新调整大小并加载该重新调整大小的图像。
这正是我想要做的,但我不知道为什么透明度不起作用。有任何想法吗 ?
解决方案
您的问题似乎是将缓冲区绘制到屏幕上的问题。Bitmap32StretchDIBits
用于忽略 Alpha 通道的绘画。
您可以使用该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;
推荐阅读
- php - 如何检查Mysql中具有逗号分隔值的列中的值?
- c# - 如何使用 .Net 内存分析器报告检查应用程序中是否存在内存泄漏?
- javascript - 在我选择你自己的冒险程序时输入错误意外结束
- flutter - Flutter 如何将 filePath 从 content://media/external/images/media/5275 转换为 /storage/emulated/0/DCIM/Camera/IMG_00124.jpg
- python - 你如何在 Pygame 中清除精灵?
- python - 从本地机器将 Python 连接到 AWS EC2 上的 kafka
- google-app-engine - Daphne on Google App Engine Flexible for Django Channels app: 502 Bad Gateway Error nginx
- amazon-elastic-beanstalk - Django,AWS EB 错误,您的 WSGIPath 引用了一个不存在的文件
- jenkins - Jenkins - java.lang.IllegalArgumentException:最后一个单元没有足够的有效位和 Gradle 错误:在根项目中找不到任务“null”
- android - 删除颤振中两列之间的空间