Given how many times I’ve been asked how to do this by my course-mates, I thought it’d be relevant to make a post here. The contents of this post are intended to be relevant to the CS-255 Graphics module at Swansea University, but may also be useful to those studying other courses elsewhere.

Gamma correction of an image takes the following equation:

In this equation, V is the gamma corrected pixel, I is the pixel to be gamma corrected, and γ being the gamma correction value. The PAL standard suggests using γ = 2.8.

The values V and I should be in the range 0 to 1, but images represented in Java are stored as bytes, in the range 0 to

  1. As such, you need to convert from the integer representation of the pixel by dividing it by 255.

double I = pixel & 255D;

Note that the 255 has a D after it; this forces the number to be interpreted as a double by Java.

Once you have your value between 0 and 1, make use of the pow function to obtain the gamma corrected value.

double V = Math.pow(I, 1 / gamma)

Then, multiply it by 255 to get your new pixel value

int newPixel = (int) (V * 255)

So, now that you understand how Gamma correction is performed, it is important to understand the slowest part of this process is the floating-point arithmetic performed by Math.pow. Now, given that the first argument given to Math.pow is always going to be in the range of (0 to 255) / 255, would it not make sense to perform the arithmetic on each possible value and store the outcome, then look it up for each pixel, rather than performing said arithmetic for each pixel?

Creating an array to map original values to new values is the pretence upon which fast gamma correction lies. You would build up this array with all the possible values and their corresponding output values, then access said array for each pixel. This means that the expensive arithmetic operation would only occur 256 times, rather than one time for each colour channel of each pixel of the image.