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