如果使用Image.Save方法将图像保存到EMF / WMF,则会出现异常(http://msdn.microsoft.com/en-us/library/ktx83wah.aspx)
还有另一种方法可以将图像保存到EMF / WMF吗? 有没有可用的编码器?
答案 0 :(得分:21)
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 +绘图命令的形式保存矢量图像。
您可以使用上述方法将Bitmap
保存到EMF文件并调用ig.DrawImage(your_bitmap)
,但请注意,这并不会将您的栅格数据神奇地转换为矢量图像。
答案 1 :(得分:12)
如果我没记错的话,可以使用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.
我认为这就是我解决问题的方法。
答案 2 :(得分:3)
元文件是记录一系列GDI操作的文件。它是可缩放的,因为捕获了生成图像的原始操作序列,因此可以缩放记录的坐标。
我认为,在.NET中,您应该创建一个Metafile
对象,使用Graphics
创建一个Graphics.FromImage
对象,然后执行绘制步骤。在您绘制文件时,文件会自动更新。您可以在Graphics.AddMetafileComment的文档中找到一个小样本。
如果您确实想要在图元文件中存储位图,请使用这些步骤,然后使用Graphics.DrawImage
绘制位图。但是,当缩放时,它将使用StretchBlt
进行拉伸。
答案 3 :(得分:3)
问题是:“还有另一种方法可以将图像保存到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。这是我无法解决的问题:/
答案 4 :(得分:2)
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位直接复制到指定文件。
答案 5 :(得分:2)
您还需要关闭CopyEnhMetaFile
处理程序:
IntPtr ptr2 = CopyEnhMetaFile(iptrMetafileHandle, "image.emf");
DeleteEnhMetaFile(ptr2);
// Delete the metafile from memory
DeleteEnhMetaFile(iptrMetafileHandle);
否则,您无法删除该文件,因为该进程仍在使用该文件。
答案 6 :(得分:1)
我建议在托管的.NET应用程序中避免使用这种extern和非托管的版本。 相反,我建议的东西更像是这个线程中给出的托管解决方案:
Convert an image into WMF with .NET?
P.S。我正在回答这个旧线程,因为这是我找到的最佳答案,但后来最终开发了一个托管解决方案,然后引导我进入上面的链接。所以,为了节省其他时间,我想我会把这一点指向那个。
答案 7 :(得分:0)
我一直在寻找一种方法将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);
答案 8 :(得分:0)
看起来有很多关于矢量与位图的混淆。此线程中的所有代码都生成位图(非向量)文件 - 它不保留向量GDI调用。要自己证明这一点,请下载“EMF Parser”工具并检查输出文件:http://downloads.zdnet.com/abstract.aspx?docid=749645。
这个问题导致许多开发人员考虑痛苦。如果微软能解决这个问题并正确支持他们自己的EMF格式,那肯定会很好。