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 are two exception to the rule of OCIO color spaces being intrinsically bound to a document: The type BaseBitmap and VideoPostData. With the methods BaseBitmap::GetColorProfile and SetColorProfile, 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. Similarly, VideoPostData::GetColorProfileInfo allows for overriding color profile information in an upcoming rendering.

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:

  • CopyLinearWorkflow: Copies the color management settings from one document to another.
  • GetOcioConfigPath: Returns the OCIO configuration path used by Cinema 4D.
  • UpdateOcioColorSpaces: Propagates changes made to the OCIO settings of a document to the bound OCIO color spaces.
  • GetOcioProfiles: Returns the color profiles for the currently active OCIO settings.

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.
Convert Colors Arbitrarily Convert colors from and to OCIO color spaces using arbitrary in- and output spaces.
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.
OCIO Aware Render Realizes a renderer which manipulates the OCIO profiles of an upcoming rendering.

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, _;
doc->GetActiveOcioColorSpacesNames(renderSpaceName, _, _, _);
// 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:2690
#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:1384
#define iferr_return
Definition: resultbase.h:1519

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(...)
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

Convert Colors Arbitrarily

Convert colors from and to OCIO color spaces using arbitrary in- and output spaces.

maxon::Result<void> ConvertOcioColorsArbitrarily(BaseDocument* doc)
{
return maxon::NullptrError(MAXON_SOURCE_LOCATION, "Invalid document pointer"_s);
// Make sure that #doc is in OCIO color management mode.
BaseContainer* bc = doc->GetDataInstance();
{
doc->UpdateOcioColorSpaces();
}
// Load the "sRGB2014" ICC profile located next to this file.
const maxon::Url directory = maxon::Url(maxon::String(__FILE__)).GetDirectory();
const maxon::Url sRgb2014File = (directory + "sRGB2014.icc"_s) iferr_return;
if (sRgb2014File.IoDetect() == maxon::IODETECT::NONEXISTENT)
return maxon::IoError(
MAXON_SOURCE_LOCATION, sRgb2014File, "Could not access sRgb2014File.icc profile."_s);
const maxon::ColorProfile srgb2014Profile = maxon::ColorProfileInterface::OpenProfileFromFile(
sRgb2014File) iferr_return;
// Get the profile for the builtin linear RGB space. This profile is required because
// conversions with OCIO profiles are only supported between profiles that originate from the
// same OCIO config and the profiles for the builtin linear or non-linear sRGB space (given that
// the OCIO config file defines the sRGB space; which is the case for the Cinema 4D profiles).
// For all other conversions, an intermediate step must be taken, e.g., in our case:
//
// sRGB2014 -> lin-RGB -> Render space
// Render space -> lin-RGB -> sRGB2014
const maxon::ColorProfile linearRgbSpaceProfile = maxon::ColorSpaces::RGBspace(
).GetDefaultLinearColorProfile();
// Get the profile and name for the active Render space in #doc.
maxon::ColorProfile renderSpaceProfile, _;
doc->GetOcioProfiles(renderSpaceProfile, _, _, _);
maxon::CString renderSpaceName, __;
doc->GetActiveOcioColorSpacesNames(renderSpaceName, __, __, __);
// Define the pixel format to operate with and check if it is supported by the profiles.
const maxon::PixelFormat rgbFormat = maxon::PixelFormats::RGB::F32();
if (!(srgb2014Profile.CheckCompatiblePixelFormat(rgbFormat) ||
linearRgbSpaceProfile.CheckCompatiblePixelFormat(rgbFormat) ||
renderSpaceProfile.CheckCompatiblePixelFormat(rgbFormat)))
return maxon::UnexpectedError(
MAXON_SOURCE_LOCATION, "Profile conversion path does not support RGB::F32 pixel format"_s);
// Construct two converters, one for converting from the ICC profile to the intermediate linear
// RGB space, and one for converting from that intermediate space to the Render space.
const maxon::ColorProfileConvert preConverter = maxon::ColorProfileConvertInterface::Init(
rgbFormat, srgb2014Profile, rgbFormat, linearRgbSpaceProfile,
const maxon::ColorProfileConvert ocioConverter = maxon::ColorProfileConvertInterface::Init(
rgbFormat, linearRgbSpaceProfile, rgbFormat, renderSpaceProfile,
// Initialize the data to convert, an input and an output buffer, as well as two buffer
// handlers for them. This could also be done by using three buffers (in, intermediate, out) and
// four handlers (const in, const intermediate, mutable intermediate, mutable out) to avoid
// having to copy data from the output buffer to the input buffer after the first conversion.
maxon::Color32 colorData ( 1, 0, 0 );
maxon::Color32 inputBuffer (colorData);
maxon::Color32 outputBuffer (0, 0, 0);
(const maxon::Pix*)&inputBuffer.r, maxon::PixelFormats::RGB::F32());
(maxon::Pix*)&outputBuffer.r, maxon::PixelFormats::RGB::F32());
// Carry out the conversion sRGB2014.icc -> linear-RGB -> Render space for the data (1, 0, 0).
preConverter.Convert(inputBufferHandler, outputBufferHandler, 1) iferr_return;
ApplicationOutput("\tIn (@): @, Out (@): @",
srgb2014Profile, colorData, linearRgbSpaceProfile, outputBuffer);
inputBuffer = outputBuffer;
ocioConverter.Convert(inputBufferHandler, outputBufferHandler, 1) iferr_return;
ApplicationOutput("\tIn (@): @, Out (@): @",
srgb2014Profile, colorData, renderSpaceName, outputBuffer);
return maxon::OK;
}
static MAXON_METHOD Result< ColorProfileConvert > Init(const PixelFormat &srcPixelFormat, const ColorProfile &srcProfile, const PixelFormat &dstPixelFormat, const ColorProfile &dstProfile, COLORCONVERSIONINTENT intent, COLORCONVERSIONFLAGS flags)
static MAXON_METHOD Result< ColorProfile > OpenProfileFromFile(const Url &fn)
Definition: string.h:1235
Definition: url.h:952
ImageBufferTemplate< PixelConstBuffer > ImageConstBuffer
Definition: gfx_image_pixelformat.h:185
UChar Pix
unspecified pixel format depth.
Definition: gfx_image_imagechannel.h:17
ImageBufferTemplate< PixelMutableBuffer > ImageMutableBuffer
Definition: gfx_image_pixelformat.h:186
@ NONEXISTENT
Url doesn't exist.
A color consisting of three components R, G and B.
Definition: col.h:16
Several functions use this helper structure to pass the image data to functions.
Definition: gfx_image_pixelformat.h:521

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:2387
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() 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:998
@ 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
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

OCIO Aware Render

Realizes a renderer which manipulates the OCIO profiles of an upcoming rendering.

void OcioAwareRenderer::GetColorProfileInfo(
{
if (!node)
return;
// GetColorProfileInfo allows us to react to or modify the color profiles of an upcoming OCIO
// rendering.Here we use it to null the display and view transform by overwriting them with the
// render transform when so indicated, causing the rendered image to be treated as "raw".
BaseContainer* data = node->GetDataInstance();
if (data->GetBool(ID_OVERWRITE_OCIO_DISPLAY_SPACE))
info.displayColorSpace = info.renderingColorSpace;
if (data->GetBool(ID_OVERWRITE_OCIO_VIEW_TRANSFORM))
info.viewColorSpace = info.renderingColorSpace;
}
RENDERRESULT OcioAwareRenderer::Execute(BaseVideoPost* node, VideoPostStruct* vps)
{
{
};
// Bail when important data is not accessible, a rendering error did occur, or the user did stop
// the renderer.
if (!vps || !vps->doc || !vps->doc->GetDataInstance() || !vps->render)
if (*vps->error != RENDERRESULT::OK)
if (vps->thread && vps->thread->TestBreak())
// Skip all calls except for a full frame being finished.
if (vps->vp == VIDEOPOSTCALL::FRAME || vps->open)
// Get the RGBA buffer of the rendering.
VPBuffer* const rgbaBuffer = vps->render->GetBuffer(VPBUFFER_RGBA, NOTOK);
if (!rgbaBuffer)
if (rgbaBuffer->GetBt() != 32)
// Get the color to "render" from the VideoPost node.
BaseContainer* nodeData = node->GetDataInstance();
Vector color = nodeData->GetVector(ID_RENDER_COLOR);
// By default, just as in other places of the API, all color computations are implicitly in
// Render space once a document is in OCIO mode. When a video post plugin is not meant to operate
// in that space, all outputs must be transformed manually.
BaseContainer* docData = vps->doc->GetDataInstance();
nodeData->GetBool(ID_PRETRANSFORM_OCIO_OUTPUT))
{
if (!converter)
// Convert the color chosen by the user from sRGB to Render space. I.e., the chosen color is
// always interpreted as an sRGB value which is then converted to and written as a Render space
// value in the output buffer.
}
// Fill the whole buffer with the color.
const Int32 width = rgbaBuffer->GetBw();
const Int32 height = rgbaBuffer->GetBh();
const Int32 bytesPerPixel = rgbaBuffer->GetCpp();
Float32* lineBuffer = NewMemClear(Float32, bytesPerPixel * width).GetPointer();
for (Int32 ix = 0; ix < width; ix++)
{
lineBuffer[ix*bytesPerPixel+0] = (Float32)color.x;
lineBuffer[ix*bytesPerPixel+1] = (Float32)color.y;
lineBuffer[ix*bytesPerPixel+2] = (Float32)color.z;
}
for (Int32 iy = 0; iy < height; iy++)
rgbaBuffer->SetLine(0, iy, width, lineBuffer, 32, false);
DeleteMem(lineBuffer);
}
Vector64 TransformColor(const Vector64 &input, COLORSPACETRANSFORMATION colortransformation)
Vector GetVector(Int32 id, const Vector &preset=Vector()) const
Definition: c4d_basecontainer.h:371
Bool GetBool(Int32 id, Bool preset=false) const
Definition: c4d_basecontainer.h:295
const BaseContainer * GetDataInstance() const
Definition: c4d_baselist.h:2346
Bool TestBreak()
Definition: c4d_thread.h:39
Definition: c4d_videopost.h:24
VPBuffer * GetBuffer(Int32 id, Int32 subid) const
A rendering bitmap buffer. Represents internally the same class as MultipassBitmap,...
Definition: c4d_tools.h:2469
Int32 GetBt() const
Definition: c4d_tools.h:2531
Bool SetLine(Int32 x, Int32 y, Int32 cnt, void *data, Int32 bitdepth, Bool dithering) const
for(i=0;i< length;i++)
Definition: unicodeobject.h:61
#define NewMemClear(T, cnt)
Definition: defaultallocator.h:204
OCIO_SRGB_TO_RENDERING
sRGB to Rendering color space transformation.
Definition: ge_prepass.h:16
OUTOFMEMORY
Not enough memory.
Definition: ge_prepass.h:1
maxon::Float32 Float32
Definition: ge_sys_math.h:68
maxon::Int32 Int32
Definition: ge_sys_math.h:60
COLORSPACETRANSFORMATION
Definition: ge_prepass.h:498
RENDERRESULT
Definition: ge_prepass.h:422
@ USERBREAK
User stopped the processing.
@ OUTOFMEMORY
Not enough memory.
@ FAILED
Generic error if a rendering has failed due to missing license or similar.
@ OK
Function was successful.
@ FRAME
Called when the renderer prepares to render a frame.
#define VPBUFFER_RGBA
RGB and alpha multipass channel.
Definition: c4d_videopostdata.h:116
void DeleteMem(T *&p)
Definition: defaultallocator.h:257
unsigned long Py_ssize_t width
Definition: pycore_traceback.h:88
_Py_clock_info_t * info
Definition: pytime.h:197
#define iferr_scope_handler
Definition: resultbase.h:1402
Definition: node.h:10
Bool open
true if it is an opening call. See also VideoPostData::Execute.
Definition: c4d_videopostdata.h:87
Render * render
The current render.
Definition: c4d_videopostdata.h:102
VIDEOPOSTCALL vp
the VideoPost call: VIDEOPOSTCALL
Definition: c4d_videopostdata.h:86
RENDERRESULT * error
The render result error: RENDERRESULT May be nullptr.
Definition: c4d_videopostdata.h:90
BaseDocument * doc
The active document.
Definition: c4d_videopostdata.h:92
BaseThread * thread
The executing thread. Use thread->TestBreak() to check for a user break.
Definition: c4d_videopostdata.h:94
Stores overwriteable color profiles associated with an upcoming rendering.
Definition: c4d_videopostdata.h:375
Definition: c4d_tools.h:2548