Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/google-maps/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi 从资源文件加载的透明PNG图像,使用Graphics32调整大小并在画布上绘制_Delphi_Resize_Transparency_Delphi 10.3 Rio_Graphics32 - Fatal编程技术网

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

Delphi 从资源文件加载的透明PNG图像,使用Graphics32调整大小并在画布上绘制,delphi,resize,transparency,delphi-10.3-rio,graphics32,Delphi,Resize,Transparency,Delphi 10.3 Rio,Graphics32,我需要一点帮助 我的应用程序资源中有一个透明的PNG图像。到目前为止,我一直在将它加载到TPngImage中,并使用Canvas.draw(X,Y,PngImage)在屏幕上绘制它。而且画得很透明。现在我将我的应用程序更新为DpiAware,我需要缩放所有图像。我需要一个高质量的重采样器,我选择使用图形32。我设法做了重采样,但我不知道如何保持透明度。。。我尝试了所有我能想到的。。。下面代码的结果是在透明区域中以黑色绘制的图像 Foto32, Buff: TBitmap32; FotoPng:

我需要一点帮助

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

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图像:

我在这里找到了一个,但我没有使用带有
TImage
的图像,而是直接在画布上绘制。在单一答案中,大卫说:

无论如何,如果是这样的话,我会结合 使用TBitmap32的重新采样功能构建解决方案 那样。将原始图像保留在TBitmap32实例中。无论何时 您需要将其加载到TImage组件中,例如 重新调整大小,使用TBitmap32执行内存中的重新调整大小并加载 重新调整图像大小


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

您的问题似乎是将缓冲区绘制到屏幕上的问题。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, 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;

你能附上一张预期情况和当前问题的图片吗?。我的意思是,如果画布上的图像背景很简单(纯色单色),那么为什么不先填充FOTO32背景,然后在其上绘制FOTOPNG,然后绘制到画布上?画布的背景不是纯色,它有其他图形。
FOTOPNG.draw(Foto32.Canvas,…
->一旦绘制png,它就结束了。您可以透明地绘制,但透明度信息丢失了,绘制不会将alpha通道传输到目标。您需要重新对png本身进行采样。请参见。@SertacAkyuz我使用了该代码,我得到了异常“仅支持颜色\RGBALPHA和颜色\RGB格式”…因为我的png图像太大了,我不得不用“pngquant”对其进行压缩::(能否将
pngquant
解压为内存中的正常png?
Bmp.AlphaFormat:=afDefined;
是关键!:)坦克!