delphi – 如何在TMetaFileCanvas上透明地绘制PNG

前端之家收集整理的这篇文章主要介绍了delphi – 如何在TMetaFileCanvas上透明地绘制PNG前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我需要在MetaFileCanvas上透明地绘制PNG.当我绘制到位图(我在屏幕上显示时使用)时这很好用,但是对于打印我需要一个MetaFile.我怎样才能做到这一点?

这是一些演示此问题的代码.将附加的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,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,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,vMeta);
      vMeta.MMHeight := vMeta.MMHeight * 2;
      Canvas.Draw(400,vMeta);
    finally
      vMeta.Free;
      ReleaseDC(0,LDC);
    end;
  finally
    vPNG.Free;
  end;
end;

解决方法

可能唯一的方法是使用 AlphaBlend()窗口函数.将PNG转换为32位RGBA文件时.你需要做什么:

>将PNG加载到32位BMP中
>使用位图中的A值预乘RGB值(是AlphaBlend调用的先决条件)

for y := 0 to FHeight - 1 do begin
            Src  := BM.ScanLine[ y ];
            Dest := FBitmap.ScanLine[ y ];
            for x := 0 to FWidth - 1 do begin
              A := Src^; Inc( Src );
              Dest^ := MulDiv( Dest^,A,255 ); Inc( Dest );
              Dest^ := MulDiv( Dest^,255 ); Inc( Dest );
              Dest^ := A;                       Inc( Dest );
            end;
          end;

>调用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,BF );

猜你在找的Delphi相关文章