Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/neo4j/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
GDI+;/C#:如何将图像保存为EMF?_C#_Gdi+_.emf - Fatal编程技术网

GDI+;/C#:如何将图像保存为EMF?

GDI+;/C#:如何将图像保存为EMF?,c#,gdi+,.emf,C#,Gdi+,.emf,如果使用Image.Save方法将图像保存到EMF/WMF,则会出现异常() 是否有其他方法将图像保存到EMF/WMF? 有可用的编码器吗?元文件是记录GDI操作序列的文件。它是可缩放的,因为生成图片的原始操作序列被捕获,因此记录的坐标可以缩放 我认为,在.NET中,您应该创建一个图元文件对象,使用Graphics.FromImage创建一个图形对象,然后执行绘图步骤。文件在绘制时会自动更新。您可以在的文档中找到一个小示例 如果确实要在图元文件中存储位图,请使用以下步骤,然后使用Graphics

如果使用Image.Save方法将图像保存到EMF/WMF,则会出现异常()

是否有其他方法将图像保存到EMF/WMF?
有可用的编码器吗?

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

我认为,在.NET中,您应该创建一个
图元文件
对象,使用
Graphics.FromImage
创建一个
图形
对象,然后执行绘图步骤。文件在绘制时会自动更新。您可以在的文档中找到一个小示例

如果确实要在图元文件中存储位图,请使用以下步骤,然后使用
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.

我想这就是我解决问题的方法。

埃里克伦的答案是正确的。我在VB.NET中尝试了这一点,并使用了两种不同的DllImport使其工作:

<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位直接复制到指定的文件。

Image
是一个抽象类:您想做什么取决于您是处理
元文件还是处理
位图

使用GDI+创建图像并将其保存为EMF使用
图元文件
非常简单。根据迈克的:

这是您大多数时候想要做的,因为这就是EMF的用途:以GDI+绘图命令的形式保存矢量图像


通过使用上述方法并调用
ig.DrawImage(您的\u位图)
,您可以将
位图
保存到EMF文件中,但请注意,这不会神奇地将光栅数据转换为矢量图像。

我正在寻找将图元文件对象中的GDI指令保存到EMF文件的方法。韩的帖子帮助我解决了这个问题。这是在我加入SOF之前。谢谢你,韩。这是我想要的

[DllImport(“gdi32.dll”)] 静态外部IntPtr CopyEnhMetaFile(//将EMF复制到文件 IntPtr hemfSrc,//EMF的句柄 字符串lpszFile//File ); [DllImport(“gdi32.dll”)] 静态extern int DELETENHMETAFILE(//Delete EMF IntPtr hemf//EMF的句柄 ); //创建图元文件的代码 //图元文件图元文件=。。。 //获取元文件的句柄 IntPtr iptrMetafileHandle=metafile.GetHenhmetafile(); //将图元文件导出到图像文件 复制元文件( iptrMetafileHandle, “image.emf”); //从内存中删除图元文件 删除图元文件(iptrMetafileHandle);
矢量和位图之间似乎有很多混淆。此线程中的所有代码都生成位图(非矢量)文件-它不保留矢量GDI调用。要证明这一点,请下载“EMF解析器”工具并检查输出文件:


这个问题已经引起了许多开发者的痛苦考虑。如果Microsoft能够解决此问题并正确支持他们自己的EMF格式,那当然很好。

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

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

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

否则,您无法删除该文件,因为进程仍在使用该文件。

我建议在托管的.NET应用程序中避免此类外部和非托管的错误。 相反,我推荐一些更类似于本线程中给出的托管解决方案的解决方案:


另外,我之所以回答这个老问题,是因为这是我找到的最好的答案,但后来我开发了一个托管解决方案,这让我找到了上面的链接。因此,为了节省其他人的时间,我想我应该把这个指向那个。

太好了,我完全忽略了这个基于图元文件构造函数创建图元文件的简单方法。我必须承认,必须通过一个原始的HDC是有点混乱,但无论如何,它是工作。哇,这真的工作!太神了这应该被接受!虽然看起来这应该可以工作,但我发现它输出的是图元文件的光栅化版本,而不是矢量GDI记录。此外,您需要调用DeleteEnhMetaFile(h),并注意调用GetHenhMetaFile()会将图元文件对象置于无效状态。完成后,您需要调用DeleteEnhMetaFile(h),并且GetHenhMetaFile调用会将图元文件对象置于无效状态。如果图元文件是基于光栅的图元文件,则会在磁盘上显示基于光栅的.emf。如果它是一个基于向量的图元文件,那么您将在磁盘上获得一个基于向量的.emf。通常,调用metafile.Save(“filename”,System.Drawing.Imaging.ImageFormat.Emf)会得到一个.png文件。注意,对于
metafile
,需要使用
System.Drawing.Imaging
;对于
MemoryStream
,则需要使用
System.IO
。您错了。例如,user120789的答案创建了矢量图形。-1:正如“reinierpost”所提到的,user120789的解决方案创建了矢量图形感谢链接,我已经搜索解决方案将近一周了…如果有人有同样的问题,我必须对
CopyEnhMetaFile
返回的IntPtr指针使用
DeleteEnhMetaFile
,以确保保存的映像未被锁定。
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();
[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);
IntPtr ptr2 = CopyEnhMetaFile(iptrMetafileHandle, "image.emf");
DeleteEnhMetaFile(ptr2);

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