C# How to: Bitmap Pixel manipulation using LINQ Queries

Article Purpose

In this article we explore manipulating a  ’s underlying pixel data. The process of Pixel data manipulation at its core feature the implementation of Queries targeting raw pixel data.

Update: I’ve published a follow-up article – Part 2: The banner images in this article were generated using the concepts explored in the follow-up article. The source image has been licenced under the Creative Commons Attribution-Share Alike 3.0 Unported license and can be downloaded from .

Led_Banner1

Sample source code

This article is accompanied by a sample source code Visual Studio project which is available for download here.

Led_Banner2

Using the sample Application

This article’s associated sample source code defines a sample application, detailing the concepts explored by this article. The sample application implements two types of image filters: Swapping each pixel’s colour components and shifting pixels to different locations within the image data buffer.

The image shown below is a screenshot of the Bitmap Pixel Manipulation application in action:

BitmapPixelManipulation

The sample application allows the user to specify an input source image which can then be modified by implementing an image filter. If desired the user has the option to save the new/result image to the file system.

Led_Banner3

Extracting Pixel values from a Bitmap image

The sample source code defines the ArgbPixel class which is implemented to represent an individual pixel. The definition as follows:

public class ArgbPixel
{
    public byte blue = 0;
    public byte green = 0;
    public byte red = 0;
    public byte alpha = 0;

public ArgbPixel() { }
public ArgbPixel(byte[] colorComponents) { blue = colorComponents[0]; green = colorComponents[1]; red = colorComponents[2]; alpha = colorComponents[3]; }
public byte[] GetColorBytes() { return new byte[]{blue, green, red, alpha}; } }

Each pixel is defined by four member variables of type byte: blue, red, green and alpha. The ArgbPixel class defines an overloaded constructor which allows for creating an instance by specifying the four colour components as byte values. By invoking the GetColorBytes method the calling code can access the underlying colour component byte values in the form of a byte array.

Led_Banner1

The Colour Swap filter

The Colour swap filter acts as an image filter by implementing various combinations of swapping each individual pixel’s Alpha, Red, Green and Blue colour channels. The sample source code defines the ColorSwapType , intended to provide a collection of possible pixel colour channel swap operations. The code snippet listed below provides the definition of the ColorSwapType type:

public enum ColourSwapType
{
    ShiftRight,
    ShiftLeft,
    SwapBlueAndRed,
    SwapBlueAndRedFixGreen,
    SwapBlueAndGreen,
    SwapBlueAndGreenFixRed,
    SwapRedAndGreen,
    SwapRedAndGreenFixBlue
}

The following section provides an explanation of each Colour Swap method:

  • ShiftRight – Starting with Blue each colour channel’s value will be copied to the colour channel to the right.
  • ShiftLeft – Starting with Blue each colour channel’s value will be copied to the colour channel to the left.
  • SwapBlueAndRed - Blue and Red values are swapped, Green remains unchanged.
  • SwapBlueAndRedFixGreen - Blue and Red values are swapped, each pixel’s Green value is set to the same value as specified by the calling code.
  • SwapBlueAndGreen - Blue and Green values are swapped, Red remains unchanged.
  • SwapBlueAndGreenFixRed - Blue and Green values are swapped, each pixel’s Red value is set to the same value as specified by the calling code.
  • SwapRedAndGreen - Red and Green values are swapped, Blue remains unchanged.
  • SwapRedAndGreenFixBlue - Red and Green values are swapped, each pixel’s Blue value is set to the same value as specified by the calling code.

Led_Banner2

From a Bitmap buffer to a Pixel List

The sample source provides the definition for the GetPixelListFromBitmap method. The purpose behind this method is to read a ’s underlying colour component byte buffer data and create a generic collection of type ArgbPixel. By representing the data as a generic collection we are able implement query operations. The code snippet below details the GetPixelListFromBitmap method definition.

private static List<ArgbPixel> GetPixelListFromBitmap(Bitmap sourceImage)
{
     BitmapData sourceData = sourceImage.LockBits(new Rectangle(0, 0, 
                 sourceImage.Width, sourceImage.Height), 
                 ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);

byte[] sourceBuffer = new byte[sourceData.Stride * sourceData.Height]; Marshal.Copy(sourceData.Scan0, sourceBuffer, 0, sourceBuffer.Length); sourceImage.UnlockBits(sourceData);
List<ArgbPixel> pixelList = new List<ArgbPixel>(sourceBuffer.Length / 4);
using (MemoryStream memoryStream = new MemoryStream(sourceBuffer)) { memoryStream.Position = 0; BinaryReader binaryReader = new BinaryReader(memoryStream);
while (memoryStream.Position + 4 <= memoryStream.Length) { ArgbPixel pixel = new ArgbPixel(binaryReader.ReadBytes(4)); pixelList.Add(pixel); }
binaryReader.Close(); }
return pixelList; }

The GetPixelListFromBitmap accepts a parameter and returns a generic collection of type ArgbPixel. Within the method body the first operation performed involves locking the pixel data in memory by invoking the method. By locking data in memory we are in effect signalling the to not shift around in memory the underlying data whilst we are busy accessing the data.

Next, the sample source code implements the method in order to copy the ’s colour component data in the form of a byte array. Once we’ve copied the pixel data we can unlock the by invoking .

The final operation performed by the GetPixelListFromBitmap involves iterating through the byte array of colour components. With each loop we make use of a , reading four bytes at a time and passing the result to the overloaded constructor exposed by the ArgbPixel class.

Led_Banner3

Applying Linq queries to Pixel Data

This article’s sample source code implements queries through the SwapColors extension method which targets the Bitmap class. The definition is detailed by the following code snippet:

 public static Bitmap SwapColors(this Bitmap sourceImage, 
                                 ColourSwapType swapType, 
                                 byte fixedValue = 0)
{
     List<ArgbPixel> pixelListSource = GetPixelListFromBitmap(sourceImage);

List<ArgbPixel> pixelListResult = null;
switch (swapType) { case ColourSwapType.ShiftRight: { pixelListResult = (from t in pixelListSource select new ArgbPixel { blue = t.red, red = t.green, green = t.blue, alpha = t.alpha}).ToList(); break; } case ColourSwapType.ShiftLeft: { pixelListResult = (from t in pixelListSource select new ArgbPixel { blue = t.green, red = t.blue, green = t.red, alpha = t.alpha}).ToList(); break; } case ColourSwapType.SwapBlueAndRed: { pixelListResult = (from t in pixelListSource select new ArgbPixel { blue = t.red, red = t.blue, green = t.green, alpha = t.alpha}).ToList(); break; case ColourSwapType.SwapBlueAndRedFixGreen: { pixelListResult = (from t in pixelListSource select new ArgbPixel { blue = t.red, red = t.blue, green = fixedValue, alpha = t.alpha}).ToList(); break; } case ColourSwapType.SwapBlueAndGreen: { pixelListResult = (from t in pixelListSource select new ArgbPixel { blue = t.green, red = t.red, green = t.blue, alpha = t.alpha}).ToList(); break; } case ColourSwapType.SwapBlueAndGreenFixRed: { pixelListResult = (from t in pixelListSource select new ArgbPixel { blue = t.green, red = fixedValue, green = t.blue, alpha = t.alpha}).ToList(); break; } case ColourSwapType.SwapRedAndGreen: { pixelListResult = (from t in pixelListSource select new ArgbPixel { blue = t.blue, red = t.green, green = t.red, alpha = t.alpha}).ToList(); break; } case ColourSwapType.SwapRedAndGreenFixBlue: { pixelListResult = (from t in pixelListSource select new ArgbPixel { blue = fixedValue, red = t.green, green = t.red, alpha = t.alpha}).ToList(); break; } }
Bitmap resultBitmap = GetBitmapFromPixelList(pixelListResult, sourceImage.Width, sourceImage.Height);
return resultBitmap; }

The SwapColors extension method accepts as parameters an value of type ColourSwapType and a byte parameter fixedValue defined with a default value of 0.

The GetPixelListFromBitmap method discussed earlier is implemented in order to create a generic of type ArgbPixel. The bulk of the method’s implementation is performed next by applying a switch statement on the ColourSwapType parameter. The original List<ArgbPixel> collection is used to populate a resulting List<ArgbPixel> collection. Assignment from source to result collection occurs through a query implementing the relevant ColourSwapType.

The last operation performed by the SwapColors extension method involves converting the resulting List<ArgbPixel> collection back to a object through invoking the GetBitmapFromPixelList method. The following section provides a description of the GetBitmapFromPixelList method.

Led_Banner1

From a Pixel List to a Bitmap

In the sample source code the GetPixelListFromBitmap method discussed earlier, is complimented by its inverse, the GetBitmapFromPixelList method. As the name implied the GetBitmapFromPixelList method’s purpose is to convert a generic of type ArgbPixel to a object. The definition as follows:

private static Bitmap GetBitmapFromPixelList(List<ArgbPixel> pixelList, int width, int height)
{
     Bitmap resultBitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb);

BitmapData resultData = resultBitmap.LockBits(new Rectangle(0, 0, resultBitmap.Width, resultBitmap.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
byte[] resultBuffer = new byte[resultData.Stride * resultData.Height];
using (MemoryStream memoryStream = new MemoryStream(resultBuffer)) { memoryStream.Position = 0; BinaryWriter binaryWriter = new BinaryWriter(memoryStream);
foreach (ArgbPixel pixel in pixelList) { binaryWriter.Write(pixel.GetColorBytes()); }
binaryWriter.Close(); }
Marshal.Copy(resultBuffer, 0, resultData.Scan0, resultBuffer.Length); resultBitmap.UnlockBits(resultData);
return resultBitmap; }

The GetBitmapFromPixelList method accepts as parameters a generic of type ArgbPixel, width and height of type int. The width and height parameters indicates the size of the original , which will be used when creating a new resulting .

The first step performed by the GetBitmapFromPixelList method is to create a resulting object and locking into memory the underlying data by invoking the method.

The bulk of the work performed by the GetBitmapFromPixelList method occurs in the form of iterating the List of ArgbPixel parameter and writing the Pixel’s underlying colour components to a byte buffer related to the resulting .

In the last step being performed byte array of colour component data is copied to the resulting by invoking .

Led_Banner2

Reversing a List of Pixels

As an additional example the sample source code also defines the FlipPixels extension method. This method provides a quick implementation of turning a image upside down. The implementation as follows:

public static Bitmap FlipPixels(this Bitmap sourceImage)
{
     List<ArgbPixel> pixelList = GetPixelListFromBitmap(sourceImage);

pixelList.Reverse();
Bitmap resultBitmap = GetBitmapFromPixelList(pixelList, sourceImage.Width, sourceImage.Height);
return resultBitmap; }

The FlipPixels extension method targets the class and returns a object. As discussed earlier the method invokes the GetPixelListFromBitmap and GetBitmapFromPixelList methods. Reversing the order of the ArgbPixel objects is achieved through invoking the method.

Led_Banner3

Filter implementation examples

This section contains the eye candy of this article. The following set of images were created from a single input source image. The original image is licensed under the Creative Commons Attribution 2.0 Generic license and can be downloaded from Wikipedia.

The Original Image

SunflowerSunset2

Shift Left

ShiftLeft

Shift Right

ShiftRight

Swap Blue and Red

SwapBlueAndRed

Swap Blue and Red, fix Green at 0

SwapBlueAndRedFixGreen0

Swap Blue and Green

SwapBlueAndGreen

Swap Blue and Green, fix Red at 25

SwapBlueAndGreenFixRed25

Swap Red and Green

SwapRedAndGreen

Swap Red and Green, fix Blue at 0

SwapRedAndGreenFixBlue0

Swap Red and Green, fix Blue at 115

SwapRedAndGreenFixBlue115

Swap Red and Green, fix Blue at 200

SwapRedAndGreenFixBlue200

43 Responses to “C# How to: Bitmap Pixel manipulation using LINQ Queries”



  1. 1 Image Filters: Sunflower | Software by Default Trackback on March 29, 2013 at 4:31 AM
  2. 2 C# How to: Linq to Bitmaps – Partial Colour Inversion | Software by Default Trackback on April 1, 2013 at 9:44 PM
  3. 3 RSS Buttons: Alternative Colours | Software by Default Trackback on April 3, 2013 at 6:41 AM
  4. 4 C# How to: Bitmap Colour Tint | Software by Default Trackback on April 26, 2013 at 1:07 AM
  5. 5 C# How to: Bitwise Bitmap Blending | Software by Default Trackback on April 26, 2013 at 1:13 AM
  6. 6 C# How to: Image Contrast | Software by Default Trackback on April 26, 2013 at 1:15 AM
  7. 7 C# How to: Image Solarise | Software by Default Trackback on April 26, 2013 at 1:17 AM
  8. 8 C# How to: Bitmap Colour Shading | Software by Default Trackback on April 26, 2013 at 1:19 AM
  9. 9 C# How to: Bi-tonal Bitmaps | Software by Default Trackback on April 26, 2013 at 1:20 AM
  10. 10 C# How to: Bitmap Colour Balance | Software by Default Trackback on April 26, 2013 at 1:22 AM
  11. 11 C# How to: Image Arithmetic | Software by Default Trackback on April 27, 2013 at 8:21 AM
  12. 12 C# How to: Image Convolution | Software by Default Trackback on May 1, 2013 at 5:41 PM
  13. 13 C# How to: Image filtering implemented using a ColorMatrix | Software by Default Trackback on May 1, 2013 at 9:04 PM
  14. 14 C# How to: Blending Bitmap images using colour filters | Software by Default Trackback on May 1, 2013 at 10:50 PM
  15. 15 C# How to: Decoding/Converting Base64 strings to Bitmap images | Software by Default Trackback on May 2, 2013 at 9:34 PM
  16. 16 C# How to: Image Edge Detection | Software by Default Trackback on May 11, 2013 at 1:22 PM
  17. 17 C# How to: Difference Of Gaussians | Software by Default Trackback on May 18, 2013 at 12:50 AM
  18. 18 C# How to: Image Median Filter | Software by Default Trackback on May 18, 2013 at 4:15 AM
  19. 19 C# How to: Image Unsharp Mask | Software by Default Trackback on May 18, 2013 at 12:18 PM
  20. 20 C# How to: Image Colour Average | Software by Default Trackback on May 18, 2013 at 9:48 PM
  21. 21 C# How to: Image Erosion and Dilation | Software by Default Trackback on May 19, 2013 at 10:24 AM
  22. 22 C# How to: Morphological Edge Detection | Software by Default Trackback on May 25, 2013 at 8:22 AM
  23. 23 C# How to: Boolean Edge Detection | Software by Default Trackback on June 1, 2013 at 2:08 AM
  24. 24 C# How to: Gradient Based Edge Detection | Software by Default Trackback on June 1, 2013 at 4:46 PM
  25. 25 C# How to: Image Cartoon Effect | Software by Default Trackback on June 2, 2013 at 4:13 PM
  26. 26 C# How to: Sharpen Edge Detection | Software by Default Trackback on June 7, 2013 at 5:11 AM
  27. 27 C# How to: Calculating Gaussian Kernels | Software by Default Trackback on June 8, 2013 at 10:58 AM
  28. 28 C# How to: Image Blur | Software by Default Trackback on June 9, 2013 at 10:19 PM
  29. 29 C# How to: Image Transform Rotate | Software by Default Trackback on June 16, 2013 at 10:39 AM
  30. 30 C# How to: Image Transform Shear | Software by Default Trackback on June 16, 2013 at 5:44 PM
  31. 31 C# How to: Compass Edge Detection | Software by Default Trackback on June 22, 2013 at 9:34 PM
  32. 32 C# How to: Oil Painting and Cartoon Filter | Software by Default Trackback on June 30, 2013 at 10:47 AM
  33. 33 C# How to: Stained Glass Image Filter | Software by Default Trackback on June 30, 2013 at 10:49 AM
  34. 34 C# How to: Generate a Web Service from WSDL | Software by Default Trackback on June 30, 2013 at 4:07 PM
  35. 35 C# How to: Bitmap Colour Substitution implementing thresholds | Software by Default Trackback on July 6, 2013 at 4:32 PM
  36. 36 C# How to: Swapping Bitmap ARGB Colour Channels | Software by Default Trackback on July 6, 2013 at 5:01 PM
  37. 37 C# How to: Image filtering by directly manipulating Pixel ARGB values | Software by Default Trackback on July 8, 2013 at 2:57 AM
  38. 38 C# How to: Image ASCII Art | Software by Default Trackback on July 14, 2013 at 7:22 AM
  39. 39 C# How to: Weighted Difference of Gaussians | Software by Default Trackback on July 14, 2013 at 8:11 PM
  40. 40 C# How to: Image Boundary Extraction | Software by Default Trackback on July 21, 2013 at 10:23 AM
  41. 41 C# How to: Image Abstract Colours Filter | Software by Default Trackback on July 28, 2013 at 7:40 PM
  42. 42 C# How to: Fuzzy Blur Filter | Software by Default Trackback on August 9, 2013 at 6:39 AM
  43. 43 C# How to: Image Distortion Blur | Software by Default Trackback on August 9, 2013 at 10:12 PM

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s




about.me :: Dewald Esterhuizen

Dewald Esterhuizen

Blog Stats

  • 144,463 hits

Gravatar :: Dewald Esterhuizen

SoftwareByDefault QR Code

SoftwareByDefault QR Code

I review for the O'Reilly Blogger Review Program

Enter your email address to follow and receive notifications of new posts by email.

Join 151 other followers

Archives

Twitter feed

del.icio.us Links

http://softwarebydefault.com
http://softwarebydefault.com
http://softwarebydefault.com
http://softwarebydefault.com
http://softwarebydefault.com

Follow

Get every new post delivered to your Inbox.

Join 151 other followers

%d bloggers like this: