C# WPFのImageをFormで使う 〜パフォーマンス比較〜
2013年2月 C#のForm上でWPFを使って画像処理(変形描画)を高速にやれました、というお話。 テストアプリとソースを公開しますので、興味があったら試してみてください。 |
FormとWPF | |
Windowsのスタンドアローンのアプリでベースとなる部品は、現在のところFormです。Windows8からタッチパネル操作が浸透し始め(?)、画面上の見た目や操作方法に重点が置かれたアプリ開発の動きがあります。そのようなアプリにはWPFが向いているとされています。presentationというくらいですから。
|
WPFの部品をForm内に持ってくる | |||||||||||||||
Formベースのアプリで画像処理に使われる技術は「GDI+」です。回転/拡大縮小といった変形はピクセル操作です。一方、WPFの画像処理技術はハードウェア(GPU)の助けを借りたベクター操作です。GDI+に比べて高速です。 デジカメで撮影したJPEG画像をスライドショーで閲覧するアプリを、Formベースで作るとします。画像はPictureBoxに表示します。PictureBoxには縦横比を保って拡大縮小表示する機能があるので助かります。しかし次の問題もあります。 (1) 画素の補間方法がバイリニア。画質が悪い。 (2) 縦横サイズが大きい画像ほど処理が遅い。 このうち(1)はPictureBoxのOnPaintメソッドをオーバーライドして解決できます。より高画質が指定できます。(2)はピクセル操作の宿命です。どうにもなりません。 ここで、「アプリ全体はFormベースでいいんだけど、画像変形だけWPF使えないかなー」と考えるわけです。 FormにはElementHostという部品があります。WPFの部品をFormにはめ込むための抜き窓です(HTMLで言ったらIFRAME要素みたいな)。ElementHostを介して、WPFのImageをFormに持ってくることができます。 WPFのImageはFormのPictureBoxに似た部品です。画像を高速に回転/拡大縮小して表示することができます。 これでPictureBoxの問題(2)は解決します。※PictureBoxを使わないことで解決なわけですが。
|
速さ比較/結果 | ||
FormのPictureBoxとWPFのImageで表示パフォーマンスを比較しました。任意の縦横サイズのJPEG画像700枚程度を順次読み込み、縦横比を保ったまま256x256ドットの枠内にピッタリ表示します。 PictureBoxの補間方法はInterpolationMode.HighQualityBicubic(事前処理付きバイキュービック)。Imageの補間方法はBitmapScalingMode.Fant。Fantは若干ぼやけた画質です。InterpolationMode.HighQualityBilinear(ないしBilinear)と同等の画質と思われます。※256x256ドットのサイズで比較して同程度のぼやけ具合に見えました。 テスト1: Core2Duo E6320 1.86GHz で実行。73秒:27秒。 テスト2: Atom N270 1.6GHz で実行。253秒:100秒。 結果。PictureBoxに比べてImageは2.5倍速いです。 1回目の実行は公平な比較ができません。左側計測のときファイルはHDDから読み込まれ、右側のときOSのキャッシュから読み込まれます。2回目以降の実行では左右共にキャッシュから読み込まれるので公平な比較になります。 なお、このドリンクの写真に意味はありません。たまたま最後に読み込まれたのがこの画像ということであり、宣伝ではありません。また、この画像を734回読み込んだわけではありません。
ElementHostの派生クラスを作り、外部からImageとBitmapImageを意識せず使えるようにしています。 Formベースのコントロールから派生したクラスは、他の部品同様にフォームデザイナ上からグラフィカルな操作で貼り付けることができます。また同様にプロパティの設定もできます。デフォルトの(引数なしの)コンストラクタを呼び出すところまでコードが自動生成されます。※その場合、下記ソースのコンストラクタの記述はあまり意味がない。 |
WPF Image サンプルアプリ | ||
比較テストよりもう少し実用性のあるアプリを作りました。ElementHost(の派生クラス)を実際にアプリ内でどう使うかという例です。WPFのImageに対する回転、反転、拡大縮小、移動操作の作り方の参考にもなると思います。 画像を読み込んだところ(元の状態)。 回転、反転、移動、縮小したところ。
|
◆ ◆ ◆ |
この記事を書いた本当の理由は「SyntaxHighlighterを使ってみたかったから」です。 広告自動挿入の関係か、iframeの水平スクロールバーの場所が変ですね。 |
(C) 『昼夜逆転』工作室 | [トップページへ戻る] |