Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Pixel Manipulation in Silverlight

0.00/5 (No votes)
3 Feb 2012 2  
Pixel Manipulation in Silverlight

Introduction

This article explains how to manipulate the individual pixels of an image to achieve some image processing functionalities. Using the techniques one can easily develop/enhance on functionalities like brightening an Image, changing the contrast of an image, applying gamma, colorizing an image etc...

Background

The reader must be reasonably familiar with Silverlight and its associated controls.

Using the Code

The Application consists of a Main Page with a slider for each image processing routine. The code behind the MouseLeftButtonUp event executes the said functionality. The code is developed in C# with Visual studio 2010 express edition.

A Bit About Initializing

To get hold of the individual pixels of an image the application first supports a Silverlight image control whose source is set to a relative path namely (Images/2.jpg). Once the image is loaded a WriteableBitmap object is created as shown below.

         wbOriginal = new WriteableBitmap((UIElement)sender,null);

Note: Sender is an image control.

WriteableBitmap objects can also be constructed from an BitmapImage object as is done in the code. Loading an image into BitmapImage object is pretty straight forward. Once loaded into BitmapImage object you just need to assign the source property of the Image Silverlight control to this BitmapImage object. Whenever the source of the Image control changes the associated WriteableBitmap object automatically gets updated to the new Image.

Let us start with the change-brightness functionality.

Brightness

Changing the brightness is just adding a fixed number(<255) to the individual pixels of an Image. First a temporary copy of the associated WriteableBitmap object is made and the individual pixel's Red, Green and Blue color is extracted into pixel as shown below:

int pixel = wb.Pixel[i];
int B = (int)(pixel & 0xFF); pixel >>= 8;
int G = (int)(pixel & 0xFF); pixel >>= 8;
int R = (int)(pixel & 0xFF); pixel >>= 8;
int A = (int)(pixel);

Every pixel is represented by a 32 bit integer, where the Blue, Green, Red occupy the first second and third positions in the pixel. Each of Red, Green and Blue can take a value starting from 0 to 255, a byte value to be precise inside the int pixel varaible.

The amount of brightness is determined by how far the Brightness slider has moved from its previous position. That value is added to the R,G,B of every individual pixel and normalized to 255 as shown below.

B += (int)sliderBrightness.Value; 
R += (int)sliderBrightness.Value; 
G += int)sliderBrightness.Value;
if (R > 255) R = 255; if (G > 255) G = 255; if (B > 255) B = 255;
if (R < 0) R = 0; if (G < 0) G = 0; if (B < 0) B = 0;

Now that this is done it is time to put back these values first into wb (the new WriteableBitmap object) and then back into Silverlight image control.

wb.Pixels[i] = B | (G << 8) | (R << 16) | (A << 24);
wb.Invalidate();
image1.Source = wb;

Let us move on to another imaging processing routine namely the Power law.

Power Law

The basics of getting hold of the individual pixels remain the same. The power law actually darkens the dark region and brightens the bright regions of an image. for this the power law first defines an array of doubles

double[] dPowerLawFactorArray = { .6, 1.7, .8, .9, 1.02, 1.03, 1.05, 1.07, 1.09, 1.1};

based on the power law slider movement a value from this array is chosen and applied to the R,G, and B values of individual pixels as shown below.

//nIndex corresponds to the current Power law slider position
double dPowerlawfactor = dPowerLawFactorArray[nIndex]; 
R = (int)Math.Pow(R, dPowerlawfactor);
G = (int)Math.Pow(G, dPowerlawfactor);
B = (int)Math.Pow(B, dPowerlawfactor);

Changing the contrast of an Image

double[] contrastArray = { 1, 1.2, 1.3, 1.6, 1.7, 1.9, 2.1, 2.4, 2.6, 2.9 };
//nIndex corresponds to the current Contrats slider position
double CFactor = contrastArray[nIndex]; 
R = (int) Math.Max(0, Math.Min(255, (((R - 128) * CFactor) + 128)));
G = (int)Math.Max(0, Math.Min(255, (((G - 128) * CFactor) + 128)));
B = (int)Math.Max(0, Math.Min(255, (((B - 128) * CFactor) + 128)));

Gamma Equations

double[] dGammaArray = new double[19];

dGammaArray[0] = .1;
dGammaArray[1] = .2;
dGammaArray[2] = .3;
dGammaArray[3] = .4;
dGammaArray[4] = .5;
dGammaArray[5] = .6;
dGammaArray[6] = .7;
dGammaArray[7] = .8;
dGammaArray[8] = .9;
dGammaArray[9] = 1;
dGammaArray[10] = 1.1;
dGammaArray[11] = 1.2;
dGammaArray[12]=1.3;
dGammaArray[13]=1.4;
dGammaArray[14] = 1.5;
dGammaArray[15] = 1.6;
dGammaArray[16] = 1.7;
dGammaArray[17] = 1.8;
dGammaArray[18] = 1.9;

//nIndex corresponds to the current Gamma slider position
double dGamma = dGammaArray[nIndex];

double dDinvgamma = 1.0 / dGamma;

double dMax = Math.Pow(255.0, dDinvgamma) / 255.0;

R = (int)Math.Max(0, Math.Min(255, (Math.Pow(R, dDinvgamma) / dMax)));
G = (int)Math.Max(0, Math.Min(255, (Math.Pow(G, dDinvgamma) / dMax)));
B = (int)Math.Max(0, Math.Min(255, (Math.Pow(B, dDinvgamma) / dMax)));

Colorizing an Image

In this the user first sets the amount of Blue, Red, Green to apply on the chosen image with the help of the given sliders. Once a choice is made the "Color Image" Button can be clicked. This functionality applies the chosen colors to the image as shown below:

R += (int)sliderRedNess.Value; 
G += (int)sliderGreenNess.Value;
B += (int)sliderBlueNess.Value;

Grey Scale

This is just the average of the R,G,B values applied to every pixel

R = G = B = (R + G + B) / 3;

Just to make the application interesting some StoryBoard animations and easing functions are applied to the image control. This animation rotates the image in X,Y and Z axis before settling down to a normal view.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here