×

Real-time Filter Demo for Windows and Windows 8.1

Real-time Filter Demo is a Nokia example application demonstrating the use of the Nokia Imaging SDK for real-time image effects. The effects are applied to the stream received from the camera and shown in the viewfinder. This app does not support capturing photos.

Compatibility

  • Compatible with Windows and Windows Phone 8.1.
  • Tested with Nokia Lumia 2520, Windows 8.1 desktop and Windows Phone 8.1 emulator.
  • Developed with Visual Studio Express 2013 from Windows.
  • Compiling the project requires Nokia Imaging SDK.

One of the targets of this project was to create a universal app for Windows and Windows Phone 8.1, sharing most of the code between the two. Therefore most of the application business logic and image processing code was implemented in a shared code project, leaving pretty much only the UI layer to be implemented separately for the specific target platforms.

Design

Application design is very simple. On both Windows 8.1 and Windows Phone 8.1 the application opens up directly into a camera viewfinder, and the application button bar contains buttons to change the currently active filter. The name of the currently active filter is displayed in the top-right corner of the view.

Windows 8.1

Windows Phone 8.1

Architecture overview

Here's a lightweight class diagram showing the overall structure of the application implementation.

Application architecture is very simple. Both platform targets have their own specific view implementations for appropriate UI layout, and most of the functionality - getting preview frames from camera, switching between filters, and rendering filtered frames - is in a viewmodel shared by both the Windows 8.1 and the Windows Phone 8.1 apps.

Initializing the camera preview

Using preview frames from device's camera is very straight forward with Nokia Imaging SDK. In the following InitializeAsync() method you can see how we're creating a camera preview specific image source.

namespace RealtimeFilterDemo
{
    public class MainPageViewModel : INotifyPropertyChanged
    {
        private readonly List<Filter> _filterList = new List<Filter>
        {
            new Filter { Name = "No Filter", Type = null},
            new Filter { Name = "Lomo", Type = typeof(LomoFilter),
                         Parameters = new object[]{0.7, 0.4, LomoVignetting.High, LomoStyle.Yellow}},

            ...
        }

        private CameraPreviewImageSource _cameraPreviewImageSource; // Using camera as our image source
        private WriteableBitmap _writeableBitmap; // Target for our renderer
        private FilterEffect _effect; // Filter to be used on the camera image
        private bool _isRendering; // Used to prevent multiple renderers running at once
        private bool _changeFilterRequest = true; // To indicate new filter selection by user
        private int _index = 0; // Index of the currently active filter

        public bool Initialized
        {
            ...
        }

        public WriteableBitmap PreviewBitmap
        {
            ...
        }

        public async Task InitializeAsync()
        {
            ...

            // Create a camera preview image source (from Imaging SDK)
            _cameraPreviewImageSource = new CameraPreviewImageSource();
            await _cameraPreviewImageSource.InitializeAsync(string.Empty);
            var properties = await _cameraPreviewImageSource.StartPreviewAsync();
           
            // Create a preview bitmap with the correct aspect ratio 
            var width = 640.0;
            var height = (width / properties.Width) * properties.Height;
            var bitmap = new WriteableBitmap((int)width, (int)height);

            PreviewBitmap = bitmap;

            // Create a filter effect to be used with the source (no filters yet)
            _effect = new FilterEffect(_cameraPreviewImageSource);
            _writeableBitmapRenderer = new WriteableBitmapRenderer(_effect, PreviewBitmap);          
         
            // Attach preview frame delegate
            _cameraPreviewImageSource.PreviewFrameAvailable += OnPreviewFrameAvailable;

            ...

            Initialized = true;

            ...
        }
    }

    ...
}

Filtering the camera preview frames

After initializing the camera preview image source in the previous code block, we can start rendering the preview frames in the delegate that was registered to the PreviewFrameAvailable event. Here we first check if the user has requested for a different filter to be used (not covered in this code block), and create the IFilter type of filter accordingly, and set it as the current filter in the filter effect. Then we use the renderer to render the image to the WriteableBitmap. Notice that we need to call the WriteableBitmap.Invalidate() method in the UI thread, and thus that call is deferred to be invoked later via the core window dispatcher.

namespace RealtimeFilterDemo
{
    ...

    public class MainPageViewModel : INotifyPropertyChanged
    {
        private async void OnPreviewFrameAvailable(IImageSize args)
        {
            // Prevent multiple rendering attempts at once
            if (Initialized && !_isRendering)
            {
                _isRendering = true;

                // User changed the filter, let's update it before rendering
                if (_changeFilterRequest)
                {
                    if (_filterList[_index].Type != null)
                    {
                        // Use reflection to create a new filter class
                        var filter = (IFilter)Activator.CreateInstance(
                            _filterList[_index].Type, _filterList[_index].Parameters);

                        _effect.Filters = new[] { filter };
                    }
                    else
                    {
                        _effect.Filters = new IFilter[0];
                    }

                    _changeFilterRequest = false;
                }

                // Render the image with the filter
                await _writeableBitmapRenderer.RenderAsync();

                // Request bitmap invalidation in the UI thread
                await Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(
                    CoreDispatcherPriority.High, () =>
                    {
                        ...

                        _writeableBitmap.Invalidate();
                    });

                _isRendering = false;
            }
        }
    }
}

Downloads

Real-time Filter Demo for Windows and Windows Phone 8.1 project v2.0 real-time-filter-demo-2.0.zip

This example application is hosted in GitHub, where you can check the latest activities, report issues, browse source, ask questions, or even contribute to the project yourself.

Note: Due to the time required to pass the store certification process, the version in the store may not always be the latest version.

Last updated 15 April 2014

Back to top

Was this page helpful?

Your feedback about this content is important. Let us know what you think.

 

Thank you!

We appreciate your feedback.

×