我需要在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中@H_403_11@>使用位图中的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 );