Every number in a profile is big-endian. The specification builds its structures from the basic types below, and stores colours in the profile connection space (PCS) in a few fixed encodings.
Basic number types
| Type | Size | What it holds |
|---|---|---|
| uInt8Number | 1 | Unsigned integer, 0 to 255 |
| uInt16Number | 2 | Unsigned integer, 0 to 65535 |
| uInt32Number | 4 | Unsigned integer |
| uInt64Number | 8 | Unsigned integer |
| s15Fixed16Number | 4 | Signed fixed point with 16 fraction bits: the two’s-complement integer divided by 65536. 80000000 is −32768.0, 00010000 is 1.0, 7FFFFFFF is 32767 + 65535/65536 |
| u16Fixed16Number | 4 | Unsigned fixed point with 16 fraction bits: 0 to 65535 + 65535/65536; 00010000 is 1.0 |
| u1Fixed15Number | 2 | Unsigned fixed point with 15 fraction bits: 8000 is 1.0, FFFF is 1 + 32767/32768 |
| u8Fixed8Number | 2 | Unsigned fixed point with 8 fraction bits: 0100 is 1.0, FFFF is 255 + 255/256 |
| float32Number | 4 | IEEE 754 single precision, without denormal numbers, infinities or NaN in the profile |
| dateTimeNumber | 12 | Six uInt16Numbers: year (in full), month 1–12, day 1–31, hours 0–23, minutes 0–59, seconds 0–59, all in UTC |
| positionNumber | 8 | A uInt32Number offset to an element and a uInt32Number size |
| response16Number | 8 | A uInt16Number device code (0000 for the device’s minimum, FFFF for its maximum), 2 reserved zero bytes, and an s15Fixed16Number measurement |
| XYZNumber | 12 | Three s15Fixed16Numbers: X, Y and Z |
| 7-bit ASCII | 1 a character | ISO/IEC 646 characters, the top bit zero |
iccMAX adds float16Number (IEEE 754 half precision) and float64Number.
XYZ values
In an XYZNumber, Y is scaled so that the perfect diffuse reflector or transmitter is 1.0, not 100 as the CIE has it, for nCIEXYZ and PCSXYZ. The numbers are signed because calculations can give negative values. Where an absolute value is meant, as in the luminanceTag and viewingConditionsType, Y is in candelas per square metre.
PCS encodings
Colours in the PCS are relative to the D50 white unless a tag says otherwise. PCSXYZ uses
16 bits a component; PCSLAB uses 8 or 16 bits a component; the floating-point transforms
(DToB and BToD tags) use float32Numbers that hold the values
directly.
PCSXYZ
| Value | u1Fixed15Number | s15Fixed16Number | float32Number |
|---|---|---|---|
| 0.0 | 0000 | 00000000 | 0.0 |
| 1.0 | 8000 | 00010000 | 1.0 |
| 1 + 32767/32768 | FFFF | 0001FFFE | 1.999969482421875 |
PCSLAB
| Value | 8-bit | 16-bit | float32Number |
|---|---|---|---|
| L* 0 | 00 | 0000 | 0.0 |
| L* 100 | FF | FFFF | 100.0 |
| a*, b* −128 | 00 | 0000 | −128.0 |
| a*, b* 0 | 80 | 8080 | 0.0 |
| a*, b* 127 | FF | FFFF | 127.0 |
The integer encodings of a* and b* are not two’s complement but a scale after an offset of 128, which keeps lookup tables free of a jump between negative and positive values. 8-bit and 16-bit values convert by multiplying or dividing by 257.
Legacy 16-bit PCSLAB
Version 2 profiles used a different 16-bit Lab encoding, and version 4 keeps it in two places only, lut16Type and namedColor2Type, for compatibility:
| Value | L* | a*, b* |
|---|---|---|
| 0000 | 0 | −128.0 |
| 8000 | 0 | |
| FF00 | 100.0 | 127.0 |
| FFFF | 100 + 25500/65280 (not a valid L*) | 127 + 255/256 |
To convert legacy values to the version 4 16-bit encoding, multiply by 65535/65280 (FFFF/FF00) and clip; to go back, divide.
White and black in the PCS
For every intent but ICC-absolute colorimetric, the media white is the PCS white:
| Component | Value | 8-bit | 16-bit |
|---|---|---|---|
| PCSLAB L*, a*, b* | 100, 0, 0 | FF 80 80 | FFFF 8080 8080 |
| PCSXYZ X, Y, Z | 0.9642, 1.0, 0.8249 | 7B6B 8000 6996 |
The perfect absorber is L* 0, a* 0, b* 0 (00 80 80, 0000 8080 8080)
and XYZ zero. Version 4 also fixes the black point of the perceptual reference medium,
which perceptual transforms map to: L* 3.1373 (08, 0808), a* and
b* 0, or XYZ 0.003357, 0.003479, 0.002869 (006E 0072 005E). Version 2
perceptual transforms usually used zero for black instead.
Device values
A device value from 0.0 to 1.0 is stored as 0 to 255 in 8 bits and 0 to 65535 in 16 bits. In the floating-point transforms device values may go below 0 and above 1.
The lookup tables work on values from 0.0 to 1.0, so device values and PCS values are scaled to that range before a table is used, the minimum of each encoding to 0 and the maximum to 1.