private void Uninitialize()
        {
            if (_cameraPreviewImageSource != null)
            {
                _cameraPreviewImageSource.Dispose();
                _cameraPreviewImageSource = null;
            }

            if (_blendEffect != null)
            {
                _blendEffect.Dispose();
                _blendEffect = null;
            }

            if (_blendImageProvider != null)
            {
                _blendImageProvider = null;
            }
        }
        private void BackgroundImage_ImageOpened(object sender, RoutedEventArgs e)
        {
            var gfxEffect = new BlendEffect
            {
                Mode       = BlendEffectMode.Multiply,
                Background = new ColorSourceEffect
                {
                    Name  = "Darken",
                    Color = Color.FromArgb(102, 0, 0, 0),
                },
                Foreground = new GaussianBlurEffect()
                {
                    Name         = "Blur",
                    BlurAmount   = 20.0f,
                    BorderMode   = EffectBorderMode.Hard,
                    Optimization = EffectOptimization.Speed,
                    Source       = new CompositionEffectSourceParameter("ImageSource")
                }
            };


            Visual     _backgroundVisual     = ElementCompositionPreview.GetElementVisual(BackgroundGrid);
            Compositor _backgroundCompositor = _backgroundVisual.Compositor;

            var effectBrush = _backgroundCompositor.CreateEffectFactory(gfxEffect).CreateBrush();

            var destinationBrush = _backgroundCompositor.CreateBackdropBrush();

            effectBrush.SetSourceParameter("ImageSource", destinationBrush);

            //Generate a UIElement visual.
            var blurSprite = _backgroundCompositor.CreateSpriteVisual();

            blurSprite.Size  = new Vector2((float)BackgroundGrid.ActualWidth, (float)BackgroundGrid.ActualHeight);
            blurSprite.Brush = effectBrush;
            //Then "inject" it to the XAML.
            ElementCompositionPreview.SetElementChildVisual(BackgroundGrid, blurSprite);

            //create animation for opacity of the image from 0 -> 1
            DoubleAnimation animation = new DoubleAnimation()
            {
                From           = 0,
                To             = 1,
                EasingFunction = new CircleEase()
                {
                    EasingMode = EasingMode.EaseOut
                },
                Duration = new Duration(TimeSpan.FromSeconds(0.3))
            };

            animation.EnableDependentAnimation = true;

            //create storyboard.
            Storyboard loadImageOpacity = new Storyboard();

            loadImageOpacity.Children.Add(animation);

            //start the storyboard
            Storyboard.SetTarget(animation, BackgroundImage);
            Storyboard.SetTargetProperty(animation, "Opacity");
            loadImageOpacity.Begin();
            gfxEffect.Dispose();
        }
        protected override async void Render()
        {
            try
            {
                if (Source != null)
                {
                    Debug.WriteLine(DebugTag + Name + ": Rendering...");

                    foreach (var change in Changes)
                    {
                        change();
                    }

                    Changes.Clear();

                    //blend source layer with mode overlay
                    var blendEffect = new BlendEffect();
                    blendEffect.Source = Source;// new StreamImageSource(new MemoryStream());
                    blendEffect.ForegroundSource = Source;
                    blendEffect.BlendFunction = BlendFunction.Overlay;
                    blendEffect.GlobalAlpha = 0.0;

                    var renderer = new JpegRenderer(blendEffect);
                    var outBuffer = await renderer.RenderAsync();

                    blendEffect.Dispose();

                    var highPassSource = new BufferImageSource(outBuffer);
                    var highPassFilter = new HighpassEffect(6, false, 1);
                    highPassFilter.Source = highPassSource;
                    var highPassRenderer = new JpegRenderer(highPassFilter);

                    var highPassOutBuffer = await highPassRenderer.RenderAsync();

                    highPassFilter.Dispose();

                    var negativeFilter = new NegativeFilter();
                    var filterEffect = new FilterEffect();
                    filterEffect.Filters = new List<IFilter>() { negativeFilter };

                    filterEffect.Source = new BufferImageSource(highPassOutBuffer);
                    var invertRenderer = new JpegRenderer(filterEffect);
                    var invertOutBuffer = await invertRenderer.RenderAsync();


                    blendEffect = new BlendEffect(Source, new BufferImageSource(invertOutBuffer), BlendFunction.Overlay, 0.5);
                    using (var bmpRender = new WriteableBitmapRenderer(blendEffect, TmpBitmap))
                    {
                        await bmpRender.RenderAsync();
                    }

                    TmpBitmap.Pixels.CopyTo(PreviewBitmap.Pixels, 0);
                    PreviewBitmap.Invalidate(); // Force a redraw
                }
                else
                {
                    Debug.WriteLine(DebugTag + Name + ": Render(): No buffer set!");
                }
            }
            catch (Exception e)
            {
                Debug.WriteLine(DebugTag + Name + ": Render(): " + e.Message);
            }
            finally
            {
                switch (State)
                {
                    case States.Apply:
                        State = States.Wait;
                        break;
                    case States.Schedule:
                        State = States.Apply;
                        Render();
                        break;
                    default:
                        break;
                }
            }
        }