AcademySoftwareFoundation / OpenColorIO

A color management framework for visual effects and animation.
https://opencolorio.org
BSD 3-Clause "New" or "Revised" License
1.76k stars 438 forks source link

Check if colorspace is invertible #928

Closed vvzen closed 4 months ago

vvzen commented 4 years ago

Hi,

I'm currently writing an API on top of OCIO and I was wondering if there's a programmatic way to detect if a colorspace is not invertible. This could be helpful to automatically detect when we should avoid applying a colorspace transformation (since we don't use looks, some of our colorspaces also apply cdl/luts to give the final graded look, so being able to filter out non invertible colorspaces is a quite useful feature).

My current understanding is that if in the FileTransform of a Colorspace we have a 1D LUT, then the transformation is always invertible (it's a 1 to 1 mapping) but if we have a 3D LUT (a potential many to 1 mapping), then the transformation is not invertible unless we have another 3D LUT that goes in the other direction. And that's one first thing to keep in mind when checking for invertibility.

So I thought about checking the from_reference and to_reference directions of each colorspaces, if we have both on a colorspace definition, then it means we have all the informations on how to go to it and come back, which in my mind means it's invertible.

But if we take for example this colorspace:

- !<ColorSpace>
    name: Input - ARRI - V3 LogC (EI320) - Wide Gamut
    family: Input/ARRI
    equalitygroup: ""
    bitdepth: 32f
    description: |
      V3 LogC (EI320) - Wide Gamut

      ACES Transform ID : IDT.ARRI.Alexa-v3-logC-EI320.a1.v1
    isdata: false
    allocation: uniform
    allocationvars: [0, 1]
    to_reference: !<GroupTransform>
      children:
        - !<FileTransform> {src: V3_LogC_320_to_linear.spi1d, interpolation: linear}
        - !<MatrixTransform> {matrix: [0.680206, 0.236137, 0.083658, 0, 0.085415, 1.01747, -0.102886, 0, 0.002057, -0.062563, 1.06051, 0, 0, 0, 0, 1]}

it has got only a 1D Lut and a MatrixTransform. So I guess that if the matrix is invertible than the colorspace itself is actually invertible, even if it doesn't have a from_reference slot.

Am I wrong? Does OCIO offer any kind of way to check for invertibility?

Thanks,

Valerio

doug-walker commented 4 years ago

Hi Valerio,

In OCIO v1, all of the transforms/operators that may be used to build a to_reference or from_reference are invertible except for Lut3D. So if only the to_reference is available and the from_reference is needed (or vice versa), OCIO is typically able to build that on-demand. In your example, even though only the to_reference is provided, OCIO will calculate the from_reference when needed.

In OCIO v2, we added the ability to also invert Lut3D and so all transforms are now invertible. (This is a critical capability, in my opinion.)

Singular matrices are I believe the only remaining edge case that could cause inversion to fail. But we are planning on fixing that for v2 so that a pseudo-inverse will be returned.

There is no API to check for invertibility, but getProcessor will throw if the inversion fails. There are also other things that could cause it to throw (e.g. a FileTransform may load a file with a syntax error). So maybe you would want to focus not just on invertibility, but rather on whether getProcessor succeeds?

Given that in OCIO v2 inversion will never fail, I will argue that no invertibility API call will be needed.

thanks,

Doug

vvzen commented 4 years ago

Hi @doug-walker , thanks a lot for your reply - it's a real gem and it helped me a lot! I imagined OCIO would do something like that (building on demand) but it's great to actually know it for sure. Can I ask you how a Lut3D could be inverted, if for example 2 points on the source are being remapped onto 1 single point in the destination space? So given that 1 point on the destination, which one between the 2 would you pick when going backward? Thanks a lot,

Valerio

Dithermaster commented 4 years ago

In the cases I needed to know this, I just asked OCIO to create the processor (config->getProcessor) and it throws and exception if it can't (e.g., because there is a 3DLUT). If you write your own logic, there's always the chance it could differ from reality, so I just go to the single source of truth.

doug-walker commented 4 years ago

Hi Valerio,

Regarding the Lut3D inversion, if the forward direction collapses several inputs into one output, then it is obviously not possible to recover the original inputs. In that case, the inverse maps to one of the set of inputs that gets collapsed together (usually the one on the edge of the bijective part of the domain). Another way to think of it is that the result of a [Forward --> Inverse --> Forward] is equivalent to just [Forward].

The same is true for the Lut1D inversion.

Doug

sobotka commented 4 years ago

Given that in OCIO v2 inversion will never fail, I will argue that no invertibility API call will be needed.

As per our discussions in the OCIO meeting, I believe it is worth making the distinction whether or not a particular transform is invertible by way of reciprocity, despite always succeeding.

Useful from a DCC vantage for UI here.

Does this seem reasonable @doug-walker ?

doug-walker commented 4 years ago

Yes Troy, as you wrote, that topic has come up. We'll need to discuss more how to implement it. For example, it seems to imply that the contents of the src and dst menus for a color space conversion should no longer be the same. This is potentially something that could be added to the new app helpers that Patrick just did.

sobotka commented 4 years ago

For example, it seems to imply that the contents of the src and dst menus for a color space conversion should no longer be the same

Can you elaborate on this a bit if you have time?

Thanks Doug!

doug-walker commented 4 years ago

I was referring to end-user-facing tools such as OCIOColorSpace Transform that have menus for a source and destination color space. What I meant is that if we provide a way for config authors to indicate that a certain direction should not be allowed (from_ref/to_ref), then that means that certain color spaces will need to be removed from either the src or dst menus. Today, apps just iterate over getColorSpace(i) to build the list, there is no concept of whether this is a src or dst list currently.