Comments on this document can be sent to the PNG specification maintainers at
Distribution of this memo is unlimited.
At present, the latest version of this document is available on the World Wide Web from
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.
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 19961226 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 pCAL No Before IDAT
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 original sample limits "X0" and "X1", 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-12-27") 1 byte: null separator x0 bytes: X0 (ASCII text) Lower limit of original sample range, a real number written as a text floating-point number. This original sample value is mapped to the stored sample value 0. 1 byte: null separator x1 bytes: X1 (ASCII text) Upper limit of original sample range, a real number written as a text floating-point number. This original sample value is mapped to the stored sample value M, where M is 2^sample_depth - 1. 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 final 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 other chunk types, to permit a decoder to select an appropriate set of chunks based on the contents of their "purpose" fields.
The "pcAL" chunk defines two mappings:
original_sample := (stored_sample * (X1 - X0) + M/2) / M + X0using integer arithmetic, where (a / b) means (integer(floor(real(a) / real(b)))). Note that this is the same as the "/" operator in the C programming language when "a" and "b" are nonnegative, but not necessarily when "a" or "b" is negative.
if equation_type == 0 then physical_value := P0 + P1 * original_sample/(X1-X0) else if equation_type == 1 then physical_value := P0 + P1 * EXP(P2 * original_sample/(X1-X0)) else if equation_type == 2 then physical_value := P0 + P1 * P2^(original_sample/(X1-X0)) else if equation_type == 3 then physical_value := P0 + P1*SINH(P2*(original_sample - P3)/(X1-X0))using floating point arithmetic, in which
SINH(x) = 0.5 * ( EXP(x) - EXP(-x) )
stored_sample := ((original_sample - X0) * M + (X1 - X0) / 2) / (X1 - X0) (limited to the range [0..M])This mapping is lossless and reversible when (X1-X0 <= M) and the original sample is in the range [X0..X1]. If (X1-X0 > M) then there can be no lossless reversible mapping, but the functions provide the best integer approximations to floating-point affine transformations.
For color_types 2, 3, and 6, the mapping algorithms are applied independently to each of the color sample values.
Pure logarithmic data can be expressed either with
X0 =: 0 X0 := 0 X1 =: M X1 := M 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. Another method 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.