パフォーマンスの最適化 : 2D グラフィックスとイメージング
WPF には、アプリケーションの要件に合わせて最適化できる広範な 2D グラフィックス機能とイメージング機能が用意されています。 このトピックでは、この領域でのパフォーマンスの最適化に関する情報を提供します。
このトピックは、次のセクションで構成されています。
- 描画と図形
- StreamGeometry オブジェクト
- DrawingVisual オブジェクト
- イメージ
- 関連トピック
描画と図形
WPF には、グラフィカルな描画コンテンツを表現するために Drawing と Shape の両方のオブジェクトが用意されています。 ただし、Drawing オブジェクトの方が Shape オブジェクトより単純で、パフォーマンス特性に優れています。
Shape を使用すると、画面にグラフィカルな図形を描画できます。 Shape オブジェクトは、FrameworkElement クラスから派生するため、パネルおよびほとんどのコントロール内で使用できます。
WPF には、グラフィックス サービスやレンダリング サービスへのアクセスのレイヤーがいくつか用意されています。 Shape オブジェクトは最上位レイヤーで使いやすく、レイアウトやイベント処理などの便利な機能を多数提供します。 WPF には、すぐに使用できるさまざまな図形オブジェクトが用意されています。 すべての図形オブジェクトは Shape クラスから継承されます。 使用可能な図形オブジェクトには、Ellipse、Line、Path、Polygon、Polyline、Rectangle などがあります。
一方、Drawing オブジェクトは FrameworkElement クラスから派生していません。Drawing オブジェクトは、図形、イメージ、およびテキストを描画するためのより軽量な実装を提供します。
Drawing オブジェクトには次の 4 つの種類があります。
GeometryDrawing – 図形を描画します。
ImageDrawing – イメージを描画します。
GlyphRunDrawing – テキストを描画します。
DrawingGroup – その他の描画を描画します。 他の描画を 1 つの複合描画に結合するには、描画グループを使用します。
GeometryDrawing オブジェクトは、ジオメトリ コンテンツを描画するために使用されます。 Geometry クラスと、そこから派生する具象クラス (CombinedGeometry、EllipseGeometry、PathGeometry など) は、2D グラフィックスを描画するための手段を提供します。ヒット テストやクリッピングもサポートされています。 ジオメトリ オブジェクトを使用すると、たとえば、コントロールの領域を定義したり、イメージに適用するクリップ領域を定義したりすることができます。 ジオメトリ オブジェクトは、四角形や円などの単純な領域にすることも、2 つ以上のジオメトリ オブジェクトから作成された複合的な領域にすることもできます。 さらに複雑な幾何学領域を作成するには、ArcSegment、BezierSegment、QuadraticBezierSegment などの PathSegment 派生オブジェクトの組み合わせを使用します。
表面的には、Geometry クラスと Shape クラスはよく似ています。 いずれのクラスも 2D グラフィックスの描画に使用され、それぞれのクラスから派生する具象クラスも似ています (EllipseGeometry と Ellipse など)。 ただし、この 2 つのクラスのセットの間には重要な違いがいくつかあります。 その 1 つとして、Geometry クラスには、Shape クラスの一部の機能 (図形そのものを描画する機能など) がありません。 ジオメトリ オブジェクトを描画するには、DrawingContext、Drawing、Path (Path が Shape であることは注目に値します) などの別のクラスを使用して描画操作を実行する必要があります。 塗りつぶし、ストローク、ストロークの太さなどの描画プロパティは、ジオメトリ オブジェクトを描画するクラスにあります。一方、図形オブジェクトにはこれらのプロパティが含まれています。 この違いは、ジオメトリ オブジェクトが円などの領域を定義するのに対し、図形オブジェクトは領域を定義し、領域の塗りつぶしやアウトラインを定義し、レイアウト システムに参加する、と考えることができます。
Shape オブジェクトは FrameworkElement クラスから派生するため、Shape オブジェクトを使用するとアプリケーションのメモリ消費が大幅に増加する可能性があります。 使用するグラフィカル コンテンツで FrameworkElement の機能がまったく必要ない場合は、より軽量な Drawing オブジェクトを使用することを検討してください。
Drawing オブジェクトの詳細については、「Drawing オブジェクトの概要」を参照してください。
StreamGeometry オブジェクト
StreamGeometry オブジェクトは、幾何学図形を作成するための PathGeometry の代替となる軽量なものです。 StreamGeometry は、複雑なジオメトリを作成する必要がある場合に使用します。 StreamGeometry は、多数の PathGeometry オブジェクトを処理することを想定して最適化されているため、多数の PathGeometry オブジェクトを個別に使用する場合に比べてパフォーマンスが向上します。
次の例では、XAML で属性構文を使用して三角形の StreamGeometry を作成します。
<Page xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml">
<StackPanel>
<Path Data="F0 M10,100 L100,100 100,50Z"
StrokeThickness="1" Stroke="Black"/>
</StackPanel>
</Page>
StreamGeometry オブジェクトの詳細については、「方法 : StreamGeometry を使用して図形を作成する」を参照してください。
DrawingVisual オブジェクト
DrawingVisual オブジェクトは、図形、イメージ、またはテキストの描画に使用する軽量の描画クラスです。 このクラスが軽量と見なされる理由は、レイアウトやイベントの処理を行わないため、パフォーマンスが向上するからです。 このため、背景やクリップ アートの描画に適しています。 詳細については、「DrawingVisual オブジェクトの使用」を参照してください。
イメージ
WPF のイメージング機能は、以前のバージョンの Windows のイメージング機能から大幅に強化されています。 イメージング機能 (ビットマップの表示や一般的なコントロール上でのイメージの使用など) は、以前は主に Microsoft Windows Graphics Device Interface (GDI) または Microsoft Windows GDI+ のアプリケーション プログラミング インターフェイス (API) によって処理されていました。 これらの API では、基本的なイメージング機能は提供されていましたが、コーデック拡張機能のサポートや忠実性の高いイメージのサポートなどの機能は含まれていませんでした。 WPF Imaging API は、GDI および GDI+ の欠点を克服し、アプリケーション内でイメージを表示および使用するための新しい API のセットを提供するために再設計されています。
イメージを使用する際には、パフォーマンスを向上させるために以下の推奨事項を考慮してください。
アプリケーションでサムネイル イメージを表示する必要がある場合は、縮小版のイメージを作成することを検討してください。 既定では、WPF は読み込んだイメージを本来のサイズにデコードします。 サムネイル バージョンのイメージのみが必要な場合は、イメージを本来のサイズにデコードしてからサムネイル サイズに縮小するという無駄が生じます。 この不要なオーバーヘッドを回避するには、WPF に対して、イメージをサムネイル サイズにデコードするように要求するか、サムネイル サイズのイメージを読み込むように要求します。
イメージは常に、既定のサイズではなく必要なサイズにデコードするようにしてください。 上で説明したように、既定の実際のサイズではなく必要なサイズにイメージをデコードするように WPF に要求します。 これにより、アプリケーションの作業セットを縮小できるだけでなく、実行速度も向上します。
可能であれば、複数のイメージを 1 つに結合します (複数のイメージから成るフィルム ストリップなど)。
詳細については、「イメージングの概要」を参照してください。
BitmapScalingMode
ビットマップのスケーリングをアニメーション化する場合、既定の高品質イメージの再サンプリング アルゴリズムは、フレーム レートを低下させるほどシステム リソースを消費する場合があり、実際にはアニメーションの動きが滑らかでなくなることがあります。 RenderOptions オブジェクトの BitmapScalingMode プロパティを LowQuality に設定することにより、ビットマップをスケーリングするときに、より滑らかなアニメーションを作成できます。 LowQuality モードは、WPF のレンダリング エンジンに対して、イメージを処理するときに品質重視のアルゴリズムから速度重視のアルゴリズムに切り替えるように指示します。
イメージ オブジェクトの BitmapScalingMode を設定する方法を次の例に示します。
' Set the bitmap scaling mode for the image to render faster.
RenderOptions.SetBitmapScalingMode(MyImage, BitmapScalingMode.LowQuality)
// Set the bitmap scaling mode for the image to render faster.
RenderOptions.SetBitmapScalingMode(MyImage, BitmapScalingMode.LowQuality);
CachingHint
既定では、WPF は、TileBrush オブジェクト (DrawingBrush や VisualBrush など) の描画された内容をキャッシュしません。 シーンで TileBrush の内容も使用状況も変化することのない静的なシナリオでは、ビデオ メモリが節約されるため、この動作には意味があります。 静的な内容の TileBrush を静的でない方法で使用する場合には、あまり意味はありません。たとえば、静的な DrawingBrush や VisualBrush が回転する 3D オブジェクトのサーフェイスにマップされている場合などです。 WPF の既定の動作では、内容が変化しない場合でも、DrawingBrush または VisualBrush のすべてのフレームの内容全体が再描画されます。
RenderOptions オブジェクトの CachingHint プロパティを Cache に設定すると、並べて表示されたブラシ オブジェクトのキャッシュ バージョンを使用してパフォーマンスを向上させることができます。
CacheInvalidationThresholdMinimum および CacheInvalidationThresholdMaximum の各プロパティ値は、スケールの変化に伴って TileBrush オブジェクトをいつ再生成する必要があるかを決定する相対的なサイズ値です。 たとえば、CacheInvalidationThresholdMaximum プロパティを 2.0 に設定すると、TileBrush のキャッシュ サイズが現在のキャッシュ サイズの倍を超えた場合にだけ、キャッシュを再生成すれば済みます。
DrawingBrush のキャッシュ ヒント オプションの使用方法を次の例に示します。
Dim drawingBrush As New DrawingBrush()
' Set the caching hint option for the brush.
RenderOptions.SetCachingHint(drawingBrush, CachingHint.Cache)
' Set the minimum and maximum relative sizes for regenerating the tiled brush.
' The tiled brush will be regenerated and re-cached when its size is
' 0.5x or 2x of the current cached size.
RenderOptions.SetCacheInvalidationThresholdMinimum(drawingBrush, 0.5)
RenderOptions.SetCacheInvalidationThresholdMaximum(drawingBrush, 2.0)
DrawingBrush drawingBrush = new DrawingBrush();
// Set the caching hint option for the brush.
RenderOptions.SetCachingHint(drawingBrush, CachingHint.Cache);
// Set the minimum and maximum relative sizes for regenerating the tiled brush.
// The tiled brush will be regenerated and re-cached when its size is
// 0.5x or 2x of the current cached size.
RenderOptions.SetCacheInvalidationThresholdMinimum(drawingBrush, 0.5);
RenderOptions.SetCacheInvalidationThresholdMaximum(drawingBrush, 2.0);