The Sad Story of PNG Gamma “Correction”

Browsers have supported the PNG bitmap format for quite some time. But still, even though PNG files can either be made smaller than GIFs or, alternatively, can contain more colors, lots of Web designers keep using JPEGs and GIFs. In fact, even designers who (for other reasons) don’t care about old browsers still often haven’t made the switch to PNG. Is it just about being stuck with the old ways or is there a good reason not to switch? Sadly, it turns out there is a reason not to switch: gamma “correction” gone wrong.

Why PNG? (Quick Recap)

Unencumbered by patents

The common expert belief is that the deflate compression algorithm which is used in the PNG format is not under patents when implemented in the way it is implemented in the zlib compression library. On the other hand, the LZW compression algorithm used when writing GIFs was subject to a U.S. patent owned by Unisys (and to similar patents in some other countries). Unisys has enforced the patent and effectively taxed software that writes GIFs. The U.S. patent has now expired, so this it is no longer a reason for avoiding GIF.

Smaller file size

This feature of PNG may not be obvious when comparing the PNGs and GIFs written by Photoshop for example, because many programs don’t use the full compression potential of PNG. However, when the full potential of the compression and the data rearrangement filters of PNG are used (eg. using pngcrush), PNG files are smaller than GIFs with the same image data.

More colors

The maximum number of colors in a GIF image is 256. The PNG format can handle RGB colors up to 16 bits per channel. Of course, with current display hardware the ability to use 8 bits per channel (Apple’s “millions of colors” or Microsoft’s “true color”) has more practical value.

Alpha channel

In GIF, one color can be made fully transparent. PNG images can have a full alpha channel which allows semi-transparent pixels.

Gamma correction
Gamma correction is supposed to make a cool bullet point. However, this is why you may not want to use PNGs in practice.

The Original Problem

Traditionally, RGB colors have been displayed simply by handing the numeric RGB color values to the display hardware—a display card controlling a cathode ray tube (CRT). This is also what Web browsers have done. The RGB color values from GIF color palettes, decoded JPEG images and from HTML have been passed unmodified to the graphics API of the system.

But mapping the numeric color values to screen colors is not that simple. Even if the numeric values were mapped linearly to voltages on the display card, the phosphors of the CRT won’t excite linearly depending on the input voltage. On most systems, the numeric color values have just been chosen in such a way that the desired colors are produced on an average CRT—or at least the CRT of the person originally choosing the color values.

Some system designers were not satisfied with the non-linear behavior of the CRT and chose to compensate by adding a transfer function to the display card. This was done by Apple, NeXT and SGI. However, they chose different default compensations. As a result, the same numeric color values produce different colors on different computer setups even when the physical properties of the CRT are the same.

To put it simply: A color with the same numeric RGB values looks brighter on an out-of-the-box Mac or SGI box than it does on an average PC.

The “Correction”

The transfer function in question is simple. The color values are scaled to the range 0.0…1.0 and then raised to power. The exponent is called gamma. It follows that the inverse function simply has the reciprocal of the gamma as the exponent. Also, it is easy to make a composite of consecutively applied functions by simply multiplying the exponents.

So compensating the effect of the transfer function looks simple—in theory.

The New Problem

In order to compensate for the different gammas, the display gamma of the system an image was authored on and the display gamma of the system where the image is being displayed both need to be known to the piece of software displaying the image. The PNG format provides a means for storing the (reciprocal of) display gamma of the authoring system to the image file. It is up to the program writing the file to store the native display gamma of the image, and then it is up to program displaying the file to compensate.

The new problem is that the programs that read and write PNG files usually have no idea about the display gamma of the system they are running on. The usual method is to take a guess based on the platform the program is running on and pick one of the default values mentioned for Mac, SGI, NeXT and PC clones in the Gamma Tutorial appendix of the PNG specification.

This approach is bogus. The platform defaults are only that: defaults. The display gamma is configurable on many systems. Also, on uncalibrated systems the default values are not exact. Writing bogus gamma information to files and then doing gamma “correction” using different bogus gamma information is not solving the problem—only perturbing it further.

In practice, a rather arbitrary gamma change is often applied to a PNG image when the image is opened in a program that did not write the file. When a PNG image is viewed in isolation, the gamma disturbance may not be obvious. However, when the colors of an image are meant to match some surrounding colors—such as the colors of a Web page—the problem becomes more serious.

Inconsistent Color on the Web

When images are used as parts of a Web page design, consistent color handling is often more important than colorimetric correcness. For a design that combines CSS and images, it is important that a color with a particular RGB value is displayed consistently regardless of the source—style sheet or image file—of the color value.

Given the same RGB values, the colors specified in CSS, HTML, JPEG, or GIF have traditionally matched. Everyone has just taken it for granted. (Colors are not represented as RGB internally in JPEG, but everyone uses the de facto color conversion of libjpeg from the Independent JPEG Group.)

PNG breaks the consistency. When the gamma of PNG images is disturbed but the CSS colors are left untouched, the colors no longer match.

There are at least two natural reactions: trying to opt out of gamma “correction” or trying to make it so that the PNG images are considered to be in the same color space as CSS colors.

Opting Out

Including the gamma information in a PNG file is optional. It would be reasonable to expect the colors of PNG images to be treated like the colors of GIF and JPEG images if the gamma information is omitted.

Sadly, it doesn’t work that way in every PNG-supporting browser. In older versions of Opera and in pre-Tiger Safari, PNG colors don’t match CSS colors when there is no color space information stored in the PNG files. Also some old Mac versions of Mozilla and Netscape 6 applied a gamma change to unlabeled PNGs.

It could be argued that a browser is free to guess anything about the color space of the incoming file and, therefore, is free to apply any arbitrary gamma change. After all, no standard mandates that in the absence of gamma information PNGs should be treated color-wise in the same way as GIFs and JPEGs. Still, treating the colors of unlabeled PNGs differently from the colors of (unlabeled) GIFs and JPEGs makes no sense.

Opera 7, the Mac version of Opera 6 and Safari 2.0 on Mac OS X 10.4 fix this problem and make the colors of PNGs that don’t carry color space information consistent with CSS colors. Even though Opera 7 and Safari 2.0 behave reasonably with unlabeled PNGs, the old versions continue to be out there.

Of the various PNG-supporting browsers, Safari on Mac OS X prior to 10.4 is the most prominent problem: It applies a gamma change to unlabeled PNGs. This means that even unlabeled PNGs are no good those who want consistent colors between images and CSS in Safari on Mac OS X 10.3 and 10.2.

The gamma information and other fancier color space information can be removed using pngcrush: pngcrush -rem gAMA -rem cHRM -rem iCCP -rem sRGB infile.png outfile.png

Making the Color Spaces Match

In theory, one could try to use the color management features of PNG to make the colors match with CSS colors. However, in practice this does not work and can even make matters worse, because what is said about color in the specifications is not generally implemented.

sRGB

When you touch the issue of color values in a formal specification, you are supposed to somehow define the meaning of the values. The easy way to describe the meaning of color values would be this: “The color values are passed to the Windows graphics API. Authors should pick the color values in such a way that the intended appearance is achieved on an average PC.” Of course, that definition wouldn’t look good in a specification that is supposed to be precise and platform-neutral. It would look much better if there were a normative reference to a formal color space definition.

Some people working with color issues realized that it isn’t realistic to try to force Windows PCs to do color management. sRGB is a color space that models an average office PC with a usual mediocre CRT.

When a Windows PC or a Linux box is said to be an “sRGB system”, it is important to realize that these device/software combinations are not explicitly engineered to conform to a specification called sRGB. Instead, the specification is designed to conform to the systems! However, not all PCs are the same, so it’s not like all PCs have an exact common color space. sRGB is just an approximation of an average case.

Also, when it it said that a Mac is not an sRGB system, it is important to realize that a Mac can be configured to be one. It just might be that a Mac owner with a fancy Apple flat panel screen doesn’t necessarily want his/her display to emulate a mediocre office CRT.

sRGB in the CSS and PNG Specifications

According to the CSS2 specification, the CSS color values refer to the sRGB color space. In practice, however, all browsers except Mac IE 5 with ColorSync enabled (disabled by default) seem to just treat the CSS color values as values in whatever color space the system color space happens to be. Still, it would be reasonable to expect the colors of an sRGB-labeled PNG image to be treated consistently with CSS colors.

Again, it just doesn’t work that way in practice.

The PNG 1.0 specification, which is a W3C Recommendation, didn’t have an unambiguous way of indicating that the color space of an image is sRGB exactly. In theory, the result should be close if the gamma value of the image is set to 1/2.2. However, in practice the colors of images labeled that way do not match CSS colors in eg. Windows IE.

The PNG 1.1 specification, which is not a W3C Recommendation, added an unambiguous way of indicating that the color space of an image is sRGB—the sRGB chunk. There are problems, however.

Impact on Authoring

In a nutshell: There is no way of making PNG images that match CSS colors in all PNG-supporting browsers. This reduces the usefulness of the otherwise excellent image format. If the image colors and the colors defined in a style sheet need to match, it is safer to use GIF or JPEG. If you want to use PNG and don’t care about older browser versions (pre-Tiger Safari in particular), the best course of action is removing all the color space information from the PNG files. If you only want a match with the background color, you could make the background a PNG image as well.

However, in cases where matching image colors with surrounding page colors is not of utmost importance, PNG images are safe to use. This not only means cases where the image is an independent rectangle but also cases where alpha blending is used.

Icons with a lighter and a darker rendering looking reasonable on different background colors thanks to alpha-blended edges.For example, fiMUG’s list of upcoming events has anti-aliased icons that can appear on two different backgrounds. Since it is a page of a Mac user group, we went ahead and used full PNG alpha transparency even though Windows IE doesn’t support it. Camino and Safari render the CSS background colors the same way but pre-Tiger Safari changes the gamma of the icons. However, thanks to alpha blending, the gamma change is mostly harmless in this case. (In the image, Camino’s rendering is on the left and pre-Tiger Safari’s is on the right.)

How did it come to this?

PNG gamma correction was supposed to make color consistent across platforms. However, the implementors weren’t sufficiently warned about the effects of gamma “correction” in situations where the image is not in isolation, so instead of fixing the original problem PNG gamma “correction” created a new, even worse problem: inconsistent color within a Web page.

The emphasis was put on doing some change to the gamma instead of emphasizing consistency with the surrounding colors in browsers. Also, guessing the gamma based on the operating system was presented as an acceptable method in the specification itself. That is, doing something was emphasized over correctness and consistency.

I’m sure many designers would agree that color consistency within a page is more important than color sameness across different computers or operating systems. I’d like to ask implementors of applications that deal with PNGs to pay attention to consistent color handling and not to do arbitrary gamma changes when the gamma properties of the output device are just guesses. Also, please treat the colors of PNGs with no color space information the same way you would treat the colors any other image file that doesn’t carry color space information.