Comments on this document can be sent to the PNG specification maintainers at
png-info@uunet.uu.netor at
png-list@dworkin.wustl.edu.
Distribution of this memo is unlimited.
At present, the latest version of this document is available on the World Wide Web from
ftp://swrinde.nde.swri.edu/pub/png-group/documents/.
Permission is granted to copy and distribute this document for any purpose and without charge, provided that the copyright notice and this notice are preserved, and that any substantive changes or deletions from the original are clearly marked.
http://www.w3.org/pub/WWW/TR/WD-png
.
Whenever you use any of these unregistered chunks you should also include a "tEXt" chunk describing it, for example:
tEXtComment\0 This file contains a pcAL chunk written according to the format given in Version 19960914 of the PNG Proposed Chunks document.For those proposed chunks that have a "signature" field, decoders should check to ensure that the signature field is present and that its contents exactly match the specified string.
Proposed Multiple Ordering chunk name OK? constraints dRNG/DrNG No Before IDAT fALS No Before IDAT lOGE/LOGE No Before IDAT tSCL (used in multi-image format) xSCL No Before IDAT ySCL No Before IDAT zSCL (used in multi-image format) pCAL No Before IDAT
Similarly, it can be used to enhance or reduce the contrast and brightness of pixel values that are stored losslessly and it is not appropriate to rescale them to fill the full range of possible pixel values. The chunk defines the minimum and maximum values that correspond to the minimum and maximum displayed intensity, respectively, normalized to floating point numbers in the range [0..1].
The chunk can be used as a critical chunk, named "DrAN", or as an ancillary chunk, named "drAN". The syntax and function is exactly the same whichever name is used. The critical version should only be used if the image cannot be meaningfully displayed without performing "DrAN" scaling. Decoders not recognizing "DrAN" will not attempt to display the image at all. Encoders are strongly encouraged to scale the image data properly and to use the noncritical version, "drAN", if at all possible.
This chunk's contents are
n bytes: purpose: (Latin-1 text) 1 byte: null separator 20 bytes: signature: ("PNG group 1996-10-27") 1 byte: null separator d bytes: denominator (ASCII text) Denominator to use in normalizing the following minimum and maximum values to the range [0..1]. Must be nonzero. This number is written as a text floating-point value. [link to Floating-Point Values in the PNG extensions document] 1 byte: null separator m bytes: min_sample (ASCII text). Raw sample value corresponding to minimum intensity of the graylevel or red channel, written as a text floating-point value. 1 byte: null separator n bytes: max_sample (ASCII text). Raw sample value corresponding to maximum intensity of the graylevel or red channel.(The following entries can be omitted for grayscale images, or for color images where identical values are to be applied to all three color channels)
1 byte: null separator n bytes: min_green (ASCII text). Raw sample value corresponding to minimum intensity of the green channel. 1 byte: null separator n bytes: max_green (ASCII text). Raw sample value corresponding to maximum intensity of the green channel. 1 byte: null separator n bytes: min_blue (ASCII text). Raw sample value corresponding to minimum intensity of the blue channel. 1 byte: null separator n bytes: max_blue (ASCII text). Raw sample value corresponding to maximum intensity of the blue channel.The "purpose" identifies the palette, which can permit applications or people to choose the appropriate one when more than one false-color palette is stored in a multiple-image file. The "purpose" string must follow the format of a "tEXt" keyword, i.e. 1-79 printable Latin-1 characters.
If this chunk is present, graylevel or color sample values are to be scaled for display between minimum and maximum intensity by linear interpolation. When the sample value falls outside the range min_value..max_value, it is to be set to min_value or max_value as appropriate. For each graylevel or color sample, the conversion is (using floating point arithmetic):
normalized_max_value := max_value/denominator normalized_min_value := min_value/denominator normalized_input_sample := input_sample/(2^sample_depth-1) ratio := (normalized_max_value - normalized_min_value) result := (normalized_input_sample - normalized_min_value) normalized_output_sample := LIMIT (0, result, 1) in which LIMIT (low, x, high) = MAX (MIN (x, high), low).In indexed-color images, "sample_depth == 8" in this calculation, regardless of the bit depth actually used to store the indices. For other color types, sample_depth is the same as the "bit_depth" given in the "IHDR" chunk.
Note that min_value and max_value are permitted to be negative, positive, or zero. The only restriction is that they be different from each other.
A decoder should apply "drAN" scaling in the following manner:
Encoders should not use "drAN/DrAN" in lieu of reasonably scaling the samples. For example, if the sample values range from 0 (black) to 1000 (white), it would be an extremely bad idea to use the "drAN" chunk to request the decoder to scale 1000 up to 65535, because a PNG viewer that does not understand "drAN/DrAN" (and, since this is an extension chunk, most viewers will probably not understand "drAN/DrAN") would simply display a very dark rectangle. Instead, multiply your samples by 64, and use "drAN" with max_sample=64000 to request the decoder to do the final adjustment.
If the "tRNS" chunk is present, its value is compared to the unscaled pixel value, prior to applying the "drAN/DrAN" scaling. The "faLT", "gAMA", "cHRM", and alpha conversions, if present, are applied to the scaled sample values.
If present, this chunk must appear before the first "IDAT" chunk. Only one "drAN/DrAN" chunk is permitted in a PNG file. In a multiple image format, multiple instances might be permitted.
The "purpose" field, in a multiple-image context, can be used to select from among a choice of "drAN" chunks, when the the "best" view of the image simply does not exist. Examples of such images include:
This chunk's contents are a zero-byte-terminated text string (purpose) that names the palette, followed [after a 20-byte signature and its null-byte separator] by a gamma field and a series of false-color palette entries:
n bytes: purpose (Latin-1 text) 1 byte: null separator 20 bytes: signature ("PNG group 1996-10-27") 1 byte: null separator 4 bytes: gamma (unsigned integer), file_gamma times 100000 2 bytes: index (unsigned integer), range [0 .. (2^bitdepth) -1)] 2 bytes: red (unsigned integer) range [0 .. 65535] 2 bytes: green (unsigned integer) range [0 .. 65535] 2 bytes: blue (unsigned integer) range [0 .. 65535] etc.The number of entries is determined from the remaining chunk length after the gamma field. This length not divisible by 8 is an error.
The "purpose" identifies the palette, which can permit applications or people to choose the appropriate one when more than one false-color palette is stored in a multiple-image file. The "purpose" string must follow the format of a "tEXt" keyword, i.e. 1-79 printable Latin-1 characters.
The gamma field gives the value of "file_gamma", times 100000, that is associated with the false-color palette samples.
This chunk can appear for color type 0 or color type 4. If it appears for any other color type, it will be ignored.
The complete 2^bitdepth-entry false-color palette can be built from the chunk data. If the first entry (index value 0) is missing, it will be assumed to be {0, 0, 0} (black). If the last entry (index value 2^bitdepth - 1) is missing, it will be assumed to be {65535, 65535, 65535} (white). The red, green, blue samples for other missing entries are filled in by linearly interpolating between the samples that are present, independently for each of the three color components.
Once the complete false-color palette is established, it is used similarly to PLTE. The first entry in the completed false-color palette is referenced by the grayscale value 0, the second by grayscale value 1, etc.
If the "tRNS" chunk is present, its value is compared to the graylevel, not to the converted false-color of the pixels. If the "bKGD" chunk is present, background pixels will be displayed in the false-color corresponding to the grayscale value found in the "bKGD" chunk. The "cHRM" and alpha conversions, if present, are applied to the color samples in the converted false-color pixels. The "gAMA" chunk is ignored when the "faLT" chunk is processed, and the supplied "file_gamma" value is used instead.
Note that the "gAMA" and other values must be selected so that the grayscale image is meaningfully displayed when the "faLT" chunk is unrecognized or ignored.
If this chunk does appear, it must precede the first "IDAT" chunk. There can be only one "faLT" chunk in a PNG datastream.
The chunk can be used as a critical chunk, named "LoGE", or as an ancillary chunk, named "loGE". The syntax and function is exactly the same whichever name is used. The critical version should only be used if the image cannot be meaningfully displayed without performing "LoGE" scaling. Decoders not recognizing "LoGE" will not attempt to display the image at all. Encoders are strongly encouraged to include a "gAMA" chunk that permits a meaningful if not completely accurate display, and use the noncritical version, "loGE", if at all possible.
The "loGE/LoGE" chunk's contents are
n bytes: P0 (ASCII Text). First parameter, a real number written as a text floating-point value [link to Floating-Point Values in extensions document] 1 byte: null separator n1 bytes: P1 (Second parameter) 1 byte: null separator n2 bytes: P2 (Third parameter)
There is no trailing zero for the final string.
The scaling algorithm is
normalized_sample := input_sample/(2^input_depth-1) scaled_value := P0 + P1 * P2^normalized_sample output_sample := LIMIT (0, scaled_value, 2^output_depth-1) in which LIMIT (low, x, high) = MAX (MIN (x, high), low).For color_types 0 and 4, the normalized sample value is the grayscale value of the pixel normalized to the range [0.0:1.0] by dividing it by the maximum value for the input bit depth, using floating point arithmetic.
For color_types 2, 3, and 6, the scaling algorithm is applied independently to each of the color samples similarly normalized to [0.0:1.0].
The alpha channel, if present, is not affected by the "loGE/LoGE" transformation. Alpha compositing is done in the normal manner, with the transformed pixels forming the foreground image [link to Decoders: Alpha Processing in core spec]
Pure logarithmic data can be expressed with
P0 := 0 P1 := min_val P2 := max_val/min_valIn which the range [min_val..max_val] includes the minimum and maximum values appearing in the source data. When the image is decoded using the "loGE/LoGE" data, the gamma calculation for the decoded samples should be done as though the "file_gamma" were 1.0, regardless of the contents of the "gAMA" chunk.
It is advisable to include a "gAMA" chunk with logarithmic data, in case a viewer does not use the "loGE" data to decode it. A value of gamma should be chosen that allows the image to be displayed as well as it can be with a viewer that supports "gAMA" but not "loGE".
You can select a value of gamma (also called "file_gamma") by eye as described in [link to Gamma Tutorial: General Gamma Handling in core spec], or you can calculate one as follows:
If the maximum value of the logarithmically decoded pixels can reasonably be displayed as white on the monitor, then specifying a value of gamma given by
gamma := LN( LN(0.2) / LN(max_val/min_val) + 1) / LN(0.2) (in which LN() is the natural logarithm function)causes the two values max_val and 0.2*max_val to be reproduced at correct brightness on screen - these can be thought of as white and mid-grey. Tones between white and mid-grey will be a bit too bright, ones darker than mid-grey will be increasingly too dark, but it's a reasonable approximation for viewable display. A max_val/min_val ratio of 64 gives a gamma of about 0.3, a max_val/min_val of 1000 gives a gamma of about 0.165, so a viewer assuming a default gamma of 0.45 is going to give a bright, washed-out image for any log-encoded image.
In cases where the maximum sample value is many times brighter than scene white (i.e. the image is encoded to retain specular highlight information), the formula above doesn't apply, but there's probably no way of getting such an image to display reasonably anyway with a viewer that doesn't understand "loGE".
If present, the "loGE/LoGE" chunk must appear before the first "IDAT" chunk. Only one instance of the "loGE/LoGE" chunk is permitted in a PNG datastream.
The "pcAL" chunk's contents are are a zero-byte-terminated text string (purpose) that names the equation, followed (after the 20-byte signature and its null-byte separator) by an equation type and a set of parameters for the equation:
n bytes: purpose (Latin-1 text) 1 byte: null separator 20 bytes: signature ("PNG group 1996-10-27") 1 byte: null separator 1 byte: Equation type (unsigned integer). 0: Linear scaling 1: Base-e exponential scaling 2: Arbitrary-base exponential scaling 3: Hypberbolic scaling 1 byte: N (unsigned integer), number of parameters. u bytes: Unit (Latin-1 string). Symbol or description of the unit, eg. K, Population Density, MPa, etc). A zero-length string can be used if the data is dimensionless. 1 byte: null separator p0 bytes: P0 (ASCII text). First parameter, a real number written as a text floating-point value [link to Floating-Point Values in PNG extensions document] 1 byte: null separator p1 bytes: P1 (ASCII text). Second parameter. etc.There is no trailing zero for the final string. All of the parameters for the specified "equation_type" must be present. If some future private "equation_type" should be defined with a variable number of parameters, the number of parameters specified by "N" must be present. A null separator is not required after the last parameter.
The "purpose" identifies the equation, which can permit applications or people to choose the appropriate one when more than one scaling equation is stored in a multiple-image file. The "purpose" string must follow the format of a "tEXt" keyword, i.e. 1-79 printable Latin-1 characters. One way the "purpose" field could be used is to identify the system of units. A "purpose" string such as "SI" or "English" could be used in the "pcAL" chunk as well as in the "xxSC" and "yySC" chunks, to permit a decoder to select an appropriate set of chunks based on the contents of their "purpose" fields.
The scaling algorithm is
if equation_type == 0 then scaled_value := P0 + P1 * normalized_sample else if equation_type == 1 then scaled_value := P0 + P1 * EXP(P2 * normalized_sample) else if equation_type == 2 then scaled_value := P0 + P1 * P2^normalized_sample else if equation_type == 3 then scaled_value := P0 + P1*SINH((normalized_sample - P2/P3)/P4)in which
SINH(x) = 0.5 * ( EXP(x) - EXP(-x) )
For color_types 2, 3, and 6, the scaling algorithm is applied independently to each of the color sample values similarly normalized to [0.0:1.0].
Pure logarithmic data can be expressed either with
Equation_type =: 1 Equation_type := 2 N =: 3 or with N := 3 P0 =: 0 P0 := 0 P1 =: min P1 := min P2 =: LOGe(max/min) P2 := max/minThe "pcAL" data is not intended to be used by a decoder to affect the way the pixels are displayed. "pcAL" is simply a comment, and could be used, for example, to construct a reference color bar scale beside the image, or to extract the original physical values recorded in the file. The "drAN/DrAN" or "loGE/LoGE" chunk should be used if the encoder wants the decoder to modify the sample values for display purposes.
If present, the "pcAL" chunk must appear before the first "IDAT" chunk. Only one instance of the "pcAL" chunk is permitted in a PNG stream.
The "xxSC" chunk's contents are
n bytes: purpose (Latin-1 text) 1 byte: null separator 20 bytes: signature ("PNG group 1996-10-11") 1 byte: null separator xu bytes: Xunit (Latin-1 text). Symbol or description of the width unit, eg. milliseconds, degrees West Longitude, etc). A zero-length string can be used if the data is dimensionless. 1 byte: null separator x0 bytes: Xoffset (ASCII text). X offset, a real number written as a text floating-point value [link to Floating-Point Values in PNG extensions document] This is the physical value of "x" corresponding to the left edge of the image. 1 byte: null separator xs bytes: Xscale (ASCII text). X scale, the distance corresponding to the width of a pixel. Must be non-zero. The positive direction is to the right.There is no trailing zero for the final string.
The scaling algorithm for finding the physical x-value of the middle of a pixel is
physical_x_value := Xoffset + Xscale * (column_number + 0.5)If present, the "xxSC" chunk must appear before the first "IDAT" chunk. Only one instance of the "xxSC" chunk is permitted in a PNG stream.
The "yySC" chunk's contents are
n bytes: purpose (Latin-1 text) 1 byte: null separator 20 bytes: signature ("PNG group 1996-10-11") 1 byte: null separator yu bytes: Yunit (Latin-1 text). Symbol or description of the width unit, eg. milliseconds, degrees West Longitude, etc). A zero-length string can be used if the data is dimensionless. 1 byte: null separator y0 bytes: Yoffset (ASCII text). Y offset, a real number written as a text floating-point value [link to Floating-Point Values in PNG extensions document]. This is the physical value of "y" corresponding to the top edge of the image. 1 byte: null separator ys bytes: Yscale (ASCII text). Y scale, the distance corresponding to the height of a pixel. Must be non-zero. The positive direction is downward.There is no trailing zero for the final string.
The scaling algorithm for finding the physical y-value of the middle of a pixel is
physical_y_value := Yoffset + Yscale * (row_number + 0.5)If present, the "yySC" chunk must appear before the first "IDAT" chunk. Only one instance of the "yySC" chunk is permitted in a PNG stream.
http://www.w3.org/pub/WWW/TR/WD-png
.
The same precautions taken when displaying "tEXt" data should be taken when displaying the text contained in the "unit" strings of the "xxSC" and "pcAL" chunks and the "purpose" string of various chunks. Viewers should not display these strings directly without first checking for the presence of nonprintable characters, and for the <ESC> character in particular.
No known additional security hazards are posed by the chunks described here.