ぼかした画像のBrushを作るマークアップ拡張
以前↓で書いた、ぼかしを強烈にかけた画像を高速にする方法ですが、
WPFで強めのブラーを高速にかける - SourceChord
これを、Brushとして使えるようにしてみました。
マークアップ拡張も作ったので、以下のようにImageBrushを使うような感覚でぼかしの効いた背景を作ることができます。
ぼかした画像を張り付けるVisualBrushの作成
まずは、前回やったのと同じようなものを、VisualBrushとして作ります。
<Rectangle Margin="50" Stroke="Black"> <Rectangle.Fill> <VisualBrush Stretch="UniformToFill"> <VisualBrush.Visual> <ContentControl> <ContentControl.CacheMode> <BitmapCache RenderAtScale="0.05" /> </ContentControl.CacheMode> <Image ClipToBounds="True" Source="Image/sample.jpg"> <Image.Effect> <BlurEffect Radius="100" /> </Image.Effect> </Image> </ContentControl> </VisualBrush.Visual> </VisualBrush> </Rectangle.Fill> </Rectangle>
結果はこんな感じで、前回の記事のように、BitmapCacheの効いた高速なぼかし処理ができています。
基本的に前回方法と同じで、BitmapCacheを組み合わせたImageコントロールに、BlurEffectをかけてるだけです。
ちなみに、ImageコントロールをClipToBounds="True"としてるところがミソ
ぼかしをかけて、外側に大きくなるので、外側にぼけて広がった部分をクリッピングしておきます。
ぼかし画像のVisualBrushを生成するマークアップ拡張を作る
で、こんなに長々とVisualBrushの定義をするのは面倒なので、普通のImageBrushと同じような感覚で使えるように、マークアップ拡張を作りました。
ぼかした画像のBrushを生成するマークアップ拡張
[MarkupExtensionReturnType(typeof(VisualBrush))] public class BluredImageBrushExtension : MarkupExtension { public ImageSource Source { get; set; } public Stretch Stretch { get; set; } public double BlurRadius { get; set; } public double RenderAtScale { get; set; } public BluredImageBrushExtension() { Source = null; Stretch = System.Windows.Media.Stretch.UniformToFill; BlurRadius = 100; RenderAtScale = 0.05; } public BluredImageBrushExtension(ImageSource source, Stretch stretch, double blurRadius, double renderAtScale) { Source = source; Stretch = stretch; BlurRadius = blurRadius; RenderAtScale = renderAtScale; } public override object ProvideValue(IServiceProvider serviceProvider) { // ぼかしをかけたImageコントロールを作成 var img = new Image() { Source = this.Source, ClipToBounds = true, Effect = new BlurEffect() { Radius = this.BlurRadius} }; // Imageコントロールを、BitmapCacheを設定したContentControlに配置 var visual = new ContentControl() { Content = img, CacheMode = new BitmapCache(this.RenderAtScale) }; // ↑のContentControlを使って、VisualBrushを作成 var brush = new VisualBrush(visual) { Stretch = this.Stretch }; return brush; } }
<Rectangle Margin="50" Fill="{local:BluredImageBrush Source=Image/sample.jpg, Stretch=UniformToFill, BlurRadius=100, RenderAtScale=0.05}" Stroke="Black" />
まとめ
今回のサンプルコードは以下の通り。
マークアップ拡張は、面倒だったのでMainWindow.xaml.csにそのまま書いてます。
MainWindow.xaml
<Window x:Class="WpfBaseTemplate1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:WpfBaseTemplate1" Title="MainWindow" Width="525" Height="350"> <Grid> <Rectangle Margin="50" Fill="{local:BluredImageBrush Source=Image/sample.jpg, Stretch=UniformToFill, BlurRadius=100, RenderAtScale=0.05}" Stroke="Black" /> </Grid> </Window>
MainWindow.xaml.cs
/// <summary> /// MainWindow.xaml の相互作用ロジック /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } } [MarkupExtensionReturnType(typeof(VisualBrush))] public class BluredImageBrushExtension : MarkupExtension { public ImageSource Source { get; set; } public Stretch Stretch { get; set; } public double BlurRadius { get; set; } public double RenderAtScale { get; set; } public BluredImageBrushExtension() { Source = null; Stretch = System.Windows.Media.Stretch.UniformToFill; BlurRadius = 100; RenderAtScale = 0.05; } public BluredImageBrushExtension(ImageSource source, Stretch stretch, double blurRadius, double renderAtScale) { Source = source; Stretch = stretch; BlurRadius = blurRadius; RenderAtScale = renderAtScale; } public override object ProvideValue(IServiceProvider serviceProvider) { // ぼかしをかけたImageコントロールを作成 var img = new Image() { Source = this.Source, ClipToBounds = true, Effect = new BlurEffect() { Radius = this.BlurRadius} }; // Imageコントロールを、BitmapCacheを設定したContentControlに配置 var visual = new ContentControl() { Content = img, CacheMode = new BitmapCache(this.RenderAtScale) }; // ↑のContentControlを使って、VisualBrushを作成 var brush = new VisualBrush(visual) { Stretch = this.Stretch }; return brush; } }