[argyllcms] Re: Pre-linearization table for BtoA LUT

  • From: Graeme Gill <graeme@xxxxxxxxxxxxx>
  • To: argyllcms@xxxxxxxxxxxxx
  • Date: Fri, 19 Oct 2007 00:09:30 +1000

John Weissberg wrote:
As I understand it, the real purpose of this pre-linearization table is to
> guarantee that the value for a or b corresponding to the case where the
> index in the 33x33x33 matrix is 16 actually map to a or b values very close 
to 0.

That's one purpose. There can be others, such as expanding the area
occupied by the devices gamut, to fill out more of the B2A table
(thereby improving accuracy), or improving overall linearity
by helping to compensate for the (usually) linear interpolation
done with CLUT lookups.

I am still a bit confused as to how this pre-linearization matrix works. Below are the values for L,a,b that correspond to the 33x33x33 matrix indices prior to processing with the pre-linearization:

idx    L    a    b
0    0.00    -128.00    -128.00
1    3.13    -120.03    -120.03
2    6.25    -112.06    -112.06
3    9.38    -104.09    -104.09
4    12.50    -96.13    -96.13
5    15.63    -88.16    -88.16
6    18.75    -80.19    -80.19
7    21.88    -72.22    -72.22
8    25.00    -64.25    -64.25
9    28.13    -56.28    -56.28
10    31.25    -48.31    -48.31
11    34.38    -40.34    -40.34
12    37.50    -32.38    -32.38
13    40.63    -24.41    -24.41
14    43.75    -16.44    -16.44
15    46.88    -8.47    -8.47
16    50.00    -0.50    -0.50
17    53.13    7.47    7.47
18    56.25    15.44    15.44
19    59.38    23.41    23.41
20    62.50    31.38    31.38
21    65.63    39.34    39.34
22    68.75    47.31    47.31
23    71.88    55.28    55.28
24    75.00    63.25    63.25
25    78.13    71.22    71.22
26    81.25    79.19    79.19
27    84.38    87.16    87.16
28    87.50    95.13    95.13
29    90.63    103.09    103.09
30    93.75    111.06    111.06
31    96.88    119.03    119.03
32    100.00    127.00    127.00

This is only true for 8 bit or V4 CLUTs. For V2 16 bit cluts,
the ranges are L* 0 .. 100 + (25500/65280), and a*b* 128 .. 127 + (255/256)

I would love if someone would help me understand exactly the formula used to apply the pre-linearization table to these points.

It's not too difficult, you just have to keep track of the
encodings. A critical value for most profiles is
L*a*b* = 100,0,0, and it should map exactly to the media
white point because of the relative colorimetric nature of the
table representations.
This means in practice that the input value for 100,0,0
should land on a grid point, since you can't interpolate
with values that are darker than white, to make white.
(ie. that grid point is at the apex of the overall gamut hull).
Assuming an odd dimensioned grid, that means that the input tables
need to map L* = 100 to a clut input value of 1.0,
and a*b* = 0 to a clut input value of 0.5.

So for (say) 8 bit L*a*b*, that means that the L* input
curve must map 0 == 0.0 -> 0.0 and 100 == 1.0 -> 1.0, while the
a*b* has to map -127 == 0.0039215 -> 0.0, and 127 -> 1.0

For V2 16 bit, you would need L* 0 == 0.0 -> 0.0, and 100 == 0.996109 -> 1.0
and a*b* (say) -127.99609 == 0.000015259 -> 0.0 and 127.99609 == 1.0 -> 1.0.

Note that the a*b* range can be any symmetric range (ie. -127 to 127 would
also work fine for V2 16 bit), you just end up with slightly earlier
per component clipping in the lookup, and restrict the gamut
you can represent slightly.

Graeme Gill.


Other related posts: