3

最近在学习UWP,想搭建一个简单的demo,只想生成一个像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 Canvas 被严重延迟了。那么,我应该怎么做才能让它高性能呢?

4

1 回答 1

1

将我的评论作为官方答案:使用 Lumia Imaging SDK。如果使用 SwapChainPanelRenderer 进行实时渲染,它有一个非常快的 BlurEffect。我在我的博客文章使用 SwapChainPanelRenderer 改进 Lumia Imaging SDK 3 中的实时渲染中对此进行了描述,其中我使用了 BlurEffect 作为示例。GitHub 上提供了完整的源代码。

它归结为每当模糊 KernelSize 值更改为新滑块值时调用RenderAsync一个实例。SwapChainPanelRenderer

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

        await this.renderer.RenderAsync();
    }
}
于 2015-11-09T12:06:29.850 回答