如何将遮罩应用于CompositionBrush

13
<Grid>
    <Image x:Name="BackgroundImage" Source="/Assets/background.png" />
    <Rectangle x:Name="ClippingRect" Margin="50" Fill="#30f0" />
</Grid>

我如何应用alpha遮罩或剪辑遮罩,以便除矩形外的一切都变得模糊?

我通常会这样做:GraphicsEffect->EffectFactory->Brush->设置为SpriteVisual。

 var graphicsEffect = new BlendEffect
 {
     Mode = BlendEffectMode.Multiply,
     Background = new ColorSourceEffect
     {
         Name = "Tint",
         Color = Windows.UI.Color.FromArgb(50,0,255,0),
     },

     Foreground = new GaussianBlurEffect()
     {
         Name = "Blur",
         Source =  new CompositionEffectSourceParameter("Backdrop"),
         BlurAmount = (float)20,
         BorderMode = EffectBorderMode.Hard,
     }
 };

 var blurEffectFactory = _compositor.CreateEffectFactory(graphicsEffect,
     new[] { "Blur.BlurAmount", "Tint.Color" });

 var _brush = blurEffectFactory.CreateBrush();
 _brush.SetSourceParameter("Backdrop", _compositor.CreateBackdropBrush());

 var blurSprite = _compositor.CreateSpriteVisual();
 blurSprite.Size = new Vector2((float)BackgroundImage.ActualWidth, (float)BackgroundImage.ActualHeight);
 blurSprite.Brush = _brush;
 ElementCompositionPreview.SetElementChildVisual(BackgroundImage, blurSprite);

在此输入图片描述


请问您能否提供预期结果的截图? - Andrii Krupka
除非有比我更熟悉WPF的人提供解决方案,否则您可以将整个背景模糊处理,然后在其上方叠加一小段没有模糊的图像片段吗? - wablab
我会选择使用GDI+工具和位图修改当前像素。 - Tatranskymedved
@Tatranskymedved:首先,GDI+不是UWP的正确选择。其次,我知道可以使用组合API实现,但由于我对该API不熟悉,所以在适当的时间内无法使其正常工作。我可能会回去再试一次。 - Liero
@Liero: 抱歉,我没有意识到这是UWP,而且老实说,我不知道在那里使用GDI+没有价值。我会从中吸取教训的。谢谢 =) - Tatranskymedved
2个回答

2
您可以使用以下解决方案,该方案使用两次相同的图像。我使用其中一个来制作模糊的背景,另一个用于剪裁的前景。
其思路是先绘制全尺寸的模糊背景,然后在其上只绘制想要剪裁的区域,这可以使用 Clip 属性来绘制前景视觉效果。
页面/控件的 XAML 代码:
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <Image x:Name="BackgroundImage" Source="/Assets/Purple Tentacle.png" />
    <Image x:Name="ClippedImage" Source="/Assets/Purple Tentacle.png" />
</Grid>

“代码背后:”
    protected override void OnNavigatedTo(NavigationEventArgs e)
    {
        _compositor = ElementCompositionPreview.GetElementVisual(this).Compositor;
        _backgroundImageVisual  = ElementCompositionPreview.GetElementVisual(BackgroundImage);

        var graphicEffect   = new BlendEffect
        {
            Mode    = BlendEffectMode.Multiply,
            Background  = new ColorSourceEffect
            {
                Color= Color.FromArgb(50, 0, 255, 0)
            },

            Foreground = new GaussianBlurEffect
            {
                Source = new CompositionEffectSourceParameter("Backdrop"),
                BlurAmount  = 20.0f,
                BorderMode = EffectBorderMode.Hard
            }
        };


        var backdropBrush       = _compositor.CreateBackdropBrush();

        var blurEffectFactory   = _compositor.CreateEffectFactory(graphicEffect);
        _brush                  = blurEffectFactory.CreateBrush();
        _brush.SetSourceParameter("Backdrop", backdropBrush);

        _blurSprite          = _compositor.CreateSpriteVisual();
        _blurSprite.Brush    = _brush;

        ElementCompositionPreview.SetElementChildVisual(BackgroundImage, _blurSprite);

        _foregroundImageVisual  = ElementCompositionPreview.GetElementVisual(ClippedImage);
        _foregroundImageVisual.Clip = _compositor.CreateInsetClip(100, 100, 100, 100);

        SizeChanged += MainPage_SizeChanged;
        MainPage_SizeChanged(this, null);
    }

    private void MainPage_SizeChanged(object sender, SizeChangedEventArgs e)
    {
        _blurSprite.Size    = new Vector2((float) BackgroundImage.ActualWidth, (float) BackgroundImage.ActualHeight);

        // change the clip values here to change the non-blurred region
        _foregroundImageVisual.Clip = _compositor.CreateInsetClip(100, 100, 100, 100);
    }

enter image description here


0
在Creators更新中,我可以创建从XamlCompositionBrushBase派生的类并将其应用于xaml元素,以便进行模糊处理:
<Grid>
    <Image x:Name="BackgroundImage" Source="/Assets/background.png" />
    <Path>
       <Path.Fill>
          <local:BlurTintBrush BlurRadius="5" TintColor="Black" TintOpacity="0.7" />
       </Path.Fill>
       <Path.Data>
           <GeometryGroup>
               <RectangleGeometry x:Name="ImageGeometry" Rect="0,0,1027,768" /
               <RectangleGeometry x:Name="CropGeometry" Rect="50,50,25,25" />
           </GeometryGroup>
       </Path.Data>
    </Path>
</Grid>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接