Welcome to the GDI+ FAQ
http://bobpowell.net/faqmain.htm
Adjusting Image Colour Saturation.
Saturation is the measure of colour intensity in an image. The less saturated the image, the more washed-out it appears until finally, when saturation is at zero, the image becomes a monochrome or grayscale image.
Generally, when dealing with images, the range of colour saturation which is normally expressed as a number in the range zero to one, maybe adjusted from a gray scale to just the amount of colour present in the original image. It is possible however to force colour saturation of images to values greater than one which tends to "beef up" the colour of an image. In figure one below, you can see the same image with a colour saturation of zero, one and two.
Figure 1. Images with different saturation levels.
Of course, if an image is monochrome to begin with it's not possible to magically increase colour saturation and turn it into a colour image.
The effect shown in the figure above was obtained by using the ColourMatrix class. This enables you to change the characteristics of an image as it is drawn. The matrix is set up to "shear" the colour space using the following set of values. Note that each colour component has an effective luminance which contributes to the overall brightness of the pixel. The effective luminance value for red is 0.3086. Green has an effective luminance of 0.6094 and the value for blue is 0.082. The reciprocal of the saturation value is multiplied by the effective luminance of the colour component to produce a value by which each colour component of each pixel is multiplied during the matrix operation.
SaturationComplement = 1.0f - _saturation
SaturationComplementR = 0.3086f * SaturationComplement
SaturationComplementG = 0.6094f * SaturationComplement
SaturationComplementB = 0.0820f * SaturationComplement
The matrix values are computed as follows...
SaturationComplementR + _saturation, SaturationComplementR, SaturationComplementR, 0.0f, 0.0f
SaturationComplementG, SaturationComplementG + _saturation, SaturationComplementG, 0.0f, 0.0f
SaturationComplementB, SaturationComplementB, SaturationComplementB + _saturation, 0.0f, 0.0f
0.0f, 0.0f, 0.0f, 1.0f, 0.0f
0.0f, 0.0f, 0.0f, 0.0f, 1.0f
The following code provides an application that may be used to visualize the saturation of an image as it is modified.
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
namespace setsaturation
{
///<summary>
/// Summary description for Form1.
///</summary>
public class Form1 : System.Windows.Forms.Form
{
private System.Windows.Forms.TrackBar trackBar1;
private System.Windows.Forms.Button button1;
private System.Windows.Forms.PictureBox pictureBox1;
///<summary>
/// Required designer variable.
///</summary>
private System.ComponentModel.Container components = null;
public Form1()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();
}
///<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()
{
this.trackBar1 = new System.Windows.Forms.TrackBar();
this.button1 = new System.Windows.Forms.Button();
this.pictureBox1 = new System.Windows.Forms.PictureBox();
((System.ComponentModel.ISupportInitialize)(this.trackBar1)).BeginInit();
this.SuspendLayout();
//
// trackBar1
//
this.trackBar1.Location = new System.Drawing.Point(296, 16);
this.trackBar1.Maximum = 512;
this.trackBar1.Name = "trackBar1";
this.trackBar1.Orientation = System.Windows.Forms.Orientation.Vertical;
this.trackBar1.Size = new System.Drawing.Size(45, 248);
this.trackBar1.TabIndex = 1;
this.trackBar1.TickFrequency = 12;
this.trackBar1.Scroll += new System.EventHandler(this.trackBar1_Scroll);
//
// button1
//
this.button1.Location = new System.Drawing.Point(352, 48);
this.button1.Name = "button1";
this.button1.TabIndex = 2;
this.button1.Text = "Open...";
this.button1.Click += new System.EventHandler(this.button1_Click);
//
// pictureBox1
//
this.pictureBox1.Location = new System.Drawing.Point(8, 24);
this.pictureBox1.Name = "pictureBox1";
this.pictureBox1.Size = new System.Drawing.Size(272, 232);
this.pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
this.pictureBox1.TabIndex = 3;
this.pictureBox1.TabStop = false;
//
// Form1
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(440, 270);
this.Controls.Add(this.pictureBox1);
this.Controls.Add(this.button1);
this.Controls.Add(this.trackBar1);
this.Name = "Form1";
this.Text = "Form1";
((System.ComponentModel.ISupportInitialize)(this.trackBar1)).EndInit();
this.ResumeLayout(false);
}
#endregion
///<summary>
/// The main entry point for the application.
///</summary>
[STAThread]
static void Main()
{
Application.Run(new Form1());
}
Image img;
float _saturation=1;
private void CalcImage()
{
if(img==null)
return;
Bitmap bm=new Bitmap(this.pictureBox1.Width,this.pictureBox1.Height);
Graphics g=Graphics.FromImage(bm);
float SaturationComplement = 1.0f - _saturation;
float SaturationComplementR = 0.3086f * SaturationComplement;
float SaturationComplementG = 0.6094f * SaturationComplement;
float SaturationComplementB = 0.0820f * SaturationComplement;
ColorMatrix cm = new ColorMatrix(new float[][]{
new float[]{SaturationComplementR + _saturation, SaturationComplementR, SaturationComplementR, 0.0f, 0.0f},
new float[]{SaturationComplementG, SaturationComplementG + _saturation, SaturationComplementG, 0.0f, 0.0f},
new float[]{SaturationComplementB, SaturationComplementB, SaturationComplementB + _saturation, 0.0f, 0.0f},
new float[]{0.0f, 0.0f, 0.0f, 1.0f, 0.0f},
new float[]{0.0f, 0.0f, 0.0f, 0.0f, 1.0f}});
ImageAttributes ia=new ImageAttributes();
ia.SetColorMatrix(cm);
g.DrawImage(img,new Rectangle(0,0,bm.Width,bm.Height),0,0,img.Width,img.Height,GraphicsUnit.Pixel,ia);
this.pictureBox1.Image=bm;
}
private void trackBar1_Scroll(object sender, System.EventArgs e)
{
_saturation=1.0f/255*this.trackBar1.Value;
CalcImage();
}
private void button1_Click(object sender, System.EventArgs e)
{
OpenFileDialog dlg=new OpenFileDialog();
dlg.Filter="Image files|*.bmp;*.jpg;*.gif";
if(dlg.ShowDialog()==DialogResult.OK)
{
img=Image.FromFile(dlg.FileName);
CalcImage();
}
}
}
}