BitmapEffectは静的に使う(RenderTargetBitmap)

WPFの最適化で真っ先に上がるのが、「BitmapEffectを使わない」ですが、静的に使えば性能を低下させずにBitmapEffectを利用することができます。静的に使うというのは、BitmapEffectの結果を変更しないという意味です。デフォルトではBitmapEffectは(対象が更新されようとされまいと)毎フレーム処理されるので、いったんBitmapEffectの処理をしたら、RenderTargetBitmapを使ってその結果をImageBrushにして、それ以降はBitmapEffectを行わないようすればよいのです。

たとえば、BitmapEffectの結果をVisualBrushとして受け取ったら、それを次のコードでImageBrushに変換します。

        private ImageBrush VisualToImage(VisualBrush vb)

        {

            Rectangle r = new Rectangle();

            double w = 100, h = 100;

            r.Width = w;

            r.Height = h;

            r.Fill = vb;

            r.Measure(new Size(w, h));

            r.Arrange(new Rect(new Size(w, h)));

            r.UpdateLayout();

            RenderTargetBitmap rtb = new RenderTargetBitmap

                ((int)r.ActualWidth, (int)r.ActualHeight, 96, 96, PixelFormats.Pbgra32);

            rtb.Render(r);

            ImageBrush ib = new ImageBrush(rtb);

            if (ib.CanFreeze) ib.Freeze();

            return ib;

        }

結果のImageBrushを使えば、VisualBrushと同じような結果が得られます。しかも、BitmapEffectは1回しか行われないので、性能は格段に向上します。注意が必要なのは、これは静的なので対象物が更新されたら同じことを繰り返さなければならないことと、ImageBrushなので解像度の調整が必要なことと、ボタンなどに適用するとコンポーネントとしての機能がなくなることです。