GDI+ FAQ: 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 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 ConvertToGr ayscale(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 ConvertToGr ayscale(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
|