CLF cameraLogToLin vs IDT

Out of curiosity, I was looking to see if I can represent an IDT using CLF, but it seems like the answer is no. My math skills are rusty, so I just wanted to confirm if I’m looking at this right. For example to convert SLog3 to linear using the official IDT looks like this in CTL:

if (SLog >= 171.2102946929 / 1023.0) {
  out = pow(10.0, (SLog*1023.0-420.0)/261.5)*(0.18+0.01)-0.01;
}
else {
  out = (SLog*1023.0-95.0)*0.01125000/(171.2102946929-95.0);
}

In LaTeX form:

y=\begin{cases} \frac{10^\frac{y-420}{261.5} \times 0.19 - 0.01} \quad &\text{if} \, y \geq (171.2102946929 / 1023) \\ \frac{(y-95)}{0.01125000} \quad &\text{if} \, y < (171.2102946929 / 1023) \\ \end{cases}

The CLF cameraLogToLin piecewise function is similar but seems like it cannot do this exactly.

y=\begin{cases} \frac{(y-linearOffset)}{linearSlope} \quad &\text{if} \, y \leq logSideBreak \\ \frac{base^\frac{y-logSideOffset}{logSideSlope} - linSideOffset}{linSideSlope} \quad &\text{if} \, y > logSideBreak \\ \end{cases}

If you have OCIO 2.0 installed, it can help you with that. The ociomakeclf tool wraps a 3D LUT in a CLF, and has the option to add conversions between ACES2065-1 and another working colour space before and after the LUT3D, to make it a “per spec” LMT. The second half of this, being a conversion from a given colour space to ACES2065-1 is effectively an IDT for that colour space.

So for example:

ociomakeclf null.cube null.clf --csc SONY_SLOG3-SGAMUT3

will produce a CLF in which the last two process nodes are:

    <Log inBitDepth="32f" outBitDepth="32f" style="cameraLogToLin">
        <LogParams base="10" linSideSlope="5.26315789473684" linSideOffset="0.0526315789473684" logSideSlope="0.255620723362659" logSideOffset="0.410557184750733" linSideBreak="0.01125" linearSlope="6.62194371177582" />
    </Log>
    <Matrix inBitDepth="32f" outBitDepth="32f">
        <Array dim="3 3">
   0.75298259539984   0.143370216235557   0.103647188364603
 0.0217076974414429    1.01531883550528 -0.0370265329467195
-0.00941605274963355  0.00337041785882367     1.00604563489081
        </Array>
    </Matrix>

These two make up an IDT for S-Log3/S-Gamut3.

1 Like

For special formulas in IDTs (that cannot be recreated by a <Log> node in CLF) you could calculate the numbers for a 1D LUT node. That 1D LUT can be as precise as you want by defining how many supporting points that 1D LUT should have, for instance, 1024 (10-bit) or 65536 (16-bit). With that you can create a CLF from any such IDT by using that 1D LUT node and a matrix node.

1 Like

Wow very cool! The ocio tool makes it much easier.
I think I made some mistakes in my first post. I will study this some more, but I can see it’s more complicated than just plugging in the numbers.

One difference I still see is the IDT says ≥ logSideBreak, while the CLF function says ≤ logSideBreak. Does this cause a problem when y is exactly equal to the break point or is this difference so small it doesn’t matter?

Or if you need higher precision over a wider range

In theory it matters, for a precise match. But In practice, if the curve doesn’t join well at the break point, such that the log side and lin side give essentially the same result at that point, then it’s not a well designed log curve. Fortunately all the major camera log curves are pretty well designed.