ACES and chromatic adaptation consistency

Hi everyone! I’m trying to make DaVinci Intermediate Wide Gamut CSC DCTL for ACES Transform in Resolve. And I can’t find any information on what chromatic adaptation transform should I use for DaVinci Wide Gamut to AP0 conversion.

If I get it right, there are different chromatic adaptation transforms used for converting camera white point to ACES white point. It’s usually CAT02 or Bradford and sometimes XYZ scaling? Who and how decides what to use for each specific device / color space?

Things become more complicated if, let’s say, I have a lot of ARRI V3 footage archived as ACES 2065-1 EXR. If again I get it right, CAT02 is used in ARRI V3 IDT. So, if I want to go from ACES AP0 archives to DaVinci Intermediate Wide Gamut and to get the same images as I would get if I did the conversion from ARRI V3 to DWG, I should use CAT02 for AP0 to DWG conversion. But for other cameras it’s another method, Bradford, for example.
This makes choosing the standard, “right” chromatic adaptation transform for DWG to AP0 (and vice versa) conversion more difficult.
So, let’s imagine I’m building ACES LMT, that uses DaVinci Intermediate Wide Gamut as its internal color space. What chromatic adaptation transform should I use?

You are raising a very subtle but important point. By all practical means, the space where you perform the chromatic adaptation defines the “connection space”; currently, in ACES, that is a moving target. Using ACES as a bridge for other colour management workflows is not ideal therefore.
But to be fair, this is not really an ACES problem in its original definition. But it makes ACES somewhat less general.

1 Like

Thank you! May I ask you what has been taken into consideration when choosing the chromatic adaptation transform for E-Gamut to AP0 gamut transform in Baselight? Or, if it can be changed by a user, how was the default method chosen?

What would be the alternative? Using a space with a D65 whitepoint? At some point, you will need to perform an illuminant change, it is hard to avoid.

1 Like

The real problem is that color science has yet to establish a definitive model for chromatic adaptation.

1 Like

EGamut is not defined in the ACES specification, so if someone would create a csc or IDT, the Bradford CAT would probably be used, as this is the default.

Let’s turn of chromatic adaptation for a second. All “virtual spaces” like AP0, AP1 etc. are all defined via the 1931 XYZ Observer. So they are really all the same, and it does not matter which you use as a connection space when you calculate a net matrix from space A to space B. You could even use Rec.709 or Rec.2020 as connection space, all will lead to the same Net matrix.

Now if you introduce chromatic adaptation, things change because you perform an operation in a specific space. So the NET Matrix changes if you do chromatic adaptation in Bradford, vonKries LMS or any other space. In other words the space you do chromatic adaptation in is your defacto connection space. All the other spaces are unimportant and do not change the result.
So if you would ask me what the “connection space” of ACES is, I would not answer with “AP0”, but with “it depends”.
That effect is super subtle because the shifts we do (D65 to D60) are tiny, and the different spaces are very similar. But from a conceptual standpoint, it is not “clean”. And it is hard work to implement ACES in a more general Colour Management System.

It is unrealistic to hope that “Colour Science” will solve this problem because the human cognitive process is not really the right framework at this early stage in the pipeline. We deal with data from non-human observers (cameras).


Thanks for clarifying your thoughts! I don’t remember if ACES mandates a specific CAT in the various publications, maybe @Alexander_Forsythe can say but aces-dev which is the reference implementation uses CAT02.

We don’t mandate. I just generally tend towards CAT02. Chromatic adaptation is intended to produce the corresponding colorimetery for two viewers adapted to different environments, which is obviously complicated. Current models are probably much simpler than they need to be, but there’s a lot of active research in the aarea around multi-step and spectral chromatic adaptation. Even those approaches are probably not accurate for all circumstances.

1 Like

Have a look in ACESlib.Utilities_Color.ctl

float[3][3] calculate_rgb_to_rgb_matrix
  ( Chromaticities SOURCE_PRIMARIES,
    Chromaticities DEST_PRIMARIES,
    float coneRespMat[3][3] = CONE_RESP_MAT_BRADFORD

And some csc do not override the default like in ACEScsc.Academy.ACES_to_Log3G10_RWG.ctl

const float AP0_2_RWG_MAT[3][3] = 
                        calculate_rgb_to_rgb_matrix( AP0, 

others do like in

const float AP0_2_AWG_MAT[3][3] = 
                        calculate_rgb_to_rgb_matrix( AP0, 

And that is the issue @meleshkevich is facing.
So going from ARRI → RED directly using their published D65 matrices will produce a different result than going ARRI → ACES → RED.


Doesn’t all this make D60-like ACES white point less convenient for the majority of cases?
I’ve read this article, and not sure I understand it correctly, but seems like the reason for choosing the D60-like white point is the theaters delivery. But I bet the majority of ACES use cases is to deliver D65 white point masters.
I think having the consistency during the production is way more important. And placing white point conversion to D60 later in the chain (into DRT, to be more precise) seems like an acceptable compromise. (And projector can already be D60, so it’s not really a conversion of white point, but chromatic adaptation only?)
Maybe the upcoming major update of ACES to version 2 is the best time to consider rethinking ACES white point?

For me, as a user, ACES white point always felt like “it’s not D65, but ok, we can deal with this strange thing somehow”. And honestly I can’t imagine any real benefits of non-D65 white point.

1 Like

Sure, I’m aware that the Bradford CAT is defined. This outlier you have shown could be fixed for ACES 2.0. We could list all the transforms to see exactly what is using what but the cursory check I did when posting yesterday shows CAT02 as being used pretty much everywhere.

Edit: I was wrong, e.g. the new SSTS and the ODTs also use Bradford, so it is certainly a topic we should bring to the Output Transforms Working Group. Paging @KevinJW and @alexfry for VIS.

The ~D60 whitepoint question itself is a good and I’m inline with @meleshkevich on this.

This can quickly become a philosophical discussion.

I’m not sure if we should load this on top of the Output Working Group, I think they already have very much on their plate.

It is a smaller price to pay now compared to once ACES 2.0 is out and we need to regenerate all the output transforms, bump their versions because we have decided to conform the chromatic adaptation transforms to Bradford or CAT02.

But it also affects the IDT side of things and all CSCs. Just saying.

Also, there is room for debate if CAT02 is really the best CAT in the context of adapting display white points.

For sure, but we could take stance as the visual difference between the two are subtle, I don’t have a strong opinion over which one! I will try to get a good rundown of which CAT is use where tonight.

Used the OpenColorIO-ACES-Config repo to go through the CTL Transforms and here are the findings:

Bradford 37
Bradford (Only OT) 33
CAT02 900
CAT02 (-ARRI CCT) 50

There is a majority of CAT02, even if we exclude the ARRI v2 & v3 CCT IDTs. If we discount the Output Transforms, then we are talking about only 4 transforms using the Bradford transform.

Spreadsheet here: aces-dev CAT - Google Sheets

Code to generate the data:

     for ctl_transform in unclassify_ctl_transforms(
        if (
            "lib" in ctl_transform.path
            or "rrt" in ctl_transform.path
            or "utilities" in ctl_transform.path

        if == "output_transform":
            if (
                "D60_2_D65_CAT" in ctl_transform.code
                or "D60_SIM = false" in ctl_transform.code
        elif == "lmt":
        elif == "input_transform":
            if (
                "CAT02" in ctl_transform.code
                or "ALEXA" in ctl_transform.code
                or "Canon" in ctl_transform.code
                or "Sony" in ctl_transform.code
        elif == "csc":
            if "CONE_RESP_MAT_CAT02" in ctl_transform.code:
            elif (
                "ACEScc" in ctl_transform.code
                or "ACEScct" in ctl_transform.code
                or "ACEScg" in ctl_transform.code
                or "ACESproxy" in ctl_transform.code
                or "ADX" in ctl_transform.code
            raise (Exception(str(ctl_transform)))



Interesting. Does this take into account the
calculate_rgb_to_rgb_matrix function defaults to Bradford?

Unless I messed up something, yes, this should account for it, e.g. all the ODTs are Bradford because of that.

Although the huge number of ARRIRAW IDTs in that list (which @joseph has said should not be there any more, IIRC) does exaggerate the prevalence of CAT02.

Yes, 50 vs 37 but then if the ODTs are moved to CAT02 we are now talking about 88 vs 4.