The Microsoft .NET Framework provides developers with many different libraries that enable them to create and modify images. This article demonstrates two methods for converting an image to grayscale and sepia-tone using built-in .NET Framework functionality from C#.

Before we dive into the code, we need to look at the algorithms used to determine how to convert the image. Each algorithm will take a colour as input and then calculate the resultant colour. For greyscale this is relatively easy. You simply calculate the brightness of the colour and use that value to create a shade of grey. A very basic implementation of this is shown below.

outputColor = (inputRed + inputGreen + inputBlue) / 3

You then set all three RGB values equal to "outputColor".

Sepia tone is a little more complex because we are no longer working in shades of grey, and we cannot rely on the average of the other colours for our output colour. For sepia tone, we will use a calculation similar to the one shown below.

outputRed = (inputRed * .393) + (inputGreen *.769) + (inputBlue * .189)

outputGreen = (inputRed * .349) + (inputGreen *.686) + (inputBlue * .168)

outputBlue = (inputRed * .272) + (inputGreen *.534) + (inputBlue * .131)

If any of these output values is greater than 255, you simply set it to 255. These specific values are the values for sepia tone that are recommended by Microsoft.

The following examples are two of the more common approaches used to convert images to greyscale or sepia tone. While there are other ways to achieve the same result, these two methods do not use unsafe code blocks or external calls to Windows APIs -- techniques some other approaches use. Because of this, these two solutions are cleaner and easier to adapt.

The first method of conversion

The first method of conversion is the SetPixel method. To do this we create a Bitmap and loop through every pixel of the Bitmap, stopping at each one to calculate the colour we want to change it to. Then, we call Bitmap.SetPixel to change the pixel to our desired colour. An example of this method is shown below.

private void btnGrayscale_Click(object sender, EventArgs e)

{

//Get the image from our PictureBox

Bitmap grayScale = (Bitmap)picOriginal.Image.Clone();

//Store the height/width of the image

int height = grayScale.Size.Height;

int width = grayScale.Size.Width;

//Loop through both the Y (vertical) and X (horizontal)

// coordinates of the image.

for (int yCoordinate = 0; yCoordinate < height; yCoordinate++)

{

for (int xCoordinate = 0; xCoordinate < width; xCoordinate++)

{

//Get the pixel that\'s at our current coordinate.

Color colour = grayScale.GetPixel(xCoordinate, yCoordinate);

//Calculate the gray to use for this pixel.

int grayColor = (colour.R + colour.G + colour.B) / 3;

//Set the pixel to the new gray colour.

grayScale.SetPixel(xCoordinate, yCoordinate, Color.FromArgb(grayColor,

grayColor,

grayColor));

}

}

//Set the modified PictureBox to our new image.

picModified.Image = grayScale;

}

The second method of conversion

The second method of conversion is to use an object called a ColorMatrix. You create the ColorMatrix object, obtain a Graphics object from the image you want to convert, create a new ImageAttributes object, which contains the colour matrix, and then use the Graphics object to draw the image with the modified attributes. This code is shown below in detail, with comments describing what is happening in each step.

private void btnMatrixGrayscale_Click(object sender, EventArgs e)

{

//ColorMatrix layout:

// Red Result Green Result Blue Result Alpha Result

//Red Value .299 .299 .299 0 (Ignored)

//Green Value .587 .587 .587 0 (Ignored)

//Blue Value .114 .114 .114 0 (Ignored)

//Alpha Value 0 0 0 1

//This is basically saying that:

// Red should be converted to (R*.299)+(G*.587)+(B*.114)

// Green should be converted to (R*.299)+(G*.587)+(B*.114)

// Blue should be converted to (R*.299)+(G*.587)+(B*.114)

// Alpha should stay the same.

//Create the colour matrix.

ColorMatrix matrix = new ColorMatrix(new float[][]{

new float[] {0.299f, 0.299f, 0.299f, 0, 0},

new float[] {0.587f, 0.587f, 0.587f, 0, 0},

new float[] {0.114f, 0.114f, 0.114f, 0, 0},

new float[] { 0, 0, 0, 1, 0},

new float[] { 0, 0, 0, 0, 0}

});

//Create our image to convert.

Image image = (Bitmap)picOriginal.Image.Clone();

//Create the ImageAttributes object and apply the ColorMatrix

ImageAttributes attributes = new ImageAttributes();

attributes.SetColorMatrix(matrix);

//Create a new Graphics object from the image.

Graphics graphics = Graphics.FromImage(image);

//Draw the image using the ImageAttributes we created.

graphics.DrawImage(image,

new Rectangle(0, 0, image.Width, image.Height),

0,

0,

image.Width,

image.Height,

GraphicsUnit.Pixel,

attributes);

//Dispose of the Graphics object.

graphics.Dispose();

picModified.Image = image;

}

The code above converts an image to greyscale using the ColorMatrix method. As you can see, it does not use the simple algorithm of (R+G+B)/3 to convert the image. Instead it uses the same algorithm used by colour TVs to display black-and-white images.

Example images

Cast your .NET This was published in Cast your .NET, check every Thursday for more stories

Related links

Leave a comment

You must read and type the 6 chars within 0..9 and A..F

* indicates mandatory fields.

Log in


Sign up | Forgot your password?

What's on?