AcademySoftwareFoundation / ColorInterop

Color Interop Forum
BSD 3-Clause "New" or "Revised" License
7 stars 0 forks source link

Standardized Color Spaces (Initial focus: texture/rendering) #1

Open carolalynn opened 6 months ago

carolalynn commented 6 months ago

Agree on a minimal set of reserved baseline color space encodings that are universally available in addition to definitions of user-defined spaces (i.e., the meaning of “lin_rec709” may not be modified). This set of color spaces would initially be based upon the spaces that MaterialX and OpenUSD support today, specifically for use in texture and render pipelines. Deliverables will include an OCIO config that documents the agreed upon names and transforms for the baseline set.

Here is the current list in MaterialX / USD as a starting point:

carolalynn commented 6 months ago

Linking the NanoColor Charter here for reference: https://docs.google.com/document/d/1eGLtOHY-hNKXdtBUJWQHK25WQcK2zjDJYkldmE6eZVY/edit?usp=sharing

lgritz commented 6 months ago

I've said it before many times, but just to memorialize it in the issue itself:

I think all of these are great except for srgb_texture, and my concern there is twofold, both related to the word "texture":

  1. For people who want sRGB for things other than texture, this is confusing -- it's hard to know if this the the space you should use if you're just trying to convert to what will display correctly on an sRGB monitor, or if you are looking for a label to apply to an obligatory-sRGB format you're reading like JPEG or PNG.

  2. For people trying to make textures, the fact that only one item in the list has the word "texture" in it might cause them to convert their textures to this color space, whereas I (coming from the high-end renderer world) think that textures stored in sRGB are a bad idea and I'd prefer to steer users to store their textures certainly in a linear encoding, and ideally as either acescg or lin_srgb, depending on which is the working color space the renderer is using for computation.

anderslanglands commented 6 months ago

Just wanted to +1 Larry’s concerns here. I realise it’s almost defacto now but srgb_texture is really a terrible name. Unfortunately looking at the rest of them it sort of implies that the “correct” name here would be srgb_srgb…

I don’t have any better suggestions but it feels like it would be a real shame to canonicalize this since it’s likely these names will be with us for ever more.

SonyDennisAdams commented 6 months ago

I saw it mentioned elsewhere, but I really like when a color space name includes the name of the primaries as well and the name of the curve, and in consistent order. An exception is when the color space name is standard and implies both (e.g., "ACEScc").

jstone-lucasfilm commented 6 months ago

From the USD/MaterialX perspective, I believe all of these names are flexible, and can be safely upgraded through the versioning system in MaterialX. I agree the name srgb_texture is a bit unusual, and its origins can be traced to the OpenColorIO configuration for ACES 1,2, where the MaterialX project inherited its original set of color space names:

https://github.com/colour-science/OpenColorIO-Configs/blob/feature/aces-1.2-config/aces_1.2/config.ocio#L4746

KelSolaar commented 6 months ago

I saw it mentioned elsewhere, but I really like when a color space name includes the name of the primaries as well and the name of the curve, and in consistent order. An exception is when the color space name is standard and implies both (e.g., "ACEScc").

This is what I was doing at work until harder adoption of the ACES config. I go as far as putting the primaries if required:

image

KelSolaar commented 6 months ago

I would also like to see srgb_ap1, we use this one almost exclusively in Unreal Engine.

scoopxyz commented 6 months ago

Kind of echoing Larry's point and to comment on Doug's excellent point in tonights meeting that we would ideally codify the image state of these spaces as well...

Although I don't agree with the current name I think the intention of the "texture" suffix is to inform that the image state of the texture/buffer/image is scene-referred, which is necessary to distinguish with output-referred spaces like sRGB or Display P3.

So I would be curious to hear if there are non-overloaded terms that could be used to distinguish the two? As a first thought (mostly to spur discussion):

So: scene_srgb and the rather silly scene_srgb_displayP3

I also must admit that even this distinction is not wholly satisfiying. For example, color textures that drive the "tint" of specular/coat/sheen BxDF shader parameters, while certainly not output-referred, may stretch the meaning of scene-referred image state a little. Perhaps the scene-referred concept of relative scene colorimetry safely encapsulates these concepts...

anderslanglands commented 6 months ago

Thomas’s scheme makes the most sense. Its explicit and consistent.

KelSolaar commented 5 months ago

Proposal for the names:

image

The User-facing Name (UI name) column represent the current names, what I'm proposing is that we pick one of the Analytical Name \d+, even for UI.

4 variants programmatically generated from the gamut, whitepoint and transfer function, if the 3 of them correspond to a standard, then we use the standard name.

I do think we need to put the whitepoint name in which case it would mean that this is the colourspace adopted whitepoint, i.e., original primaries and new whitepoint, and not that the colourspace has been chromatically adapted to the whitepoint, i.e., chromatically adapted primaries and new whitepoint.

anderslanglands commented 5 months ago

Shouldn't F9 be P3 - D65 - Linear? I'd also make F10 P3 - D65 - sRGB

KelSolaar commented 5 months ago

Absolutely fine with it, I only piggybacked on the fact that it is a standard space. I don't have a strong opinion about on the specific names, I do have about the way we construct them though. The advantage of having them built programmatically like above is that once we agree on the process, there is no further discussion to be had, akin to a code formatter!

anderslanglands commented 5 months ago

Cool. Yeah reason I bring it up is that my problem with the UI names is that they're very opaque ("what does Texture mean? Does it have the transfer function or not?"), so I feel there's a lot of value in making the analytic names as explicit as possible. I'd even go so far as to suggest not collapsing e.g. ACEScg.

KelSolaar commented 5 months ago

Sorry, my post was not clear, the User-facing Name (UI name) are the current names, what I'm proposing is that we pick one of the Analytical Name \d+, even for UI. As for shorthands, we can use a sluggifier like we do for the OCIO ACES Config.

anderslanglands commented 5 months ago

Yes I get that :) What I'm saying is that explicit is better so there's no confusion.

doug-walker commented 5 months ago

Thomas, thanks for adding the new tab to the spreadsheet with various options. I've been having various discussions with people and would like to add my two cents to the thread.

meshula commented 5 months ago

To Jonathan's point earlier about adopting consensus names for MatX and USD, my hope is to have a preliminary list that I can publish in USD 24.08, and that I can rely on that list being stable. More can be added over time.

The ones I need for sure immediately are

That's necessary in order to support existing functionality. Anything beyond that will be in order to support the other spaces consensus here identifies.

anderslanglands commented 5 months ago

Don't we need ACEScg as well?

Could that last one be srgb-rec709, or would that break something already in existence?

carolalynn commented 5 months ago

I don’t think Nick was implying those names as final, just that those are the spaces needed - but I agree acescg likely is as well. All the ones Nick mentions plus more are on the spreadsheet.

Thanks for the pared down list Nick, it’s really helpful.

On Thu, May 16, 2024 at 14:35 Anders Langlands @.***> wrote:

Don't we need ACEScg as well?

Could that last one be srgb-rec709, or would that break something already in existence?

— Reply to this email directly, view it on GitHub https://github.com/AcademySoftwareFoundation/ColorInterop/issues/1#issuecomment-2116229642, or unsubscribe https://github.com/notifications/unsubscribe-auth/AMPHU2FON3R4J4EYFTHIOZ3ZCURCJAVCNFSM6AAAAABGPTMLK2VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDCMJWGIZDSNRUGI . You are receiving this because you authored the thread.Message ID: @.***>

meshula commented 5 months ago

That's right, that was not meant to be a final list, it was meant to be the spaces I have to support today, so it's my most-minimum list, others will have different most-minimum :)

Anders, srgb-rec709 means EOTF of srgb and rec709 chromaticities, but the chromaticities are identical; do we gain anything from mix and match like that? I guess it emphasizes that Rec709 predates sRGB by a few years, but that's "interesting" as opposed to "practical". Since both are standards, do we gain anything by a more complicated name? I'm not opposed, just wondering.

anderslanglands commented 5 months ago

Just because you already called out lin-rec709, so the symmetrical name would be sRGB-rec709.

Personally I prefer Thomas’s tryptich form including the white point as the least ambiguous naming. It may seem like pedantry but I firmly believe the only hope we have of making this stuff possible to understand and converse about meaningfully is to be as explicit as possible. It’s hard enough to hold all the required steps in a chain of transforms in your head at once without also having to decode ambiguous names for each of them at the same time.

Case in point: just a couple of days ago I got tripped up trying to convert something to DisplayP3 in Nuke (for someone else who couldn’t figure it out themselves) because the config I was using didn’t have that and I accidentally used the similarly named “P3 - D65 - Display” instead. I consider myself a reasonably well-read colour enthusiast yet I still wasted a couple of hours including writing a “help!” email to Thomas before it clicked that that was applying the P3 2.6 gamma instead of sRGB.

KelSolaar commented 5 months ago

I agree with @anderslanglands here and would favour explicitness over anything.

Many of us understand what sRGB - Texture but it is easy because a) we built those configs and chose those names! b) spend a significant time swimming in colour science. However, it is a very much different for artists, I explain them important concepts and THE critical one is always the disambiguation between primaries, whitepoint and transfer function for a RGB colourspace.

The configs I was authoring for my team before full adoption of the ACES one were always very explicit so that artists understood exactly what they were picking by just looking at the name of the colourspace. Retrospectively, I have had much more questions with the ACES configs compared to those I was authoring before.

This is a unique opportunity to make this right and I hope that as a group we can think more about the users and can adopt a consistent scheme that can be analytically implemented.

lucafascione commented 5 months ago

I agree with what others are saying.

In particular I would like to bring up two points:

A) It seems to me the compact name should be strictly a tuple of (transfer, gamut, whitepoint, view). I don't feel all that strongly about how exactly it is represented (it seems each entry at the moment is picked from a list of short strings, more or less like an enum, and the elements are joined with an underscore. I think that's fine). I do think that because there will be a fair bit of software that will manipulate these codes, that it would be unwise to have every single "re"-implementor handling all the various cases of 'sRGB alone really means sRGB transfer, rec709 primaries, D65, "such and such" view'. When the alternative is to simply tokenize on '_' and pick the n-th entry. Per @KelSolaar point, this will also be a helpful reminder to less experienced users (or absent-minded ones like me) as to "what the whitepoint is for AcesP0", which I think it's a very nice plus. In case someone feels like proposing that "there will be libraries to tell you the for a given compact name", I'd like to present my counter that I've seen more bugs than I what I could have enjoyed fixing, caused by reimplementors that "should have known better", for me to accept that argument. Stuff happens, folks can't link to "library X", because it's "too big", or "is only available in python and I need shell script today" or all sorts of reasons. The other reason why I favor this, is that there is no guessing as to what something should be called. This helps both because it reduces the things you need to remember ('sRGB' is not a special case of anything) and because it's very simple to predict what new entries in the list should be called, which means folks that add spaces waiting for standardization/adoption, will have a maximized opportunity to naturally introduce names identical to what the 'standardization group' will decide upon. This seems very useful, especially to make it more likely that data created with one version of the software will work with as many newer and older versions as possible with minimal extra effort. Lastly I agree a single special case for data seems sensible. Maybe it could be called -data- instead, to make it more obvious it's special (or <data>, I guess some decoration we wouldn't normally use)

B) I'm sorry, but this 'texture' word really does not work with my senses. To me a texture is a thing that says "I'm mipmapped, and tiled in a specific way", I don't see why that would have anything to imply wrt view transforms. Is there any chance that we could pick a different word? I seem to recall @doug-walker had a reason why 'scene' was a poor choice, but I can't remember what his insight was there, forgive me. But if 'scene' is a poor choice, couldn't we pick something else please?

lucafascione commented 5 months ago

[Just about srgb <-> Rec709] Also, is there a chance we could just pick one among designating the primaries between 'sRGB' and 'Rec.709' and make sure we never need the other one? There seems to me some swaying around in that space, and I think (again especially in less experienced users) there is more opportunity to confuse folks than there is to help them

lgritz commented 5 months ago

A) It seems to me the compact name should be strictly a tuple of (transfer, gamut, whitepoint, view). I don't feel all that strongly about how exactly it is represented (it seems each entry at the moment is picked from a list of short strings, more or less like an enum, and the elements are joined with an underscore. I think that's fine).

I think the one wrinkle on this is that it's very common in many places to have a convention that embeds the color space names in filenames, path names, and asset names. It's not just something you read in a pull-down menu, it's also something people will have to type a lot, and that will take up column space when your bloodshot eyes are trying to look at long lists of mostly similar names. So people who have to deal with all that would greatly appreciate having a super compact alias.

My 2 cents about these competing use cases is that you really need 3 aliases for each color space, which applications should treat as equivalent:

  1. A long pedantic name such as the full formal name of an ISO specification (and which can contain spaces, punctuation, etc.);
  2. A compact machine+human readable, C-identifier-compliant, semi-compact but explicit version, perhaps as "transfer_gamut_whitepoint_view";
  3. A shorthand alias (one short word when possible, at most two) for use in filenames, typing, and display purposes where brevity is an important consideration.
lucafascione commented 5 months ago

I think 3 names as you propose is lovely, actually

L

On Mon, 20 May 2024, 17:43 Larry Gritz, @.***> wrote:

A) It seems to me the compact name should be strictly a tuple of (transfer, gamut, whitepoint, view). I don't feel all that strongly about how exactly it is represented (it seems each entry at the moment is picked from a list of short strings, more or less like an enum, and the elements are joined with an underscore. I think that's fine).

I think the one wrinkle on this is that it's very common in many places to have a convention that embeds the color space names in filenames, path names, and asset names. It's not just something you read in a pull-down menu, it's also something people will have to type a lot, and that will take up column space when your bloodshot eyes are trying to look at long lists of mostly similar names. So people who have to deal with all that would greatly appreciate having a super compact alias.

My 2 cents about these competing use cases is that you really need 3 aliases for each color space, which applications should treat as equivalent:

  1. A long pedantic name such as the full formal name of an ISO specification (and which can contain spaces, punctuation, etc.);
  2. A compact machine+human readable, C-identifier-compliant, semi-compact but explicit version, perhaps as "transfer_gamut_whitepoint_view";
  3. A shorthand alias (one short word when possible, at most two) for use in filenames, typing, and display purposes where brevity is an important consideration.

— Reply to this email directly, view it on GitHub https://github.com/AcademySoftwareFoundation/ColorInterop/issues/1#issuecomment-2120715375, or unsubscribe https://github.com/notifications/unsubscribe-auth/AYDJZE7MOMDJXSBYPRLITYDZDIKYJAVCNFSM6AAAAABGPTMLK2VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDCMRQG4YTKMZXGU . You are receiving this because you commented.Message ID: @.***>

carolalynn commented 5 months ago

The only situation where the white point is ambiguous is for the P3 primary set. For the other primaries (Rec.709, Rec.2020, AP0, AP1, AdobeRGB, RIMM) they are always (to my knowledge) used with one specific white point, so I question the value of adding that. For P3, the existing names either name it "DisplayP3" in which case the white is part of the spec, or use "P3-D65".

I would just like to re-surface this exact part of Doug's comment. I am of course happy to go with what the group wants, but personally, I'd favor being explicit about deviations from published standards vs explicit about everything. These color spaces do not live on an island, and our secondary responsibility is to write good documentation such that if an artist truly has a "what space do I pick from this dropdown" question, it can be answered by good documentation. We cannot expect a short name of something to answer all questions all the time.

In my opinion, the image state, or "context" of a color space in this list, due to many of them also being used in the context of a display, is much more a source of confusion than a whitepoint. We are all trying to think without our color science hats on - do most artists know/understand the concept of white point? I suppose many in the lighting/lookdev world likely do, to a certain extent...

SonyDennisAdams commented 5 months ago

Opinion: I'm a fan of at least being specific of the gamut and transfer function. That's how all of our internal color spaces names are done, and it helps prevent confusion (often my own).

Question: I noticed there were different gammas for Rec.709 (and maybe others). Do these always, sometimes, or never have the "linear segment" near zero?

KelSolaar commented 5 months ago

Following the meeting earlier this week, I would like to discuss some more about the inclusion of the image state in the colourspace names.

I could be wrong that we might be seeing conflicts due to OCIO design where RGB colourspaces are implicitly defined as a transformation from/to many reference spaces versus an explicit definition using chromaticities/primaries/transfer function (or a single reference space).

Let's start with the simple case of sRGB scene referred data exhibited onto a sRGB display without any reference space:

image

The blue boxes represent sRGB as a space explicitly defined, e.g., with chromaticities like with NanoColor, Colour, etc...

With OCIO and the current ACES configs, the processing chain as follows:

image

The lighter blue box are not explicitly defining a sRGB anymore but a transformation from/to it. One of the issue is there are many reference spaces, thus many transformations converting to sRGB. This imposes have a unique name per-conversion path.

A variant with a unique reference space would be as follows:

image

We only need an explicit definition of the chromaticities/primaries/transfer function or a single implicit transformation, technically two because of the inverse but it is a single conversion path.

During the meeting, we discussed about doing something along those lines, i.e., putting the image state as some sort of qualifier to disambiguate which conversion path we are dealing with:

image

All those blue boxes, irrespective of their light or dark appearance represent sRGB.

What annoys me, and was unable to articulate properly in the meeting, is that because OCIO cannot define chromaticities/primaries/transfer function explicitly and does not enforce a single reference space, we find ourselves having to pollute our RGB colourspace names with image state affixes. I understand that OCIO is the key enabler for colour management in our industry, but I have the feeling that we are trying to solve design issues/lack of enforcement at the wrong place: Those RGB colourspace names should describe a space, not a conversion path. Alternatively, if we are describing a conversion path, then let's be clear about it.

What ticked on me was the subsequent NanoColor meeting introducing a new CIE-XYZ-D65 colourspace for the scene, so now we would have one for the scene state, one for the output state. Without OCIO as context, this does not make a lot of sense and outsiders would be left wondering what we were thinking.

doug-walker commented 5 months ago

Maybe we could discuss this at the next OCIO TSC meeting as it's going to be very difficult to do such a wide-ranging, "let's start over" type of discussion in a GitHub issue. And unfortunately I needed to take some time off most of tomorrow and Friday.

I must refer you back to Giorgianni's book and ISO 22028-1 (which I know you know), and their definition of color space encodings.

You wrote: "Those RGB colourspace names should describe a space, not a conversion path." That is exactly the point of OCIO v2, where the view transforms were moved outside of the color space definitions. Hence, it does not matter how you get to a color space, as long as you follow the color space encoding, which includes not only the transfer function and gamut but also the viewing environment, numerical representation, and the image state. The TSC has discussed many times adding a more ICC-based approach of using chromaticities and power functions, but as you know ICC does not well handle scene-referred color spaces. Furthermore, many of us have gone down that path and experienced the many interop problems that arise as a result (in comparison to a transform-based approach). But that is mostly orthogonal to the naming issue. Adding the image state to the name has nothing to do with the transforms, it's based on the definition of the color space encoding. Part of the problem with sRGB is that its use for textures doesn't yet have a color space encoding definition. There is a need for a separate color space encoding, and hence a separate name.

Regarding the addition of a scene-referred CIE-XYZ-D65 option, that was trying to meet a request I've heard from a lot of people. It must be named differently since the image state and viewing environment are different. But if people don't want to add that, it's totally fine with me. I realize the gist of your objections are to other matters, but it seems we are not even aligned on what is currently in OCIO, so I'm hoping we could discuss this at a live meeting.

KelSolaar commented 5 months ago

Hey Doug,

I'm not saying we should start over, but I wanted a) to understand the reasoning behind the image state choice in the name and b) explain why I find this odd.

I don't follow you entirely on the encoding side: The ACES output transforms have different viewing conditions, and afaik, those are not explicitly defined anywhere in the C++ codebase (I don't think that they are even commented).

We are also connecting them all to the same CIE-XYZ-D65 colourspace but should not we have CIE-XYZ-D65-Display-Dark, CIE-XYZ-D65-Display-Dim, CIE-XYZ-D65-Display-Bright then? This goes back to the point I raised during the meeting: Do we need to have the viewing conditions in the name, what else is missing and where do we stop?

When, looking at sRGB - Display and Rec.1886 Rec.709 - Display in the OCIO config, we don't describe the viewing conditions anywhere and the image state is not really expressed explicitly, i.e., there is no dedicated yaml property:

  - !<ColorSpace>
    name: sRGB - Display
    aliases: [srgb_display]
    family: Display
    equalitygroup: ""
    bitdepth: 32f
    description: Convert CIE XYZ (D65 white) to sRGB (piecewise EOTF)
    isdata: false
    categories: [file-io]
    encoding: sdr-video
    allocation: uniform
    from_display_reference: !<BuiltinTransform> {style: DISPLAY - CIE-XYZ-D65_to_sRGB}

  - !<ColorSpace>
    name: Rec.1886 Rec.709 - Display
    aliases: [rec1886_rec709_display]
    family: Display
    equalitygroup: ""
    bitdepth: 32f
    description: Convert CIE XYZ (D65 white) to Rec.1886/Rec.709 (HD video)
    isdata: false
    categories: [file-io]
    encoding: sdr-video
    allocation: uniform
    from_display_reference: !<BuiltinTransform> {style: DISPLAY - CIE-XYZ-D65_to_REC.1886-REC.709}

C++ implementation for reference:

        auto CIE_XYZ_D65_to_SRGB_Functor = [](OpRcPtrVec & ops)
        {
            MatrixOpData::MatrixArrayPtr matrix
                = build_conversion_matrix_from_XYZ_D65(REC709::primaries, ADAPTATION_NONE);
            CreateMatrixOp(ops, matrix, TRANSFORM_DIR_FORWARD);

            const GammaOpData::Params rgbParams   = { 2.4, 0.055 };
            const GammaOpData::Params alphaParams = { 1.0, 0.0 };
            auto gammaData = std::make_shared<GammaOpData>(GammaOpData::MONCURVE_REV,
                                                           rgbParams, rgbParams, rgbParams, alphaParams);
            CreateGammaOp(ops, gammaData, TRANSFORM_DIR_FORWARD);
        };

        auto CIE_XYZ_D65_to_REC1886_REC709_Functor = [](OpRcPtrVec & ops)
        {
            MatrixOpData::MatrixArrayPtr matrix
                = build_conversion_matrix_from_XYZ_D65(REC709::primaries, ADAPTATION_NONE);
            CreateMatrixOp(ops, matrix, TRANSFORM_DIR_FORWARD);

            const GammaOpData::Params rgbParams   = { 2.4 };
            const GammaOpData::Params alphaParams = { 1.0 };
            auto gammaData = std::make_shared<GammaOpData>(GammaOpData::BASIC_REV,
                                                           rgbParams, rgbParams, rgbParams, alphaParams);
            CreateGammaOp(ops, gammaData, TRANSFORM_DIR_FORWARD);
        };

There is a lot of implicitness and many assumptions are being made, and I still have the feeling that we are adding the image state affix because of the way OCIO is currently designed. The image state does not provide critically useful information that can be used later: For example, I received a TIFF file that is mq_110_v1_rec1886_rec709_display.tiff The fact that there is _display does not help me in any way. On the other hand having the DRT instead, e.g., mq_110_v1_rec1886_rec709_aces-11-sdr-cinema-d60-sim-on-d65.tiff allows me to go back to the scene. Likewise for mq_110_v1_srgb_scene.exr, there is _scene and...?

Adding the image state to the name has nothing to do with the transforms, it's based on the definition of the color space encoding.

I'm not convinced it has nothing to do with the transforms: We must have a unique name because there are multiple reference spaces, hence different transformations lead to the same geometric representation and they need to be disambiguated.

Put another way, if we were to replace - Display with - Nemo the Config would still work perfectly fine, however, if we were to drop - Texture and - Display from sRGB - Texture and sRGB - Display respectively, things would break instantly.

I realize the gist of your objections are to other matters, but it seems we are not even aligned on what is currently in OCIO

There is not too much misalignment, OCIO is doing things in its own way which I'm generally fine with, we could talk about reference spaces but it is a different thread.

KelSolaar commented 5 months ago

Let me try another approach by going back to the Color Interop Goals: 2024_05_24_image_1 My understanding is as follows: We want to improve colour interchange between M&E industry software and thus adopt a lingua franca. We desire that when someone picks lin_rec709 in MaterialX, USD, OCIO but also Nuke, Baselight, Resolve, Colour, or any software that adopts our recommendation, they reference the same geometric representation of RGB colour. It seems like before we involve higher level concepts such as viewing conditions, image state, and so forth, we should try to solve the low level foundations, i.e., the least common denominator.

For reference, there are usually 2 ways to define a RGB colourspace programmatically:

Explicitly

Using a set of primaries and whitepoint under a given Standard Observer and transfer functions from which a transformation to the Standard Observer Tristimulus Space can be directly derived. This is what Unreal Engine, Nuke, Colour, ITU-T H.273, NanoColor, etc... for example tend to do:

Unreal Engine

2024_05_24_image_2

Nuke Colorspace Node

2024_05_24_image_3

Colour

2024_05_24_image_4

ITU-T H.273

2024_05_24_image_5

NanoColor

2024_05_24_image_6

Implicitly

Using a transformation to an arbitrary reference space, commonly ACES2065-1 or CIE-XYZ-D65, like OCIO and Unreal Engine:

OpenColorIO

2024_05_24_image_6

Unreal Engine (Yes too!)

2024_05_24_image_8

Now, let's assume that The Foundry finds useful to modify their Colorspace Node and add some presets using our some new potential names, those two hypothetical different presets would yield the same transformation:

2024_05_24_image_9 2024_05_24_image_10

The colour implementation of those colourspaces might look something along those lines:

colour.RGB_COLOURSPACES["srgb_rec709_tx"] = colour.RGB_COLOURSPACES["sRGB"].copy()
colour.RGB_COLOURSPACES["srgb_rec709_tx"].name = "srgb_rec709_tx"
colour.RGB_COLOURSPACES["srgb_rec709_dsp"] = colour.RGB_COLOURSPACES["sRGB"].copy()
colour.RGB_COLOURSPACES["srgb_rec709_dsp"].name = "srgb_rec709_dsp"

What is the advantage over doing this:

2024_05_24_image_11

colour.RGB_COLOURSPACES["srgb_rec709"] = colour.RGB_COLOURSPACES["sRGB"].copy()
colour.RGB_COLOURSPACES["srgb_rec709"].name = "srgb_rec709"

I think that this is inline with the concerns @lucafascione and @anderslanglands raised.

doug-walker commented 5 months ago

Thomas, I always appreciate your efforts to help us understand these issues thoroughly! However, I don't agree with all of your points.

The ACES output transforms have different viewing conditions, and afaik, those are not explicitly defined anywhere in the C++ codebase (I don't think that they are even commented).

The viewing conditions are generally commented in the ACES reference CTL, the C++ in OCIO is just a port of that, so it did not repeat that information, though I'm certainly not opposed to adding it.

We are also connecting them all to the same CIE-XYZ-D65 colourspace but should not we have CIE-XYZ-D65-Display-Dark, CIE-XYZ-D65-Display-Dim, CIE-XYZ-D65-Display-Bright then?

No, it should be possible to have a single display-referred connection space. That said, for the ACES 2 config, we should revisit where the viewing environment correction happens so that connections between all displays are more rigorous.

This goes back to the point I raised during the meeting: Do we need to have the viewing conditions in the name, what else is missing and where do we stop?

If the display in question already has an associated viewing environment, it's not helpful to complicate the names by adding that. For example, it generally wouldn't help to name something "Rec.1886 Rec.709 dim-surround" rather than simply "Rec.1886 Rec.709" given that the display is only specified for use in a dim surround. As you point out, we must be pragmatic and decide where to stop.

Of course, part of the goal of the color interop forum is to reduce ambiguity and confusion around the use of these standards and so we plan to include discussion of viewing environment (among other topics) in the published recommendation, along with the names. As you know, some of these standards either don't specify a viewing environment or the specification may be out of sync with how it is commonly used in practice and so that should be clarified. However, as Carol pointed out during the meeting, we cannot rely on the name alone to carry every potentially relevant piece of information or else they will be too cumbersome to actually use. We must choose only the essential aspects (and I argue image state is one of them, but only when it is ambiguous).

When, looking at sRGB - Display and Rec.1886 Rec.709 - Display in the OCIO config, we don't describe the viewing conditions anywhere and the image state is not really expressed explicitly, i.e., there is no dedicated yaml property

Regarding the sRGB - Display and Rec.1886 Rec.709 - Display in the OCIO config, the image state is expressed explicitly because they are in the display_colorspaces section of the config and therefore are display-referred.

... I still have the feeling that we are adding the image state affix because of the way OCIO is currently designed. The image state does not provide critically useful information that can be used later

I disagree. Image state is core to all modern color management standards, independent of OCIO, and does provide critical information. As an application developer, knowing the image state is essential since that conveys whether a viewing transform (aka tone-map) must be applied or not.

... On the other hand having the DRT instead, e.g., mq_110_v1_rec1886_rec709_aces-11-sdr-cinema-d60-sim-on-d65.tiff allows me to go back to the scene ...

As you point out, simply knowing the image state does not convey the entire history of a specific image. However, I would argue that we should not attempt to try to pack all of that into color space names. If that sort of history is needed, other mechanisms, such as AMF would be more appropriate.

As an application developer, the main thing I want to know is whether a view transform is required. If one must be applied (in either the forward or inverse direction), the app may ask the user to choose the appropriate one.

... we must have a unique name because there are multiple reference spaces, hence different transformations lead to the same geometric representation and they need to be disambiguated.

Yes, but it's only the "same geometric representation" in a local sense. From the point of view of any other color spaces one needs to transform them to or from, there may be a view transform involved.

It seems like before we involve higher level concepts such as viewing conditions, image state, and so forth, we should try to solve the low level foundations, i.e., the least common denominator.

Although that may at first sound very reasonable, I must strongly disagree. Having had the benefit of working at Kodak with Ed Giorgianni, Scott Gregory, and the others that developed the image state concept, I can tell you that the whole point of it was to educate people about when simple colorimetry-based techniques (like the ones you cite) are not appropriate and will cause problems.

As you well know, colorimetry alone is only a sufficient proxy for color appearance if a whole host of other variables are held constant. Although this was well known at Kodak for decades (since much of the early research was done there), as they started interacting on digital standards with people at other companies, they realized that most digital imaging engineers were not aware of this and that it would cause huge interop problems. Too many people had the expectation that they could take measured colorimetry from a scene, put it up on a monitor, and it should look like the scene. Hence Kodak originated the ISO 22028-1 standards process and related efforts.

Similarly today, many uneducated users wrongly assume they can paint a texture in Photoshop, assign it to some geometry in a scene, render it, and that it should look the same. Of course, that could only be true if the view transform is a no-op. However, most of us know that some view transform (whether from ACES, ARRI, FilmLight, or elsewhere) is necessary in order to make good looking images. (And let's simplify the discussion here by focusing on live action rather than animated content.)

So while the tools that you referenced that allow people to convert color "explicitly" with a drop-down menu of gamuts and transfer functions are appealing in their simplicity, they are inappropriate when trying to convert amongst color spaces of different image states. For example, some people probably wrongly assume those tools are appropriate to convert from ACEScg to sRGB for display on a monitor (after all, the options are right there in the menus).

I hope that explains where I disagree. But I thank you for taking time to write up your observations, it's definitely helping me understand what may be the disconnect between the various camps (which was no doubt part of your plan, so well done sir!).

The way I would try to summarize the difference of viewpoint is as follows:

Camp 1: The color space names are intended to convey a specific pair of options in the gamut and transfer function drop-downs in a Nuke color space node (or equivalent). The transformation to convert to another color space is always just a matrix and a 1D transfer function.

Camp 2: The color space names are (essentially) intended to convey either a stimulus in a scene OR an appearance on a display in a given environment. (And that is an exclusive "or", it must be one or the other!) The transformation implied by that depends on whether the conversion is within the same image state or not. If it's within the same image state, a matrix and 1D transfer function are usually sufficient, otherwise the application should ask the user what view transform (aka tone-map) is involved.

For now, since we're working on a limited set of color spaces specifically for the texture asset use-case, both camps are essentially equivalent. But as we said during the meeting, there is energy around a follow-up project expanding the list of color spaces and so it's important to come up with names that will work across roughly the domain covered by the OCIO Studio config for ACES and hence both image states.

In summary, the image state is the piece of information that lets an application know whether a view transform has been applied or not and hence is an essential disambiguation whenever an equivalent geometric encoding is used in both image states. To put it in an OCIO-specific context, it tells the application whether a ColorSpaceTransform or DisplayViewTransform should be used for a conversion. But the benefit is certainly not unique to OCIO and would equally apply to applications using other color management systems that need to work across image states.

KelSolaar commented 5 months ago

Thanks for the long reply!

However, I don't agree with all of your points.

It does not seem that you disagree with everything, starting with "That said, for the ACES 2 config, we should revisit where the viewing environment correction happens so that connections between all displays are more rigorous". For sure, we can connect everything to the same space, it was feigned naivety (or gentle sarcasm). The point still stand though that we do not track viewing conditions properly and we agree on that :)

rather than simply "Rec.1886 Rec.709" given that the display is only specified for use in a dim surround. As you point out, we must be pragmatic and decide where to stop.

Ah! :) See you did write Rec.1886 Rec.709 not Rec.1886 Rec.709 - Display here, maybe because - Display is redundant and we are unambiguously talking about a display specification? ;)

the image state is expressed explicitly because they are in the display_colorspaces section of the config and therefore are display-referred.

That's one way to see it, here, I would say that it is "inherited" but we are probably nitpicking. With that said, there are more than the two states we typically use in the VFX or video games and if we are going down the rigorous road, let's be rigorous and maybe consider add this to OCIO ColorSpace.

Image state is core to all modern color management standards, independent of OCIO, and does provide critical information. As an application developer, knowing the image state is essential since that conveys whether a viewing transform (aka tone-map) must be applied or not.

Hang on! You might have misinterpreted what I was meaning: I'm not saying that image state is not critical, the context was image state as an affix. If I send someone a mq_110_v2_rec1886_rec709.tiff file are we saying that because I forgot to add the _display affix the person would be unable to figure out the image state? Let me quote you: "it's not helpful to complicate the names by adding that." I see _display as redundant as the surround. The thing that would truly be useful in term of processing is mq_110_v2_rec1886_rec709_aces-11-sdr-cinema-d60-sim-on-d65.tiff: Free pathway back to the scene! How do we go back to the scene with mq_110_v2_rec1886_rec709_display.tiff? Embedded metadata, sidecar metadata, AMF? Well, why not put the image state and viewing conditions there then?

As you well know, colorimetry alone [...] I hope that explains where I disagree.

I wholeheartedly agree with what you wrote and I'm not the person that you should try to convince. I however tend to be pragmatic and I'm working with artists, all day long, (hence Cinematic Color 2 or the Precis). Adding _scene and especially _display as a filename suffix (or in the metadata) will not solve their problems: They will still come ask me how to get back to the scene.

To put it in an OCIO-specific context, it tells the application whether a ColorSpaceTransform or DisplayViewTransform should be used for a conversion.

As critical as the image state is, I cannot configure a DisplayViewTransform and write any automation around without knowing the view transform name.

Suffice to say that, with a OCIO v1 style config, it was trivial: mq_110_v3_out_p3d65d60simulation.tiff

PS: See, we are not so much in disagreement! :)

Shootfast commented 1 month ago

Hi folks, apologies for the somewhat late reply, but I've attempted to collate our (ILM's) feedback into a single document. https://docs.google.com/document/d/1915_iNFSw8J5myhflL12oVGMxb8_SMaZsFPP6VrJqZo/edit?usp=sharing

In short we have concerns about the naming convention chosen (The promotion of long, detailed names, and the addition of an unnecessary "_scene" suffix), the choice to incorrectly refer to the ACES whitepoints as D60, and the combination of CIE XYZ primaries with illuminant D65.

We also feel that certain colorspaces don't have enough "clout", or evidence of frequent interoperability to warrant inclusion in a list such as this, but at this time are more concerned with the naming convention and points above.

Happy to discuss in more detail

doug-walker commented 1 month ago

Thanks for the feedback Mark. Given that the feedback was also posted on the ASWF Slack and the discussion happened there, here is the URL to that conversation, for those interested: https://academysoftwarefdn.slack.com/archives/C06KER1N8KT/p1726770004688569