CIE Lab

The CIE Lab colour model in tc-lib-color: L*a*b* components, the D65 white point, and where perceptual distance is measured

Lightness on one axis and two opponent chroma axes, scaled so that equal numeric steps are approximately equal perceptual steps. Lab coordinates describe a colour independently of the device rendering it.

Two parts of the library use that: perceptual distance on Nearest Colour, and the Lab alternate colour space of a spot colour in a PDF.

Model

ItemValue
Type stringLAB
Enum caseColorModelType::Lab
Class\Com\Tecnick\Color\Model\Lab
PDF colour spaceDeviceRGB, by conversion
Notationslab()

Components

ComponentKeyRangeOut of range
L* (lightness)lstar0.0 to 100.0clamped
a* (green to red)astar-128.0 to 127.0clamped
b* (blue to yellow)bstar-128.0 to 127.0clamped
Alphaalpha0.0 to 1.0, default 1.0clamped

These are the only components in the library that are not fractions in [0..1], and the only ones that go negative.

Construction

<?php

require_once __DIR__ . '/vendor/autoload.php';

$lab = new \Com\Tecnick\Color\Model\Lab([
    'lstar' => 42.008144,
    'astar' => -0.151700,
    'bstar' => -32.846040,
]);

echo $lab->getCssColor(), "\n";
echo $lab->getRgbHexColor(), "\n";
echo $lab->getPdfColor();
lab(42.0081% -0.1517 -32.846)
#336699
0.200000 0.400000 0.600000 rg

Output

Every accessor, against #336699:

CallResult
getCssColor()lab(42.0081% -0.1517 -32.846)
getRgbHexColor()#336699
getRgbaHexColor()#336699ff
getComponentsString()42.008144 -0.151700 -32.846040
getPdfColor()0.200000 0.400000 0.600000 rg
getPdfColor(true)0.200000 0.400000 0.600000 RG
getJsPdfColor()["RGB",0.200000,0.400000,0.600000]
getArray()['L' => 42.0081436628616, 'a' => -0.15169986265223256, 'b' => -32.84603952194887, 'A' => 1.0]
getNormalizedArray(255)['L' => 42.0, 'a' => -0.0, 'b' => -33.0, 'A' => 1.0]
getPDFacArray()[0.20000005882999666, 0.3999999766783507, 0.6000000097846151]

Two results from that table. getNormalizedArray(255) ignores its argument and rounds to integers, so the -0.1517 the CSS form keeps arrives as -0.0; getArray() returns the unrounded components. getPdfColor() emits DeviceRGB, since PDF has no Lab colour space for a plain fill. A Lab value reaches a PDF as the alternate space of a spot colour, not as a colour operator.

The White Point

D65, fixed, as the row sums of the sRGB to XYZ matrix the conversion uses. A Lab value computed elsewhere under D50, which is the illuminant most print workflows use, will not match one computed here.

addSpotLabColor() takes a white point option, but it only sets the metadata written into the PDF Lab colour space. The CMYK equivalent it stores alongside is computed under D65 regardless.

Clamping

$lab = new \Com\Tecnick\Color\Model\Lab([
    'lstar' => 120.0,   // clamped to 100
    'astar' => 200.0,   // clamped to 127
    'bstar' => -200.0,  // clamped to -128
]);

echo $lab->getCssColor(), "\n";
print_r($lab->getNormalizedArray(255));
lab(100% 127 -128)
Array
(
    [L] => 100
    [a] => 127
    [b] => -128
    [A] => 1
)

The a* and b* axes are not bounded in theory. The [-128..127] interval is what this model represents, and addSpotLabColor() clamps its range option to the same interval, so a spot colour cannot declare a range wider than the components it stores.

See Also