How to create grayscale images on .NET

In this example we will use simple color recalculation method to grayscale images. For each pixel on image we will calculate "average color" that we write back on image. Average color is sum of current color’s red, green and blue channels integer value divided by three. This value is assigned to all three channels for current pixel.

Color picture of rabbit on crime
Colored picture of rabbit commiting
the crime.

Althoug grayscaled she is still on action
Although grayscaled she is still on action.

The cool thing about this rabbit is her colors – black, white and gray. As you can see rabbit colors are almost the same on both pictures. Okay, let’s see the code.

public Bitmap GrayScale(Bitmap Bmp)
{
   
int
rgb;
    Color c;

   
for (int
y = 0; y < Bmp.Height; y++)
       
for (int
x = 0; x < Bmp.Width; x++)
        {
            c = Bmp.GetPixel(x, y);
            rgb = (
int
)((c.R + c.G + c.B) / 3);
            Bmp.SetPixel(x, y, Color.FromArgb(rgb, rgb, rgb));
        }
   
return Bmp;
}

Some notes about this code. It is also possible to calculate grayscale colors for channels differently. Instead of average of channels colors we can also use:

  • maximum of channel values,
  • minimum of channel values,
  • custom divider.

It depends purely on context what one may need. Channel values maximum is good for pictures that are little bit too dark. Minimum is good for pictures that are little bit too bright. Custom divider may find usage in applications where user may want to change brightness manually. Current example by itself is goof for original pictures that are okay enough to publish them.

I know there are faster methods available for grayscaling. These methods are usually based on unmanaged code. This example here is slower but it is managed code you can use safely in your applications.

Gunnar Peipman

Gunnar Peipman is ASP.NET, Azure and SharePoint fan, Estonian Microsoft user group leader, blogger, conference speaker, teacher, and tech maniac. Since 2008 he is Microsoft MVP specialized on ASP.NET.

    4 thoughts on “How to create grayscale images on .NET

    • October 24, 2007 at 10:57 am
      Permalink

      Or use unsafe code by locking the bitmap object and retrieving the pointer in memory. The colormatrix through gdi is the fastest as this also can be done accellerated.

      By the way… you are doing a very rude color to grey conversion. You should weight the color components differently.

    • October 25, 2007 at 9:33 am
      Permalink

      how to 8-bit bmp to 8-bit jpg??thanks!

    • April 6, 2012 at 10:42 am
      Permalink

      There’s a problem in not weighting the different colours, since neither the human eye nor display tech works that way. This works well in the example image, but not as well as in others.

      Changing

      rgb = (int)((c.R + c.G + c.B) / 3);

      to:

      rgb = (int)(sqrt( 0.241 * c.R * c.R + 0.691 * c.G * c.G + 0.068 * c.B * c.B ));

      Will give a much more accurate version, though we can do pretty well much faster with:

      rgb = (int)(0.299 * c.R + 0.587 * c.G + 0.114 * c.B);

      Perhaps the most commonly seen is the slight rounding of this:

      rgb = (int)(0.3 * c.R + 0.59 * c.G + 0.11 * c.B);

      Which in practice is going to come out much the same.

    Leave a Reply

    Your email address will not be published. Required fields are marked *