×

Discussion Board

Results 1 to 4 of 4
  1. #1
    Registered User
    Join Date
    Oct 2013
    Posts
    8

    ColorMatrix filter using Nokia Imaging SDK

    I'm new to image processing and Imaging SDK. The API reference doesn't have a filter that would accept a color transformation matrix to apply to the image.
    For example, consider this "matrix" in pseudo-code:
    r = [1.25, 0.0, 0.4];
    g = [0.2, 1.25, 0.4];
    b = [0.0, 0.0, 1.25];

    Is there any way for me to achieve the same effect using the predefined filters?

    The alternative seems to be to use WriteableBitmap for per-pixel manipulation which is less desireable.

    Edit: added matrix sample.
    Last edited by vishnevetskaya; 2013-10-03 at 00:41.

  2. #2
    Registered User
    Join Date
    Oct 2013
    Posts
    8

    Re: ColorMatrix filter using Nokia Imaging SDK

    I thought I'd post my implementation of a color matrix transformation for anyone who might need it. Feedback welcome.

    Sample usage:
    Code:
    	var matrix = new ColorMatrixFilter(
    		red: new[] { 0.9f, 0.06f, 0.23f, 0 },
    		green: new[] { 0.1f, 0.755f, 0.25f, 0 },
    		blue: new[] { 0f, 0, 0.95f, 0 });
    
    	await matrix.ApplyAsync(bitmap);
    And here is the filter implementation:
    Code:
    using System;
    using System.Threading.Tasks;
    using System.Windows.Media.Imaging;
    
    namespace Filters
    {
    	public class ColorMatrixFilter : IBitmapFilter
    	{
    		private readonly float[] _alpha;
    		private readonly float[] _bias;
    		private readonly float[] _blue;
    		private readonly float[] _green;
    		private readonly float[] _red;
    
    		public ColorMatrixFilter(float[] red = null, float[] green = null, float[] blue = null, float[] alpha = null, float[] bias = null)
    		{
    			if (red != null && red.Length != 4)
    				throw new ArgumentException("Vector must have 4 components.", "red");
    			if (green != null && green.Length != 4)
    				throw new ArgumentException("Vector must have 4 components.", "green");
    			if (blue != null && blue.Length != 4)
    				throw new ArgumentException("Vector must have 4 components.", "blue");
    			if (alpha != null && alpha.Length != 4)
    				throw new ArgumentException("Vector must have 4 components.", "alpha");
    			if (bias != null && bias.Length != 4)
    				throw new ArgumentException("Vector must have 4 components.", "bias");
    
    			_red = red ?? new[] {1f, 0, 0, 0};
    			_green = green ?? new[] {0, 1f, 0, 0};
    			_blue = blue ?? new[] {0, 0, 1f, 0};
    			_alpha = alpha ?? new[] {0, 0, 0, 1f};
    			_bias = bias;
    		}
    
    		public async Task ApplyAsync(WriteableBitmap bitmap)
    		{
    			if (bitmap == null)
    				throw new ArgumentNullException("bitmap");
    
    			//if larger than 2Mpix run on threadpool
    			if (bitmap.PixelWidth*bitmap.PixelHeight >= 2663424)
    				await Task.Run(() => Apply(bitmap));
    			else
    				Apply(bitmap);
    		}
    
    		private void Apply(WriteableBitmap bitmap)
    		{
    			for (int y = 0; y < bitmap.PixelHeight; y++)
    			{
    				for (int x = 0; x < bitmap.PixelWidth; x++)
    				{
    					int index = y*bitmap.PixelWidth + x;
    
    					// extract color components
    					int c = bitmap.Pixels[index];
    
    					// premultiplied alpha
    					var a = (byte) (c >> 24);
    					// prevent division by zero
    					int ai = a == 0 ? 1 : a;
    					// scale inverse alpha to use cheap integer mul bit shift
    					ai = (255 << 8)/ai;
    					var r = (byte) ((c >> 16 & 0xFF)*ai >> 8);
    					var g = (byte) ((c >> 8 & 0xFF)*ai >> 8);
    					var b = (byte) ((c & 0xFF)*ai >> 8);
    
    					// transform
    					float red = r*_red[0] + g*_red[1] + b*_red[2] + a*_red[3] + 0.5f;
    					float green = r*_green[0] + g*_green[1] + b*_green[2] + a*_green[3] + 0.5f;
    					float blue = r*_blue[0] + g*_blue[1] + b*_blue[2] + a*_blue[3] + 0.5f;
    					float alpha = r*_alpha[0] + g*_alpha[1] + b*_alpha[2] + a*_alpha[3] + 0.5f;
    
    					if (_bias != null)
    					{
    						red += _bias[0];
    						green += _bias[1];
    						blue += _bias[2];
    						alpha += _bias[3];
    					}
    
    					// clamp to 0-255 range
    					if (red > 255)
    						r = 255;
    					else if (red < 0)
    						r = 0;
    					else
    						r = (byte) red;
    
    					if (green > 255)
    						g = 255;
    					else if (green < 0)
    						g = 0;
    					else
    						g = (byte) green;
    
    					if (blue > 255)
    						b = 255;
    					else if (blue < 0)
    						b = 0;
    					else
    						b = (byte) blue;
    
    					if (alpha > 255)
    						a = 255;
    					else if (alpha < 0)
    						a = 0;
    					else
    						a = (byte) alpha;
    
    					ai = a + 1;
    
    					// set the transformed values back
    					bitmap.Pixels[index] = (a << 24)
    					                       | (byte) (r*ai >> 8) << 16
    					                       | (byte) (g*ai >> 8) << 8
    					                       | (byte) (b*ai >> 8);
    				}
    			}
    		}
    	}
    }
    Last edited by vishnevetskaya; 2013-10-08 at 05:52. Reason: Added alpha and bias vectors

  3. #3
    Nokia Developer Moderator
    Join Date
    Feb 2006
    Location
    Oslo, Norway
    Posts
    28,692

    Re: ColorMatrix filter using Nokia Imaging SDK

    Yes, checking the available filters, a custom loop is the only way. Wrapping it into an asynchronous Task is also a good idea.
    You can always do some bit-hunting (having a single loop, making it to count downwards, using separate readonly fields for each matrix element, perhaps experimenting with fixed point mathematics), but generally it should be efficient enough already.

  4. #4
    Registered User
    Join Date
    Oct 2013
    Posts
    8

    Re: ColorMatrix filter using Nokia Imaging SDK

    I've updated my implementation to include alpha & bias vectors into the matrix as happened to need those features. The bit crunching comes from the awesome WriteableBitmapEx lib.

Similar Threads

  1. Nokia Imaging SDK Feedback (Competition)
    By skalogir in forum Windows Phone Imaging
    Replies: 77
    Last Post: 2013-11-15, 00:22
  2. Unable to Install nokia imaging sdk 0.9.2
    By bluzak in forum Windows Phone Imaging
    Replies: 3
    Last Post: 2013-08-16, 01:47
  3. Replies: 2
    Last Post: 2008-09-30, 11:01

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
×