5#if defined(WITH_OPENCOLORIO)
32 const bool use_hdr_buffer)
76static OCIO_NAMESPACE::TransformRcPtr create_extended_srgb_transform(
81 auto to_ui = OCIO_NAMESPACE::ExponentWithLinearTransform::Create();
82 to_ui->setGamma({2.4, 2.4, 2.4, 1.0});
83 to_ui->setOffset({0.055, 0.055, 0.055, 0.0});
85 to_ui->setNegativeStyle(OCIO_NAMESPACE::NEGATIVE_MIRROR);
86 to_ui->setDirection(OCIO_NAMESPACE::TRANSFORM_DIR_INVERSE);
91 auto to_ui = OCIO_NAMESPACE::ExponentTransform::Create();
92 to_ui->setValue({2.2, 2.2, 2.2, 1.0});
94 to_ui->setNegativeStyle(OCIO_NAMESPACE::NEGATIVE_MIRROR);
95 to_ui->setDirection(OCIO_NAMESPACE::TRANSFORM_DIR_INVERSE);
99static void adjust_for_hdr_image_file(
const LibOCIOConfig &config,
100 OCIO_NAMESPACE::GroupTransformRcPtr &group,
101 StringRefNull display_name,
102 StringRefNull view_name)
105 const LibOCIODisplay *display =
static_cast<const LibOCIODisplay *
>(
106 config.get_display_by_name(display_name));
107 const LibOCIOView *
view = (display) ?
static_cast<const LibOCIOView *
>(
108 display->get_view_by_name(view_name)) :
110 const LibOCIOColorSpace *display_colorspace =
static_cast<const LibOCIOColorSpace *
>(
111 view->display_colorspace());
113 if (display_colorspace ==
nullptr || !display_colorspace->is_display_referred()) {
117 const ColorSpace *image_display_colorspace = config.get_color_space_for_hdr_image(
118 display_colorspace->name());
119 if (
ELEM(image_display_colorspace,
nullptr, display_colorspace)) {
123 auto to_display_linear = OCIO_NAMESPACE::ColorSpaceTransform::Create();
124 to_display_linear->setSrc(display_colorspace->name().c_str());
125 to_display_linear->setDst(image_display_colorspace->
name().
c_str());
126 group->appendTransform(to_display_linear);
129static void display_as_extended_srgb(
const LibOCIOConfig &config,
130 OCIO_NAMESPACE::GroupTransformRcPtr &group,
131 StringRefNull display_name,
132 StringRefNull view_name,
133 const bool use_hdr_buffer)
147 const LibOCIODisplay *display =
static_cast<const LibOCIODisplay *
>(
148 config.get_display_by_name(display_name));
149 const LibOCIOView *
view = (display) ?
static_cast<const LibOCIOView *
>(
150 display->get_view_by_name(view_name)) :
152 if (
view ==
nullptr) {
154 "Unable to find display '%s' and view '%s', display may be incorrect",
155 display_name.
c_str(),
160 const TransferFunction target_transfer_function = system_extended_srgb_transfer_function(
161 view, use_hdr_buffer);
164 if ((
view->transfer_function() == target_transfer_function ||
169 auto clamp = OCIO_NAMESPACE::RangeTransform::Create();
170 clamp->setStyle(OCIO_NAMESPACE::RANGE_CLAMP);
171 clamp->setMinInValue(0.0);
172 clamp->setMinOutValue(0.0);
174 clamp->setMaxInValue(1.0);
175 clamp->setMaxOutValue(1.0);
177 group->appendTransform(
clamp);
181 const LibOCIOColorSpace *lin_cie_xyz_d65 =
static_cast<const LibOCIOColorSpace *
>(
182 config.get_color_space(OCIO_NAMESPACE::ROLE_INTERCHANGE_DISPLAY));
183 const LibOCIOColorSpace *display_colorspace =
static_cast<const LibOCIOColorSpace *
>(
184 view->display_colorspace());
187 if (lin_cie_xyz_d65 ==
nullptr) {
189 "Failed to find %s colorspace, disabling automatic display color management",
190 OCIO_NAMESPACE::ROLE_INTERCHANGE_DISPLAY);
193 if (display_colorspace ==
nullptr) {
195 "Failed to find display colorspace for view %s, disabling automatic display color "
200 if (!display_colorspace->is_display_referred()) {
202 "Color space %s is not a display color space, disabling automatic display color "
204 display_colorspace->name().c_str());
209 std::optional<double4x4> xyz_to_display_gamut;
210 switch (
view->gamut()) {
236 auto to_cie_xyz_d65 = OCIO_NAMESPACE::ColorSpaceTransform::Create();
237 to_cie_xyz_d65->setSrc(display_colorspace->name().c_str());
238 to_cie_xyz_d65->setDst(lin_cie_xyz_d65->name().c_str());
239 group->appendTransform(to_cie_xyz_d65);
241 auto to_lin_gamut = OCIO_NAMESPACE::MatrixTransform::Create();
242 to_lin_gamut->setMatrix(
math::transpose(xyz_to_display_gamut.value()).base_ptr());
243 group->appendTransform(to_lin_gamut);
247 double clamp_max = 0.0;
248 switch (
view->transfer_function()) {
269 auto clamp = OCIO_NAMESPACE::RangeTransform::Create();
270 clamp->setStyle(OCIO_NAMESPACE::RANGE_CLAMP);
271 clamp->setMinInValue(0.0);
272 clamp->setMinOutValue(0.0);
273 if (clamp_max != DBL_MAX) {
274 clamp->setMaxInValue(clamp_max);
275 clamp->setMaxOutValue(clamp_max);
277 group->appendTransform(
clamp);
281 auto to_rec709 = OCIO_NAMESPACE::MatrixTransform::Create();
282 to_rec709->setMatrix(
285 group->appendTransform(to_rec709);
293 auto clamp = OCIO_NAMESPACE::RangeTransform::Create();
294 clamp->setStyle(OCIO_NAMESPACE::RANGE_CLAMP);
295 clamp->setMinInValue(0.0);
296 clamp->setMinOutValue(0.0);
298 clamp->setMaxInValue(1.0);
299 clamp->setMaxOutValue(1.0);
301 group->appendTransform(
clamp);
305 auto to_cie_xyz_d65 = OCIO_NAMESPACE::ColorSpaceTransform::Create();
306 to_cie_xyz_d65->setSrc(display_colorspace->name().c_str());
307 to_cie_xyz_d65->setDst(lin_cie_xyz_d65->name().c_str());
308 group->appendTransform(to_cie_xyz_d65);
310 auto to_rec709 = OCIO_NAMESPACE::MatrixTransform::Create();
312 group->appendTransform(to_rec709);
315 group->appendTransform(create_extended_srgb_transform(target_transfer_function));
318OCIO_NAMESPACE::TransformRcPtr create_ocio_display_transform(
319 const OCIO_NAMESPACE::ConstConfigRcPtr &ocio_config,
320 StringRefNull display,
323 StringRefNull from_colorspace)
325 OCIO_NAMESPACE::GroupTransformRcPtr group = OCIO_NAMESPACE::GroupTransform::Create();
328 bool use_look = (look !=
nullptr && look[0] !=
'\0' && look !=
"None");
330 const char *look_output =
nullptr;
333 look_output = OCIO_NAMESPACE::LookTransform::GetLooksResultColorSpace(
334 ocio_config, ocio_config->getCurrentContext(), look.
c_str());
336 catch (OCIO_NAMESPACE::Exception &exception) {
337 report_exception(exception);
341 if (look_output !=
nullptr && look_output[0] != 0) {
342 OCIO_NAMESPACE::LookTransformRcPtr lt = OCIO_NAMESPACE::LookTransform::Create();
343 lt->setSrc(from_colorspace.
c_str());
344 lt->setDst(look_output);
345 lt->setLooks(look.
c_str());
346 group->appendTransform(lt);
349 from_colorspace = look_output;
358 OCIO_NAMESPACE::DisplayViewTransformRcPtr dvt = OCIO_NAMESPACE::DisplayViewTransform::Create();
359 dvt->setSrc(from_colorspace.
c_str());
360 dvt->setLooksBypass(use_look);
361 dvt->setView(
view.c_str());
362 dvt->setDisplay(display.
c_str());
363 group->appendTransform(dvt);
368static OCIO_NAMESPACE::TransformRcPtr create_untonemapped_ocio_display_transform(
369 const LibOCIOConfig &config,
370 StringRefNull display_name,
371 StringRefNull from_colorspace,
375 const auto group = OCIO_NAMESPACE::GroupTransform::Create();
377 const auto to_scene_linear = OCIO_NAMESPACE::ColorSpaceTransform::Create();
380 group->appendTransform(to_scene_linear);
382 const auto to_rec709 = OCIO_NAMESPACE::MatrixTransform::Create();
384 group->appendTransform(to_rec709);
386 const LibOCIODisplay *display =
static_cast<const LibOCIODisplay *
>(
387 config.get_display_by_name(display_name));
388 const LibOCIOView *
view = (display) ?
static_cast<const LibOCIOView *
>(
389 display->get_untonemapped_view()) :
391 group->appendTransform(create_extended_srgb_transform(
392 system_extended_srgb_transfer_function(
view, use_hdr_buffer)));
396OCIO_NAMESPACE::ConstProcessorRcPtr create_ocio_display_processor(
399 using namespace OCIO_NAMESPACE;
401 const ConstConfigRcPtr &ocio_config = config.get_ocio_config();
403 GroupTransformRcPtr group = GroupTransform::Create();
405 const char *from_colorspace = display_parameters.from_colorspace.
c_str();
408 if (display_parameters.scale != 1.0f || display_parameters.use_white_balance) {
410 ColorSpaceTransformRcPtr ct = ColorSpaceTransform::Create();
411 ct->setSrc(from_colorspace);
412 ct->setDst(ROLE_SCENE_LINEAR);
413 group->appendTransform(ct);
416 from_colorspace = ROLE_SCENE_LINEAR;
419 MatrixTransformRcPtr mt = MatrixTransform::Create();
423 if (display_parameters.use_white_balance) {
425 config, display_parameters.temperature, display_parameters.tint);
429 group->appendTransform(mt);
432 if (!display_parameters.view.is_empty()) {
434 group->appendTransform(create_ocio_display_transform(ocio_config,
435 display_parameters.display,
436 display_parameters.view,
437 display_parameters.look,
440 if (display_parameters.exponent != 1.0f) {
441 ExponentTransformRcPtr et = ExponentTransform::Create();
442 const double value[4] = {display_parameters.exponent,
443 display_parameters.exponent,
444 display_parameters.exponent,
447 group->appendTransform(et);
450 if (display_parameters.is_image_output) {
451 adjust_for_hdr_image_file(
452 config, group, display_parameters.display, display_parameters.view);
456 if (display_parameters.use_display_emulation) {
457 display_as_extended_srgb(config,
459 display_parameters.display,
460 display_parameters.view,
461 display_parameters.use_hdr_buffer);
466 group->appendTransform(create_untonemapped_ocio_display_transform(
467 config, display_parameters.display, from_colorspace, display_parameters.use_hdr_buffer));
470 if (display_parameters.inverse) {
471 group->setDirection(TRANSFORM_DIR_INVERSE);
475 std::stringstream sstream;
477 CLOG_TRACE(&
LOG,
"Creating display transform:\n%s", sstream.str().c_str());
482 ConstProcessorRcPtr p;
484 p = ocio_config->getProcessor(group);
486 catch (Exception &exception) {
487 report_exception(exception);
#define CLOG_DEBUG(clg_ref,...)
#define CLOG_WARN(clg_ref,...)
#define CLOG_CHECK(clg_ref, verbose_level,...)
#define CLOG_TRACE(clg_ref,...)
constexpr const char * c_str() const
constexpr const char * c_str() const
virtual StringRefNull name() const =0
constexpr T clamp(T, U, U) RET
BLI_INLINE ColorSceneLinear4f< eAlpha::Straight > to_scene_linear(const ColorTheme4f &theme4f)
float3x3 scene_linear_to_rec709
MatBase< T, NumCol, NumRow > transpose(const MatBase< T, NumRow, NumCol > &mat)
CartesianBasis invert(const CartesianBasis &basis)
float3x3 calculate_white_point_matrix(const Config &config, const float temperature, const float tint)
static const double4x4 OCIO_XYZ_TO_P3
static const double4x4 OCIO_XYZ_TO_REC2020
static const double4x4 OCIO_XYZ_TO_REC709
MatBase< float, 3, 3 > float3x3
MatBase< double, 4, 4 > double4x4
static MatBase identity()