×
Namespaces

Variants
Actions

Negative Custom Effect (Nokia Imaging SDK)

From Nokia Developer Wiki
Jump to: navigation, search

This article explains how to create a Negative Effect similar to the NegativeFilter in the Nokia Imaging SDK. It is provided for educational purposes rather than developer re-use.

SignpostIcon XAML 40.png
WP Metro Icon WP8.png
Article Metadata
Tested with
Devices(s): Nokia Lumia 920
Compatibility
Platform(s):
Windows Phone 8
Article
Created: Rob.Kachmar (03 Feb 2014)
Last edited: Rob.Kachmar (18 Feb 2014)

Contents

Introduction

The NegativeEffect allows you reverse the color in an image, very similar to the Nokia Imaging SDK's inbuilt NegativeFilter. The main differences are that it is implemented as a custom effect and it is less efficient.

Warning.pngWarning: The NegativeEffect should not be used in place of the inbuilt NegativeFilter. It is provided for educational purposes - to make it easier to understand the techniques used so that more complex filters can be created.

The article provides links to the filter source code and test code, an explanation of how the filter works, and code snippets showing how it is used.

Source code

Full source code for the NegativeEffect custom effect is provided below (toggle "Expand") and also in a ready-to-use file here: NegativeEffect.cs.

NegativeEffect.cs (03 Feb 2014)

  1. // ============================================================================
  2. // DATE        AUTHOR                   DESCRIPTION
  3. // ----------  -----------------------  ---------------------------------------
  4. // 2014.01.15  Rob.Kachmar              Initial creation
  5. // 2014.02.03  Rob.Kachmar              Handling static images
  6. // ============================================================================
  7.  
  8. using Nokia.Graphics.Imaging;
  9. using System;
  10.  
  11. namespace NISDKExtendedEffects.ImageEffects
  12. {
  13.     public class NegativeEffect : CustomEffectBase
  14.     {
  15.         public NegativeEffect(IImageProvider source)
  16.             : base(source)
  17.         {
  18.         }
  19.  
  20.         protected override void OnProcess(PixelRegion sourcePixelRegion, PixelRegion targetPixelRegion)
  21.         {
  22.             var sourcePixels = sourcePixelRegion.ImagePixels;
  23.             var targetPixels = targetPixelRegion.ImagePixels;
  24.  
  25.             sourcePixelRegion.ForEachRow((index, width, position) =>
  26.             {
  27.                 for (int x = 0; x < width; ++x, ++index)
  28.                 {
  29.                     // This only works for a realtime feed.  It does not work with static images.
  30.                     // 16-17 FPS with built-in NegativeFilter() and 15 FPS with this technique on Lumia 920
  31.                     //targetPixels[index] = ~sourcePixels[index]; 
  32.  
  33.  
  34.                     // 16-17 FPS with built-in NegativeFilter() and 13-14 FPS with this technique on Lumia 920
  35.                     // This techinque will work with both a realtime feed and static images.
  36.                     ///*
  37.                     uint pixel = sourcePixels[index]; // get the current pixel
  38.  
  39.                     if (pixel > 0) // Only take the negative of pixels that have color
  40.                     {
  41.                         // Flip the bits of the pixel to create the negative effect
  42.                         pixel = ~pixel;
  43.  
  44.                         // Assign the pixels back by each component so we can ensure the alpha channel 
  45.                         // is at 255. Otherwise the image will not be visible if it is static.
  46.                         targetPixels[index] = 0xff000000 | (pixel & 0x00ff0000) | (pixel & 0x0000ff00) | pixel & 0x000000ff;
  47.                     }
  48.                     //*/
  49.                 }
  50.             });
  51.         }
  52.     }
  53. }

Testing

The Test Apps for Viewing Custom Filters allow you to cycle through a number of different custom effects (including NegativeEffect) and apply them to the real-time camera preview or a static image.

In addition, the custom effect file can be dropped into your own project, and used as described in the section Using the filter.

Pre-requisites

Performance

The NegativeEffect is less efficient than the Nokia Imaging SDK's inbuilt NegativeFilter.

Device NegativeEffect NegativeFilter
Lumia 920 13-14 FPS 17-18 FPS

The NegativeEffect class runs at about 13-14 FPS (frames per second). The inbuilt NegativeFilter runs at around 17-18 FPS.

The Real Time Filter Demo test project is configured so that the inbuilt and custom effect run side-by-side for easy comparison.

Code walkthrough

The technique for creating a negative image, where the colors are inverted, is as simple as appending a tilde (~) character to the source pixel before assigning it to the target pixel destination. However, this simplicity only seems to work with a realtime camera feed. If you try to do it with a static image, and stop at the tilde conversion without any additional code, it will produce nothing. In order to make it work with static images you must follow it up with a technique to ensure that the alpha channel (0xff000000) is set to 255 when creating the final pixel.

Below we have the ultra simple approach commented out toward the top since it only works with a realtime camera feed. If you do not need to work with static images, then you can use that approach and gain a couple extra FPS. However, if you want a technique that will work with both, at the expense of an extra couple FPS, then the non-commented out section below will do the trick.

  1. // This only works for a realtime feed.  It does not work with static images.
  2. // 16-17 FPS with built-in NegativeFilter() and 15 FPS with this technique on Lumia 920
  3. //targetPixels[index] = ~sourcePixels[index]; 
  4.  
  5.  
  6. // 16-17 FPS with built-in NegativeFilter() and 13-14 FPS with this technique on Lumia 920
  7. // This techinque will work with both a realtime feed and static images.
  8. ///*
  9. uint pixel = sourcePixels[index]; // get the current pixel
  10.  
  11. if (pixel > 0) // Only take the negative of pixels that have color
  12. {
  13.     // Flip the bits of the pixel to create the negative effect
  14.     pixel = ~pixel;
  15.  
  16.     // Assign the pixels back by each component so we can ensure the alpha channel 
  17.     // is at 255. Otherwise the image will not be visible if it is static.
  18.     targetPixels[index] = 0xff000000 | (pixel & 0x00ff0000) | (pixel & 0x0000ff00) | pixel & 0x000000ff;
  19. }
  20. //*/


Using the filter

Drop an image control into your XAML.

  1. <Image x:Name="FilterEffectImage" Width="800" Height="480" Stretch="Fill" Grid.RowSpan="2" />

Use this code to apply the filter effect to your chosen image and assign it to the XAML image control.

  1. // Initialize a WriteableBitmap with the dimensions of the XAML image control
  2. WriteableBitmap writeableBitmap = new WriteableBitmap((int)FilterEffectImage.Width, (int)FilterEffectImage.Height);
  3.  
  4. // Example: Accessing an image stream within a standard photo chooser task callback
  5. // http://msdn.microsoft.com/en-us/library/windowsphone/develop/hh394019(v=vs.105).aspx
  6. //using (var imageStream = new StreamImageSource(e.ChosenPhoto))
  7.  
  8. // Example: Accessing an image stream from a sample picture loaded with the project in a folder called "Pictures"
  9. var resource = App.GetResourceStream(new Uri(string.Concat("Pictures/", "sample_photo_08.jpg"), UriKind.Relative));
  10. using (var imageStream = new StreamImageSource(resource.Stream))
  11. {
  12.     // Applying the custom filter effect to the image stream
  13.     using (var customEffect = new NegativeEffect(imageStream))
  14.     {
  15.         // Rendering the resulting image to a WriteableBitmap
  16.         using (var renderer = new WriteableBitmapRenderer(customEffect, writeableBitmap))
  17.         {
  18.             // Applying the WriteableBitmap to our xaml image control
  19.             FilterEffectImage.Source = await renderer.RenderAsync();
  20.         }
  21.     }
  22. }


License

The code has been released with the standard MIT License, and can be viewed in the Github project here.


Summary

Hopefully you've enjoyed seeing how this custom effect implementation unlocks some of the mystery behind the amazing Nokia Imaging SDK.

As with all articles on the wiki, you are welcome to contribute any changes to this code that would improve the quality, whether it be additional features or improving its efficiency.

This page was last modified on 18 February 2014, at 09:38.
86 page views in the last 30 days.
×