情况是我有一个打印机EMF文件。我想在将数据发送到打印机之前覆盖一些数据。打印机文件为300dpi。保持相同的打印质量非常重要。
我正在使用此代码转换emf文件...
b:=TBitmap.create;
MyMetaFile.LoadFromFile(emf);
MyCanvas:= TMetafileCanvas.Create(MyMetaFile, 0);
try
Width:=MyMetaFile.Width;
Height:=MyMetaFile.Height;
b.width:=width;
b.height:=height;
b.Canvas.Draw(0, 0, MyMetaFile);
b.SaveToFile('c:\emftest.bmp');
除了你只得到emf文件的左上角之外,这种作品。如果你在windows中查看EMF文件的属性,它会显示2551x3301。但这里的宽度和高度设置为613x792。如果我用这些值覆盖b.width和b.height就可以了,但我显然不想这样做。 EMF文件为300dpi,屏幕dpi约为100,但错误是4.16。知道这里发生了什么吗?
由于 特里
答案 0 :(得分:2)
您必须在此处使用StrechDraw
而不是Draw
才能将内容扩展到预期的位图大小。
例如:
function MetafileToBitmap(Source: TMetafile; ScaleX,ScaleY: integer): TBitmap;
var R: TRect;
begin
result := nil;
if Source=nil then // self=nil is OK below
Exit;
R.Left := 0;
R.Right := (Source.Width*ScaleX)div 100;
R.Top := 0;
R.Bottom := (Source.Height*ScaleY)div 100;
result := TBitmap.Create;
result.Width := R.Right;
result.Height := R.Bottom;
Dec(R.Right); // Metafile rect includes right and bottom coords
Dec(R.Bottom);
PlayEnhMetaFile(Result.Canvas.Handle,Source.Handle,R);
end;
如果您想使用GDI +进行抗锯齿绘制,则需要枚举图元文件内容,然后使用our Open Source SynGdiPlus unit进行渲染:
function LoadFrom(const MetaFile: TMetaFile): TBitmap;
答案 1 :(得分:1)
(感谢Arnaud的评论。)
使用matafiles时,除非使用Windows GDI方法渲染(或播放)矢量内容,否则只有在加载文件时才会呈现位图数据。我使用第三方库(GDI +)为我做的工作。每当我处理图像时,我也会使用Graphics32。
作者的网站似乎不再有源代码了。但是,我通过搜索gdipobj.pas
找到了here。我也在code.google.com
上找到了它(包含在几个项目like this one中)。
Graphics32的源代码位于SourceForge here上。 SVN命令是:
svn co https://graphics32.svn.sourceforge.net/svnroot/graphics32/trunk graphics32
花了一段时间才弄清楚如何正确渲染元文件,大小合适等等。这是我使用的功能。
uses
GR32, GDIPOBJ, ActiveX;
procedure RenderWMF(var WMF: TMemoryStream; OutputBitmap: TBitmap32; const ScreenResolution: Integer = 96);
var
gph: TGPGraphics;
img: TGPImage;
bmap: TBitmap;
ms: IStream;
pLi: PLongint;
iPos: Int64;
tmpms: TMemoryStream;
begin
WMF.Position := 0;
ms := TStreamAdapter.Create(WMF, soReference);
try
pLi := nil;
ms.Write(WMF.Memory, WMF.Size, pLi);
bmap := TBitmap.Create;
try
ms.Seek(0, soFromBeginning, iPos);
img := TGPImage.Create(ms);
try
bmap.width := Trunc(img.GetWidth / img.GetHorizontalResolution * ScreenResolution + 0.5);
bmap.height := Trunc(img.GetHeight / img.GetVerticalResolution * ScreenResolution + 0.5);
gph := TGPGraphics.Create(bmap.Canvas.Handle);
try
gph.DrawImage(img, 0, 0, bmap.Width, bmap.Height);
tmpms := TMemoryStream.Create;
try
bmap.SaveToStream(tmpms);
tmpms.Position := 0;
OutputBitmap.LoadFromStream(tmpms);
finally
tmpms.Free;
end;
finally
gph.Free;
end;
finally
img.Free;
end;
finally
bmap.Free;
end;
finally
ms := nil;
end;
end;
我用这样的代码调用它:
var
bm32: TBitmap32;
wmf: TMemoryStream;
begin
bm32 := TBitmap32.Create;
try
wmf := TMemoryStream.Create;
try
wmf.LoadFromFile('metafile.emf');
RenderWMF(wmf, bm32, Screen.PixelsPerInch);
// Do something with 'bm32'
finally
wmf.Free;
end;
finally
bm32.Free;
end;
end;
我知道这个答案比how to properly set the canvas size
宽得多。我希望它有所帮助。