Authoring Configurations

Config syntax

OpenColorIO is primarily controlled by a central configuration file, usually named config.ocio. This page will only describe how to syntactically write this OCIO config - e.g. what transforms are available, or what sections are optional.

This page alone will not help you to write a useful config file! See the Configurations section for examples of complete, practical configs, and discussion of how they fit within a facilities workflow.

Please note that you should use the OCIO Python or C++ API to generate the config.ocio file rather than writing the YAML by hand in a text editor. However, if you do ever modify YAML by hand rather than via the API, you should run ociocheck on it to ensure that the syntax is correct.

YAML basics

This config file is a YAML document, so it is important to have some basic knowledge of this format.

The Wikipedia article on YAML has a good overview.

OCIO configs typically use a small subset of YAML, so looking at existing configs is probably the quickest way to familiarise yourself (just remember the indentation is important!).

Checking for errors

Use the ociocheck command line tool to validate your config. It will inform you of YAML-syntax errors, but more importantly it performs various OCIO-specific validations. There are also validate methods on the Config class in the C++ and Python APIs, (although they do not do the role checking that ociocheck does).

For more information, see the overview of ociocheck

Config sections

An OCIO config has the following sections:

  • Config header – The header contains the version and LUT search path.

  • Environment – The environment defines the context variables used in the config.

  • Roles – The roles define which color spaces should be used for common tasks.

  • File & Viewing rules – These rules define sensible defaults that help applications provide a better user experience.

  • Displays & Views – This section defines how color spaces should be viewed.

  • Looks – Looks are transforms used to adjust colors, such as to apply a creative effect.

  • Colorspaces – This section defines the scene-referred color space encodings available within the config.

  • Display Colorspaces – This section defines the display-referred color space encodings available within the config.

  • Named Transforms – Named Transforms are a way to provide transforms that do not have a fixed relationship to a specific reference space, such as a utility curve.

A collection of Available transforms is provided for use in the various sections of the config file.

Config header

ocio_profile_version

Required.

By convention, the profile starts with ocio_profile_version.

This is a string, specifying which version of the OCIO config syntax is used.

The currently supported version strings are 1 and 2.

ocio_profile_version: 2

description

Optional. A brief description of the configuration.

description: This is the OCIO config for show: foo.

name

Optional. A unique name for the config. Future versions of OCIO might use this as a sort of “namespace” for the color spaces defined in the rest of the config.

name: studio-config-v1.0.0_aces-v1.3_ocio-v2.1

search_path

Optional. Default is an empty search path.

search_path is a colon-separated list of directories. Each directory is checked in order to locate a file (e.g. a LUT).

This works is very similar to how the UNIX $PATH env-var works for executables.

A common directory structure for a config is:

config.ocio
luts/
  lg10_to_lnf.spi1d
  lg10_to_p3.3dl

For this, we would set search_path as follows:

search_path: "luts"

In a color space definition, we might have a FileTransform which refers to the LUT lg10_to_lnf.spi1d. It will look in the luts directory, relative to the config.ocio file’s location.

Paths can be relative (to the directory containing config.ocio), or absolute (e.g. /mnt/path/to/my/luts)

Multiple paths can be specified, including a mix of relative and absolute paths. Each path is separated with a colon :

search_path: "/mnt/path/to/my/luts:luts"

Paths may also be written on separate lines (this is more Windows friendly):

search_path:
  - luts1
  - luts2

Finally, paths can reference OCIO’s context variables:

search_path: "/shots/show/$SHOT/cc/data:luts"

This allows for some clever setups, for example per-shot LUT’s with fallbacks to a default. For more information, see the examples in Looks Example

family_separator

Optional. Defines the character used to split color space family strings into hierarchical menus. It may only be a single character. If no separator is defined, the Menu Helpers API will not generate hierarchical menus.

family_separator: /

inactive_colorspaces

Optional. Identify a list of color spaces that should not be used. These spaces may stay in the config and will still work in ColorSpaceTransforms, but they will not be added to application menus. This will be overridden by the environment variable OCIO_INACTIVE_COLORSPACES.

inactive_colorspaces: [ do_not_use_this_colorspace, prev_version_colorspace ]

luma

Deprecated. Optional. Default is the Rec.709 primaries specified by the ASC:

luma: [0.2126, 0.7152, 0.0722]

These are the luminance coefficients, which can be used by OCIO-supporting applications when adjusting saturation (e.g. in an image-viewer when displaying a single channel)

Note

While the API method is not yet officially deprecated, luma is a legacy option from Imageworks’ internal, closed-source predecessor to OCIO.

The luma value is not respected anywhere within the OCIO library. Also very few (if any) applications supporting OCIO will respect the value either.

Environment

environment

Optional. The envrionment section declares all of the context variables used in the configuration.

environment:
  SEQ: default_sequence
  SHOT: $SHOT

It is highly recommended that config authors using context variables include the environment section for the following reasons:

  • It provides performance benefits to applications

  • It will make the config easier to read and maintain

  • It allows defining default values

  • It improves the validation that may be performed on a config

This config uses two context variables: SEQ and SHOT. SEQ has a default value of default_sequence. This is the value that will be used if the environment does not contain the SEQ variable and the context variable is not otherwise defined. The SHOT variable does not have a default and hence the use of the syntax shown.

The environment must be self-contained and may not refer to any other variables. For instance, in the example above it would not be legal to have SHOT: $FOO since FOO is not one of the declared variables.

Every context variable used in the config must be declared since no other environment variables will be loaded into the context. In studios that use a large number of environment variables, this may provide a performance benefit for applications.

Roles

roles

Required.

A “role” is an alternate name to a color space, which can be used by applications to perform task-specific color transforms without requiring the user to select a color space by name.

For example, the Nuke node OCIOLogConvert: instead of requiring the user to select the appropriate log color space, the node performs a transform between scene_linear and compositing_log, and the OCIO config specifies the project-appropriate color spaces. This simplifies life for artists, as they don’t have to remember which is the correct log color space for the current project - the OCIOLogConvert always does the correct thing.

A typical role definition looks like this, taken from the spi-vfx example configuration:

roles:
  color_picking: cpf
  color_timing: lg10
  compositing_log: lgf
  data: ncf
  default: ncf
  matte_paint: vd8
  reference: lnf
  scene_linear: lnf
  texture_paint: dt16

All values in this example (such as cpf, lg10 and ncf) refer to color spaces defined later the config, in the colorspaces section.

Here is a description of the roles defined within OpenColorIO. Note that application developers may also define roles for config authors to use to control other types of tasks not listed below.

Warning

Unfortunately there is a fair amount of variation in how applications interpret OCIO roles. This section should be expanded to try and clarify the intended usage.

  • aces_interchange - defines the color space in the config that implements the ACES2065-1 color space defined in SMPTE ST2065-1. This role is used to convert scene-referred color spaces between different configs that both define this role.

  • cie_xyz_d65_interchange - defines the color space in the config that implements standard CIE XYZ colorimetry, adapted to a D65 white. This role is used to convert display-referred color spaces between different configs that both define this role.

  • color_picking - colors in a color-selection UI can be displayed in this space, while selecting colors in a different working space (e.g. scene_linear or texture_paint).

  • color_timing - color space used for applying color corrections, e.g. user-specified grade within an image viewer (if the application uses the DisplayTransform::setDisplayCC API method)

  • compositing_log - a log color space used for certain processing operations (plate resizing, pulling keys, degrain, etc). Used by the OCIOLogConvert Nuke node.

  • data - used when writing data outputs such as normals, depth data, and other “non color” data. The color space in this role should typically have data: true specified, so no color transforms are applied.

  • default - when strictparsing: false, this color space is used as a fallback.

  • matte_paint - color space which matte-paintings are created in (for more information, see the guide on baking ICC profiles for Photoshop, and spi-vfx).

  • reference - the color space against which the other color spaces are defined.

Note

The reference role has sometimes been misinterpreted as being the space in which “reference art” is stored in.

  • scene_linear - the scene-referred linear-to-light color space, often the same as the reference space (see:ref:faq-terminology).

  • texture_paint - similar to matte_paint but for painting textures for 3D objects (see the description of texture painting in SPI’s pipeline).

File & Viewing rules

file_rules

Warning

Either the file_rules section or the default role are Required for configs of version 2 or higher.

Use the File Rules to assign a default color space to files based on their path.

Here is example showing the various types of rules that may be defined:

file_rules:
  - !<Rule> {name: LogC, extension: "*", pattern: "*LogC*", colorspace: ARRI LogC}
  - !<Rule> {name: OpenEXR, extension: "exr", pattern: "*", colorspace: ACEScg}
  - !<Rule> {name: TIFF, regex: ".*\\.TIF?F", colorspace: sRGB}
  - !<Rule> {name: ColorSpaceNamePathSearch}
  - !<Rule> {name: Default, colorspace: default}

The File Rules are a set of mappings that are evaluated from the top down. The first rule to match is what determines which ColorSpace is returned.

There are four types of rules available. Each rule type has a name key that may be used by applications to refer to that rule. Name values must be unique. The other keys depend on the rule type.

1. Basic Rules – This is the basic rule type that uses Unix glob style pattern matching and is thus very easy to use. It contains the keys:

  • name: Name of the rule.

  • pattern: Glob pattern to be used for the main part of the name/path. This is case-sensitive. It must be in double-quotes. Set it to “*” if you only want the rule to consider the extension.

  • extension: Glob pattern or string to be used for the file extension. Note that if glob tokens are not used, the extension will be used in a non-case-sensitive way by default. For example the simple string “exr” would match “exr” and “EXR”. If you only want to match “exr”, use the glob pattern “[e][x][r]”. It must be in double-quotes. Set it to “*” if you only want the rule to consider the pattern.

  • colorspace: ColorSpace name to be returned.

2. RegEx Rules – This is similar to the basic rule but allows additional capabilities for power-users. It contains the keys:

  • name: Name of the rule.

  • regex: Regular expression to be evaluated. It must be in double-quotes.

  • colorspace: ColorSpace name to be returned.

Note that a backslash character in a RegEx expression needs to be doubled up as \\ (as shown in the example above for the TIFF rule) to make it through the Yaml parsing.

3. OCIO v1 style Rule – This rule allows the use of the OCIO v1 style, where the string is searched for ColorSpace names from the config. This rule may occur 0 or 1 times in the list. The position in the list prioritizes it with respect to the other rules. It has the key:

  • name: Must be ColorSpaceNamePathSearch.

4. Default Rule – The file_rules section must always end with this rule. If no prior rules match, this rule specifies the ColorSpace applications will use. It has the keys:

  • name: must be Default.

  • colorspace: ColorSpace name to be returned.

Note: OCIO v1 defined a default role intended to specify a default color space when reading files. However, given the confusion over the usage of this role, the Default file rule is now the preferred way to indicate this mapping. However, if the file_rules section is not present in the config, the new API will try to use the default role in place of the Default Rule. If both are present, the Default Rule takes precedence. If both the file_rules section and the default role are missing, an exception will be thrown when loading the config.

Note that the strictparsing token does not affect the behavior of the File Rules API. In other words, evaluating the rules will always result in a ColorSpace being available to an application. However, the API also allows the application to know which rule was the matching one. So apps that want to work in “strict” mode should first check if strictparsing is true and if so check to see if the matching rule was the Default Rule. If so, it could then notify the user and take whatever action is appropriate. (As an alternative to checking which rule number was matched, the API call filepathOnlyMatchesDefaultRule may be used instead.)

Roles may be used rather than ColorSpace names in the rules.

It is also legal for rules to have additional key:value pairs where the value may be an arbitrary string. The API provides access to getting/setting these additional pairs and will preserve them on a Config read/write. These may be used to define application-specific behavior.

Note to developers: The older parseColorSpaceFromString API call is now deprecated and should be replaced with getColorSpaceFromFilepath.

strictparsing

Optional. Valid values are true and false. Default is true (assuming a config is present):

strictparsing: true

Warning

This attribute is from OCIO v1. In OCIO v2, the FileRules system was introduced and so the strictparsing attribute is less relevant now. The parseColorSpaceFromString API call is now deprecated and the proper way to obtain this information is getColorSpaceFromFilepath. The FileRules always return a default color space but the API filepathOnlyMatchesDefaultRule may be used by applications that want to take some special action if strictparsing is true.

OCIO v1 provided a mechanism for applications to extract the colorspace from a filename (the parseColorSpaceFromString API method).

So for a file like example_render_v001_lnf.0001.exr it will determine the colorspace lnf (it being the right-most substring containing a colorspace name).

However, if the colorspace cannot be determined and strictparsing: true, it will return an empty string.

If the colorspace cannot be determined and strictparsing: false, the default role will be used. This allows unhandled images to operate in “non-color managed” mode.

Application authors should note: when no config is present (e.g. via $OCIO), the default internal profile specifies strictparsing=false, and the default color space role is raw. This means that ANY string passed to OCIO will be parsed as the default raw. This is nice because in the absence of a config, the behavior from your application perspective is that the library essentially falls back to “non-color managed”.

viewing_rules

Optional.

Use the Viewing Rules to assign default views to color spaces.

The Viewing Rules allow config authors to help applications provide a better user experience by specifying the views appropriate to use for a given color space. For example, applications may use the default view when making thumbnail images for its user interface. Likewise, an application could select the default view the first time it displays an image in a viewport.

Here is an example:

viewing_rules:
  - !<Rule> {name: video-spaces, colorspaces: [sRGB, Rec709]}
  - !<Rule> {name: data-spaces, colorspaces: [alpha, normals]}

displays:
  sRGB:
    - !<View> {name: Video, view_transform: colorimetry, display_colorspace: sRGB, rule: video-spaces}
    - !<View> {name: Raw, colorspace: nc10, rule: data-spaces}

This is helpful for situations where a given view is intended for use with just a few specific color spaces. However in other situations, it would be helpful to be able to define rules to be used with a broader set of color spaces.

Color spaces may now have an “encoding” attribute to allow grouping color spaces into groups such as “scene-linear”, “log”, “sdr-video”, and “data”. The Viewing Rules makes it possible to define a rule based on the encoding attribute of a color space rather than a set of named color spaces. For example:

viewing_rules:
  - !<Rule> {name: scene-linear-or-log, encodings: [scene-linear, log]}

displays:
  sRGB:
    - !<View> {name: ACES, view_transform: ACES-sdr-video, display_colorspace: sRGB, rule: scene-linear-or-log}

The colorspaces and encodings attributes may contain a single value or a list of values. It is illegal for a rule to define both a list of colorspaces and encodings simultaneously.

Also, similar to the file_rules, it is allowed for a rule to define a set of custom key/value pairs like this:

- !<Rule> { name: scene-linear-rule, encodings: scene-linear, custom: {key1: value1, key2: value2} }

The key names and values are arbitrary strings. This may be useful to control application-specific behavior.

A Viewing Rule may contain the following keys:

  • name: The name of the rule (must be unique).

  • encodings: The color space encodings used by the rule (may be a list).

  • colorspaces: The color space names used by the rule (may be a list).

  • custom: A set of arbitrary key/value string pairs.

The API allows applications to request the list of views for a given color space. This uses the viewing rules to filter the views for the given display based on the color space name and encoding. Views that do not have a rules attribute are always returned (so if no rules are present, the results are the same as the unfiltered API call).

Note that the active_views may be used to remove views that are not appropriate for a given user or workstation. If the active_views list is non-empty, any views that are not in that list will not appear in the results provided to the application (regardless of whether the view appears in a rule).

Furthermore, active_views will continue to sort (that is, determine the index order) the list of views in all of the API calls.

The first allowed view for a color space is the default.

Displays & Views

displays

Required.

This section defines all the display devices which will be used. For example you might have a sRGB display device for artist workstations, a DCIP3 display device for the screening room projector.

Each display device has a number of “views”. These views provide different ways to display the image on the selected display device. Examples of common views are:

  • “Film” to emulate the final projected result on the current display

  • “Log” to send log-space pixel values directly to the display, resulting in a “lifted” image useful for checking black-levels.

  • “Raw” when assigned a colorspace with raw: yes set will show the unaltered image, useful for tech-checking images

An example of the displays section from the spi-vfx config:

displays:
  DCIP3:
    - !<View> {name: Film, colorspace: p3dci8}
    - !<View> {name: Log, colorspace: lg10}
    - !<View> {name: Raw, colorspace: nc10}
  sRGB:
    - !<View> {name: Film, colorspace: srgb8}
    - !<View> {name: Log, colorspace: lg10}
    - !<View> {name: Raw, colorspace: nc10}
    - !<View> {name: Film, colorspace: srgb8}

All the colorspaces (p3dci8, srgb8 etc) refer to colorspaces defined later in the config.

Unless the active_displays and active_views sections are defined, the first display and first view will be the default.

A view may be defined as a transform directly from the scene-referred reference space to the display, as illustrated above. Alternatively a view may be defined using the combination of a View Transform and a Display Color Space. In this case, the View Transform converts from the scene-referred reference space to the display-referred reference space and then the Display Color Space is used to convert from the display-referred reference space to the display. Here is an example:

displays:
  DCIP3:
    - !<View> {name: Film, view_transform: FilmView, display_colorspace: DCIP3}

view_transforms:
  - !<ViewTransform>
    name: FilmView
    from_reference: <omitted for brevity>

display_colorspaces:
  - !<ColorSpace>
    name: DCIP3
    from_display_reference: <omitted for brevity>

The keys allowed with a View are:

  • name: A name for the View.

  • colorspace: The color space whose transform will be used to convert from the reference space to the display.

  • view_transform: The transform used to convert from either the scene-referred reference to the display-referred reference space or as a transform to be applied in the display-referred reference.

  • display_colorspace: The display color space that is used to convert from the display-referred reference space to the display.

  • looks: One or more Look Transforms to be applied. The string may use the ‘+’ character to apply a look in the forward direction and the ‘-’ character to apply in reverse. See Looks

  • rule: The viewing rule to be used with this View. See viewing_rules

  • description: A description string for this View.

Note that a View may use either the colorspace key or it may use both the view_transform and dispay_colorspace keys. No other combinations are allowed.

view_transforms

Optional. Defines transforms to convert between the OCIO reference spaces.

An OCIO config may contain two Reference spaces: one scene-referred and the other display-referred. The View Transforms are mappings between these reference spaces. There are a variety of terms used in the industry for these mappings. In ISO 22028-1 and in ACES, they are called “color-rendering transforms” and in the ITU standards for HDR television (such as ITU-R BT.2100 and BT.2390) they are called an “Opto-optical Transfer Function” or OOTF.

It is also possible to specify a View Transform for adjusting display-referred reference space values. In other words, it may convert from the display-referred reference space back to itself. This is useful for describing transforms used for HDR to SDR video conversion, or vice versa.

A View Transform may use the following keys:

  • name: A name for the ViewTransform.

  • description: A description of the ViewTransform.

  • family: A family string (similar to ColorSpace).

  • categories: The categories used for menu filtering (similar to ColorSpace).

  • from_scene_reference: The transform from the scene-referred reference space to the display-referred reference space.

  • to_scene_reference: The transform from the display-referred reference space to the scene-referred reference space.

  • from_display_reference: The transform from the display-referred reference space to the display-referred reference space.

  • to_display_reference: The inverse of the from_display_reference transform.

default_view_transform

Optional. Defines the default view transform.

The default view transform is the view transform that is used if a ColorSpaceTransform needs to convert between a scene-referred and display-referred colorspace. If this key is missing, the first view transform in the config is used.

default_view_transform: un-tone-mapped

shared_views

Optional. Allows a view to be defined once for use in multiple displays.

For example, this:

shared_views:
  - !<View> {name: Log, colorspace: lg10}
  - !<View> {name: Raw, colorspace: nc10}

displays:
  DCIP3:
    - !<View> {name: Film, colorspace: p3dci8}
    - !<Views> [ Log, Raw ]
  sRGB:
    - !<View> {name: Film, colorspace: srgb8}
    - !<Views> [ Log, Raw ]

Is equivalent to this:

displays:
  DCIP3:
    - !<View> {name: Film, colorspace: p3dci8}
    - !<View> {name: Log, colorspace: lg10}
    - !<View> {name: Raw, colorspace: nc10}
  sRGB:
    - !<View> {name: Film, colorspace: srgb8}
    - !<View> {name: Log, colorspace: lg10}
    - !<View> {name: Raw, colorspace: nc10}

A shared view may use the special token <USE_DISPLAY_NAME> to request that the display_colorspace name be set equal to the display name that the shared view is used with. In the following example, when the ACES shared view is used with the sRGB display, its display_colorspace is set to “sRGB” and when it is used with the Rec709 display, its display_colorspace is set to “Rec709”.

shared_views:
  - !<View> {name: ACES, view_transform: ACES-sdr-video,
             display_colorspace: <USE_DISPLAY_NAME>}
  - !<View> {name: Log, colorspace: lg10}
  - !<View> {name: Raw, colorspace: nc10}

displays:
  sRGB:
    - !<Views> [ ACES, Log, Raw ]
  Rec709:
    - !<Views> [ ACES, Log, Raw ]

display_colorspaces:
  - !<ColorSpace>
    name: sRGB
    from_display_reference: <omitted for brevity>
  - !<ColorSpace>
    name: Rec709
    from_display_reference: <omitted for brevity>

As with any other view, a shared view may appear (or not) in the list of active_views.

Application developers do not need to worry about shared views since the API presents them as if they were a typical View.

active_displays

Optional. Default is for all displays to be visible, and to respect order of items in displays section.

You can choose what display devices to make visible in UI’s, and change the order in which they appear.

Given the example displays block in the previous section - to make the sRGB device appear first:

active_displays: [sRGB, DCIP3]

To display only the DCIP3 device, simply remove sRGB:

active_displays: [DCIP3]

The value can be overridden by the OCIO_ACTIVE_DISPLAYS env-var. This allows you to make the sRGB the only active display, like so:

active_displays: [sRGB]

Then on a review machine with a DCI P3 projector, set the following environment variable, making DCIP3 the only visible display device:

export OCIO_ACTIVE_DISPLAYS="DCIP3"

Or specify multiple active displays, by separating each with a colon:

export OCIO_ACTIVE_DISPLAYS="DCIP3:sRGB"

active_views

Optional. Default is for all views to be visible, and to respect order of the views under the display.

Works identically to active_displays, but controls which views are visible.

Overridden by the OCIO_ACTIVE_VIEWS env-var:

export OCIO_ACTIVE_VIEWS="Film:Log:Raw"

virtual_display

Optional. A virtual display may be defined to allow OCIO to instantiate new displays from ICC profiles.

The syntax is similar to a conventional display. It may incorporate both views and shared views. There may only be one virtual display in a config.

When OCIO instantiates a display from an ICC monitor profile it will create a display colorspace which is used with any views that have the display_colorspace set to <USE_DISPLAY_NAME>.

So in this example, if the application asks OCIO to instantiate a display from an ICC profile, the user would then see a second display, in addition to “sRGB”, named after the ICC profile. The views available for that new display are taken from the virtual display.

displays:
  sRGB:
    - !<View> {name: ACES, view_transform: ACES-sdr-video,
               display_colorspace: <USE_DISPLAY_NAME>}
    - !<View> {name: Log, colorspace: lg10}
    - !<Views> [ Raw ]

virtual_display:
  - !<View> {name: ACES, view_transform: ACES-sdr-video,
             display_colorspace: <USE_DISPLAY_NAME>}
  - !<View> {name: Log, colorspace: lg10}
  - !<Views> [ Raw ]

Looks

looks

Optional.

This section defines a list of “looks”. A look is a color transform defined similarly to a colorspace, with a few important differences.

For example, a look could be defined for a “first pass DI beauty grade”, which is used to view shots with a rough approximation of the final grade.

When the look is defined in the config, you must specify a name, the color transform, and the colorspace in which the grade is performed (the “process space”). You can optionally specify an inverse transform for when the look transform is not trivially invertable (e.g. it applies a 3D LUT)

When an application applies a look, OCIO ensures the grade is applied in the correct colorspace (by converting from the input colorspace to the process space, applies the look’s transform, and converts the image to the output colorspace)

Here is a simple looks: section, which defines two looks:

looks:
  - !<Look>
    name: beauty
    process_space: lnf
    transform: !<CDLTransform> {slope: [1, 2, 1]}

  - !<Look>
    name: neutral
    process_space: lg10
    transform: !<FileTransform> {src: 'neutral-${SHOT}-${SEQ}.csp', interpolation: linear }
    inverse_transform: !<FileTransform> {src: 'neutral-${SHOT}-${SEQ}-reverse.csp', interpolation: linear }

Here, the “beauty” look applies a simple, static ASC CDL grade, making the image very green (for some artistic reason!). The beauty look is applied in the scene-linear lnf colorspace (this colorspace is defined elsewhere in the config.

Next is a definition for a “neutral” look, which applies a shot-specific CSP LUT, dynamically finding the correct LUT based on the SEQ and SHOT context variables.

For example if SEQ=ab and SHOT=1234, this look will search for a LUT named neutral-ab-1234.csp in locations specified in search_path.

The process_space here is lg10. This means when the look is applied, OCIO will perform the following steps:

  • Transform the image from it’s current colorspace to the lg10 process space

  • Apply apply the FileTransform (which applies the grade LUT)

  • Transform the graded image from the process space to the output colorspace

The “beauty” look specifies the optional inverse_transform, because in this example the neutral CSP files contain a 3D LUT. For many transforms, OCIO will automatically calculate the inverse transform (as with the “beauty” look), however with a 3D LUT the inverse transform needs to be defined.

If the look was applied in reverse, and inverse_transform as not specified, then OCIO would give a helpful error message. This is commonly done for non-invertable looks

As in colorspace definitions, the transform can be specified as a series of transforms using the GroupTransform, for example:

looks:
  - !<Look>
    name: beauty
    process_space: lnf
    transform: !<GroupTransform>
      children:
        - !<CDLTransform> {slope: [1, 2, 1]}
        - !<FileTransform> {src: beauty.spi1d, interpolation: nearest}

Colorspaces

colorspaces

Required.

This section is a list of the scene-referred colorspaces in the config. A colorspace may be referred to elsewhere within the config (including other colorspace definitions), and are used within OCIO-supporting applications.

A colorspace may use the following keys:

to_scene_reference and from_scene_reference

These keys specify the transforms that define the relationship between the colorspace and the scene-referred reference space.

Note: In OCIO v1, the keys to_reference and from_reference were used (since there was only one reference space). These are still supported as synonyms.

Here is a example of a very simple colorspaces section, modified from the spi-vfx example config:

colorspaces:
  - !<ColorSpace>
    name: lnf
    bitdepth: 32f
    description: |
      lnf : linear show space

  - !<ColorSpace>
    name: lg16
    bitdepth: 16ui
    description: |
      lg16 : conversion from film log
    to_scene_reference: !<FileTransform> {src: lg16_to_lnf.spi1d, interpolation: nearest}

First the lnf colorspace (short for linear float) is used as our reference colorspace. The name can be anything, but the idea of a reference colorspace is an important convention within OCIO: all other colorspaces are defined as transforms either to or from this colorspace.

The lg16 colorspace is a 16-bit log colorspace (see spi-vfx for an explanation of this colorspace). It has a name, a bit-depth and a description.

The lg16 colorspace is defined as a transform from lg16 to the reference colorspace (lnf). That transform is to apply the LUT lg16_to_lnf.spi1d. This LUT has an input of lg16 integers and outputs linear 32-bit float values

Since the 1D LUT is automatically invertable by OCIO, we can use this colorspace both to convert lg16 images to lnf, and lnf images to lg16

Importantly, because of the reference colorspace concept, we can convert images from lg16 to the reference colorspace, and then on to any other colorspace.

Here is another example colorspace, which is defined using from_scene_reference.

- !<ColorSpace>
  name: srgb8
  bitdepth: 8ui
  description: |
    srgb8 :rgb display space for the srgb standard.
  from_scene_reference: !<FileTransform> {src: srgb8.spi3d, interpolation: linear}

We use from_scene_reference here because we have a LUT which transforms from the reference colorspace (lnf in this example) to sRGB.

In this case srgb8.spi3d is a complex 3D LUT which cannot be inverted, so it is considered a “display only” colorspace. If we did have a second 3D LUT to apply the inverse transform, we can specify both to_scene_reference and from_scene_reference

- !<ColorSpace>
  name: srgb8
  bitdepth: 8ui
  description: |
    srgb8 :rgb display space for the srgb standard.
  from_scene_reference: !<FileTransform> {src: lnf_to_srgb8.spi3d, interpolation: linear}
  to_scene_reference: !<FileTransform> {src: srgb8_to_lnf.spi3d, interpolation: linear}

Using multiple transforms

The previous example colorspaces all used a single transform each, however it is often useful to use multiple transforms to define a colorspace.

- !<ColorSpace>
  name: srgb8
  bitdepth: 8ui
  description: |
    srgb8 :rgb display space for the srgb standard.
  from_scene_reference: !<GroupTransform>
    children:
      - !<ColorSpaceTransform> {src: lnf, dst: lg16}
      - !<FileTransform> {src: lg16_to_srgb8.spi3d, interpolation: linear}

Here to get from the reference colorspace, we first use the ColorSpaceTransform to convert from lnf to lg16, then apply our 3D LUT on the log-encoded images.

This primarily demonstrates the meta-transform GroupTransform: a transform which simply composes two or more transforms together into one. Anything that accepts a transform like FileTransform or CDLTransform will also accept a GroupTransform

It is also worth noting the ColorSpaceTransform, which transforms between lnf and lg16 colorspaces (which are defined within the current config).

Example transform steps

This section explains how OCIO internally applies all the transforms. It can be skipped over if you understand how the reference colorspace works.

colorspaces:
  - !<ColorSpace>
    name: lnf
    bitdepth: 32f
    description: |
      lnf : linear show space

  - !<ColorSpace>
    name: lg16
    bitdepth: 16ui
    description: |
      lg16 : conversion from film log
    to_scene_reference: !<FileTransform> {src: lg16.spi1d, interpolation: nearest}

  - !<ColorSpace>
    name: srgb8
    bitdepth: 8ui
    description: |
      srgb8 :rgb display space for the srgb standard.
    from_scene_reference: !<GroupTransform>
      children:
        - !<ColorSpaceTransform> {src: lnf, dst: lg16}
        - !<FileTransform> {src: lg16_to_srgb8.spi3d, interpolation: linear}

To explain how this all ties together to display an image, say we have an image in the lnf colorspace (e.g. a linear EXR) and wish to convert it to srgb8 - the transform steps are:

  • ColorSpaceTransform is applied, converting from lnf to lg16

  • The FileTransform is applied, converting from lg16 to srgb8.

A more complex example: we have an image in the lg16 colorspace, and convert to srgb8 (using the lg16 definition from earlier, or the spi-vfx config):

First OCIO converts from lg16 to the reference space, using the transform defined in lg16’s to_scene_reference:

  • FileTransform applies the lg16.spi1d

With the image now in the reference space, srgb8’s transform is applied:

  • ColorSpaceTransform to transform from lnf to lg16

  • FileTransform applies the lg16_to_srgb8.spi3d LUT.

Note

OCIO has an transform optimizer which removes redundant steps, and combines similar transforms into one operation.

In the previous example, the complete transform chain would be “lg16 -> lnf, lnf -> lg16, lg16 -> srgb8”. However the optimizer will reduce this to “lg16 -> srgb”.

encoding

Optional. Specify how color space values are numerically encoded.

It is very helpful for applications to be able to know the basic type of encoding of a color space. For example, it is well known that the performance of various types of image processing algorithms varies based on the type of encoding. Applying a spatial filter to a scene-linear image gives a different subjective result than if applied to the same image encoded in a log color space. Likewise certain algorithms such as keying or tracking may assume that the color encoding is roughly perceptually uniform and thus may have difficulties with scene-linear images.

The allowed values and definitions are:

scene-linear – A scene-referred encoding where the numeric representation is proportional to scene luminance. Examples: ACES2065-1, ACEScg.

display-linear – A display-referred encoding where the numeric representation is proportional to display luminance. Example: CIE XYZ values measured off of a display or projection screen.

log – A scene-referred encoding where the numeric representation is roughly proportional to the logarithm of scene-luminance (often with some divergence in the shadows as with most camera log encodings). Examples: ACEScct, ACEScc, ARRI LogC, Sony S-Log3/S-Gamut3.

sdr-video – A display-referred encoding where the numeric representation is proportional to an SDR video signal. Examples: Rec.709/Rec.1886 video, sRGB.

hdr-video – A display-referred encoding where the numeric representation is proportional to an HDR video signal. Examples: Rec.2100/PQ or Rec.2100/HLG.

data – A non-color channel. Note that typically such a color space would also have the isdata attribute set to true. Examples: alpha, normals, Z-depth.

bitdepth

Optional. Default: 32f

Specify an appropriate bit-depth for the colorspace, and applications can use this to automatically output images in the correct bit-depth.

Valid options are:

  • 8ui

  • 10ui

  • 12ui

  • 14ui

  • 16ui

  • 32ui

  • 16f

  • 32f

The number is in bits. ui stands for unsigned integer. f stands for floating point.

Example:

- !<ColorSpace>
  name: srgb8
  bitdepth: 8ui

  from_scene_reference: [...]

isdata

Optional. Default: false. Boolean.

The isdata key on a colorspace informs OCIO that this colorspace is used for non-color data channels, such as the “normals” output of a a multipass 3D render.

Here is example “non-color” colorspace from the spi-vfx config:

- !<ColorSpace>
  name: ncf
  family: nc
  equalitygroup:
  bitdepth: 32f
  description: |
    ncf :nc,Non-color used to store non-color data such as depth or surface normals
  isdata: true
  allocation: uniform

equalitygroup

Optional.

If two colorspaces are in the “equality group”, transforms between them are considered non-operations.

You might have multiple colorspaces which are identical, but operate at different bit-depths.

For example, see the lg10 and lg16 colorspaces in the spi-vfx config. If loading a lg10 image and converting to lg16, no transform is required. This is of course faster, but may cause an unexpected increase in precision (e.g. it skip potential clamping caused by a LUT)

- !<ColorSpace>
  name: lg16
  equalitygroup: lg
  bitdepth: 16ui
  to_scene_reference: !<FileTransform> {src: lg16.spi1d, interpolation: nearest}

- !<ColorSpace>
  name: lg10
  equalitygroup: lg
  bitdepth: 10ui
  to_scene_reference: !<FileTransform> {src: lg10.spi1d, interpolation: nearest}
Do not put different colorspaces in the same equality group. For

logical grouping of “similar” colorspaces, use the family option.

family

Optional.

Allows for logical grouping of colorspaces within a UI.

For example, a series of “log” colorspaces could be put in one “family”. Within a UI like the Nuke OCIOColorSpace node, these will be grouped together.

The Menu Helpers API allows applications to build hierarchical menus for color spaces based on the family key. The family_separator key of the config is used to define the character used to separate the family string into tokens.

family_separator: /

color_spaces:
  - !<ColorSpace>
    name: ACME_log4
    family: Log/Cameras/ACME
    equalitygroup: ACME_log4
    [...]

  - !<ColorSpace>
    name: ACEScct
    family: Log/ACES
    equalitygroup: ACEScct
    [...]

  - !<ColorSpace>
    name: Rec.709
    family: Video/Broadcast/SDR
    equalitygroup: Rec.709
    [...]

Unlike equalitygroup, the family has no impact on image processing.

aliases

Optional.

The aliases key is used to define alternate names for the colorspace. For example, it may be useful to define a shorter version of the name that is easier to include in texture path names. Or it may be necessary to define an older version of the name for the color space for backwards compatibility.

aliases: [shortName, obsoleteName]

allocation and allocationvars

Optional.

These two options were used in OCIO v1 when transforms were applied on the GPU. However, the new GPU renderer in OCIO v2 does not need these.

However, they may still be used to automatically generate a “shaper LUT” when baking LUT’s unless one is explicitly specified (not all output formats utilise this)

For a detailed description, see How to Configure ColorSpace Allocation

Example of a “0-1” colorspace

allocation: uniform
allocationvars: [0.0, 1.0]
allocation: lg2
allocationvars: [-15, 6]

description

Optional.

A human-readable description of the colorspace.

The YAML syntax allows for either single-line descriptions:

- !<ColorSpace>
  name: kodaklog
  [...]
  description: A concise description of the kodaklog colorspace.

Or multiple-lines:

- !<ColorSpace>
  name: kodaklog
  [...]
  description:
    This is a multi-line description of the kodaklog colorspace,
    to demonstrate the YAML syntax for doing so.

    Here is the second line. The first one will be unwrapped into
    a single line, as will this one.

It’s common to use literal | block syntax to preserve all newlines:

- !<ColorSpace>
  name: kodaklog
  [...]
  description: |
    This is one line.
    This is the second.

Display Colorspaces

display_colorspaces

Optional.

This section is a list of all the display-referred colorspaces in the config. A display colorspace is very similar to a colorspace except its transforms go from or to the display-referred reference space rather than the scene-referred reference space.

A display colorspace may use all the same keys as a colorspace except it uses to_display_reference and from_display_reference rather than to_scene_reference and from_scene_reference to specify its transforms.

display_colorspaces:

  - !<ColorSpace>
    name: sRGB
    family:
    description: |
      sRGB monitor (piecewise EOTF)
    isdata: false
    categories: [ file-io ]
    encoding: sdr-video
    from_display_reference: !<GroupTransform>
      children:
        - !<BuiltinTransform> {style: "DISPLAY - CIE-XYZ-D65_to_sRGB"}
        - !<RangeTransform> {min_in_value: 0., min_out_value: 0., max_in_value: 1., max_out_value: 1.}

Available transforms

AllocationTransform

Transforms from reference space to the range specified by the vars:

Keys:

  • allocation

  • vars

  • direction

BuiltInTransform

Builds one of a known set of transforms, on demand

Keys:

  • style

  • direction

CDLTransform

Applies an ASC CDL compliant grade

Keys:

  • slope

  • offset

  • power

  • sat

  • style

  • name

  • direction

ColorSpaceTransform

Transforms from src colorspace to dst colorspace.

Keys:

  • src

  • dst

  • data_bypass

  • direction

DisplayViewTransform

Applies a View from one of the displays.

Keys:

  • src

  • display

  • view

  • looks_bypass

  • data_bypass

  • direction

ExponentTransform

Raises pixel values to a given power (often referred to as “gamma”)

!<ExponentTransform> {value: [1.8, 1.8, 1.8, 1]}

Keys:

  • value

  • style

  • name

  • direction

ExponentWithLinearTransform

Applies a power but with a linear section near black. May be used to implement sRGB, CIE L*, and the Rec.709 camera OETF (not the display!).

Keys:

  • gamma

  • offset

  • style

  • name

  • direction

ExposureContrastTransform

Applies an exposure, contrast, or gamma adjustment. Uses dynamic properties for optimal live adjustments (e.g., in viewports).

!<ExposureContrastTransform> {style: linear, exposure: -1.5,
  contrast: 0.5, gamma: 1.1, pivot: 0.18}

Keys:

  • exposure

  • contrast

  • pivot

  • gamma

  • style

  • log_exposure_step

  • log_midway_gray

  • name

  • direction

FileTransform

Applies a lookup table (LUT)

Keys:

  • src

  • cccid

  • cdl_style

  • interpolation

  • direction

FixedFunctionTransform

Applies one of a set of fixed, special purpose, mathematical operators.

Keys:

  • style

  • params

  • name

  • direction

GradingPrimaryTransform

Applies primary color correction.

Keys:

  • style

  • brightness

  • contrast

  • pivot

  • offset

  • exposure

  • lift

  • gamma

  • gain

  • saturation

  • clamp

  • name

  • direction

GradingRGBCurveTransform

Applies a spline-based curve.

Keys:

  • style

  • red

  • green

  • blue

  • master

  • lintolog_bypass

  • name

  • direction

GradingToneTransform

Applies an adjustment to various tonal ranges.

Keys:

  • style

  • blacks

  • shadows

  • midtones

  • highlights

  • whites

  • s_contrast

  • name

  • direction

GroupTransform

Combines multiple transforms into one.

colorspaces:

  - !<ColorSpace>
    name: adx10

    [...]

    to_reference: !<GroupTransform>
      children:
        - !<FileTransform> {src: adx_adx10_to_cdd.spimtx}
        - !<FileTransform> {src: adx_cdd_to_cid.spimtx}

A group transform is accepted anywhere a “regular” transform is.

Keys:

  • children

  • name

  • direction

LogAffineTransform

Applies a logarithm as well as a scale and offset on both the linear and log sides. May be used to implement Cineon or Pivoted (Josh Pines) style lin-to-log transforms.

Keys:

  • base

  • lin_side_offset

  • lin_side_slope

  • log_side_offset

  • log_side_slope

  • name

  • direction

LogCameraTransform

Similar to LogAffineTransform but also allows a linear section near black. May be used to implement the ACEScct non-linearity as well as many camera vendor lin-to-log transforms.

Keys:

  • base

  • lin_side_offset

  • lin_side_slope

  • log_side_offset

  • log_side_slope

  • lin_side_break

  • linear_slope

  • name

  • direction

LogTransform

Applies a mathematical logarithm with a given base to the pixel values.

Keys:

  • base

  • name

  • direction

LookTransform

Applies a named look

Keys:

  • src

  • dst

  • looks

  • direction

MatrixTransform

Applies a matrix transform to the pixel values

Keys:

  • matrix

  • offset

  • name

  • direction

RangeTransform

Applies an affine transform (scale & offset) and clamps values to min/max bounds.

Keys:

  • min_in_value

  • max_in_value

  • min_out_value

  • max_out_value

  • style

  • name

  • direction

Note

If a min_in_value is present, then min_out_value must also be present and the result is clamped at the low end. Similarly, if max_in_value is present, then max_out_value must also be present and the result is clamped at the high end.

Named Transforms

Sometimes it is helpful to include one or more transforms in a config that are essentially stand-alone transforms that do not have a fixed relationship to a reference space or a process space. An example would be a “utility curve” transform where the intent is to simply apply a LUT1D without any conversion to a reference space. In these cases, a named_transforms section may be added to the config with one or more named transforms.

Note that named transforms do not show up in color space menus by default, so the application developer must implement support to make them available to users.

This feature may be used to emulate older methods of color management that ignored the RGB primaries and simply applied one-dimensional transformations. However, config authors are encouraged to implement transforms as normal OCIO color spaces wherever possible.

Named transforms support the keys:

  • name

  • aliases

  • description

  • family

  • categories

  • encoding

  • transform

  • inverse_transform

named_transforms:
  - !<NamedTransform>
    name: Utility Curve -- Cineon Log to Lin
    transform: !<FileTransform> {src: logtolin_curve.spi1d}

Looks Example

Warning

This section is from OCIO v1 and has not been updated yet.

A “look” is a named color transform, intended to modify the look of an image in a “creative” manner (as opposed to a colorspace definition which tends to be technically/mathematically defined). An OCIO look typically exists as a flexible addendum to a defined viewing transform.

Examples of looks may be a neutral grade, to be applied to film scans prior to VFX work, or a per-shot DI grade decided on by the director, to be applied just before the viewing transform.

Looks are defined similarly to colorspaces, you specify a name and a transform (possibly a GroupTransform containing several other transforms), and optionally an inverse transform.

Where looks differ from colorspace definitions are in how they are applied. With a look, you also specify the “process space” - the colorspace in which the transform is applied.

Example configuration

Step 1: Setup a Look

A look is a top-level OCIO configuration object. Conceptually, it’s a named transform which gets applied in a specific color space. All of the changes below to the .ocio configs can be done manually by editing the text, or using the Python API.

Example look definition in a OCIO config:

looks:
- !<Look>
  name: di
  process_space: rclg16
  transform: !<FileTransform> {src: look_di.cc, interpolation: linear}

Example Python API call:

look = OCIO.Look(name='di', processSpace='rclg16')
t = OCIO.FileTransform('look_di.cc', interpolation=OCIO.INTERP_LINEAR)
look.setTransform(t)
config.addLook(look)

The src file can be any LUT type that OCIO supports (in this case, it’s a file that contains the <ColorCorrection> element from a CDL file.) You could also specify a .3dl, etc.

Once you define a look in your configuration, you’ll see that the OCIOLookTransform node in Nuke will provide the named option. In this example, the ‘DI’ look conceptually represents a look that will be applied in DI. Other look names we often used are ‘onset’, ‘editorial’, etc. The process_space specifies that the transform should be applied in that space. In this example, if you provide linear input to the OCIOLookTransform node, the pixels will be converted to rclg16 before applying the look_di.cc file-transform.

Step 2: Update the Display to use a look.

You can specify an optional ‘looks’ tag in the View tag, which will apply the specified look(s). This lets application in the viewer provide options which use the looks.

Example YAML config:

displays:
  DLP:
    - !<View> {name: Raw, colorspace: nc10}
    - !<View> {name: Log, colorspace: rclg10}
    - !<View> {name: Film, colorspace: p3dci16}
    - !<View> {name: Film DI, colorspace: p3dci16, looks: di}
  sRGB:
    - !<View> {name: Raw, colorspace: nc10}
    - !<View> {name: Log, colorspace: rclg10}
    - !<View> {name: Film, colorspace: srgb10}
    - !<View> {name: Film DI, colorspace: srgb10, looks: di}

Example Python API call:

for name,colorspace,look in [ ['Raw','nc10',''], ['Log','rclg10',''],
        ['Film','p3dci16',''], ['Film DI','p3dci16','di'] ]:
    config.addDisplay('DLP',name,colorspace,look)

for name,colorspace,look in [ ['Raw','nc10',''], ['Log','rclg10',''],
        ['Film','srgb10',''], ['Film DI','srgb10','di'] ]:
    config.addDisplay('sRGB',name,colorspace,look)

Option for advanced users: The looks tag is actually a comma-delimited list supporting +/- modifiers. So if you you wanted to specify a View that undoes DI, and then adds Onset, you could do “-di,+onset”.

Step 3: Get per-shot looks supported.

In the top example, look_di.cc, being a relative path location, will check each location in the config’s search_path. The first file that’s found will be used.

So if your config contains:

search_path: luts

… then only the ‘luts’ subdir relative to the OCIO config will be checked.

However if you specify:

search_path: /shots/show/$SHOT/cc/data:luts

…the directory ‘/shots/show/$SHOT/cc/data/’ will be evaluated first, and only if not found will the ‘luts’ directory be checked.

env-vars, absolute, and relative paths can be used both in the config’s search_path, as well as the View’s src specification.

Example:

- !<Look>
  name: di
  process_space: rclg16
  transform: !<FileTransform> {src: looks/$SHOT_di/current/look_$SHOT_di.cc, interpolation: linear}

Note that if the per-shot lut is not found, you can control whether a fallback LUT succeeds based on if it’s in the main location. You can also use this for multiple levels (show, shot, etc).

Advanced option: If some shots use .cc files, and some use 3d-luts currently there’s no simple way to handle this. What we’d recommend as a work around is to label all of your files with the same extension (such as .cc), and then rely on OCIO’s resilience to misnamed lut files to just load them anyways. Caveat: this only works in 1.0.1+ (commit sha-1: 6da3411ced)

Advanced option: In the Nuke OCIO nodes, you often want to preview looks ‘across shots’ (often for reference, same-as, etc). You can override the env-vars in each node, using the ‘Context’ menu. For example, if you know that $SHOT is being used, in the context key1 you should specify ‘SHOT’, and the in value1 specify the shot to use (such as dev.lookdev). You can also use expressions, to say parse a shot name out of [metadata "input/filename"]

Advanced option: If you are writing your own OCIO integration code, getProcessor will fail if the per-shot lut is not found, and you may want to distinguish this error from other OCIO errors. For this reason, we provide OCIO::ExceptionMissingFile, which can be explicitly caught (this can then handled using OCIO::DisplayTransform::setLooksOverride()). I’d expect image flipbook applications to use this approach.

Contexts Example

Warning

This section is from OCIO v1 and has not been updated yet.

OCIO’s allows different LUT’s or grades to be applied based on the current context.

These contexts are usually based on environment variables, but also allows on-the-fly context switching in applications that operate on multiple shots (such as playback tools)

Typically these would be used as part of the display transform, to apply shot-specific looks (such as a CDL color correction, or a 1D grade LUT)

A contrived example

The simplest way to explain this feature is with examples. Say we have two shots, ab-123 and sf-432, and each shot requires a different LUT to view. The current shot name is stored in the environment variable SHOT.

In the OCIO config, you can use this SHOT environment variable to construct the LUT’s path/filename. This path can be absolute (e.g /example/path/${SHOT}.spi1d), or relative to any directory on the OCIO search path, which includes the resource path (e.g ${SHOT}.spi1d)

This is a simplified example, to demonstrate the context feature. Typically this “contextual LUT” would be used in conjunction with other LUT’s (e.g before a scene-linear to log transform, followed by a 3D film emulation LUT), this will be covered in Per-shot grades

So, we have our empty OCIO config in ~/showcfg, and our two LUTs in ~/showcfg/luts which are named af-123.spi1d and sf-432.spi1d:

~/showcfg/
    config.ocio
    luts/
        af-123.spi1d
        sf-432.spi1d

In the config, we first specify the config version, and the resource path (usually this is relative to the directory containing config.ocio, although can be an absolute path):

ocio_profile_version: 1
resource_path: luts

Next, we define a colorspace that transforms from the show reference space to the display colorspace:

colorspaces:
  - !<ColorSpace>
    name: srgb8
    family: srgb
    bitdepth: 8ui
    from_reference: !<FileTransform> {src: ${SHOT}.spi1d}

Then add a display alias for this transform:

displays:
  - !<Display> {device: sRGB, name: "Shot LUT", colorspace: srgb8}

Finally, we point the OCIO env-variable to the config, set the SHOT env-variable to the shot being worked on, and launch Nuke (or any other OCIO-enabled application):

export OCIO=~/showcfg/config.ocio
export SHOT=af-123
nuke

In Nuke, we create an OCIODisplay node, select our “sRGB” device with the “Shot LUT” transform, and this will apply the af-123.spi1d LUT.

Per-shot grades

Similarly to LUTs, we use a .cc file (an XML file containing a single ASC CDL <ColorCorrection>), or a .ccc file (an XML file containing multiple ASC CDL color corrections, each with a unique ID)

The .cc file is applied identically to a regular LUT files, using a FileTransform. For example, if we have af-123.cc in the luts/ directory:

<ColorCorrection id="mygrade">
        <SOPNode>
             <Slope>2 1 1</Slope>
             <Offset>0 0 0</Offset>
             <Power>1 1 1</Power>
        </SOPNode>
        <SatNode>
             <Saturation>1</Saturation>
        </SatNode>
  </ColorCorrection>

We wish to apply this grade on the scene-linear image, then transform into log and apply a 3D print emulation LUT. Since this requires multiple transforms, instead of using a single FileTransform, we use a GroupTransform (which is is just a collection of other transforms):

colorspaces:
  - !<ColorSpace>
    name: lnh
    family: ln
    bitdepth: 16f:
    isdata: false

  - !<ColorSpace>
    name: lg10
    family: lg
    bitdepth: 10ui
    isdata: false
    to_reference: !<FileTransform> {src: lg10.spi1d, interpolation: nearest}

  - !<ColorSpace>
    name: srgb8
    family: srgb
    bitdepth: 8ui
    isdata: false
    from_reference: !<GroupTransform>
      children:
        - !<FileTransform> {src: ${SHOT}.cc}
        - !<ColorSpaceTransform> {src: lnh, dst: lg10}
        - !<FileTransform> {src: film_emulation.spi3d, interpolation: linear}

A .ccc file is a collection of <ColorCorrection>’s. The only difference is when defining the FileTransform, you must specify the cccdid key, which you can also construct using the context’s environment variables. This means we could create a grades.ccc file containing the grade for all our shots:

<ColorCorrectionCollection xmlns="urn:ASC:CDL:v1.2">
      <ColorCorrection id="af-123">
              <SOPNode>
                   <Slope>2 1 1</Slope>
                   <Offset>0 0 0</Offset>
                   <Power>1 1 1</Power>
              </SOPNode>
              <SatNode>
                   <Saturation>1</Saturation>
              </SatNode>
        </ColorCorrection>
        <ColorCorrection id="mygrade">
                <SOPNode>
                     <Slope>0.9 0.7 0.9</Slope>
                     <Offset>0 0 0</Offset>
                     <Power>1 1 1</Power>
                </SOPNode>
                <SatNode>
                     <Saturation>1</Saturation>
                </SatNode>
          </ColorCorrection>
</ColorCorrectionCollection>

And the colorspace definition to utilise this:

- !<ColorSpace>
  name: srgb8
  family: srgb
  bitdepth: 8ui
  isdata: false
  from_reference: !<GroupTransform>
    children:
      - !<FileTransform> {src: grades.ccc, cccid: ${SHOT}}
      - !<ColorSpaceTransform> {src: lnh, dst: lg10}
      - !<FileTransform> {src: film_emulation.spi3d, interpolation: linear}

A complete example

Warning

This is incomplete, the lnh_graded space is likely wrong

The context feature can be used to accommodate complex grading pipelines. In this example, we have a “neutral grade” for each shot, to neutralise color casts and exposure variations, keeping plates consistent throughout a sequence.

To view a shot, we reverse this neutral grade, apply a “beauty grade”, then apply the display transform (the usual lin-to-log and a film emulation LUT)

We will use the same two example shots from before, af-123 (which is in the af sequence) and sg-432 (in the sg sequence). Imagine we have many shots in each sequence, so we wish to put the grades for each sequence in a separate file.

Using the same directory structure as above, in ~/showcfg/luts we first create two grade files, grades_af.ccc:

<ColorCorrectionCollection xmlns="urn:ASC:CDL:v1.2">
      <ColorCorrection id="af/af-123/neutral">
              <SOPNode>
                   <Slope>2 1 1</Slope>
                   <Offset>0 0 0</Offset>
                   <Power>1 1 1</Power>
              </SOPNode>
              <SatNode>
                   <Saturation>1</Saturation>
              </SatNode>
        </ColorCorrection>

      <ColorCorrection id="af/af-123/beauty">
              <SOPNode>
                   <Slope>1.5 1.2 0.9</Slope>
                   <Offset>0 0 0</Offset>
                   <Power>1 1 1</Power>
              </SOPNode>
              <SatNode>
                   <Saturation>0.8</Saturation>
              </SatNode>
        </ColorCorrection>

        <!-- More ColorCorrection's... -->
</ColorCorrectionCollection>

And grades_sg.ccc:

<ColorCorrectionCollection xmlns="urn:ASC:CDL:v1.2">
        <ColorCorrection id="sg/sg-432/neutral">
                <SOPNode>
                     <Slope>0.9 0.7 0.9</Slope>
                     <Offset>0 0 0</Offset>
                     <Power>1 1 1</Power>
                </SOPNode>
                <SatNode>
                     <Saturation>1</Saturation>
                </SatNode>
          </ColorCorrection>

        <ColorCorrection id="sg/sg-432/beauty">
                <SOPNode>
                     <Slope>1.1 0.9 0.8</Slope>
                     <Offset>0 0 0</Offset>
                     <Power>1.2 0.9 1.5</Power>
                </SOPNode>
                <SatNode>
                     <Saturation>1</Saturation>
                </SatNode>
          </ColorCorrection>

          <!-- More ColorCorrection's.. -->
</ColorCorrectionCollection>

Next, we create the config.ocio file, containing a colorspace to define several colorspaces:

  • lnh, the scene-linear, 16-bit half-float space in which compositing will happen

  • lg10, the 10-bit log space in which material will be received (e.g in .dpx format)

  • srgb8, the display colorspace, for viewing the neutrally graded footage on an sRGB display

  • srgb8graded, another display colorspace, for viewing the final “beauty grade”

ocio_profile_version: 1

# The directory relative to the location of this config
resource_path: "luts"

roles:
  scene_linear: lnh
  compositing_log: lgf

displays:
  # Reference to display transform, without reversing the working grade
  - !<Display> {device: sRGB, name: Film1D, colorspace: srgb8}

  # Reference to display, reversing the working grade, and applying
  # the beauty grade
  - !<Display> {device: sRGB, name: Film1DGraded, colorspace: srgb8graded}

colorspaces:

  # The source space, containing a log to scene-linear LUT
  - !<ColorSpace>
    name: lg10
    family: lg
    bitdepth: 10ui
    isdata: false
    to_reference: !<FileTransform> {src: lg10.spi1d, interpolation: nearest}

  # Our scene-linear space (reference space)
  - !<ColorSpace>
    name: lnh
    family: ln
    bitdepth: 16f
    isdata: false

  # Neutrally graded scene-linear
  - !<ColorSpace>
    name: lnh_graded
    family: ln
    bitdepth: 16f
    isdata: false
    to_reference: !<FileTransform> {src: "grades_${SEQ}.ccc", cccid: "${SEQ}/${SHOT}/neutral"}


  # The display colorspace - how to get from scene-linear to sRGB
  - !<ColorSpace>
    name: srgb8
    family: srgb
    bitdepth: 8ui
    isdata: false
    from_reference: !<GroupTransform>
      children:
        - !<ColorSpaceTransform> {src: lnh, dst: lg10}
        - !<FileTransform> {src: lg_to_srgb.spi3d, interpolation: linear}

  # Display color, with neutral grade reversed, and beauty grade applied
  - !<ColorSpace>
    name: srgb8graded
    family: srgb
    bitdepth: 8ui
    isdata: false
    from_reference: !<GroupTransform>
      children:
        - !<FileTransform> {src: "grades_${SEQ}.ccc", cccid: "${SEQ}/${SHOT}/neutral", direction: inverse}
        - !<FileTransform> {src: "grades_${SEQ}.ccc", cccid: "${SEQ}/${SHOT}/beauty", direction: forward}
        - !<ColorSpaceTransform> {src: lnh, dst: srgb8}

How to Configure ColorSpace Allocation

The allocation / allocation vars were utilized using during GPU 3dlut / shader text generation in OCIO v1. However in OCIO v2, the GPU renderer does not need to bake color transforms and the allocation vars are not utilized unless an application requests the legacy GPU shader. However, the allocation vars are still utilized by the ociobakelut command-line utility.

If, in the course of baking, a 3D lut is required, the “allocation / allocation vars” direct how OCIO should sample the colorspace, with the intent being to maintain maximum fidelity and minimize clamping.

Currently support allocations / variables:

ALLOCATION_UNIFORM::

2 vars: [min, max]

ALLOCATION_LG2::

2 vars: [lg2min, lg2max] 3 vars: [lg2min, lg2max, linear_offset]

So say you have an srgb image (such as an 8-bit tif), where you know the data ranges between 0.0 - 1.0 (after converting to float). If you wanted to apply a 3d lut to this data, there is no danger in sampling that space uniformly and clamping data outside (0,1). So for this colorspace we would tag it:

allocation: uniform
allocationvars: [0.0, 1.0]

These are the defaults, so the tagging could also be skipped.

But what if you were actually first processing the data, where occasionally small undershoot and overshoot values were encountered? If you wanted OCIO to preserve this overshoot / undershoot pixel information, you would do so by modifying the allocation vars.

allocation: uniform
allocationvars: [-0.125, 1.125]

This would mean that any image data originally within [-0.125, 1.125] will be preserved during GPU processing. (Protip: Data outside this range may actually be preserved in some circumstances - such as if a 3d lut is not needed - but it’s not required to be preserved).

So why not leave this at huge values (such as [-1000.0, 1000.0]) all the time? Well, there’s a cost to supporting this larger dynamic range, and that cost is reduced precision within the 3D luts sample space. So in general you’re best served by using sensible allocations (the smallest you can get away with, but no smaller).

Now in the case of high-dynamic range color spaces (such as float linear), a uniform sampling is not sufficient because the max value we need to preserve is so high.

Say you were using a 32x32x32 3d lookup table (a common size). Middle gray is at 0.18, and specular values are very much above that. Say the max value we wanted to preserve in our coding space is 256.0, each 3d lut lattice coordinates would represent 8.0 units of linear light! That means the vast majority of the perceptually significant portions of the space wouldn’t be sampled at all!

unform allocation from 0-256: 0 8.0 16.0 … 240.0 256.0

So another allocation is defined, lg2

- !<ColorSpace>
  name: linear
  description: |
      Scene-linear, high dynamic range. Used for rendering and compositing.
  allocation: lg2
  allocationvars: [-8, 8]

In this case, we’re saying that the appropriate ways to sample the 3d lut are logarithmically, from 2^-8 stops to 2^8 stops.

Sample locations: 2^-8: 0.0039 2^-7: 0.0078 2^-6: 0.0156 … 2^0: 1.0 … 2^6: 64.0 2^7: 128.0 2^8: 256.0

Which gives us a much better perceptual sampling of the space.

The one downside of this approach is that it can’t represent 0.0, which is why we optionally allow a 3d allocation var, a black point offset. If you need to preserve 0.0 values, and you have a high dynamic range space, you can specify a small offset.

Example:

allocation: lg2
allocationvars: [-8, 8, 0.00390625]

The [-15.0, 6.0] values in spi-vfx come from the fact that all of the linearizations provided in that profile span the region from 2^-15 stops, to 2^6 stops. One could probably change that black point to a higher number (such as -8), but if you raised it too much you would start seeing black values be clipped. Conversely, on the high end one could raise it a bit but if you raised it too far the precision would suffer around gray, and if you lowered it further you’d start to see highlight clipping.