C# How to: Image filtering implemented using a ColorMatrix

Article purpose

This is based around creating basic filters. The different types of filters discussed are: Grayscale, Transparency, Image Negative and Sepia tone. All filters are implemented as targeting the Image class, as well as the Bitmap class as the result of inheritance and upcasting.

Note: This is a follow up to . The previously published related article implements filtering by performing calculations and updating pixel colour component values namely Alpha, Red, Green and Blue. This achieves the same filtering through implementing various transformations, in essence providing an alternative solution. For the sake of convenience I have included the pixel manipulation in addition to the detailed by this article.

Sample source code

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

Implementing a ColorMatrix

From :

Defines a 5 x 5 matrix that contains the coordinates for the RGBAW space. Several methods of the ImageAttributes class adjust image colors by using a color matrix.

The matrix coefficients constitute a 5 x 5 linear transformation that is used for transforming ARGB homogeneous values. For example, an ARGB vector is represented as red, green, blue, alpha and w, where w is always 1.

When implementing a translation using the class values specified are added to one or more of the four colour components. A value that is to be added may only range from 0 to 1 inclusive. Note that adding a negative value results in subtracting values. A good article that illustrates implementing a can be found on MSDN: How to: Translate Image Colors.

The following code snippet provides the implementation of the ApplyColorMatrix method.

private static Bitmap ApplyColorMatrix(Image sourceImage, ColorMatrix colorMatrix)
{
    Bitmap bmp32BppSource = GetArgbCopy(sourceImage);
    Bitmap bmp32BppDest = new Bitmap(bmp32BppSource.Width, bmp32BppSource.Height, PixelFormat.Format32bppArgb);

using (Graphics graphics = Graphics.FromImage(bmp32BppDest)) { ImageAttributes bmpAttributes = new ImageAttributes(); bmpAttributes.SetColorMatrix(colorMatrix); graphics.DrawImage(bmp32BppSource, new Rectangle(0, 0, bmp32BppSource.Width, bmp32BppSource.Height), 0, 0, bmp32BppSource.Width, bmp32BppSource.Height, GraphicsUnit.Pixel, bmpAttributes);
}
bmp32BppSource.Dispose();
return bmp32BppDest; }

The ApplyColorMatrix method signature defines a parameter of type and a second parameter of type . This method is intended to apply the specified upon the parameter specified.

The source is firstly copied in order to ensure that the that is to be transformed is defined with a pixel format of 32 bits per pixel, consisting of the colour components Alpha, Red, Green and Blue. Next we create a blank memory defined to reflect the same size dimensions as the original source . A can be implemented by means of applying an when invoking the defined by the class.

Creating an ARGB copy

The source code snippet listed below converts source images into 32Bit ARGB formatted :

private static Bitmap GetArgbCopy(Image sourceImage)
{
    Bitmap bmpNew = new Bitmap(sourceImage.Width, sourceImage.Height, PixelFormat.Format32bppArgb);

using(Graphics graphics = Graphics.FromImage(bmpNew)) { graphics.DrawImage(sourceImage, new Rectangle (0, 0, bmpNew.Width, bmpNew.Height), new Rectangle (0, 0, bmpNew.Width, bmpNew.Height), GraphicsUnit.Pixel); graphics.Flush(); }
return bmpNew; }

The GetArgbCopy method creates a blank memory Bitmap having the same size dimensions as the source image. The newly created Bitmap is explicitly specified to conform to a 32Bit ARGB format. By making use of a Graphics object of which the context is bound to the new Bitmap instance the source code draws the original image to the new Bitmap.

The Transparency Filter

The transparency filter is intended to create a copy of an , increase the copy’s level of transparency and return the modified copy to the calling code. Listed below is source code which defines the DrawWithTransparency extension method.

public static Bitmap DrawWithTransparency(this Image sourceImage)
{
    ColorMatrix colorMatrix = new ColorMatrix(new float[][]
                        {
                            new float[]{1, 0, 0, 0, 0},
                            new float[]{0, 1, 0, 0, 0},
                            new float[]{0, 0, 1, 0, 0},
                            new float[]{0, 0, 0, 0.3f, 0},
                            new float[]{0, 0, 0, 0, 1}
                        });

return ApplyColorMatrix(sourceImage, colorMatrix); }

Due to the ApplyColorMatrix method defined earlier implementing an filter simply consists of defining the filter algorithm in the form of a and then invoking ApplyColorMatrix.

The is defined to apply no change to the Red, Green and Blue components whilst reducing the Alpha component by 70%.

Image Filters Transparency ColorMatrix

The Grayscale Filter

All of the filter illustrated in this are implemented in a fashion similar to the DrawWithTransparency method. The DrawAsGrayscale is implemented as follows:

public static Bitmap DrawAsGrayscale(this Image sourceImage)
{
    ColorMatrix colorMatrix = new ColorMatrix(new float[][]
                        {
                            new float[]{.3f, .3f, .3f, 0, 0},
                            new float[]{.59f, .59f, .59f, 0, 0},
                            new float[]{.11f, .11f, .11f, 0, 0},
                            new float[]{0, 0, 0, 1, 0},
                            new float[]{0, 0, 0, 0, 1}
                        });

return ApplyColorMatrix(sourceImage, colorMatrix); }

The grayscale filter is achieved by adding together 11% blue, 59% green and 30% red, then assigning the total value to each colour component.

Image Filters Grayscale ColorMatrix

The Sepia Tone Filter

The sepia tone filter is implemented in the DrawAsSepiaTone. Notice how this method follows the same convention as the previously discussed filters. The source code listing is detailed below.

 public static Bitmap DrawAsSepiaTone(this Image sourceImage)
{
     ColorMatrix colorMatrix = new ColorMatrix(new float[][] 
                {
                        new float[]{.393f, .349f, .272f, 0, 0},
                        new float[]{.769f, .686f, .534f, 0, 0},
                        new float[]{.189f, .168f, .131f, 0, 0},
                        new float[]{0, 0, 0, 1, 0},
                        new float[]{0, 0, 0, 0, 1}
                });

return ApplyColorMatrix(sourceImage, colorMatrix); }

The formula used to calculate a sepia tone differs significantly from the grayscale filter discussed previously. The formula can be simplified as follows:

  • Red Component: Sum total of: 39.3% red, 34.9% green , 27.2% blue
  • Green Component: Sum total of: 76.9% red, 68.6% green , 53.4% blue
  • Blue Component: Sum total of: 18.9% red, 16.8% green , 13.1% blue

Image Filters Sepia ColorMatrix

The Negative Image Filter

We can implement an filter that resembles film negatives by literally inverting every pixel’s colour components. Listed below is the source code implementation of the DrawAsNegative .

 public static Bitmap DrawAsNegative(this Image sourceImage)
{
     ColorMatrix colorMatrix = new ColorMatrix(new float[][] 
                    {
                            new float[]{-1, 0, 0, 0, 0},
                            new float[]{0, -1, 0, 0, 0},
                            new float[]{0, 0, -1, 0, 0},
                            new float[]{0, 0, 0, 1, 0},
                            new float[]{1, 1, 1, 1, 1}
                    });

return ApplyColorMatrix(sourceImage, colorMatrix); }

Notice how the negative filter subtracts 1 from each colour component, remember the valid range being 0 to 1 inclusive. This in reality inverts each pixel’s colour component bits. The transform being applied can also be expressed as implementing the bitwise compliment operator on each pixel.

Image Filters Negative Color Matrix

The implementation

The filters described in this are all implemented by means of a . filtering is applied by selecting the corresponding radio button. The source loaded from the file system serves as input to the various filter methods, the filtered copy returned will be displayed next to the original source .

The following code snippet details the radio button checked changed event handler:

private void OnCheckChangedEventHandler(object sender, EventArgs e)
{
    if (picSource.BackgroundImage != null)
    {
        if (rdGrayscaleBits.Checked == true)
        {
             picOutput.BackgroundImage = picSource.BackgroundImage.CopyAsGrayscale();
        }
        else if (rdGrayscaleDraw.Checked == true)
        {
             picOutput.BackgroundImage = picSource.BackgroundImage.DrawAsGrayscale();
        }
        else if (rdTransparencyBits.Checked == true)
        {
             picOutput.BackgroundImage = picSource.BackgroundImage.CopyWithTransparency();
        }
        else if (rdTransparencyDraw.Checked == true)
        {
             picOutput.BackgroundImage = picSource.BackgroundImage.DrawWithTransparency();
        }
        else if (rdNegativeBits.Checked == true)
        {
             picOutput.BackgroundImage = picSource.BackgroundImage.CopyAsNegative();
        }
        else if (rdNegativeDraw.Checked == true)
        {
             picOutput.BackgroundImage = picSource.BackgroundImage.DrawAsNegative();
        }
        else if (rdSepiaBits.Checked == true)
        {
             picOutput.BackgroundImage = picSource.BackgroundImage.CopyAsSepiaTone();
        }
        else if (rdSepiaDraw.Checked == true)
        {
             picOutput.BackgroundImage = picSource.BackgroundImage.DrawAsSepiaTone();
        }
    }
}

Related Articles

41 Responses to “C# How to: Image filtering implemented using a ColorMatrix”



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

Leave a comment




Dewald Esterhuizen

Blog Stats

  • 869,667 hits

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

Join 228 other subscribers

Archives

RSS SoftwareByDefault on MSDN

  • An error has occurred; the feed is probably down. Try again later.