×

Quick Start for Windows and Windows Phone 8.1

Create a new project

To create a new project, follow these steps:

  1. In the Visual Studio, select File > New > Project...
  2. In the New Project window, select Visual C# > Store Apps > Universal Apps > Blank App (Universal Apps).
  3. Press OK .

A project has now been created for you.

Include libraries to your project

Before starting to use the functionality provided by the SDK, the Nokia Imaging SDK libraries must be added to the project. For detailed instructions, please see the chapter Adding libraries to the project.

Define your XAML UI

The UI we will build for this tutorial is very simple. There will be two XAML image controls and two buttons. One XAML image control will display the original image, and the other will display the filtered image. Similarly, one button is used for selecting the image, and the other one is used for saving the filtered image to the phone library.

Here are the steps to accomplish this:

  1. Move MainPage.xaml and MainPage.xaml.cs to the QuickStart.Shared project, in order to share as much as possible, even the UI.
  2. In the Visual Studio's Solution Explorer, open the MainPage.xaml.
  3. Let's now add all the controls that make our UI. In the XAML view, search for the layout root grid that was generated when creating the project:
    <Grid>
    
    </Grid>

    Replace the grid and all its content by this grid:

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> 
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions> 
    
        <Image x:Name="CartoonImage" Stretch="UniformToFill" /> 
        <Image x:Name="OriginalImage" Width="200" Height="200" Stretch="Uniform"
               HorizontalAlignment="Left" VerticalAlignment="Top" Margin="12,12,0,0" />
    
        <Button Content="Pick an image" Click="PickImage_Click" HorizontalAlignment="Left" Grid.Row="2" />
        <Button Content="Save the image" Click="SaveImage_Click" x:Name="SaveButton" 
                HorizontalAlignment="Right" Grid.Row="2" IsEnabled="False" /> 
    </Grid>
    The only noteworthy thing in the code above is that we define the two preview images, CartoonImage and OriginalImage, without specifying any source for the image to display. We will bind the image source later; code examples will also be given in the chapters below.

Pick an image from the camera roll

For picking the image, we will use the FileOpenPicker which is part of the SDK. For Windows Phone 8.1 some more code is required to handle the file picking though, since it requires your application to handle continuations. Please refer to http://msdn.microsoft.com/en-us/library/windowsphone/develop/dn614994.aspx for a more detailed description.

Open the App.xaml.cs in Visual Studio Solution Explorer and add the following snippets to the shared App class.

#if WINDOWS_PHONE_APP
ContinuationManager continuationManager;
#endif
#if WINDOWS_PHONE_APP
protected override void OnActivated(IActivatedEventArgs e)
{     
    base.OnActivated(args);

    continuationManager = new ContinuationManager();

    var continuationEventArgs = args as IContinuationActivatedEventArgs;
    if (continuationEventArgs == null)
        return;

    var frame = Window.Current.Content as Frame;
    if (frame != null)
    {
        // Call ContinuationManager to handle continuation activation
        continuationManager.Continue(continuationEventArgs, frame);             
    }
}
#endif  

Next, open the MainPage.xaml.cs where we will add the code to pick the image and save the image.

private void PickImage_Click(object sender, RoutedEventArgs e)
{    
    SaveButton.IsEnabled = false;
    var openPicker = new FileOpenPicker
    {
        SuggestedStartLocation = PickerLocationId.PicturesLibrary,
        ViewMode = PickerViewMode.Thumbnail
    };

    // Filter to include a sample subset of file types.
    openPicker.FileTypeFilter.Clear();
    openPicker.FileTypeFilter.Add(".bmp");
    openPicker.FileTypeFilter.Add(".png");
    openPicker.FileTypeFilter.Add(".jpeg");
    openPicker.FileTypeFilter.Add(".jpg");

    PickImage(openPicker);
}

Note the last call to PickImage, which does not exist yet, but will be added to a specific partial implementation for each platform.

private void SaveImage_Click(object sender, RoutedEventArgs e) 
{ 
    SaveButton.IsEnabled = false;    

    var savePicker = new FileSavePicker()
    {
        SuggestedStartLocation = PickerLocationId.PicturesLibrary,
        SuggestedFileName = string.Format("CartoonImage_{0}", DateTime.Now.ToString("yyyyMMddHHmmss"))
    };

    savePicker.FileTypeChoices.Add("JPG File", new List<string> { ".jpg" });
    SaveImage(savePicker);
}  

Note the last call to SaveImage, which does not exist yet, but will be added to a specific partial implementation for each platform.

Now create a new class in each platform project, for example MainPage.Windows.cs and MainPage.WindowsPhone.cs, each one declaring a sealed partial MainPage class.

For the Windows version of the partial MainPage class, add the following code:

private async void PickImage(FileOpenPicker openPicker)
{
    // Open the file picker.
    StorageFile file = await openPicker.PickSingleFileAsync();

    // file is null if user cancels the file picker.
    if (file != null)
    {
        if (!(await ApplyFilterAsync(file)))
            return;

        SaveButton.IsEnabled = true;
    }
}

private async void SaveImage(FileSavePicker savePicker)
{
    var file = await savePicker.PickSaveFileAsync();
    if (file != null)
    {
        await SaveImageAsync(file);
    }

    SaveButton.IsEnabled = true;
}

For the Windows Phone version of the partial MainPage class, add the following code.

private void PickImage(FileOpenPicker openPicker)
{
    openPicker.PickSingleFileAndContinue();
}

private void SaveImage(FileSavePicker savePicker)
{
    savePicker.PickSaveFileAndContinue();
}

public async void ContinueFileOpenPicker(FileOpenPickerContinuationEventArgs args)
{
    var file = args.Files.FirstOrDefault();
    if (file == null)
        return;

    if (!await ApplyFilterAsync(file))
        return;

    SaveButton.IsEnabled = true;
}

public async void ContinueFileSavePicker(FileSavePickerContinuationEventArgs args)
{
    if (args.File == null)
        return;

    if (!await SaveImageAsync(args.File))
        return;

    SaveButton.IsEnabled = true;         
}

Now we are ready to start using the Nokia Imaging SDK.

Use FilterEffect to decode an image with an effect

Finally, we are ready to use the Nokia Imaging SDK!

  1. Add the following using directives:
    using Nokia.Graphics.Imaging; 
    using System.Threading.Tasks;
    using Windows.ApplicationModel.Activation;
    using Windows.Storage;
    using Windows.Storage.Pickers;
    using Windows.Storage.Streams;
    using Windows.UI.Popups;
    using Windows.UI.Xaml.Media.Imaging;
    
  2. In the MainPage.xaml.cs class, declare the following member variables.
    public partial class MainPage : PhoneApplicationPage
    {
    
        // FilterEffect instance is used to apply different
        // filters to an image.
        // Here we will apply Cartoon filter to an image.
        private FilterEffect _cartoonEffect  		 =	null;
    
        // The following  WriteableBitmap contains 
        // The filtered and thumbnail image.
        private WriteableBitmap _cartoonImageBitmap 	 =	null;
        private WriteableBitmap _thumbnailImageBitmap 	 =	null;
        ...
        ...
    }	
    
  3. Next we have to initialize the private members that we have just declared. We will initialize them in the constructor.
    public Mainpage()
    {
        this.InitializeComponent()
            
        // Initialize WriteableBitmaps to render the filtered and original image.
        double scaleFactor = 1.0; 	
    #if WINDOWS_PHONE_APP
        scaleFactor = DisplayInformation.GetForCurrentView().RawPixelsPerViewPixel;
    #endif
    
        _cartoonImageBitmap = new WriteableBitmap((int)(Window.Current.Bounds.Width * scaleFactor), (int)(Window.Current.Bounds.Height * scaleFactor));
        _thumbnailImageBitmap = new WriteableBitmap((int)OriginalImage.Width, (int)OriginalImage.Height); 
    }
  4. Once the image is selected we can apply filters on the image. In this tutorial we apply Cartoon filter and display the result in XAML image control (CartoonImage). The complete code of the ApplyFilterAsync method becomes:
    private async Task<bool> ApplyFilterAsync(StorageFile file)
    {    
        // Open a stream for the selected file. 
        IRandomAccessStream fileStream = await file.OpenAsync(FileAccessMode.Read); 
    
        string errorMessage = null;
    
        try
        { 
            // Show thumbnail of original image. 
            _thumbnailImageBitmap.SetSource(fileStream); 
            OriginalImage.Source = _thumbnailImageBitmap; 
     
            // Rewind stream to start. 
            fileStream.Seek(0); 
     
            // A cartoon effect is initialized with selected image stream as source.  
            var imageSource = new RandomAccessStreamImageSource(fileStream);  
            _cartoonEffect = new FilterEffect(imageSource);  
     
            // Add the cartoon filter as the only filter for the effect. 
            var cartoonFilter = new CartoonFilter();  
            _cartoonEffect.Filters = new[] { cartoonFilter }; 
     
            // Render the image to a WriteableBitmap. 
            var renderer = new WriteableBitmapRenderer(_cartoonEffect, _cartoonImageBitmap); 
            _cartoonImageBitmap = await renderer.RenderAsync(); 
            _cartoonImageBitmap.Invalidate(); 
     
            // Set the rendered image as source for the cartoon image control. 
            CartoonImage.Source = _cartoonImageBitmap; 
        } 
        catch (Exception exception) 
        { 
    	errorMessage = exception.Message;
        }
    
        if (!string.IsNullOrEmpty(errorMessage))
        {
            var dialog = new MessageDialog(errorMessage);
            await dialog.ShowAsync();
            return false;
        }
    
        return true;
    }    

We first set the image stream, from the selected image, to _thumbnailImageBitmap without applying any filters to get the thumbnail of the original image. The next line resets the position of the stream to the beginning. This step is necessary, as the current reading position of the stream will be at the end as a result of the previous step. Next we create a RandomAccessStreamImageSource with the selected file, and initialize the _cartoonEffect with it. A cartoon filter is then added to the filter list of the _cartoonEffect.

The filtered image is then rendered to the _cartoonImageBitmap using WriteableBitmapRenderer. The rendering to the _cartoonImageBitmap is asynchronous; RenderAsync replaces the image source with the current image in the _cartoonEffect. We then enable the SaveButton, so that the filtered image could be saved.

Add capabilities

The application reads data from the Pictures folder, and therefore it needs certain capabilities. In the Visual Studio's Solution Explorer, open the Package.appxmanifest and open the Capabilities tab. Make sure that the Pictures Library capability is checked.

Rendering and encoding to full resolution JPEG

Rendering to full resolution output JPEG is simple once we have an instance of FilterEffect. Every pixel of the original image will be processed by the library and then saved as a JPEG.

This code example demonstrates how to add the functionality to save the filtered image as a full resolution JPEG:

private async Task<bool> SaveImageAsync(StorageFile file) 
{ 
    if (_cartoonEffect == null) 
    { 
        return false; 
    } 

    string errorMessage = null;
 
    try 
    { 
        using (var jpegRenderer = new JpegRenderer(_cartoonEffect)) 
        using (var stream = await file.OpenAsync(FileAccessMode.ReadWrite)) 
        { 
            // Jpeg renderer gives the raw buffer containing the filtered image. 
            IBuffer jpegBuffer = await jpegRenderer.RenderAsync(); 
            await stream.WriteAsync(jpegBuffer); 
            await stream.FlushAsync(); 
        }
    } 
    catch (Exception exception)      
    {
        errorMessage = exception.Message;
    }      

    if (!string.IsNullOrEmpty(errorMessage))     
    {
        var dialog = new MessageDialog(errorMessage);
        await dialog.ShowAsync(); 
        return false;     
    }
 
    return true; 
}          

Running the application

To run the application:

  1. Select either "Device" or "Emulator", "Debug" with the selectors in the Visual Studio's standard toolbar.
  2. Build the application.
  3. Connect a device (if you are deploying it on device) and run.
  4. Select an image using "Pick an image" button.
  5. You should see the main page containing the decoded image with a Cartoon style filter effect added.
Tip:

If you are testing an app on an emulator, you may experience an emulator bug. If your app can't see any content in the pictures library, it is likely a result of a bug in the emulator.

If you need to access the in-built images, you need to open the photos app at least once before you begin testing your application. Once you browse through the photos, the content will become available to your app.

Get the complete source

The complete source code of the tutorial:

Quick Start for Windows and Windows Phone 8.1 ? universal app project v1.0 quick-start-windows81-wp81-v1_0.zip

A version of the app made as a Windows Phone 8.1 Silverlight app can be found here.


Last updated 18 June 2014

Back to top

×