GDI + / C#:如何将图像另存为EMF?
如果使用Image.Save方法将图像保存到EMF / WMF,则会出现异常(http://msdn.microsoft.com/zh-cn/library/ktx83wah.aspx)
还有另一种将图像保存到EMF / WMF的方法吗?
有没有可用的编码器?
解决方案
图元文件是记录GDI操作序列的文件。它是可伸缩的,因为捕获了生成图片的原始操作序列,因此可以缩放所记录的坐标。
我认为,在.NET中,我们应该创建一个"元文件"对象,使用" Graphics.FromImage"创建一个" Graphics"对象,然后执行绘制步骤。绘制时会自动更新文件。我们可以在Graphics.AddMetafileComment的文档中找到一个小示例。
如果我们真的想将位图存储在图元文件中,请执行以下步骤,然后使用" Graphics.DrawImage"绘制位图。但是,缩放后将使用StretchBlt
对其进行拉伸。
问题是:"还有另一种将图像保存到EMF / WMF的方法吗?"不是"什么是图元文件"或者"如何创建图元文件"或者"如何在图形中使用图元文件"。
我也在寻找"如何保存EMF / WMF"这个问题的答案
实际上,如果我们使用:
Graphics grfx = CreateGraphics(); MemoryStream ms = new MemoryStream(); IntPtr ipHdc = grfx.GetHdc(); Metafile mf = new Metafile(ms, ipHdc); grfx.ReleaseHdc(ipHdc); grfx.Dispose(); grfx = Graphics.FromImage(mf); grfx.FillEllipse(Brushes.Gray, 0, 0, 100, 100); grfx.DrawEllipse(Pens.Black, 0, 0, 100, 100); grfx.DrawArc(new Pen(Color.Red, 10), 20, 20, 60, 60, 30, 120); grfx.Dispose(); mf.Save(@"C:\file.emf", ImageFormat.Emf); mf.Save(@"C:\file.png", ImageFormat.Png);
在这两种情况下,图像均保存为png格式。这是我无法解决的问题:/
如果我没记错的话,可以使用Metafile.GetHenhmetafile(),API GetEnhMetaFileBits()和Stream.Write()的组合来完成,例如
[DllImport("gdi32")] static extern uint GetEnhMetaFileBits(IntPtr hemf, uint cbBuffer, byte[] lpbBuffer); IntPtr h = metafile.GetHenhMetafile(); int size = GetEnhMetaFileBits(h, 0, null); byte[] data = new byte[size]; GetEnhMetaFileBits(h, size, data); using (FileStream w = File.Create("out.emf")) { w.Write(data, 0, size); } // TODO: I don't remember whether the handle needs to be closed, but I guess not.
我认为这是解决问题时解决问题的方式。
erikkallen的答案是正确的。我从VB.NET尝试过此操作,不得不使用2种不同的DllImports使其起作用:
<System.Runtime.InteropServices.DllImportAttribute("gdi32.dll", EntryPoint:="GetEnhMetaFileBits")> _ Public Shared Function GetEnhMetaFileBits(<System.Runtime.InteropServices.InAttribute()> ByVal hEMF As System.IntPtr, ByVal nSize As UInteger, ByVal lpData As IntPtr) As UInteger End Function <System.Runtime.InteropServices.DllImportAttribute("gdi32.dll", EntryPoint:="GetEnhMetaFileBits")> _ Public Shared Function GetEnhMetaFileBits(<System.Runtime.InteropServices.InAttribute()> ByVal hEMF As System.IntPtr, ByVal nSize As UInteger, ByVal lpData() As Byte) As UInteger End Function
第一次导入用于第一次调用以获取emf大小。第二次导入以获取实际位。
或者,我们可以使用:
Dim h As IntPtr = mf.GetHenhmetafile() CopyEnhMetaFileW(h, FileName)
这会将emf位直接复制到命名文件中。
"图像"是一个抽象类:我们要做什么取决于我们要处理的是"图元文件"还是"位图"。
使用" Metafile",使用GDI +创建图像并将其另存为EMF很简单。根据迈克的帖子:
var path = @"c:\foo.emf" var g = CreateGraphics(); // get a graphics object from your form, or wherever var img = new Metafile(path, g.GetHdc()); // file is created here var ig = Graphics.FromImage(img); // call drawing methods on ig, causing writes to the file ig.Dispose(); img.Dispose(); g.ReleaseHdc(); g.Dispose();
这是我们大多数时候想要做的,因为这就是EMF的目的:以GDI +绘图命令的形式保存矢量图像。
我们可以使用上述方法并调用ig.DrawImage(your_bitmap)将Bitmap保存到EMF文件中,但是请注意,这不会将栅格数据秘密地转换为矢量图像。