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

我需要一点帮助...

我的应用程序资源中有一个透明的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,FotoPng.Width,FotoPng.Height));

 ImgWidth:= Round(Real(Foto32.Width / Foto32.Height) * BkgHeight);
 SRect:= Rect(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,Buff.Width,Buff.Height);
 Res.Resample(Buff,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一起使用,而是直接将其绘制在画布上。在一个答案中,大卫说:

无论如何,如果是这样,我将结合以下方面的透明性支持: 具有TBitmap32重采样功能的TImage构建解决方案 那样。将原始图像保留在TBitmap32实例中。每当 您需要将其加载到TImage组件中,例如 重新调整大小,请使用TBitmap32执行内存调整大小并加载 调整尺寸的图片。

这正是我要执行的操作,但我不知道为什么透明胶片无法正常工作。有任何想法吗 ?

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

您的问题似乎与在屏幕上绘制缓冲区有关。 Bitmap32使用StretchDIBits进行绘制,而忽略了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,Buff.Width,Buff.Height,Buff.Canvas.Handle,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,Bmp);
  finally
    Bmp.Free;
  end;
end;
本文链接:https://www.f2er.com/2715418.html

大家都在问