Convert an image to grayscale

Viewed 164355

Is there a way to convert an image to grayscale 16 bits per pixel format, rather than setting each of the r,g and b components to luminance. I currently have a bmp from file.

Bitmap c = new Bitmap("filename");

I want a Bitmap d, that is grayscale version of c. I do see a constructor that includes System.Drawing.Imaging.PixelFormat, but I don't understand how to use that. I'm new to Image Processing and the relevant C# libraries, but have a moderate experience with C# itself.

Any help, reference to an online source, hint or suggestion will be appreciated.

EDIT: d is the grayscale version of c.

7 Answers

"I want a Bitmap d, that is grayscale. I do see a consructor that includes System.Drawing.Imaging.PixelFormat, but I don't understand how to use that."

Here is how to do this

Bitmap grayScaleBP = new 
         System.Drawing.Bitmap(2, 2, System.Drawing.Imaging.PixelFormat.Format16bppGrayScale);

EDIT: To convert to grayscale

             Bitmap c = new Bitmap("fromFile");
             Bitmap d;
             int x, y;

             // Loop through the images pixels to reset color.
             for (x = 0; x < c.Width; x++)
             {
                 for (y = 0; y < c.Height; y++)
                 {
                     Color pixelColor = c.GetPixel(x, y);
                     Color newColor = Color.FromArgb(pixelColor.R, 0, 0);
                     c.SetPixel(x, y, newColor); // Now greyscale
                 }
             }
            d = c;   // d is grayscale version of c  

Faster Version from switchonthecode follow link for full analysis:

public static Bitmap MakeGrayscale3(Bitmap original)
{
   //create a blank bitmap the same size as original
   Bitmap newBitmap = new Bitmap(original.Width, original.Height);

   //get a graphics object from the new image
   using(Graphics g = Graphics.FromImage(newBitmap)){

       //create the grayscale ColorMatrix
       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}
          });

       //create some image attributes
       using(ImageAttributes attributes = new ImageAttributes()){

           //set the color matrix attribute
           attributes.SetColorMatrix(colorMatrix);

           //draw the original image on the new image
           //using the grayscale color matrix
           g.DrawImage(original, new Rectangle(0, 0, original.Width, original.Height),
                       0, 0, original.Width, original.Height, GraphicsUnit.Pixel, attributes);
       }
   }
   return newBitmap;
}

I think it's a good way in this case:

    /// <summary>
    /// Change the RGB color to the Grayscale version
    /// </summary>
    /// <param name="color">The source color</param>
    /// <param name="volume">Gray scale volume between -255 - 255</param>
    /// <returns></returns>
    public virtual Color Grayscale(Color color, short volume = 0)
    {
        if (volume == 0) return color;
        var r = color.R;
        var g = color.G;
        var b = color.B;
        var mean = (r + g + b) / 3F;
        var n = volume / 255F;
        var o = 1 - n;
        return Color.FromArgb(color.A, Convert.ToInt32(r * o + mean * n), Convert.ToInt32(g * o + mean * n), Convert.ToInt32(b * o + mean * n));
    }

    public virtual Image Grayscale(Image source, short volume = 0)
    {
        if (volume == 0) return source;
        Bitmap bmp = new Bitmap(source);
        for (int x = 0; x < bmp.Width; x++)
            for (int y = 0; y < bmp.Height; y++)
            {
                Color c = bmp.GetPixel(x, y);
                if (c.A > 0)
                    bmp.SetPixel(x, y, Grayscale(c,volume));
            }
        return bmp;
    }

Enjoy...

Related