Image.Save メソッドを使用してイメージを EMF/WMF に保存すると、例外が発生します ( http://msdn.microsoft.com/en-us/library/ktx83wah.aspx ) 。
画像を EMF/WMF に保存する別の方法はありますか? 利用可能なエンコーダはありますか?
Image.Save メソッドを使用してイメージを EMF/WMF に保存すると、例外が発生します ( http://msdn.microsoft.com/en-us/library/ktx83wah.aspx ) 。
画像を EMF/WMF に保存する別の方法はありますか? 利用可能なエンコーダはありますか?
Image
は抽象クラスです。何をしたいかは、 を扱っているか を扱っているかによって異なりMetafile
ますBitmap
。
GDI+ で画像を作成し、EMF として保存するのは簡単Metafile
です。マイクの投稿ごと:
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)
、これは魔法のようにラスター データをベクター イメージに変換するわけではないことに注意してください。
私の記憶が正しければ、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 操作を記録するファイルです。画像を生成した操作の元のシーケンスがキャプチャされるため、スケーラブルです。したがって、記録された座標をスケーリングできます。
.NET では、オブジェクトを作成し、を使用してオブジェクトをMetafile
作成してから、描画手順を実行する必要があると思います。描画すると、ファイルは自動的に更新されます。Graphics.AddMetafileCommentのドキュメントに小さなサンプルがあります。Graphics
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 形式で保存されます。そして、これは私が解決できない問題です:/
CopyEnhMetaFile
また、ハンドラーを閉じる必要があります。
IntPtr ptr2 = CopyEnhMetaFile(iptrMetafileHandle, "image.emf");
DeleteEnhMetaFile(ptr2);
// Delete the metafile from memory
DeleteEnhMetaFile(iptrMetafileHandle);
そうしないと、ファイルがまだプロセスで使用されているため、ファイルを削除できません。
erikallen の答えは正しいです。私はこれを 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 サイズを取得するための最初の呼び出しに使用されます。実際のビットを取得するための 2 番目のインポート。または、次を使用できます。
Dim h As IntPtr = mf.GetHenhmetafile()
CopyEnhMetaFileW(h, FileName)
これにより、emf ビットが指定されたファイルに直接コピーされます。
Metafile オブジェクトの GDI 命令を EMF ファイルに保存する方法を探していました。ハンの投稿は、問題の解決に役立ちました。SOFに入る前の話です。ありがとう、ハン。これが私が試したものです。
[DllImport("gdi32.dll")] static extern IntPtr CopyEnhMetaFile( // EMF をファイルにコピー IntPtr hemfSrc, // EMF へのハンドル String lpszFile // ファイル ); [DllImport("gdi32.dll")] static extern int DeleteEnhMetaFile( // EMF を削除 IntPtr hemf // EMF へのハンドル ); // メタファイルを作成するコード // メタファイル metafile = ... // メタファイルへのハンドルを取得します IntPtr iptrMetafileHandle = metafile.GetHenhmetafile(); // メタファイルを画像ファイルにエクスポート CopyEnhMetaFile( iptrMetafileハンドル、 "image.emf"); // メモリからメタファイルを削除します DeleteEnhMetaFile(iptrMetafileHandle);
マネージド .NET アプリでは、このような extern やアンマネージド クラフトを避けることをお勧めします。代わりに、このスレッドで提供されているマネージド ソリューションにもう少し似たものをお勧めします。
PSこれは私が見つけた最良の答えだったので、この古いスレッドに答えていますが、最終的に管理されたソリューションを開発し、それが上記のリンクにつながりました。それで、その時他の人を救うために、私はこれをあの人に向けようと思いました.
ベクトルとビットマップについては多くの混乱があるようです。このスレッドのすべてのコードは、ビットマップ(非ベクター)ファイルを生成します-ベクターGDI呼び出しを保持しません。これを自分で証明するには、「EMFパーサー」ツールをダウンロードし、出力ファイルを調べます:http: //downloads.zdnet.com/abstract.aspx?docid=749645。
この問題により、多くの開発者が苦悩を検討しています。Microsoftがこれを修正し、独自のEMF形式を適切にサポートするのであれば確かにいいでしょう。