如何在UWP应用程序中应用实时高斯模糊效果?

3

最近我在学习UWP并尝试构建一个简单的演示,我想要生成一个类似Aero的简单实时模糊效果。它有时很有用(例如实时相机滤镜),所以我想出了以下想法:

首先我导入了win2D库,并在RootGrid上放置了一个CanvasAnimatedControl

<canvas:CanvasAnimatedControl x:Name="BlurLayer" Draw="BlurLayer_Draw" 
                              VerticalAlignment="Stretch" HorizontalAlignment="Stretch"/>

这个模糊层的资源是一个Frame
<Frame x:Name="MainFrame" LayoutUpdated="MainFrame_LayoutUpdated" 
       VerticalAlignment="Stretch" HorizontalAlignment="Stretch"/>

每次框架更新后,MainFrame_LayoutUpdated方法都会尝试使用RenderTargetBitmap保存快捷方式,但是win2D无法接收此对象作为其CanvasBitmap,因此它被转换为byte[]并保存;

    RenderTargetBitmap renderer = new RenderTargetBitmap();
    CanvasBitmap bitmap;
    byte[] RendererStream;
    public static int FrameWidth;
    public static int FrameHeight;
    public ICanvasImage RenderFinal;
    public bool Frame_Updated = false;
private async void MainFrame_LayoutUpdated(object sender, object e)
    {
        await renderer.RenderAsync(MainFrame);
        FrameWidth = renderer.PixelWidth;
        FrameHeight = renderer.PixelHeight;
        RendererStream = WindowsRuntimeBufferExtensions.ToArray(await renderer.GetPixelsAsync());
        if (FrameHeight != 0)
            Frame_Updated = true;
    }

BlurLayer_Draw方法中,只需刷新并应用模糊效果: private void BlurLayer_Draw(ICanvasAnimatedControl sender,

CanvasAnimatedDrawEventArgs args)
        {
            if (Frame_Updated)
            {
                bitmap = CanvasBitmap.CreateFromBytes(sender, RendererStream, FrameWidth, FrameHeight, DirectXPixelFormat.B8G8R8A8UIntNormalized);
                RenderFinal = new GaussianBlurEffect
                                 {
                                      Source = bitmap
                                 };
                RenderFinal.BorderMode = EffectBorderMode.Hard;
                RenderFinal.BlurAmount = 8.0f;
                Frame_Updated = false;
            }
            if (RenderFinal != null)
                args.DrawingSession.DrawImage(RenderFinal);
        }

所有的这些都完成后,它可以工作了。 但是这个解决方案真的很糟糕,Win2D 画布严重延迟。 我应该怎么做才能让它高性能?


也许SharpDX可以帮助你?http://sharpdx.org/documentation/api/t-sharpdx-direct2d1-effects-gaussianblur 它使用DirectX,应该更加高效。 - sibbl
我有一篇关于使用Lumia Imaging SDK进行快速模糊的博客文章,链接是http://igrali.com/2015/09/26/using-swapchainpanelrenderer-to-improve-real-time-rendering-in-lumia-imaging-sdk-3/,并且这个项目也在GitHub上https://github.com/igrali/PropertyDescriptions,也许这对你会有帮助! - Igor Ralic
@sibbl 我想试试。 - EmbraceZXS
@igrali 我读了你的博客并尝试了你的示例,速度真的很快,正是我想要的。谢谢。 - EmbraceZXS
@EmbraceZXS 好的,太棒了!我也把它发布为答案了 :) - Igor Ralic
1个回答

1
让我来帮助您翻译这段内容,它与编程有关。建议使用Lumia Imaging SDK,它具有BlurEffect功能,如果与SwapChainPanelRenderer实时渲染一起使用,则非常快速。我在我的博客文章Using SwapChainPanelRenderer to improve real-time rendering in Lumia Imaging SDK 3中写到了它,其中我以BlurEffect为例。完整的源代码available on GitHub

只需在滑动条KernelSize值更改为新的值时,在SwapChainPanelRenderer实例上调用RenderAsync即可。

private async void EffectRangeSlider_OnValueChanged(object sender, RangeBaseValueChangedEventArgs e)
{
    if (this.renderer != null)
    {
        this.viewModel.blur.KernelSize = (int)e.NewValue;

        await this.renderer.RenderAsync();
    }
}

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