Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/24.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 如何在TMetaFileCanvas上透明地绘制PNG_Delphi_Png_Metafile - Fatal编程技术网

Delphi 如何在TMetaFileCanvas上透明地绘制PNG

Delphi 如何在TMetaFileCanvas上透明地绘制PNG,delphi,png,metafile,Delphi,Png,Metafile,我需要在MetaFileCanvas上透明地绘制PNG。当我绘制位图(在屏幕上显示时使用位图)时,这可以很好地工作,但打印时需要一个图元文件。我怎样才能做到这一点 下面是一些演示问题的代码。将附加的PNG放在某个地方,并更新代码中的路径 procedure TForm1.Test; var vPNG : TPNGImage; vBMP : TBitmap; vMeta : TMetafile; vMetaCanvas : TMetafileCanvas; LDC : HDC

我需要在MetaFileCanvas上透明地绘制PNG。当我绘制位图(在屏幕上显示时使用位图)时,这可以很好地工作,但打印时需要一个图元文件。我怎样才能做到这一点

下面是一些演示问题的代码。将附加的PNG放在某个地方,并更新代码中的路径

procedure TForm1.Test;
var
  vPNG : TPNGImage;

  vBMP : TBitmap;
  vMeta : TMetafile;
  vMetaCanvas : TMetafileCanvas;
  LDC : HDC;
begin
  vPNG := TPNGImage.Create;
  try
    vPNG.LoadFromFile('c:\temp\pic\pic.png'); 

    //1. Draw to bitmap. Draw stuff behind PNG to demonstrate transparency
    vBMP := TBitmap.Create;
    try
      vBMP.SetSize(vPNG.Width + 20,vPNG.Height + 20);
      vBMP.Canvas.Pen.Color := clLime;
      vBMP.Canvas.Pen.Width := 5;
      vBMP.Canvas.MoveTo(0,0);
      vBMP.Canvas.LineTo(vBMP.Width,vBMP.Height);
      vBMP.Canvas.MoveTo(vBMP.Width,0);
      vBMP.Canvas.LineTo(0,vBMP.Height);
      vBMP.Canvas.Draw(10,10,vPNG);  //This is drawn correctly and transparently

      Canvas.Draw(10,10,vBMP); //Draw to demo form
    finally
      vBMP.Free;
    end;

    //2. Draw to metafile
    vMeta := TMetaFile.Create;
    try
      LDC := GetDC(0);
      vMetaCanvas := TMetafileCanvas.Create(vMeta,LDC);
      try
        vMetaCanvas.Pen.Color := clLime;
        vMetaCanvas.Pen.Width := 5;
        vMetaCanvas.MoveTo(0,0);
        vMetaCanvas.LineTo(vPNG.Width+20,vPNG.Height+20);
        vMetaCanvas.MoveTo(vPNG.Width+20,0);
        vMetaCanvas.LineTo(0,vPNG.Height+20);

        vMetaCanvas.Draw(10,10,vPNG); //Not correct. Can't see the green line
      finally
        vMetaCanvas.Free;
      end;

      //Demonstrate that resizing works fine:
      Canvas.Draw(10,130,vMeta);
      vMeta.MMWidth := vMeta.MMWidth * 2;
      Canvas.Draw(150,130,vMeta);
      vMeta.MMHeight := vMeta.MMHeight * 2;
      Canvas.Draw(400,130,vMeta);
    finally
      vMeta.Free;
      ReleaseDC(0,LDC);
    end;
  finally
    vPNG.Free;
  end;
end;

实现这一点的唯一方法可能是使用()windows函数。将PNG转换为32位RGBA文件时。您需要做的是:

  • 将PNG加载到32位BMP中

  • 将RGB值和位图中的值预乘(是AlphaBlend调用的先决条件)

  • 调用Alphablend,源HDC作为预乘位图的Canvas.Handle,目标句柄作为元文件画布句柄

    BF.BlendOp             := AC_SRC_OVER;
    BF.BlendFlags          := 0;
    BF.SourceConstantAlpha := 255;
    BF.AlphaFormat         := AC_SRC_ALPHA;
    AlphaBlend( Bitmap.Canvas.Handle, X, Y, BM.Width, BM.Height, BM.Canvas.Handle, 0, 0, BM.Width, BM.Height, BF );
    

  • 我认为您可以简单地使用函数

    +1来出色地表示问题。pngimage必须从目标设备上下文中读取,才能透明地绘制源设备上下文中的内容。元文件画布不是实际的绘图表面,它表示可播放的记录。您无法从元文件画布读取像素值,例如“像素[x,y]将返回“-1”@塞塔克:我担心我会得到这样的回答。这意味着它无法完成,我们必须在程序中做很多更改:-/啊,好吧。谢谢:-)跳过元文件。。您可以始终打印位图图像,而不是图元文件。@PA:是的,我们可能不得不这样做,但我希望不会。太多的未知数,主要与缩放有关。(生成的图元文件用于报告中,我们不知道它是填充了整个页面还是只填充了一小部分)
    BF.BlendOp             := AC_SRC_OVER;
    BF.BlendFlags          := 0;
    BF.SourceConstantAlpha := 255;
    BF.AlphaFormat         := AC_SRC_ALPHA;
    AlphaBlend( Bitmap.Canvas.Handle, X, Y, BM.Width, BM.Height, BM.Canvas.Handle, 0, 0, BM.Width, BM.Height, BF );