Serge's World

Blogging about software development, astronomy, genealogy and more.

Image Processing in C#: Part 5 - Adjusting the Gamma

Gamma correction has a history based on the properties of CRT’s and was first noted in televisions.

The light intensity of a CRT is not directly proportional to the input voltage, but is rather proportional to the input voltage raised to a particular power. This power was known as gamma, and varied with CRT. The value was usually around 2.5.

This means that different CRT’s (televisions and monitors before the flatscreen days) all showed the same images slightly differently, and gamma correction was implement to correct this.

A gamma filter works by creating an array of 256 values called a gamma ramp for each value of the red, blue and green components. The gamma value must be between 0.2 and 5.

The formula for calculating the gamma ramp is 255 * (i / 255)1/gamma + 0.5.

If this value is greater than 255, then it is clamped to 255. It is possible to have a different gamma value for each of the 3 colour components.

Then for each pixel in the image, we can substitute the value in this array for the original value of that component at that pixel.

Gamma

public void ApplyGamma(double r, double g, double b)
{
	byte A, R, G, B;
	Color pixelColor;

	byte[] redGamma = new byte[256];
	byte[] greenGamma = new byte[256];
	byte[] blueGamma = new byte[256];

	for (int i = 0; i < 256; ++i)
	{
		redGamma[i] = (byte)Math.Min(255, (int)((255.0
			* Math.Pow(i / 255.0, 1.0 / r)) + 0.5));
		greenGamma[i] = (byte)Math.Min(255, (int)((255.0
			* Math.Pow(i / 255.0, 1.0 / g)) + 0.5));
		blueGamma[i] = (byte)Math.Min(255, (int)((255.0
			* Math.Pow(i / 255.0, 1.0 / b)) + 0.5));
	}

	for (int y = 0; y < bitmapImage.Height; y++)
	{
		for (int x = 0; x < bitmapImage.Width; x++)
		{
			pixelColor = bitmapImage.GetPixel(x, y);
			A = pixelColor.A;
			R = redGamma[pixelColor.R];
			G = greenGamma[pixelColor.G];
			B = blueGamma[pixelColor.B];
			bitmapImage.SetPixel(x, y, Color.FromArgb((int)A, (int)R, (int)G, (int)B));
		}
	}
}

The full source used in the series is available from https://github.com/sjmeunier/image-processor.

Originally posted on my old blog, Smoky Cogs, on 19 Nov 2009

Tag Cloud

Algorithms (3) Android (10) Astronomy (25) Audio (1) Audiobooks (1) Barcodes (9) C# (69) Css (1) Deep sky (6) Esoteric languages (3) Family (3) Fractals (10) Gaming (1) Genealogy (14) General (2) Geodesy (3) Google (1) Graphics (3) Hubble (2) Humour (1) Image processing (23) Java (8) Javascript (5) jQuery (3) Jupiter (3) Maths (22) Moon (5) Music (4) Pets (5) Programming (88) Saturn (1) Science (1) Spitzer (4) Sun (4) Tutorials (68) Unity (3) Web (9) Whisky (13) Windows (1) Xamarin (2)