×
Namespaces

Variants
Actions

Color Adjust Custom Effect (Nokia Imaging SDK)

From Nokia Developer Wiki
Jump to: navigation, search

This article explains how to create a Color Adjust Effect similar to the ColorAdjustFilter 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
Dependencies: Nokia Imaging SDK 1.0
Article
Created: Rob.Kachmar (01 Feb 2014)
Last edited: Rob.Kachmar (18 Feb 2014)

Contents

Introduction

The ColorAdjustEffect allows you to adjust the level for each RGB color component up or down, very similar to the Nokia Imaging SDK's inbuilt ColorAdjustFilter. The main differences are that it is implemented as a custom effect and it is less efficient.

Warning.pngWarning: The ColorAdjustEffect should not be used in place of the inbuilt ColorAdjustFilter. 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 ColorAdjustEffect custom effect is provided below (toggle "Expand") and also in a ready-to-use file here: ColorAdjustEffect.cs.

ColorAdjustEffect.cs (03 Feb 2014)

  1. // ============================================================================
  2. // DATE        AUTHOR                   DESCRIPTION
  3. // ----------  -----------------------  ---------------------------------------
  4. // 2014.01.15  Rob.Kachmar              Initial creation
  5. // ============================================================================
  6. // NOTE: The built-in ColorAdjustFilter() is 3 times faster than this. It was 
  7. //       simply created to show the logic that can be used to achieve an effect
  8. //       that allows adjusting the color components of an image.
  9. // ============================================================================
  10.  
  11. using Nokia.Graphics.Imaging;
  12. using System;
  13.  
  14. namespace NISDKExtendedEffects.ImageEffects
  15. {
  16.     public class ColorAdjustEffect : CustomEffectBase
  17.     {
  18.         private double m_RedPercentage = 0;
  19.         private double m_GreenPercentage = 0;
  20.         private double m_BluePercentage = 0;
  21.  
  22.         public ColorAdjustEffect(IImageProvider source, double red = 0, double green = 0, double blue = 0)
  23.             : base(source)
  24.         {
  25.             m_RedPercentage = red;
  26.             m_GreenPercentage = green;
  27.             m_BluePercentage = blue;
  28.         }
  29.  
  30.         protected override void OnProcess(PixelRegion sourcePixelRegion, PixelRegion targetPixelRegion)
  31.         {
  32.             var sourcePixels = sourcePixelRegion.ImagePixels;
  33.             var targetPixels = targetPixelRegion.ImagePixels;
  34.  
  35.             sourcePixelRegion.ForEachRow((index, width, position) =>
  36.             {
  37.                 for (int x = 0; x < width; ++x, ++index)
  38.                 {
  39.                     uint currentPixel = sourcePixels[index]; // get the current pixel
  40.                     uint red = (currentPixel & 0x00ff0000) >> 16; // red color component
  41.                     uint green = (currentPixel & 0x0000ff00) >> 8; // green color component
  42.                     uint blue = currentPixel & 0x000000ff; // blue color component
  43.  
  44.                     // Take the percentage of each color component and add it to itself
  45.                     // ex. A -1.0 or -100% will completely reduce a color component to 0
  46.                     // ex. A 1.0 or 100% will double the value of the color component, up to the maximum of 255 of course
  47.                     red = (uint)Math.Max(0, Math.Min(255, (red + (red * m_RedPercentage))));
  48.                     green = (uint)Math.Max(0, Math.Min(255, (green + (green * m_GreenPercentage))));
  49.                     blue = (uint)Math.Max(0, Math.Min(255, (blue + (blue * m_BluePercentage))));
  50.  
  51.                     uint newPixel = 0xff000000 | (red << 16) | (green << 8) | blue; // reassembling each component back into a pixel
  52.                     targetPixels[index] = newPixel; // assign the newPixel to the equivalent location in the output image
  53.                 }
  54.             });
  55.         }
  56.     }
  57. }

Testing

The Test Apps for Viewing Custom Filters allow you to cycle through a number of different custom effects (including ColorAdjustEffect) 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 ColorAdjustEffect is less efficient than the Nokia Imaging SDK's inbuilt ColorAdjustFilter.

Device ColorAdjustEffect ColorAdjustFilter
Lumia 920 6-7 FPS 18-19 FPS

The ColorAdjustEffect class runs at about 6-7 FPS (frames per second). The inbuilt ColorAdjustFilter runs at around 18-19 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 changing the levels of individual color components in an image involves extracting each RGB color component and then adjusting it up or down as desired. Moving the colors down gets them closer to zero, and moving them up gets them closer to 255.

If you are reducing a color component, you will use a negative percentage value to indicate how much less of the color you would like. If you choose -1.0 (-100%), then the given color component will go to zero. Any other percentage value will be that portion of a particular color component subtracted from itself.

If you are increasing a color component, you will use a positive percentage value to indicate how much more of the color you would like. If you choose 1.0 (100%), then the given color component will be doubled up to the maximum allowable value of 255. Any other percentage value will be that portion of a particular color component added to itself up to the maximum allowable value of 255.

  1. uint currentPixel = sourcePixels[index]; // get the current pixel
  2. uint red = (currentPixel & 0x00ff0000) >> 16; // red color component
  3. uint green = (currentPixel & 0x0000ff00) >> 8; // green color component
  4. uint blue = currentPixel & 0x000000ff; // blue color component
  5.  
  6. // Take the percentage of each color component and add it to itself
  7. // ex. A -1.0 or -100% will completely reduce a color component to 0
  8. // ex. A 1.0 or 100% will double the value of the color component, up to the maximum of 255 of course
  9. red = (uint)Math.Max(0, Math.Min(255, (red + (red * m_RedPercentage))));
  10. green = (uint)Math.Max(0, Math.Min(255, (green + (green * m_GreenPercentage))));
  11. blue = (uint)Math.Max(0, Math.Min(255, (blue + (blue * m_BluePercentage))));


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 ColorAdjustEffect(imageStream, 0.00, 0.50, 0.00))
  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:34.
92 page views in the last 30 days.

Was this page helpful?

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

 

Thank you!

We appreciate your feedback.

×