如果使用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