OpenColorIO Manual

Convert colors with the color profiles provided by the OpenColorIO (OCIO) configuration of a scene.

Overview

Cinema 4D implements color management primarily with International Color Consortium (ICC) color profiles and the OpenColorIO (OCIO) standard. OCIO implements a color management pipeline for digital content creation applications to decouple the color representation requirements of color computations from the requirements of displaying colors on hardware-devices. This allows for a lossless transfer of color data between different applications while giving artists always the ability to view their artwork with the colors the final consumer will see. OCIO achieves this by defining color spaces by purpose so that they can be applied selectively to color data. The three abstract color spaces defined by the OCIO standard are:

  • The Render Space is the color space the application does operate in. All color data is converted to this space before processing and the application does carry out all computations in this space. This is usually a linear color space. For Cinema 4D documents in OCIO mode this is by default the ACEScg space.
  • The Display Space is a space to convert colors from the Render Space to a color representation which is suited for displaying these colors on a screen. This is usually a non-linear color space. For Cinema 4D documents in OCIO mode this is by default the sRGB space.
  • The View Transform is a transform which is applied after the display space and is meant to emulate the final look of color data on a consumer device. This could for example emulate the look of a movie-screen on the display of an artist. For Cinema 4D documents in OCIO mode this is by default the ACES 1.0 SDR-video space.
  • Cinema 4D adds to this a special transform which is only applied to thumbnails, the Thumbnail View Transform.

Each application in a color management pipeline assigns a color profile to each of these abstract color spaces to suite its specific needs. Applications communicate the possible choices for each space with the help of OCIO configuration files, allowing for a persistent color previewing experience along the pipeline without having to bake hardware dependent information into outputs (Fig. I).

Fig. I: An example for an OCIO pipeline, the raw color data is passed in a linear format through the pipeline. For the Texturing stage this is a linear sRGB profile, for the Rendering and Editing stage, it is the ACEScg profile. Within each stage, the data from the Render Space is transformed into a form which can be displayed on the display device of the artist, a non-linear sRGB profile for SDR displays in the first two stages, and a DCI-P3 profile for HDR displays in the Editing stage. Finally, the output of the display transform it further transformed with the view transform, to emulate the look of the final product on a consumer device, in the example an SDR video device is being emulated in all three stages. This forms a horizontal data transfer axis and a per stage individually configurable vertical view axis.

Technical Overview

Cinema 4D currently does provide only shallow public access to its OCIO API, with the consequence that high level OCIO concepts such as an OCIO configuration or an OCIO processor are not represented by dedicated types in the public API. There are however multiple entry points which provide access to the most important functionalities of OCIO.

OCIO is bound intrinsically to a scene in form of BaseDocument, a scene can either have OCIO enabled or not, and also stores the currently active color profiles for the principal OCIO spaces. These settings are expressed as the parameters:

Note
There is one exception to the rule of OCIO color spaces being intrinsically bound to a document: The type BaseBitmap. With its GetColorProfile and SetColorProfile methods, the three OCIO transforms render, display, and view can be overwritten on a per bitmap basis. This can be useful when a bitmap should ignore the OCIO display and view transforms in the Picture Viewer of Cinema 4D.

These parameters can be read and written with BaseDocument::GetParameter and SetParameter. Due to the fact that the values of OCIO color spaces and transforms depend on the loaded OCIO configuration, the values written to the parameters must be retrieved with the following functions:

Additionally, the following methods exist:

To convert colors between OCIO color space representations, the type OcioConverter must be used, providing the methods:

The transform paths are defined by the enumeration COLORSPACETRANSFORMATION. Note that a path can contain multiple transforms, as the path is always carried out in a sensible manner, e.g., OCIO_RENDERING_TO_VIEW will contain the display transform, as the OCIO transform chain is render->display->view. The available paths are:

Related Topics

Articles Color Management Manual Convert color data between color spaces and color formats provided by the maxon API or loaded from disk.
BaseDocument Manual

Access the data structures of a Cinema 4D scene file.

Important API Entities BaseDocument Represents a scene file and provides access to its OCIO settings and color spaces.
OcioConverter Converts colors along OCIO conversion paths associated with a scene.
SceneColorConverter Converts colors contained in scenes or elements of scenes to a new OCIO Render space.
BaseBitmap

Represents a bitmap which can be modified, read and written from disk, and displayed in GUIs.

SDK Plugins OCIO Plugin

Contains the examples shown in this manual.

Examples Color Convert Scenes Convert all colors contained in a document or contained in a set of elements in a document to a new OCIO Render space.
Copy Color Management Settings Copy all color management settings from one document to another.
Read and Write OCIO Settings Read and write the OCIO color management settings stored in a document.
Convert Colors Convert colors along OCIO conversion paths defined by the OCIO color spaces associated with a document.
Get and Set Color Parameters Read and write color parameters in an OCIO document either in the native Render space of the document or other spaces.
Manage Bitmap OCIO Color Profiles Read and write the OCIO color spaces associated with BaseBitmap instances to change or nullify parts of an OCIO conversion path for them.

Examples

The examples shown here are all part of the OCIO Plugin in the SDK. Once the SDK has been compiled and installed, the plugin can be found under the menu entry Extensions\Example.image\C++ SDK: OCIO Examples.

Color Convert Scenes

Convert all colors contained in a document or contained in a set of elements in a document to a new OCIO Render space.

maxon::Result<void> ConvertSceneOrElements(BaseDocument* doc)
{
// Using SceneColorConverter is only necessary when the operation must be carried out silently
// with no GUI. If showing a popup dialog is acceptable or even desired, one can simply call
// the command plugin for it.
// Int32 idConvertSceneCommand = 1059360;
// CallCommand(idConvertSceneCommand);
// Ensure that the document is in OCIO color management mode.
BaseContainer* bc = doc->GetDataInstance();
{
doc->UpdateOcioColorSpaces();
}
// Get then OCIO render space name to convert to, we could also define it manually here.
maxon::CString renderSpaceName, _dummy;
doc->GetActiveOcioColorSpacesNames(renderSpaceName, _dummy, _dummy, _dummy);
// Allocate and initialize the converter, currently it is not possible to retrieve the linear
// and non-linear input color space names "input-low" and "input-high" that are associated
// with an OCIO config file. Instead they must be hardcoded. Except for the the target render
// space, the Init call uses here the default values of the native dialog.
if (!converter)
return maxon::OutOfMemoryError(MAXON_SOURCE_LOCATION, "Could not allocate converter interface."_s);
converter->Init(doc, "sRGB"_cs, "scene-linear Rec.709-sRGB"_cs, renderSpaceName) iferr_return;
// Carry out the conversion for the whole document, the second argument is the conversion target,
// here the whole document. But it could for example also be a singular BaseMaterial. Multiple
// objects in a single document can be converted at once with ::ConvertObjects().
converter->ConvertObject(doc, doc, result) iferr_return;
// When converting a whole document, one should mark it as already converted when the conversion
// did succeed.
ApplicationOutput("\tConverted @ elements in '@' to OCIO Render space named '@'.",
result.GetCount(), doc, renderSpaceName);
return maxon::OK;
}
void EventAdd(EVENT eventflag=EVENT::NONE)
Definition: ge_autoptr.h:37
Definition: c4d_basecontainer.h:47
Int32 GetInt32(Int32 id, Int32 preset=0) const
Definition: c4d_basecontainer.h:303
void SetInt32(Int32 id, Int32 l)
Definition: c4d_basecontainer.h:505
Definition: c4d_basedocument.h:498
Definition: c4d_gedata.h:83
Definition: string.h:1490
Definition: hashmap.h:2956
PyObject PyObject * result
Definition: abstract.h:43
@ DOCUMENT_COLOR_MANAGEMENT
Definition: ddoc.h:152
@ DOCUMENT_COLOR_MANAGEMENT_OCIO_CONVERTED
Definition: ddoc.h:156
@ DOCUMENT_COLOR_MANAGEMENT_OCIO
Definition: ddoc.h:154
return OK
Definition: apibase.h:2667
#define MAXON_FUNCTIONNAME
This macro returns the function name of the current member or global function.
Definition: objectbase.h:2860
#define MAXON_SOURCE_LOCATION
Definition: memoryallocationbase.h:67
#define ApplicationOutput(formatString,...)
Definition: debugdiagnostics.h:210
const char * doc
Definition: pyerrors.h:226
#define iferr_scope
Definition: resultbase.h:1374
#define iferr_return
Definition: resultbase.h:1465

Copy Color Management Settings

Copy all color management settings from one document to another.

This does not entail any scene element color space conversions, one must instead use SceneColorConverter as demonstrated in the example Color Convert Scenes .

maxon::Result<void> CopyColorManagementSettings(BaseDocument* doc)
{
// Allocate a new document and copy over the settings from #doc to #newDoc. This is just a
// convenient manner to copy all color management settings from one document to another. This
// does NOT entail a conversion of the colors of scene elements to OCIO, see
// ConvertSceneOrElements() for that.
newDoc->SetName(doc->GetName() + "(Copy)");
ApplicationOutput("\tCopied color management settings from '@' to '@'.",
doc->GetName(), newDoc->GetName());
newDoc.Free();
return maxon::OK;
}
void Free()
Calls TYPE::Free(ptr) with the internal pointer and sets it to nullptr.
Definition: ge_autoptr.h:128
static void CopyLinearWorkflow(const BaseDocument *src, BaseDocument *dst, Bool isMaterialPreview)

Read and Write OCIO Settings

Read and write the OCIO color management settings stored in a document.

maxon::Result<void> GetSetColorManagementSettings(BaseDocument* doc)
{
return maxon::NullptrError(MAXON_SOURCE_LOCATION, "Invalid document pointer"_s);
// Ensure that the document is in OCIO color management mode.
BaseContainer* bc = doc->GetDataInstance();
{
doc->UpdateOcioColorSpaces();
}
// Print the names for all OCIO color spaces and transforms that are available in the OCIO
// configuration file loaded by the document.
ApplicationOutput("\tAll OCIO transform names: @", doc->GetOCIOColorSpaceNames());
ApplicationOutput("\tOCIO render transform names: @", doc->GetOCIORenderingColorSpaceNames());
ApplicationOutput("\tOCIO view transform names: @", doc->GetOCIOViewTransformNames());
ApplicationOutput("\tOCIO display transform names: @", doc->GetOCIODisplayColorSpaceNames());
// Since an OCIO configuration file can contain any combination of color spaces and transforms,
// the description IDs for the render space, display space, view transform, and view thumbnail
// transform parameters must be dynamic IDs.
for (maxon::CString s : doc->GetOCIORenderingColorSpaceNames())
{
ApplicationOutput("\t\tThe render transform label '@' corresponds to the ID '@'.",
s, doc->GetColorSpaceIdFromName(DOCUMENT_OCIO_RENDER_COLORSPACE, s));
}
// So, this would be the pattern to set for example the render space to a specific space name,
// here the 'ACES2065 - 1' render space contained in the default OCIO 2.0 config file.
// The method GetColorSpaceIdFromName() will return #NOTOK to indicate unknown space labels.
maxon::Int32 id = doc->GetColorSpaceIdFromName(DOCUMENT_OCIO_RENDER_COLORSPACE, "ACES2065-1"_cs);
if (id == NOTOK)
return maxon::IllegalArgumentError(MAXON_SOURCE_LOCATION,
"OCIO configuration does not contain a 'ACES2065 - 1' render space."_s);
doc->UpdateOcioColorSpaces();
return maxon::OK;
}
PyObject PyObject const char const char char ** s
Definition: bytesobject.h:60
Definition: lib_description.h:330
@ DOCUMENT_OCIO_RENDER_COLORSPACE
Definition: ddoc.h:143
#define NOTOK
Definition: ge_sys_math.h:267
int32_t Int32
32 bit signed integer datatype.
Definition: apibase.h:176
#define MAXON_UNLIKELY(X)
Definition: compilerdetection.h:404

Convert Colors

Convert colors along OCIO conversion paths defined by the OCIO color spaces associated with a document.

{
return maxon::NullptrError(MAXON_SOURCE_LOCATION, "Invalid document pointer"_s);
// OcioConverter can only initialized with a document which is in OCIO color management mode.
BaseContainer* bc = doc->GetDataInstance();
{
doc->UpdateOcioColorSpaces();
}
// Initialize an OcioConverter for #doc. OcioConverter is a helper interface to convert colors
// between the color spaces associated with the OCIO configuration of a document, for its
// initialization to succeed, the document must be in OCIO color management mode.
if (!converter)
return maxon::NullptrError(MAXON_SOURCE_LOCATION, "Could not init OCIO converter for document."_s);
// The to be converted color, it has no implicitly defined color space.
const maxon::Vector64 colorInput { 1, 0, 0 };
// Convert the color from sRGB space to render space. With the default OCIO settings of Cinema
// 4D 2023.1, this will convert to ACEScg space. Doing this is only necessary when computation
// results or color definitions are explicitly outside of the render space.
const maxon::Vector64 colorRender = converter->TransformColor(
// Convert the color from render space to display space, i.e., the space the physical display
// device operates in. With the default OCIO settings of Cinema 4D 2023.1, this will convert
// from ACEScg to sRGB space.
const maxon::Vector64 colorDisplay = converter->TransformColor(
// Convert a color from render space to view transform (space), i.e., to the value which
// will be finally shown on the screen of a user. With the default OCIO settings of Cinema 4D
// 2023.1, this will convert from ACEScg to ACES 1.0 SDR-video space.
const maxon::Vector64 colorView = converter->TransformColor(
// There are multiple other conversion paths to be found in #COLORSPACETRANSFORMATION, including
// inverse operations, as for example converting a color in view space back to the render space.
const maxon::Vector64 colorRenderViewRender = converter->TransformColor(
// Print the results.
ApplicationOutput("\tinput: @", colorInput);
ApplicationOutput("\tinput->render: @", colorRender);
ApplicationOutput("\trender->display: @", colorDisplay);
ApplicationOutput("\trender->view: @", colorView);
ApplicationOutput("\trender->view->render: @", colorRenderViewRender);
return maxon::OK;
}
Class which transforms colors from one OCIO color space to another.
Definition: c4d_shader.h:212
static maxon::Result< OcioConverter * > Init(const BaseDocument *doc, Int32 overrideViewTransform=-1)
Definition: c4d_shader.h:233
Vector64 TransformColor(const Vector64 &v, COLORSPACETRANSFORMATION colorSpaceTransformation) const
Definition: c4d_shader.h:244
@ OCIO_RENDERING_TO_DISPLAY
Rendering to display color space transformation.
@ OCIO_RENDERING_TO_VIEW
Rendering to view color space transformation.
@ OCIO_SRGB_TO_RENDERING
sRGB to Rendering color space transformation.
@ OCIO_VIEW_TO_RENDERING
View to rendering color space transformation.
A vector consisting of three components X, Y and Z.
Definition: vec.h:21

Get and Set Color Parameters

Read and write color parameters in an OCIO document either in the native Render space of the document or other spaces.

maxon::Result<void> GetSetColorValuesInOcioDocuments(BaseDocument* doc)
{
return maxon::NullptrError(MAXON_SOURCE_LOCATION, "Invalid document pointer"_s);
// Ensure that the document is in OCIO color management mode.
BaseContainer* bc = doc->GetDataInstance();
{
doc->UpdateOcioColorSpaces();
}
// Get the names of the active OCIO spaces in #doc for #ApplicationOutput calls invoked below.
maxon::CString renderSpace, viewTransform, _;
doc->GetActiveOcioColorSpacesNames(renderSpace, _, viewTransform, _);
// When a document is in OCIO mode, all color parameters of scene elements are implicitly in
// Render space. When for example the default color for objects is being retrieved from a
// document, the value is expressed in Render space.
GeData data;
const Vector defaultColor = data.GetVector();
ApplicationOutput("\tdefaultColor(@): @", renderSpace, defaultColor);
// Unlike in the color chooser GUI, there is no direct way to read color values in any other
// space, as an sRGB value for example. Such conversions must be carried out with the type
// OcioConverter manually. The argument #doc to OcioConverter::Init must be a document in OCIO
// mode.
if (!converter)
return maxon::NullptrError(MAXON_SOURCE_LOCATION, "Could not init OCIO converter for document."_s);
// Transform #defaultColor from Render space to sRGB space.
const Vector colorSrgb = converter->TransformColor(
ApplicationOutput("\tdefaultColor(@): @", "sRGB"_s, colorSrgb);
// Allocate three materials to write color values to.
if (MAXON_UNLIKELY(!(m1 && m2 && m3)))
return maxon::OutOfMemoryError(MAXON_SOURCE_LOCATION, "Could not allocate materials."_s);
// Analogously, when color values are written, they are interpreted as Render space values by
// default, and all other input spaces must be converted first.
const Vector color { 1, 0, 0 };
const DescID colorChannel (MATERIAL_COLOR_COLOR);
// Write the color channel color of m1 as (1, 0, 0) in Render space.
m1->SetParameter(colorChannel, GeData(color), DESCFLAGS_SET::NONE);
// Write the color channel color of m2 as (1, 0, 0) in sRGB space.
m2->SetParameter(colorChannel, GeData(fromSrgb), DESCFLAGS_SET::NONE);
// Write the color channel color of m3 as (1, 0, 0) in View space, i.e., what the color chooser
// does in its Display tab.
m3->SetParameter(colorChannel, GeData(fromView), DESCFLAGS_SET::NONE);
ApplicationOutput("\tMATERIAL_COLOR_COLOR(@): @", renderSpace, color);
ApplicationOutput("\tMATERIAL_COLOR_COLOR(@): @", "sRGB"_s, fromSrgb);
ApplicationOutput("\tMATERIAL_COLOR_COLOR(@): @", viewTransform, fromView);
// Set the name of and insert all three materials.
m1->SetName("Material (Render Space)"_s);
m2->SetName("Material (sRGB)"_s);
m3->SetName("Material (View Transform)"_s);
doc->InsertMaterial(m1);
doc->InsertMaterial(m2);
doc->InsertMaterial(m3);
return maxon::OK;
}
void SetName(const maxon::String &name)
Definition: c4d_baselist.h:2369
Definition: c4d_basematerial.h:28
static BaseMaterial * Alloc(Int32 type)
Bool SetParameter(const DescID &id, const GeData &t_data, DESCFLAGS_SET flags)
const Vector & GetVector(void) const
Definition: c4d_gedata.h:451
@ DOCUMENT_DEFAULTMATERIAL_COLOR
Definition: ddoc.h:67
@ OCIO_RENDERING_TO_SRGB
Rendering to sRGB color space transformation.
#define Mmaterial
Standard material.
Definition: ge_prepass.h:992
@ MATERIAL_COLOR_COLOR
Definition: mmaterial.h:56

Manage Bitmap OCIO Color Profiles

Read and write the OCIO color spaces associated with BaseBitmap instances to change or nullify parts of an OCIO conversion path for them.

This makes it for example possible to disable the Display and View transform for a singular bitmap when displayed in the Picture Viewer.

maxon::Result<void> GetSetBitmapOcioProfiles(BaseDocument* doc)
{
BaseBitmap* clone;
finally { BaseBitmap::Free(clone); };
return maxon::NullptrError(MAXON_SOURCE_LOCATION, "Invalid document pointer"_s);
// Ensure that the document is in OCIO color management mode.
BaseContainer* bc = doc->GetDataInstance();
{
doc->UpdateOcioColorSpaces();
}
// Get the Asset API user preferences repository to get the "HDR004.hdr" texture asset in
// Textures/HDR/Legacy and retrieve its URL. It is important to use here an HDR image (the
// dynamic range, not the necessarily the format), as the view transform is disabled for SDR
// content in the Picture Viewer (as of 2023.1, might change in future releases).
maxon::AssetRepositoryRef repository = maxon::AssetInterface::GetUserPrefsRepository();
if (MAXON_UNLIKELY(!repository))
return maxon::UnexpectedError(MAXON_SOURCE_LOCATION, "Could not retrieve user repository."_s);
const maxon::Id assetId("file_9748feafc2c00be8");
const maxon::AssetDescription asset = repository.FindLatestAsset(
// --- Start of Image API related code ----------------------------------------------------------
// Allocate a bitmap and load the texture asset.
if (MAXON_UNLIKELY(!bitmap))
return maxon::OutOfMemoryError(MAXON_SOURCE_LOCATION, "Could not allocate bitmap."_s);
if (bitmap->Init(MaxonConvert(textureUrl)) != IMAGERESULT::OK)
return maxon::IoError(MAXON_SOURCE_LOCATION, textureUrl, "Could not load image file."_s);
// Clone the loaded bitmap.
clone = bitmap->GetClone();
if (MAXON_UNLIKELY(!clone))
return maxon::UnexpectedError(MAXON_SOURCE_LOCATION, "Could not clone bitmap."_s);
// Get the OCIO Render space color profile associated with the bitmap.
const ColorProfile* const profile = clone->GetColorProfile(BaseBitmap::COLORPROFILE_INDEX_RENDERSPACE);
// Null the Display color space and the View Transform by overwriting them with the Render space
// profile, the data will be displayed "raw".
clone->SetColorProfile(profile, BaseBitmap::COLORPROFILE_INDEX_DISPLAYSPACE);
clone->SetColorProfile(profile, BaseBitmap::COLORPROFILE_INDEX_VIEW_TRANSFORM);
// Display both bitmaps in the picture viewer.
ShowBitmap(bitmap);
ShowBitmap(clone);
return maxon::OK;
}
maxon::Url MaxonConvert(const Filename &fn, MAXONCONVERTMODE convertMode)
Bool ShowBitmap(const Filename &fn)
Definition: c4d_basebitmap.h:428
static void Free(BaseBitmap *&bm)
Definition: c4d_basebitmap.h:156
static MAXON_METHOD const UpdatableAssetRepositoryRef & GetUserPrefsRepository()
static MAXON_METHOD Result< Url > GetAssetUrl(const AssetDescription &asset, Bool isLatest)
Definition: apibaseid.h:253
Definition: url.h:942
OK
Ok.
Definition: ge_prepass.h:0
IMAGERESULT
Definition: ge_prepass.h:3914
The maxon namespace contains all declarations of the MAXON API.
Definition: autoweight.h:14
@ LATEST
Set this flag to obtain only the latest version of the asset.
const char const char const char * file
Definition: object.h:439