The PNG Guide is an eBook based on Greg Roelofs' book, originally published by O'Reilly.

Writing PNG Images

Writing PNG images is both simpler and more complex than reading them. Weighing in on the side of simplicity is the fact that there is no need for a lot of platform-specific code, particularly platform-specific graphical code--unless, of course, the application already is graphical. In general, there is also no need for a special progressive mode; writing a PNG file, or almost any image format, for that matter, is more or less progressive by nature, although some complexity creeps in when the image is interlaced.

Writing PNGs is more explicitly complex when it comes to dealing with ancillary information like text annotations, timestamps, and so forth. A simple PNG viewer can ignore all of that; its only concern is with displaying the pixels correctly and in a timely manner. But a PNG-writing application should be prepared to preserve any existing textual information and to give the user the option of adding new information--for example, a title, the author's name, and copyright information. One wants to avoid adding too much baggage to the image, but the user should also be given the option of adding a timestamp (e.g., the tIME chunk for time of last modification, or perhaps a tEXt chunk indicating the creation time).

When it comes to the actual image data, at a minimum, the application should be able to detect when there are no more than 256 colors or color-transparency pairs, including a possible background color, and write a palette-based image if that is the case. Ideally, it should also be able to write a grayscale image as grayscale instead of RGB, but unless there is already information available that indicates the pixels are gray, or the user indicates that the image is to be converted to grayscale, detecting such images can be both CPU- and memory-intensive.

It should go without saying that any such application should include gamma-correction information with the image whenever possible, and that it should be correct information; this may entail providing the user with a calibration screen. And image converters must be much more careful, since most images lacking explicit gamma information also lack any information from which one can infer the gamma value unambiguously; guessing incorrectly is worse than omitting the gamma info in the first place.

High-end, professional applications should also provide chromaticity information, if it is known, and mark any images created in the standard RGB color space with an appropriate sRGB chunk. They may also want to include a complete International Color Consortium embedded profile (iCCP chunk), but given the size of such profiles, this should always be an option given to the user, and generally it should not be the default option. See Chapter 10, "Gamma Correction and Precision Color", for a more detailed discussion of gamma correction and color spaces.

Applications such as image editors, which usually include the generation of web-friendly graphics as one of their features, should also provide the user with the option of converting truecolor images into colormapped ones. This is known as quantization, and it should include images with an alpha channel. As I described in Chapter 8, "PNG Basics", PNG's tRNS chunk effectively transforms a palette from RGB samples into RGBA; thus, any program that can quantize a 24-bit RGB image down to a 256-color palette-based image should also be capable of quantizing a 32-bit RGBA or 16-bit gray/alpha image down to a 256-entry PLTE/tRNS-based image. But because quantization is a lossy procedure, it should never be the default--unless, of course, the entire purpose of the application is the lossy conversion of truecolor images into colormapped ones.

Special-purpose applications that deal with sampled data from scientific or medical apparatus will often encounter odd bit depths or oddly calibrated data, at least compared with standard computer images. For example, medical tomographic (CT) images are usually stored as 16-bit integer samples, but the implied upper bound of 65,535 is misleading. Such images rarely use more than 10 to 12 bits of each sample, their maximum intensity value is typically less than 4,096 and sometimes less than 1,024, though rarely less than 256. When stored as PNG images, their samples should be scaled up so that the maximum value is near 65,535. For example, an image whose raw data has a maximum value of 1,891 is using only 11 bits of each sample--i.e., the next power of two is 2,048, or 211. It should be scaled up either by a factor of 32 (25), which corresponds simply to shifting the bits five to the left, or more properly by a factor of 65,535/2,047, which happens to be very closely approximated by what the PNG spec calls ``left bit replication.'' These two approaches are more easily understood as C code:

    /* how to scale 11-bit data up to 16 bits */
    new_sample = (old_sample << 5) | (old_sample >> 3);
    new_sample = (old_sample << 5);    /* simple shift method */

Either way, the application should write an sBIT chunk into the file to indicate the number of significant bits in the original data; in this case, the sBIT value would be 11. It might also want to write a pCAL chunk indicating the calibration of the sample values relative to the physical quantity being measured. It is not intuitively obvious how one would allow the user to provide information for the pCAL chunk interactively, however; more likely, a programmer would hardcode things like the pCAL equation type directly into the application, given advance knowledge of the type of data being collected or manipulated.

Last Update: 2010-Nov-26