-->

GDI + / C#:如何将图像保存为EMF?(GDI+ / C#: How to save an

2019-07-21 03:58发布

如果您使用Image.Save方法来保存到一个EMF / WMF图像,你会得到一个异常( http://msdn.microsoft.com/en-us/library/ktx83wah.aspx )

有另一种方法将图像保存到一个EMF / WMF? 是否有任何编码器可用?

Answer 1:

Image是一个抽象类:你想要做什么取决于你是否正在处理一个MetafileBitmap

创建与GDI +图像并保存为一个EMF是用简单的Metafile 。 每Mike的帖子 :

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)但要注意,这并不神奇隐蔽栅格数据到矢量图像。



Answer 2:

如果我没有记错,它可以与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.

我觉得这是我如何解决这个问题时,我受够了。



Answer 3:

图元文件是一种记录GDI的一系列操作的文件。 因为生成该图像的操作的原始序列被捕获,因此,记录该坐标可以缩放它是可伸缩的。

我认为,在.NET中,你应该创建一个Metafile对象,创建一个Graphics对象使用Graphics.FromImage ,然后执行您的绘图步骤。 当你在失败中汲取的文件会自动更新。 你可以找到的文档中的一个小样本Graphics.AddMetafileComment 。

如果你真的要存储一个位图元文件,使用以下步骤,然后使用Graphics.DrawImage来绘制位图。 然而,当缩放将使用拉伸StretchBlt



Answer 4:

现在的问题是:“是否有另一种方式将图像保存到一个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格式。 这是我解决不了这个问题:/



Answer 5:

通过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)

这直接拷贝电动势位到指定的文件。



Answer 6:

您还需要关闭CopyEnhMetaFile处理程序:

IntPtr ptr2 = CopyEnhMetaFile(iptrMetafileHandle, "image.emf");
DeleteEnhMetaFile(ptr2);

// Delete the metafile from memory
DeleteEnhMetaFile(iptrMetafileHandle);

否则,你无法删除该文件,因为它仍然使用的过程。



Answer 7:

我会建议避免在托管的.NET应用程序这样的extern的和非托管的残余。 相反,我建议更多的东西有点像在这个线程给出的托管解决方案:

将图像转换成WMF使用.NET?

PS我回答这个古老的线程,因为这是最好的答案我已经找到了,但后来最终开发一个托管解决方案,然后带我到上面的链接。 因此,为了救别人那个时候,我想我会指出这一个那一个。



Answer 8:

我一直在寻找一种方式来在图元文件对象的GDI指令保存到一个EMF文件。 韩寒的后帮我解决这个问题。 这是在我加入特种部队。 谢谢你,啥。 以下是我试过 。

    [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);



Answer 9:

这似乎在说明了矢量与位图很大的混乱。 所有在此线程的代码生成位图(非向量)文件 - 它不保留矢量GDI调用。 为了证实这一点,下载“EMF分析器”工具,并检查输出文件: http://downloads.z​​dnet.com/abstract.aspx?docid=749645 。

这个问题已经引起许多开发商考虑的痛苦。 肯定会是很好,如果微软可以解决这个问题,并适当地支持他们自己的EMF格式。



文章来源: GDI+ / C#: How to save an image as EMF?
标签: c# gdi+ .emf