.
Xamarin
GDI+ FAQ
Skip Navigation LinksWelcome : GDI+ FAQ : Convert color images to grayscale

How to convert a colour image to grayscale

Colours in an image may be converted to a shade of gray by calculating the effective

brightness or luminance of the colour and using this value to create a shade of gray

that matches the desired brightness.

 

The following code snippet isn't really a good example of how it should be done in a production situation but it does show the principles involved clearly. For every day use. see the ColorMatrix example below.

 

The effective luminance of a pixel is calculated with the following formula:

Y=0.3RED+0.59GREEN+0.11Blue

This luminance value can then be turned into a grayscale pixel using Color.FromArgb(Y,Y,Y).

Converting an image from colour to monochrome can be performed using the following code:

[C#]

public Bitmap ConvertToGrayscale(Bitmap source)

{

  Bitmap bm = new Bitmap(source.Width,source.Height);

  for(int y=0;y<bm.Height;y++)

  {

    for(int x=0;x<bm.Width;x++)

    {

      Color c=source.GetPixel(x,y);

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

      bm.SetPixel(x,y,Color.FromArgb(luma,luma,luma));

    }

  }

  return bm;

}

[VB]

Public Function ConvertToGrayscale(ByVal source As Bitmap) as Bitmap

  Dim bm as new Bitmap(source.Width,source.Height)

  Dim x

  Dim y

  For y=0 To bm.Height

    For x=0 To bm.Width

      Dim c as Color = source.GetPixel(x,y)

      Dim luma as Integer = CInt(c.R*0.3 + c.G*0.59 + c.B*0.11)

      bm.SetPixel(x,y,Color.FromArgb(luma,luma,luma)

    Next

  Next

  Return bm

End Function

The images below show a color image and its monochrome conversion.

Alternative Version using the ColorMatrix class

Jacob Grass ( http://www.windowsforms.net ) sent me an excellent alternative to the

previous method which uses a colour matrix shear to create the greyscale. While this is

an effective and quick method of performing the monochrome manipulation, colour

geeks will tell you that the luminance values are all off and the grey balance of the

final image is not correct.

 

Note: Since I first posted this article, Gilles Khouzam has provided me with a ColorMatrix shear that maintains the luminance correctly. I have placed this matrix definition in the code provided by Jacob and you can see the difference by commenting out one matrix and substituting the other. 

[C#]

using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
namespace GrayShear
{
  /// <summary>
  /// Summary description for Form1.
  /// </summary>
  public class Form1 : System.Windows.Forms.Form
  {
    /// <summary>
    /// Required designer variable.
    /// </summary>
    private System.ComponentModel.Container components = null;
    public Form1()
    {
      //
      // Required for Windows Form Designer support
      //
      InitializeComponent();
      //
      // TODO: Add any constructor code after InitializeComponent call
      //
    }
    /// <summary>
    /// Clean up any resources being used.
    /// </summary>
    protected override void Dispose( bool disposing )
    {
      if( disposing )
      {
        if (components != null) 
        {
          components.Dispose();
        }
      }
      base.Dispose( disposing );
    }
    #region Windows Form Designer generated code
    /// <summary>
    /// Required method for Designer support - do not modify
    /// the contents of this method with the code editor.
    /// </summary>
    private void InitializeComponent()
    {
      // 
      // Form1
      // 
      this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
      this.ClientSize = new System.Drawing.Size(296, 269);
      this.Name = "Form1";
      this.Text = "Form1";
      this.Load += new System.EventHandler(this.Form1_Load);
    }
    #endregion
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main() 
    {
      Application.Run(new Form1());
    }
    private void Form1_Load(object sender, System.EventArgs e)
    {
      OpenFileDialog dlg = new OpenFileDialog();
      dlg.Filter="Image files (*.BMP, *.JPG, *.GIF)|*.bmp;*.jpg;*.gif";
      if(dlg.ShowDialog()==DialogResult.OK)
      {
        Image img = Image.FromFile(dlg.FileName);
        Bitmap bm = new Bitmap(img.Width,img.Height);
        Graphics g = Graphics.FromImage(bm);
 
        
        ColorMatrix cm = new ColorMatrix(new float[][]{   new float[]{0.5f,0.5f,0.5f,0,0},
                                  new float[]{0.5f,0.5f,0.5f,0,0},
                                  new float[]{0.5f,0.5f,0.5f,0,0},
                                  new float[]{0,0,0,1,0,0},
                                  new float[]{0,0,0,0,1,0},
                                  new float[]{0,0,0,0,0,1}});
        
        /*
        //Gilles Khouzams colour corrected grayscale shear
        ColorMatrix cm = new ColorMatrix(new float[][]{   new float[]{0.3f,0.3f,0.3f,0,0},
                                  new float[]{0.59f,0.59f,0.59f,0,0},
                                  new float[]{0.11f,0.11f,0.11f,0,0},
                                  new float[]{0,0,0,1,0,0},
                                  new float[]{0,0,0,0,1,0},
                                  new float[]{0,0,0,0,0,1}});
        */

        ImageAttributes ia = new ImageAttributes();
        ia.SetColorMatrix(cm);
        g.DrawImage(img,new Rectangle(0,0,img.Width,img.Height),0,0,img.Width,img.Height,GraphicsUnit.Pixel,ia);
        g.Dispose();
        this.BackgroundImage=bm;
      }  
    }
  }
}

[VB]

Imports System.Drawing.Imaging
Public Class Form1
  Inherits System.Windows.Forms.Form
#Region " Windows Form Designer generated code "
  Public Sub New()
    MyBase.New()
    'This call is required by the Windows Form Designer.
    InitializeComponent()
    'Add any initialization after the InitializeComponent() call
  End Sub
  'Form overrides dispose to clean up the component list.
  Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
    If disposing Then
      If Not (components Is Nothing) Then
        components.Dispose()
      End If
    End If
    MyBase.Dispose(disposing)
  End Sub
  'Required by the Windows Form Designer
  Private components As System.ComponentModel.IContainer
  'NOTE: The following procedure is required by the Windows Form Designer
  'It can be modified using the Windows Form Designer.  
  'Do not modify it using the code editor.
  <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
    components = New System.ComponentModel.Container()
    Me.Text = "Form1"
  End Sub
#End Region
  Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
    Dim dlg As OpenFileDialog = New OpenFileDialog()
    dlg.Filter = "Image files (*.BMP, *.JPG, *.GIF)|*.bmp;*.jpg;*.gif"
    If dlg.ShowDialog() = DialogResult.OK Then
      Dim img As Image = Image.FromFile(dlg.FileName)
      Dim bm As Bitmap = New Bitmap(img.Width, img.Height)
      Dim g As Graphics = Graphics.FromImage(bm)
      Dim cm As ColorMatrix = New ColorMatrix(New Single()() _
           {New Single() {0.5, 0.5, 0.5, 0, 0}, _
          New Single() {0.5, 0.5, 0.5, 0, 0}, _
          New Single() {0.5, 0.5, 0.5, 0, 0}, _
          New Single() {0, 0, 0, 1, 0}, _
          New Single() {0, 0, 0, 0, 1}})
    
    'Gilles Khouzams colour corrected grayscale shear
      'Dim cm As ColorMatrix = New ColorMatrix(New Single()() _
      '     {New Single() {0.3, 0.3, 0.3, 0, 0}, _
      '    New Single() {0.59, 0.59, 0.59, 0, 0}, _
      '    New Single() {0.11, 0.11, 0.11, 0, 0}, _
      '    New Single() {0, 0, 0, 1, 0}, _
      '    New Single() {0, 0, 0, 0, 1}})
      
    Dim ia As ImageAttributes = New ImageAttributes()
      ia.SetColorMatrix(cm)
      g.DrawImage(img, New Rectangle(0, 0, img.Width, img.Height), 0, 0, img.Width, img.Height, GraphicsUnit.Pixel, ia)
      g.Dispose()
      Me.BackgroundImage = bm
    End If
  End Sub
End Class

In conclusion, the technique of turning a colour image into an accurate gray scale is most easily accomplished using the ColorMatrix class initialized with the classic luminance calculation values.

Back to the GDI+ FAQ

 
Bob Powell

Create your badge

Copyright ©Bob Powell 2000-2014. All rights reserved.