How To Ideas | How To Articles | How To Tutorials


0

How To Apply Gamma Filter on Images using C#


First of all, I want describe about the term Gamma and its effect. According to the information found on internet especially Wikipedia, In the early days of television, the intensity produced by a CRT(Cathode Ray Tube) is proportional to the input voltage raised to the power gamma. The value of gamma is dependant on CRT but it is usually close to 2.2. A Gamma Filter attempts to correct for this.

The process for this filter is totally discussed on the Wikipedia page, and to summarise that information in code, we have to generate a pool of 256 values of Red, Green and Blue based on the Gamma value passed in, and then we will change the value of every pixel colour according to the values in this pool. Let me explain the things with an example, Say the very first pixel of of our image has Red colour value equal to 200, then we replace this value with the 201st value or 200th indexed value (0 – 255) from the pool of Red value generated using code.

To match up the things with Wikipedia information, I am using the same concept (gamma correction) instead of just gamma and gamma correction is just inverse of the gamma.

For the normal modifications, the value of gamma or gamma correction is same for all the three Red, Blue and Green, but in code you can provide the different values as well. This is totally dependant on you and how you want to modify your image. I will be using the same image Wikipedia page has used to clear out the things which can be downloaded from the here.

Instructions:

  1. First of all add a reference to following namespaces in your code.

    using System.Drawing.Imaging;
    using System.Runtime.InteropServices;

  2. Now you have to load the Image in Bitmap class object, because we can apply any kind of manipulation on images using Bitmap Object.

    Bitmap bitmap = (Bitmap)Bitmap.FromFile(pictureBox1.ImageLocation);

  3. Now we need a rectangle having width and height equal to width and height of the Image we loaded in bitmap. This rectangle will be used to carry all the pixels of Image in the memory.

    Rectangle rectangle = new Rectangle(0, 0, bitmap.Width, bitmap.Height);

  4. Now we have to use BitmapData class to lock all the bits or pixels of the Image in memory. This is required because when we perform changes on our image, that image information must be available in memory. So that if by mistake we perform any wrong manipulation that won’t effect the Image directly and this process is faster as well as we have to perform manipulations on single byte at a time not the whole image in a single step.

    BitmapData bitmapData = 
                    bitmap.LockBits(rectangle, System.Drawing.Imaging.ImageLockMode.ReadWrite,
                    bitmap.PixelFormat);

  5. Now as our Image is in memory, so we have to use pointers to access all the bits of that Image from memory. Using the following line of code, our pointer will point to the starting bit of the Image in memory.

    IntPtr ptr = bmpData.Scan0;

  6. Now we have to create byte array of size equal to the number of words in the image. Now what is word here??? If you just consider a single pixel, it constitute Red, Green and Blue values mixed together to give us a unique colour. Value for each of these colours(Red, Green, Blue) ranges from 0 to 255. Now a pixel constitute all the three values but in actual pixel further consist of three words one for each of these RGB colour. and in those words, value of Red, Green and Blue is stored. So in total we have three times words as compared to pixel. In some cases, there is some padding also applied on images, and in that section no colour information is available, but we are not considering that for now.
  7. We have Stride property of BitmapData object which will give us number of words present in a single line of pixel. and Height property of BitmapData object will give us the height of Image, actually it will give us the number of lines of pixels we have in our image. So if we multiply the two values we will be having number of words present in our Image. And then we can create an array of bytes of the calculated size.

    int size  = Math.Abs(bitmapData.Stride) * bitmap.Height;
    byte[] rgbValues = new byte[size];

  8. Now we need to copy all the words values to this bytes array using the pointer we already created which is pointing to the starting bit of the image. For this we will use Marshal class.

    Marshal.Copy(ptr, rgbValues, 0, size);

  9. Now we have colour information of every pixel or word of that image in this bytes array. So now we need to create 3 more byte array, one for every colour which will be used to create pool of colour values according to the gamma value supplied.

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

  10. As I have already told you that I will be coding in the sense that we can specify different gamma correction for every different colour. So, here I need three variables to hold the value of gamma correction for every colour.

    double red, blue, green;

  11. You can specify the value for these three variables in the code only or you can make the user to input gamma correction value in the interface provided. I am using the 2nd case, so, I am fetching the value for these three variables from the input provided by user.

    red = Convert.ToDouble(textBox2.Text);
    blue = Convert.ToDouble(textBox3.Text);
    green = Convert.ToDouble(textBox4.Text);

  12. Now we have to generate the pool of 256 values each for Red, Blue and Green colours according to the value of gamma correction supplied. Now, to do this, here is the calculation you have to perform and save the data in the pool of values.

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

  13. Now what I am doing is, I am generating a value by calculating 255.0 * Math.Pow(i / 255.0, 1.0 * red) + .5 and then I am fetching the minimum value among 255 and the generated value by the code and then converting the value from int to byte and saving the value to our pool of values.
  14. Now we have our pool ready, and now we just have to fetch the correct value from this pool for every word present in our image. i.e for a word (Red) with value 200, i will replace this value with redGamma[200].

    for (int i = 0; i < rgbValues.Length; i++)
    {
        if (i % 3 == 0)
        { rgbValues[i] = redGamma[rgbValues[i]]; }
        else if (i % 3 == 2)
        { rgbValues[i] = greenGamma[rgbValues[i]]; }
        else
        { rgbValues[i] = blueGamma[rgbValues[i]]; }
    }

  15. Now our image bytes array have all the bytes with manipulated colour information. Now we have to copy back all these bytes information to the memory using Marshal class again.

    Marshal.Copy(rgbValues, 0, ptr, size);

  16. Now we have to unlock the bits from memory and then our Bitmap object will be having manipulated Image which we can show in a Picture Box or save in our hard disk.

    bitmap.UnlockBits(bitmapData);
    pictureBox1.Image = bitmap;

Here is the output of the same image present on Wikipedia for gamma correction value of .5 Just have a look at the two images one present on Wikipedia after applying gamma correction and one after applying manipulation using C# code. These two images are almost same, except the clarity in the image provide on Wikipedia is comparatively high. 
 Gamma Filter Using C#

You can download my sample code as well. Click Here To Download.
You can also download sample application. Click Here To Download Sample Application.

Incoming search terms:

  • c# bitmap gama correction (1)
  • gamma effect c# (1)
Filed in: C# Tags: , , , ,

Leave a Reply

Submit Comment



© 2096 How To Ideas. All rights reserved.
Proudly designed by Theme Junkie.