OpenColorIO Color Management System - Study Notes

OpenColorIO Color Management System - Study Notes

What Is OpenColorIO (OCIO)

OpenColorIO (OCIO) is a complete color management solution aimed primarily at film production, with a particular focus on visual effects (VFX) and computer animation. It helps implement the management methods required for high-fidelity color imaging in modern computer graphics.

Core Concepts

OCIO’s color science knowledge comes entirely from its execution of the transforms defined in an OCIO config file. These transforms can be:

  • Defined by the end user in a custom OCIO config file
  • Inherited from publicly available configs (such as ACES)

By specifying the desired config.ocio file in your local environment, all OCIO-compatible applications and software libraries will recognize the color transform “universe” you’ve defined, and guide image data from one defined OCIO.ColorSpace to another.

OCIO Architecture

Configs

A config is the top-level entity, representing the entirety of the current color “universe.” Configs are serialized to .ocio files, read at runtime, and are typically used in a “read-only” context.

Example configs:

  • ACES - The Academy of Motion Picture Arts and Sciences standardized color workflow
  • spi-vfx - Some VFX projects from Sony Pictures Imageworks (e.g., Spider-Man)
  • aces_1.0.3 - ACES 1.0.3 stable release
  • aces_2.0.0+ - ACES 2.0 config (built into OCIO 2.5+)

Note: The OpenColorIO-Configs repository was archived as read-only in September 2025. It’s recommended to use the ACES config built into OCIO, or obtain configs from other sources.

ColorSpaces

A ColorSpace typically corresponds to:

  • An input image state
  • An output image state
  • An image state used for internal processing

ColorSpace examples (from the ACES config):

  • aces - HDR, scene-linear
  • adx10 - Log-like density encoding space
  • slogf35 - Sony F35 slog camera encoding
  • rrt_srgb - Baked display transform for sRGB displays
  • rrt_p3dci - Baked display transform for DCI-P3 displays

Transforms

ColorSpaces contain an ordered list of transforms that define how to convert to and from the config’s “reference” space.

Transform types:

OCIO 1.x / 2.x common types:

  • FileTransform - File-based transforms (1D LUT, 3D LUT, CLF/CTF files, matrix files, etc.)
  • GroupTransform - Contains an ordered list of transforms
  • LookTransform - Color transform for applying creative looks
  • CDLTransform - ASC CDL (Color Decision List)
  • MatrixTransform - Matrix transform
  • LogTransform - Log/anti-log transform
  • ExposureTransform - Exposure adjustment (in stops)

New types added in OCIO 2.0+:

  • BuiltinTransform - Built-in transforms that require no external files (used extensively in the ACES 2.0 config)
  • ViewTransform - Display/view transforms
  • NamedTransform - A standalone color transform not bound to a specific color space
  • ColorSpaceTransform - Color space conversion
  • AllocationTransform - Range allocation transform
  • GradingPrimaryTransform - Primary grading (brightness, contrast, saturation)

Processors

A processor represents one “baked” color conversion. When querying a processor, you specify two parameters:

  • The source color space (colorspace_section)
  • The destination color space (colorspace_section)

Major changes in OCIO 2.x:

  • New config file format (.ocio v2)
  • New ViewTransform and DisplayView color space types
  • New BuiltinTransform — use common transforms without external files
  • Built-in ACES 2.0 config support
  • Improved GPU code generation and performance optimizations

Code example (OCIO 1.x API):

Note: The following example uses the OCIO 1.x API. OCIO 2.0+ has API changes but maintains backward compatibility.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <OpenColorIO/OpenColorIO.h>
namespace OCIO = OCIO_NAMESPACE;

try
{
// Get the global OpenColorIO config
OCIO::ConstConfigRcPtr config = OCIO::GetCurrentConfig();

// Get a processor
OCIO::ConstProcessorRcPtr processor = config->getProcessor("adx10", "aces");
OCIO::ConstCPUProcessorRcPtr cpu = processor->getDefaultCPUProcessor();

// Wrap the image in a lightweight ImageDescription
OCIO::PackedImageDesc img(imageData, w, h, 4);

// Apply the color transform (in-place)
cpu->apply(img);
}
catch(OCIO::Exception & exception)
{
std::cerr << "OpenColorIO Error: " << exception.what() << std::endl;
}

ACES 1.0.3 Color Spaces - A Detailed Look

ACES Color Spaces

Color Space Description
ACES2065-1 Core working and exchange space (AP0 primaries, linear, used for archiving)
ACEScc Image editing space, pure log encoding (AP1 primaries)
ACEScct Color correction transfer space, pseudo-log encoding (AP1 primaries, linear near black)
ACESproxy Proxy working space, integer encoded
ACEScg Scene-linear space for rendering (AP1 primaries)

ACEScc vs ACEScct: Both use AP1 primaries, but ACEScc is pure log encoding suited for traditional grading workflows; ACEScct is pseudo-log encoded with a linear segment near black, more closely resembling native camera response.

Output Color Spaces

Color Space Notes
sRGB Standard monitor
sRGB (D60 sim.) D60-simulated sRGB
Rec.709 HD television standard
Rec.2020 UHD television standard
Rec.2020 ST2048 (1000 nits) HDR at 1000 nits
DCDM Digital Cinema Distribution Master
P3-D60 DCI-P3 gamut, D60 white point
P3-D60 ST2048 (1000/2000/4000 nits) HDR gamut, multiple brightness levels

Input Color Spaces

Input color spaces cover different camera manufacturers, gamut ranges, transfer functions, and camera parameter settings:

Naming conventions:

  • Manufacturer 'Format - Gamut' - Full conversion scheme

    • Example: ARRI 'V3 LogC (EI160) - Wide Gamut'
    • Example: RED 'REDlogFilm - DRAGONcolor2'
    • Example: Canon 'Canon-Log - DCI-P3 Daylight'
  • Linear - Gamut - Gamut conversion only, no transfer function applied

  • Curve - CurveName - Transfer function only, no gamut conversion

Supported manufacturers:

  • ARRI (LogC series)
  • RED (REDlogFilm, REDgamma)
  • Canon (C-Log)
  • Panasonic (V-Log/V-Gamut)
  • Sony (S-Log)
  • GoPro (experimental)

ADX Color Spaces

ADX (Academy Density Exchange) spaces are specifically for film scanning and printing workflows:

  • ADX10 - 10-bit film scan
  • ADX16 - 16-bit film scan

Conversion schemes are generated based on the ACES CTL transform standard.

Functional Role Spaces (Roles)

OCIO roles map abstract color space names to concrete implementations:

Role Points To Purpose
color_picking Output - Rec.709 Color picking
color_timing ACEScc Color correction
compositing_log ADX10 Compositing log
data Raw Data channels
default ACES2065-1 Default space
matte_paint ACEScc Matte painting
reference Raw Reference space
scene_linear ACEScg Scene-linear
texture_paint Raw Texture painting
compositing_linear ACEScg Compositing linear
rendering ACEScg Rendering

Display Devices and Views

The default config contains a display device called “ACES” with the following views:

View Name Color Space
sRGB sRGB
sRGB D60 sim. sRGB (D60 sim.)
DCDM DCDM
DCDM P3 gamut clip DCDM (P3 gamut clip)
P3-D60 P3-D60
P3-D60 PQ 1000/2000/4000 nits P3-D60 PQ (1000/2000/4000 nits)
P3-DCI P3-DCI
Rec.2020 Rec.2020
Rec.2020 ST2048 1000 nits Rec.2020 ST2048 (1000 nits)
Rec.709 Rec.709
Rec.709 D60 sim. Rec.709 (D60 sim.)
Raw Raw
Log ACEScc

Sony Pictures Imageworks (SPI) Color Pipeline in Practice

File Naming Conventions

Every image on disk has a substring in its filename that encodes color space information. All applications that load, write, or display images respect this convention.

Important:

  • File extensions and metadata are ignored for color processing purposes
  • The file format extension does not imply a color space

Examples:

Filename Color Space
colorimage_lnf.exr lnf (linear float)
dataimage_ncf.exr ncf (non-color float)
plate_lg10.dpx lg10 (log 10-bit)
texture_dt8.tif dt8 (diffuse texture 8-bit)

Common File Formats

Purpose Format
Render output exr
Render input (mipmap textures) exr, tif (txtif)
Film negative (scanned) dpx
Composite output dpx, exr
On-set reference NEF, CR2, and other camera raw formats
Painted textures psd, tif
Output proxies jpg

Rendering Pipeline

Rendering and shading happen in scene-linear floating-point space:

  • ln - Scene-linear (generic)
  • lnh - 16-bit half-float scene-linear
  • lnf - 32-bit full-float scene-linear

Rules:

  1. All image inputs should be converted to ln before rendering
    • This is typically done at texture publish time
  2. Renderer output is always in floating-point format
  3. Color output is typically stored as lnh (16-bit half-float)
  4. Data output (normals, depth data, etc.) is stored as ncf (“non-color” data, 32-bit full-float)
  5. Lossy compression is never used

Texture Painting / Matte Painting

Texture painting workflow:

  1. Original texture filenames include color space information
  2. Color processing (linearization) is applied before mipmap generation
    • This ensures energy conservation in the renderer
    • If you process in the opposite order, the apparent intensity of texture values changes as objects move closer to or farther from the camera

Texture type classification:

Texture Type Color Space Tag Notes
Data textures (bump, opacity, blend maps) nc (non-color) + bit depth e.g., skin_opacity_nc8.tif
Diffuse textures dt (diffuse texture) The dt8 color space is designed so values don’t exceed 1.0 after linearization
Environment maps (emissive) vd (video) May produce highlight values well above 1.0 after linearization

Bit depth promotion:

  • Even if the original painted texture is only 8-bit, mipmap textures are stored as 16-bit floating-point images
  • Linear textures require more storage space

Tools:

  • OpenImageIO’s maketx (linked to OpenColorIO)
  • Source code available in the public OIIO repository

Compositing Pipeline

Most compositing operations happen in scene-linear lnf color space:

  1. Input stage

    • All image inputs are linearized to lnf on load
    • Custom input nodes make this process convenient
    • Rendered elements (already stored as linear) require no processing
    • Film negatives are linearized based on source type (lg10 for film scans, gn10 for Genesis, etc.)
  2. Output stage

    • All output images are de-linearized from lnf on write
    • Custom output nodes make this process convenient
  3. Log data operations

    • Certain processing operations require log data
    • Film resize, keying, degrain, etc.
    • Each project specifies a color space suitable for this
    • Artists don’t need to track which color space is appropriate
    • The OCIOLogConvert node is always used for this purpose
      • In the OCIO config, this is specified using the ‘compositing_log’ role

Color Management Best Practices

Environment Variables

  • $OCIO - The environment variable is set during the “setshot” process before launching other applications
  • Artists are not allowed to work across different projects without using a new shell + setshot

Color Configs

  • Color configs are project-specific
  • While the list of color spaces may be project-specific, naming is kept as consistent as possible across projects
  • Even if two projects don’t use exactly the same color spaces, they use the same names if the spaces serve similar purposes

Example: 10-bit scanned film negatives are labeled lg10. Even if two different projects use different capture film stocks and rely on different linearization curves, both are labeled lg10.

Cross-Project Asset Transfer

There is no explicit guarantee that image assets copied across projects will transfer in a color-correct manner.

Example: In the film scan example, linearized versions of scans processed on different projects may not match.

In practice, this isn’t a serious problem — color spaces that are convenient to copy (such as texture assets) happen to be defined similarly across project configs.

LUT Generation and Usage

Default Resolutions

  • 3D LUT: 65x65x65
  • 1D LUT: 4096

OCIO Internal LUTs

  • LUTs used internally by OCIO are available from the repository
  • Used for internal color processing

Pre-generated LUTs

LUTs located in the baked directory can be used outside of OCIO.

LUT naming convention:

1
[Output transform name] for [Input color space name].[extension]

Example: sRGB (D60 sim.) for ACEScc.icc

Supported application formats:

Extension Application
.3dl Autodesk Flame, Autodesk Lustre
.lut SideFX Houdini
.csp Autodesk Maya
.icc Adobe Photoshop

OpenColorIO Internal Processing Architecture

Op Abstraction

Why not rely on transforms to perform pixel processing directly?

  • FileTransform represents a wide range of image processing operations
  • For example: A Houdini LUT format may include a log transform, a 1D LUT, and a 3D LUT all within a single file
  • Creating lightweight processing operations (ops) is much simpler

Op interface:

1
virtual void apply(float * rgbaBuffer, long numPixels)

Given a packed float array and a specified pixel count, process them.

Op type examples:

  • Lut1DOp
  • Lut3DOp
  • MtxOffsetOp
  • LogOp

Optimization Flow

  1. A Transform converts itself into a list of Ops
  2. The Op list is optimized (folded with adjacent operations as appropriate, etc.)
  3. This is highly beneficial for optimization, since compositors typically have complex, branching image processing operation trees

CPU Code Path

  1. The main Op list is optimized and stored inside the processor
  2. A small tile of pixels from the image is formatted into a contiguous RGBA block
  3. op->apply is called in-place for each Op

Tile size: Optimized for compute (SSE) simplicity and performance, typically similar in size to an image scanline

GPU Code Path

The main Op list is divided into 3 ordered lists:

  1. gpu-preops - Operations that can be resolved in shader code
  2. gpu-postops - Operations that can be resolved in shader code
  3. gpu-latticeops - Cannot be supported by shader code; baked into a 3D LUT

Allocation optimization:

  • Op stream metadata is analyzed between gpu-preops and gpu-latticeops
  • An appropriate allocation is determined to minimize clamping, quantization, etc.
  • Resolved by inserting a forward allocation at the end of the preops and a reverse allocation at the start of the lattice ops

Building and Installing

Dependencies

macOS Build Commands

1
2
3
4
5
6
7
8
# Install OpenColorIO (current Homebrew method)
brew install opencolorio

# Install OpenImageIO
brew install openimageio

# Install CTL (required for ACES transforms)
brew install ctl

Note: The following are historical commands (now outdated) included for reference only:

  • brew tap homebrew/science — this tap was deprecated in 2023
  • brew install --with-python — compile options were removed in Homebrew 2.0+
  • The ociolutimage tool is still available in OCIO 2.x, but the build process has been simplified

Getting ACES CTL Source

Note: The ACES project has migrated to a new organization repository.

Official ACES repositories:

Historical versions (for reference only):

1
2
# ACES 1.0.3 historical version (old repository)
git clone --branch v1.0.3 https://github.com/ampas/aces-dev.git

Python Config Generation

Configs can be generated via the following Python package:

1
cd aces_1.0.3/python

User-customizable features:

  • 1D LUT and 3D LUT resolution settings
  • Custom Look integration
  • Two generation modes for the OCIO display device and view list
  • Shaper function selection: Log2 or Dolby PQ

Notes on Using OCIO in UE5

Known Issues

UE5.3–5.4 has some known OpenColorIO-related issues:

  1. “OCIO Invalid” watermark error — When using the ACES OpenColorIO config, Composure output may display this error
  2. Viewport color discrepancies — UE5.3 projects opened in UE5.4 may exhibit viewport color differences
  3. Material Editor display issues — Some users report that HDR textures encoded as Linear with ACEScg color space may display incorrectly on sRGB monitors

Recommendation: When you encounter issues, check the latest discussions on the Epic official forums, or consider upgrading to a newer version of UE5.

Color Space Setup Recommendations

When doing color management in UE:

  1. Set the working color space to ACES AP1/ACEScg
  2. Load the OCIO config file
  3. Add color spaces in OCIO:
    • Lit
    • OCIO Display
    • Select the OCIO Asset
    • From ACEScg to Rec.709 - ARRI ALF2 or ARRI Reveal

Glossary

Term Notes
Transform A function that changes RGB(A) data (e.g., converting an image from scene-linear to sRGB)
Reference space The connecting space between color spaces
Colorspace A meaningful space that can be converted to and from the reference space
Display A virtual or physical display device (e.g., an sRGB display)
View A meaningful view of the reference space on a display device
Role An abstractly named color space
Look A color transform that applies a creative look

References

Official Documentation

Classic Documents

Historical References (Archived)

  • OpenColorIO-Configs repository (archived September 2025)