syghの新フラグメント置き場

プログラミングTipsやコード断片の保管場所です。お絵描きもときどき載せます。

GDI+でアンチエイリアスEMFを作成

(これは2012-09-08に書いた故OCNブログの記事を移植したものです)

MFCのCMetaFileDCでWindows拡張メタファイル(EMF)を作成した場合、たとえGdiplus::Graphics::FromHDC()でバインドしたGDI+グラフィックスを使ってそのメタファイルを描画してもアンチエイリアスがかかりません。

アンチエイリアスのかかったWindows拡張メタファイル(EMF+)を作りたい場合、Gdiplus::Metafileを使う必要があります。Gdiplus::EmfTypeEmfPlusOnlyもしくはGdiplus::EmfTypeEmfPlusDualオプションを付けてストリーム上に作成したMetafileに、Graphics::FromImage()でバインドしたGDI+グラフィックスを使って描画すればOK。Metafileコンストラクタの第1引数にはファイルパス文字列のほかにCOMのIStreamを渡せるオーバーロードがあるので、ファイルストリーム上だけでなくメモリーストリーム上にメタファイルを作成することもできます。

なお、Graphics::EnumerateMetafile()を使うことで、アンチエイリアスのかかっていないEMFファイルを開き、アンチエイリアスのかかったEMF+ファイルに変換して書き出す、ということもできます。

「EnumerateMetafile()を使ってEMFをEMF+に変換するにはどうすればいいの?」という質問をいただいたので、参考までに簡単なサンプルを下記にアップロードしておきました。ただし、色の半透明化として使われているタイル パターン ブラシまわりなど、対応が不十分だったり、完全に未対応だったりするEMRコマンドがたくさんあります。ソースコードの2次利用はご自由に、ただし自己責任でどうぞ。

MetafileConvertTest.zip

なお、EnumerateMetafile()で列挙されるレコード(コマンド+付随データ)をそのままMetafile::PlayRecord()に渡しても、アンチエイリアスの効いたEMF+(GDI+コマンド)に自動変換してくれるようなことはありません。EMRレコードの意味的な解析が必要になります。また、EMRコマンド構造体が必要になるので、.NETよりネイティブC++のほうが変換処理を書きやすいはずです。変換プログラムとしては、コマンドラインのフリーウェア「EMF to EMF+ Converter」がありますが、こちらはソースコードが公開されてないようです。ちなみにGDIのコマンドと従来のEMFファイルのコマンドは1対1で対応するため、EMFファイルからGDIコマンドを復元するのは容易ですが、GDI+のDrawRectangle()やDrawEllipse()で描画した図形を、従来のEMF Onlyメタファイル形式で保存すると、PolygonやBezierで記録されてしまいます(1対1で対応しない、つまり情報が欠落してしまう不可逆変換)。なので、EMF OnlyのGDIコマンドを、GDI+のDrawPolygon()やDrawBeziers()で変換すること自体はできますが、元となる描画に使用されたGDI+コマンドを復元するのは困難となります。個人的には、EMFからEMF+に変換するよりは、メタファイル生成プログラムを書き直して最初からEMF+として出力するように修正することをお勧めします。

■ EMF+ (オリジナル)
https://sygh-jp.github.io/content_hosting/my_program_ss/emf_plus_test.png

■ EMF (ダウンコンバート、アンチエイリアスの欠落と半透明効果のタイル化)
https://sygh-jp.github.io/content_hosting/my_program_ss/emf_only_test.png

■ EMF+ (アップコンバート、ただし半透明効果の復元には未対応)
https://sygh-jp.github.io/content_hosting/my_program_ss/emf_plus_convert_output_test.png

ネイティブXPSドキュメントAPIが使えるWindows 7(とVista SP2 + Platform Update)以降では、メタファイルの存在意義が小さくなりつつありますし、WPFではWindowsメタファイル形式がそもそもサポートされていません。が、WordやExcelに直接貼り付けられるEMFは、Windows上でのベクトル画像フォーマットとしてまだ利用価値がありそうです。

ちなみにWin7からVistaにPlatform Updateの形でバックポートされたネイティブAPIは、XPSのほかにもかなりたくさんあります。自分が知っている範囲でも、リボン フレームワーク、Direct2D/DirectWrite、DirectX 11、Windows Animation Manager (WAM)、など。全部COMです。WAMはゲーム開発にも使えそうです。

Windows 8(とWin7 SP1 + Platform Update)以降に搭載されている新しいDirect2D 1.1は、印刷処理やメタファイルへの出力もサポートするらしいんですが、メタファイルってのはどういうフォーマットになるんでしょうか? EMF+をサポートするわけじゃないと思うけど……やっぱりXPSなんでしょうか? いずれ試してみたいと思います。