If you have access to the World Wide Web, read Charles Poynton's
excellent "Gamma FAQ" at
http://www.inforamp.net/~poynton/notes/colour_and_gamma/GammaFAQ.html
.
It explains gamma in more detail than we have room for here.
It would be convenient for graphics programmers if all of the components of an imaging system were linear. The voltage coming from an electronic camera would be directly proportional to the intensity (power) of light in the scene, the light emitted by a CRT would be directly proportional to its input voltage, and so on. However, real-world devices do not behave in this way. All CRT displays, almost all photographic film, and many electronic cameras have nonlinear signal-to-light-intensity or intensity-to-signal characteristics.
Fortunately, it turns out that all of these non-linear devices have a transfer function that is approximated fairly well by a single type of mathematical function: a power function. This power function has the general equation
output = input ^ gammawhere ^ denotes exponentiation, and "gamma" (often printed using the Greek letter gamma, thus the name) is simply the exponent of the power function.
By convention, "input" and "output" are both normalized to the [0..1] range, with 0 representing black and 1 representing maximum white (or red, etc). Normalized in this way, the power function is completely described by a single number, the exponent "gamma".
So, given a particular device, we can measure its output as a function of its input, fit a power function to this measured transfer function, extract the exponent, and call it gamma. We often say "this device has a gamma of 2.5" as a shorthand for "this device has a power-law response with an exponent of 2.5". We can also talk about the gamma of a mathematical transform, or of a lookup table in a frame buffer, so long as the input and output of the thing are related by the power-law expression above.
Also, stages that are linear pose no problem, since a power function with an exponent of 1.0 is really a linear function. So a linear transfer function is just a special case of a power function, with a gamma of 1.0.
Thus, as long as our imaging system contains only stages with linear and power-law transfer functions, we can meaningfully talk about the gamma of the entire system. It turns out that most real imaging systems use power-law transfer functions all the way through, so this is most convenient.
When the reproduced image is to be viewed in "bright surround" conditions, where other white objects nearby in the room have about the same brightness as white in the image, then an overall gamma of 1.0 does indeed give real-looking reproduction of a natural scene. Photographic prints viewed under room light and computer displays in bright room light are typical "bright surround" viewing conditions.
However, sometimes images are intended to be viewed in "dark surround" conditions, where the room is substantially black except for the image. This is typical of the way movies and slides (transparencies) are viewed by projection. Under these circumstances, an accurate reproduction of the original scene results in an image that human viewers judge as "flat" and lacking in contrast. It turns out that the projected image needs to have a gamma of about 1.5 relative to the original scene for viewers to judge it "natural". Thus, slide film is designed to have a gamma of about 1.5, not 1.0.
There is also an intermediate condition called "dim surround", where the rest of the room is still visible to the viewer, but it is noticeably darker than the reproduced image itself. This is typical of television viewing, at least in the evening, as well as subdued-light computer work areas. In dim surround conditions, the reproduced image needs to have a gamma of 1.15-1.25 relative to the original scene in order to look natural.
The requirement for boosted contrast (gamma) in dark surround conditions is due to the way the human visual system works, and applies equally well to computer monitors. Thus, a PNG viewer trying to achieve the maximum realism for the images it displays really needs to know what the room lighting conditions are, and adjust the gamma of the displayed image accordingly.
If asking the user about room lighting conditions is inappropriate or too difficult, just assume that the overall gamma (viewing_gamma as defined below) is 1.0 or 1.15. That's all that most systems that implement gamma correction do.
An exception to this rule is the fancy "calibrated" CRTs that have internal electronics to alter their transfer function. If you have one of these, you probably should believe what it tells you its gamma is. But in all other cases, assuming 2.5 is likely to be pretty accurate.
There are various images around that purport to measure gamma, usually
by comparing the intensity of an area containing alternating white and
black with a series of areas of continuous gray of different intensity.
These are usually not reliable. Test images that use a "checkerboard"
pattern of black and white are the worst, because a single white pixel
will be reproduced considerably darker than a large area of white.
An image that uses alternating black and white horizontal lines (such as
the "gamma.png" test image at
ftp://ftp.uu.net/graphics/png/images/suite/gamma.png
)
is much better, but even it may be inaccurate at high "picture"
settings on some CRTs.
Because of the difficulty of measuring gamma, you're generally better off just assuming it's 2.5 rather than trying to measure it. (Unless you have a good photometer and the patience to make multiple measurements and fit a power function to them.)
In video systems, gamma correction is done in the camera. This goes back to the days when television was all analog. The camera has a transfer characteristic with a gamma of 0.45. Combined with the CRT gamma of 2.5, the image on screen ends up with a gamma of 1.15 relative to the original scene, which is appropriate for "dim surround" viewing.
These days, video signals are often digitized and stored in computer frame buffers. This works fine, but remember that the gamma correction is "built into" the video signal, and so the digitized video has a gamma of 0.45 relative to the original scene.
Computer rendering programs often want to work with linear samples, where intensity on the CRT is directly proportional to the sample values in the frame buffer. To achieve this, there may be a special hardware lookup table between the frame buffer and the CRT hardware. The lookup table (often called LUT) is loaded with a mapping that implements a power function with a gamma of 0.4, thus providing "gamma correction" for the CRT gamma.
Thus, gamma correction sometimes happens before the frame buffer, sometimes after. As long as images created in a particular environment are always displayed in that environment, everything is fine. But when people try to exchange images, differences in gamma correction conventions often results in images that seem far too bright and washed out, or far too dark and contrasty.
In an ideal world, sample values would be stored in floating point, there would be lots of precision, and it wouldn't really matter much. But in reality, we're always trying to store images in as few bits as we can.
If we decide to use samples that are linearly proportional to intensity, and do the gamma correction in the frame buffer LUT, it turns out that we need to use at least 12 bits for each of red, green, and blue to have enough precision in intensity. With any less than that, we will sometimes see "contour bands" or "Mach bands" in the darker areas of the image, where two adjacent sample values are still far enough apart in intensity for the difference to be visible.
However, through an interesting coincidence, the human eye's subjective perception of lightness is related to the physical stimulation of light intensity in a manner which is very much like the power function used for gamma correction. If we apply gamma correction to measured (or calculated) light intensity before quantizing to an integer for storage in a frame buffer, it turns out we can get away with using many fewer bits to store the image. In fact, 8 bits per color is almost always sufficient to avoid contouring artifacts. This is because, since gamma correction is so closely related to human perception, we are assigning our 256 available sample codes to intensity values in a manner that approximates how visible those intensity changes are to the eye. Compared to a linear-sample image, we allocate fewer sample values to brighter parts of the tonal range and more sample values to the darker portions of the tonal range.
Thus, for the same apparent image quality, images using gamma-corrected sample values need only about 2/3 as many bits of storage as images using linear samples.
file_gamma = camera_gamma * encoding_gamma
display_gamma = LUT_gamma * CRT_gamma
When displaying an image file, the image decoding program is responsible for making the overall gamma of the system equal to the desired viewing_gamma, by selecting the decoding_gamma appropriately. When displaying a PNG file, the gAMA chunk provides the file_gamma value. The display_gamma may be known for this machine, or it may be obtained from the system software, or the user might have to be asked what it is. The correct viewing_gamma depends on lighting conditions, and that will generally have to come from the user.
Ultimately, you should have
file_gamma * decoding_gamma * display_gamma = viewing_gamma
On the IBM PC, most PC clones, and many graphics workstations and X terminals, there is no LUT for gamma correction. Here, display_gamma is always 2.5.
On the Macintosh, there is a LUT. By default, it is loaded with a table whose gamma is about 0.72, giving a display_gamma (LUT and CRT combined) of about 1.8. Some Macs have a "gamma" control panel that allows gamma to be changed to 1.0, 1.2, 1.4, 1.8, or 2.2. These settings load alternate LUTs that are designed to give a display_gamma that is equal to the label on the selected button. Thus, the "gamma" control panel settings can be used directly as display_gamma in the decoder calculations.
Most Silicon Graphics workstations also have a gamma correction LUT, and it can be changed by the user with the "gamma" command. However, the gamma command sets the LUT_gamma to the reciprocal of the number you give it. For example, the default SGI system gamma value is 1.7, which gives a LUT_gamma of 1/1.7 or 0.59. The resulting display_gamma is 2.5/1.7 or about 1.5. Setting a system gamma of 1.0 gives a display_gamma of 2.5, which is sometimes used for viewing video images, while a system gamma of 2.5 gives a display_gamma of 1.0, sometimes used for displaying images with linear sample values.
For computer-generated images, it depends on the rendering program. Most commonly, the program writes sample values linearly proportional to calculated light intensity. Such renderers should write files with gAMA of 1.0.
Sometimes, renderers will do their own internal gamma correction before quantization. In this case, gamma correction and quantization are performed by an expression like:
sample = (intensity ^ exponent) * (2^bitdepth-1)In this case, the file gAMA value is just the value of "exponent" in the above expression. Alternatively, if the renderer says that it is "gamma correcting for a monitor gamma of 2.2", then the file gAMA value should be 1/2.2, or 0.4545.
In the case of hand-drawn images, you have to determine what conditions they were viewed under when being drawn, and then determine the file_gamma value by calculating
file_gamma = viewing_gamma / display_gammaFor example, someone created a piece of artwork on a Mac with the default display_gamma, which is 1.8. The room was dim at the time, so the appropriate viewing_gamma is about 1.2. The file_gamma is 0.667.
There are often cases where an image's exact origins are unknown, particularly if it began life as a GIF or TIFF or some other file format, and someone other than the original author is converting it to PNG. In these cases, all that can be done is to make the image look good on whatever system is being used for the conversion, and then follow the same rules as given for hand-drawn images above. For example, if I have an image that looks good on my SGI workstation when the system gamma is set to 1.7, and I'm looking at the monitor in a bright room, then display_gamma is 2.5/1.7=1.47, viewing_gamma is 1.0, and file_gamma is 1.0/1.47 = 0.68.