如果使用Image.Save方法将图像保存到一个EMF/WMF,你会得到一个异常(http://msdn.microsoft.com/en-us/library/ktx83wah.aspx)GDI +/C#:如何将图像保存为EMF?
有另一种方法将图像保存到一个EMF/WMF? 有没有可用的编码器?
如果使用Image.Save方法将图像保存到一个EMF/WMF,你会得到一个异常(http://msdn.microsoft.com/en-us/library/ktx83wah.aspx)GDI +/C#:如何将图像保存为EMF?
有另一种方法将图像保存到一个EMF/WMF? 有没有可用的编码器?
元文件是一个记录GDI操作序列的文件。它具有可伸缩性,因为捕捉了生成图片的原始操作序列,因此可以缩放记录的坐标。
我认为,在.NET中,您应该创建一个Metafile
对象,使用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.
我想这就是我在解决问题时的方法。
虽然它看起来应该工作,但我发现它输出的是元文件的栅格化版本,而不是矢量GDI记录。此外,您需要调用DeleteEnhMetaFile(h)并注意调用GetHenhMetaFile()会将图元文件对象置于无效状态。 – 2009-09-14 20:51:51
完成后,您需要调用DeleteEnhMetafile(h),并通过GetHenhMetafile调用将Metafile对象置于无效状态。 如果Metafile是一个基于栅格的图元文件,这将给你一个基于.emf磁盘上的光栅。如果它是一个基于矢量的图元文件,那么你将在磁盘上得到一个基于.emf的矢量。通常调用metafile.Save(“文件名”,System.Drawing.Imaging.ImageFormat.Emf)会给你一个.png文件。 – 2009-09-14 20:59:01
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
第一个进口用于在第一次调用得到电动势的大小。第二次导入得到实际的位。 或者你可以使用:
Dim h As IntPtr = mf.GetHenhmetafile()
CopyEnhMetaFileW(h, FileName)
这将emf位直接复制到指定的文件。
Image
是一个抽象类:你想要做什么取决于你是在处理一个Metafile
还是一个Bitmap
。
使用GDI +创建图像并将其保存为EMF很简单,Metafile
。每迈克的post:
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文件,但请注意,这不会神奇地将您的栅格数据转换为矢量图像。
很好,我完全忽略了这种基于Metafile构造函数创建元文件的简单方法。我必须承认,必须通过一个原始的HDC有点混乱,但它仍然有效。 – 2009-09-01 03:22:00
我正在寻找一种方法来将Metafile对象中的GDI指令保存为EMF文件。韩的文章帮助我解决了这个问题。这是在我加入SOF之前。谢谢你,韩。这是什么I tried。
[DllImport("gdi32.dll")] static extern IntPtr CopyEnhMetaFile( // Copy EMF to file IntPtr hemfSrc, // Handle to EMF String lpszFile // File ); [DllImport("gdi32.dll")] static extern int DeleteEnhMetaFile( // Delete EMF IntPtr hemf // Handle to EMF ); // Code that creates the metafile // Metafile metafile = ... // Get a handle to the metafile IntPtr iptrMetafileHandle = metafile.GetHenhmetafile(); // Export metafile to an image file CopyEnhMetaFile( iptrMetafileHandle, "image.emf"); // Delete the metafile from memory DeleteEnhMetaFile(iptrMetafileHandle);
它看起来对矢量与位图有很多混淆。该线程中的所有代码都会生成位图(非矢量)文件 - 它不保留向量GDI调用。为了证明这一点,请下载“EMF Parser”工具并检查输出文件:http://downloads.zdnet.com/abstract.aspx?docid=749645。
这个问题已经引起许多开发人员考虑到痛苦。如果微软能够解决这个问题并且正确地支持他们自己的EMF格式,那肯定会很好。
你错了。例如,user120789的答案会创建矢量图形。 – reinierpost 2013-05-14 14:35:41
您还需要关闭CopyEnhMetaFile
处理程序:
IntPtr ptr2 = CopyEnhMetaFile(iptrMetafileHandle, "image.emf");
DeleteEnhMetaFile(ptr2);
// Delete the metafile from memory
DeleteEnhMetaFile(iptrMetafileHandle);
否则,你无法删除该文件,因为它仍然使用的过程。
我建议避免这样的extern和非托管cruft在一个托管的.NET应用程序。 相反,我建议更多的东西有点像在这个线程给出的托管解决方案:
Convert an image into WMF with .NET?
附:我正在回答这个老话题,因为这是我找到的最好答案,但最终开发了一个托管解决方案,然后将我带到上面的链接。所以,为了节省那些时间,我想我会指出这一个。
请注意,您需要为``Metafile`使用`System.Drawing.Imaging`并为'MemoryStream`使用`System.IO`。 – 2012-07-24 09:24:48