From 784d5630cd56e164cc366b374713b60f3902565c Mon Sep 17 00:00:00 2001 From: Cedrik Fuoco Date: Tue, 18 Oct 2022 16:10:49 -0400 Subject: [PATCH 1/6] First iteration of isColorspaceLinear. Signed-off-by: Cedrik Fuoco --- include/OpenColorIO/OpenColorIO.h | 18 +++++++ src/OpenColorIO/Config.cpp | 79 +++++++++++++++++++++++++++++++ tests/cpu/ColorSpace_tests.cpp | 25 ++++++++++ 3 files changed, 122 insertions(+) diff --git a/include/OpenColorIO/OpenColorIO.h b/include/OpenColorIO/OpenColorIO.h index 89f58cc08e..ae51c552c3 100644 --- a/include/OpenColorIO/OpenColorIO.h +++ b/include/OpenColorIO/OpenColorIO.h @@ -572,6 +572,24 @@ class OCIOEXPORT Config */ void setInactiveColorSpaces(const char * inactiveColorSpaces); const char * getInactiveColorSpaces() const; + + /** + * /brief Return true if the specified color space is linear. + * + * The color space is evaluated against multiple criteria in order to determine if its + * linearity. + * + * - Encoding type and the reference space type. + * - Returned value of isData() + * - Color space's reference space type and the specified argument. + * - Some heuristic that tries to calculate if the color space is linear. + * + * \param colorSpace Color space to evaluate. + * \param referenceSpaceType Evaluate the color space to this reference space type. + + * \return + */ + bool isColorSpaceLinear(const char * colorSpace, ReferenceSpaceType referenceSpaceType) const; // // Roles diff --git a/src/OpenColorIO/Config.cpp b/src/OpenColorIO/Config.cpp index 784a400419..462365f283 100644 --- a/src/OpenColorIO/Config.cpp +++ b/src/OpenColorIO/Config.cpp @@ -2536,6 +2536,85 @@ void Config::clearColorSpaces() getImpl()->refreshActiveColorSpaces(); } +bool Config::isColorSpaceLinear(const char * colorSpace, ReferenceSpaceType referenceSpaceType) const +{ + auto cs = getColorSpace(colorSpace); + + std::string encoding = cs->getEncoding(); + if (!encoding.empty()) + { + // Check the encoding value if it is set. + if ((StringUtils::Compare(cs->getEncoding(), "scene-linear") && + referenceSpaceType == REFERENCE_SPACE_DISPLAY) || + (StringUtils::Compare(cs->getEncoding(), "display-linear") && + referenceSpaceType == REFERENCE_SPACE_SCENE)) + { + // Mismatch between Encoding and Reference Type. + return false; + } + } + + if (cs->isData()) + { + return false; + } + + // Colorspace is not linear if the types are opposite. + if (cs->getReferenceSpaceType() != referenceSpaceType) + { + return false; + } + + // Can not set anything since this method is const (which makes sense) + // Two options: + // 1 - isColorSpaceLinear is const, the user can use a normal config object, but he will + // have to disable the cache himself if he don't want to processor caches to polluted + // by the getProcessors below. + // 2 - The const can be removed but the user will have to create an editable + // config in order to use isColorspaceLinear. + // We can setProcessorCacheFlags with this option. + //setProcessorCacheFlags(OCIO::PROCESSOR_CACHE_OFF); + + auto evaluate = [this](ConstTransformRcPtr &t) -> bool + { + std::vector img = { 0.0625f, 0.0625f, 0.0625f, 4.f, 4.f, 4.f }; + std::vector dst = { 0.f, 0.f, 0.f, 0.f, 0.f, 0.f }; + PackedImageDesc desc(&img[0], 2, 1, CHANNEL_ORDERING_RGB); + PackedImageDesc descDst(&dst[0], 2, 1, CHANNEL_ORDERING_RGB); + + auto procToReference = getProcessor(t); + auto optCPUProc = procToReference->getOptimizedCPUProcessor(OPTIMIZATION_LOSSLESS); + + // TODOCED: Offset? + + // Based on the issue description. Is this still needed? + // TODOCED The CDL op would return true if the power values are 1 ? + // TODOCED Other ops (excluding Matrix, Range, CDL) would return true if their isIdentity is true ? + optCPUProc->apply(desc, descDst); + + bool ret = true; + for (auto i = 0; i < dst.size()/2; i++ ) + { + ret &= EqualWithAbsError(dst[i]*64.f, dst[i+3], 1e-5f); + } + return ret; + }; + + ConstTransformRcPtr transformToReference = cs->getTransform(COLORSPACE_DIR_TO_REFERENCE); + ConstTransformRcPtr transformFromReference = cs->getTransform(COLORSPACE_DIR_FROM_REFERENCE); + if (transformToReference && transformFromReference || transformToReference) + { + // Color space has transforms for to-reference direction. + return evaluate(transformToReference); + } + else if (transformFromReference) + { + // Color space has transforms for from-reference direction. + return evaluate(transformFromReference); + } + + return true; +} /////////////////////////////////////////////////////////////////////////// diff --git a/tests/cpu/ColorSpace_tests.cpp b/tests/cpu/ColorSpace_tests.cpp index 087a6c5f49..8a3141cefb 100644 --- a/tests/cpu/ColorSpace_tests.cpp +++ b/tests/cpu/ColorSpace_tests.cpp @@ -716,3 +716,28 @@ active_views: [] OCIO_CHECK_EQUAL(std::string(cfg->getColorSpaceFromFilepath("test_aces_test")), "colorspace"); } + +OCIO_ADD_TEST(Config, is_colorspaces_linear) +{ + // Load config. + OCIO::ConstConfigRcPtr config; + OCIO_CHECK_NO_THROW(config = OCIO::Config::CreateFromFile("ocio://default")); + OCIO_REQUIRE_ASSERT(config); + OCIO_CHECK_NO_THROW(config->validate()); + + auto numberOfColorspaces = config->getNumColorSpaces(); + for (int i = 0; i < numberOfColorspaces; i++) + { + auto cs = config->getColorSpace(config->getColorSpaceNameByIndex(i)); + bool isLinearToSceneReference = config->isColorSpaceLinear(config->getColorSpaceNameByIndex(i), OCIO::REFERENCE_SPACE_SCENE); + bool isLinearToDisplayReference = config->isColorSpaceLinear(config->getColorSpaceNameByIndex(i), OCIO::REFERENCE_SPACE_DISPLAY); + std::cout << "[" << cs->getName() << "] " + << "Scene-ref. [" + << (isLinearToSceneReference ? "Linear" : "Non-linear") + << "]" + << ", Display-ref. [" + << (isLinearToSceneReference ? "Linear" : "Non-linear") + << "]" + << std::endl; + } +} From fe65de8dc922ac2fd87e468e7480532d35b3b812 Mon Sep 17 00:00:00 2001 From: Cedrik Fuoco Date: Wed, 19 Oct 2022 13:34:59 -0400 Subject: [PATCH 2/6] - Comments. - Added a private getProcessor method that ignore caching. - Fix the algorithm for isColorspaceLinear. - Now testing R, G, B and neutral values. Signed-off-by: Cedrik Fuoco --- include/OpenColorIO/OpenColorIO.h | 41 ++++-- src/OpenColorIO/Config.cpp | 112 ++++++++++------ tests/cpu/ColorSpace_tests.cpp | 216 ++++++++++++++++++++++++++++-- 3 files changed, 305 insertions(+), 64 deletions(-) diff --git a/include/OpenColorIO/OpenColorIO.h b/include/OpenColorIO/OpenColorIO.h index ae51c552c3..f484805827 100644 --- a/include/OpenColorIO/OpenColorIO.h +++ b/include/OpenColorIO/OpenColorIO.h @@ -574,20 +574,41 @@ class OCIOEXPORT Config const char * getInactiveColorSpaces() const; /** - * /brief Return true if the specified color space is linear. + * \brief Return true if the specified color space is linear. * - * The color space is evaluated against multiple criteria in order to determine if its - * linearity. + * The determination of linearity is made with respect to one of the two reference spaces + * (i.e., either the scene-referred one or the display-referred one). If the reference space + * type of the color space is the opposite of the requested reference space type, false is + * returned immediately rather than trying to invoke the default view transform to convert + * between the reference spaces. * - * - Encoding type and the reference space type. - * - Returned value of isData() - * - Color space's reference space type and the specified argument. - * - Some heuristic that tries to calculate if the color space is linear. + * Note: This function relies on heuristics that may sometimes give an incorrect result. + * For example, if the encoding attribute is not set appropriately or the sampled values fail + * to detect non-linearity. + * + * The algorithm proceeds as follows: + * -- If the color space isdata attribute is true, return false. + * + * -- If the reference space type of the color space differs from the requested reference + * space type, return false. + * + * -- If the color space's encoding attribute is present, return true if it matches the + * expected reference space type (i.e., "scene-linear" for REFERENCE_SPACE_SCENE or + * "display-linear" for REFERENCE_SPACE_DISPLAY) and false otherwise. + * + * -- Evaluate several points through the color space's transform and check if the output only + * differs by a scale factor (which may be different per channel, e.g. allowing an arbitrary + * matrix transform, with no offset). + * + * Note that the encoding test happens before the sampled value test to give config authors + * ultimate control over the linearity determination. For example, they could set the encoding + * attribute to indicate linearity if they want to ignore some areas of non-linearity + * (e.g., at extreme values). Or they could set it to indicate that a color space should not + * be considered linear, even if it is, in a mathematical sense. * * \param colorSpace Color space to evaluate. - * \param referenceSpaceType Evaluate the color space to this reference space type. - - * \return + * \param referenceSpaceType Evaluate linearity with respect to the specified reference space + * (either scene-referred or display-referred). */ bool isColorSpaceLinear(const char * colorSpace, ReferenceSpaceType referenceSpaceType) const; diff --git a/src/OpenColorIO/Config.cpp b/src/OpenColorIO/Config.cpp index 462365f283..06f333602f 100644 --- a/src/OpenColorIO/Config.cpp +++ b/src/OpenColorIO/Config.cpp @@ -1071,6 +1071,30 @@ class Config::Impl return -1; } + ConstProcessorRcPtr getProcessorWithoutCaching( + const Config & config, + const ConstTransformRcPtr & transform, + TransformDirection direction) const + { + if (!transform) + { + throw Exception("Config::GetProcessor failed. Transform is null."); + } + + // Create helper method. + auto CreateProcessor = [](const Config & config, + const ConstContextRcPtr & context, + const ConstTransformRcPtr & transform, + TransformDirection direction) -> ProcessorRcPtr + { + ProcessorRcPtr processor = Processor::Create(); + processor->getImpl()->setProcessorCacheFlags(PROCESSOR_CACHE_OFF); + processor->getImpl()->setTransform(config, context, transform, direction); + return processor; + }; + + return CreateProcessor(config, m_context, transform, direction); + } }; @@ -2540,20 +2564,6 @@ bool Config::isColorSpaceLinear(const char * colorSpace, ReferenceSpaceType refe { auto cs = getColorSpace(colorSpace); - std::string encoding = cs->getEncoding(); - if (!encoding.empty()) - { - // Check the encoding value if it is set. - if ((StringUtils::Compare(cs->getEncoding(), "scene-linear") && - referenceSpaceType == REFERENCE_SPACE_DISPLAY) || - (StringUtils::Compare(cs->getEncoding(), "display-linear") && - referenceSpaceType == REFERENCE_SPACE_SCENE)) - { - // Mismatch between Encoding and Reference Type. - return false; - } - } - if (cs->isData()) { return false; @@ -2565,55 +2575,77 @@ bool Config::isColorSpaceLinear(const char * colorSpace, ReferenceSpaceType refe return false; } - // Can not set anything since this method is const (which makes sense) - // Two options: - // 1 - isColorSpaceLinear is const, the user can use a normal config object, but he will - // have to disable the cache himself if he don't want to processor caches to polluted - // by the getProcessors below. - // 2 - The const can be removed but the user will have to create an editable - // config in order to use isColorspaceLinear. - // We can setProcessorCacheFlags with this option. - //setProcessorCacheFlags(OCIO::PROCESSOR_CACHE_OFF); + std::string encoding = cs->getEncoding(); + if (!encoding.empty()) + { + // Check the encoding value if it is set. + if ((StringUtils::Compare(cs->getEncoding(), "scene-linear") && + referenceSpaceType == REFERENCE_SPACE_SCENE) || + (StringUtils::Compare(cs->getEncoding(), "display-linear") && + referenceSpaceType == REFERENCE_SPACE_DISPLAY)) + { + return true; + } + else + { + return false; + } + } + // We want to assess linearity over at least a reasonable range of values, so use a very dark + // value and a very bright value. Test neutral, red, green, and blue points to detect situations + // where the neutral may be linear but there is non-linearity off the neutral axis. auto evaluate = [this](ConstTransformRcPtr &t) -> bool { - std::vector img = { 0.0625f, 0.0625f, 0.0625f, 4.f, 4.f, 4.f }; - std::vector dst = { 0.f, 0.f, 0.f, 0.f, 0.f, 0.f }; - PackedImageDesc desc(&img[0], 2, 1, CHANNEL_ORDERING_RGB); - PackedImageDesc descDst(&dst[0], 2, 1, CHANNEL_ORDERING_RGB); - - auto procToReference = getProcessor(t); + std::vector img = + { + 0.0625f, 0.0625f, 0.0625f, 4.f, 4.f, 4.f, + 0.0625f, 0.f, 0.f, 4.f, 0.f, 0.f, + 0.f, 0.0625f, 0.f, 0.f, 4.f, 0.f, + 0.f, 0.f, 0.0625f, 0.f, 0.f, 4.f + }; + std::vector dst = + { + 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, + 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, + 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, + 0.f, 0.f, 0.f, 0.f, 0.f, 0.f + }; + + PackedImageDesc desc(&img[0], 8, 1, CHANNEL_ORDERING_RGB); + PackedImageDesc descDst(&dst[0], 8, 1, CHANNEL_ORDERING_RGB); + + auto procToReference = getImpl()->getProcessorWithoutCaching(*this, t, TRANSFORM_DIR_FORWARD); auto optCPUProc = procToReference->getOptimizedCPUProcessor(OPTIMIZATION_LOSSLESS); - - // TODOCED: Offset? - - // Based on the issue description. Is this still needed? - // TODOCED The CDL op would return true if the power values are 1 ? - // TODOCED Other ops (excluding Matrix, Range, CDL) would return true if their isIdentity is true ? optCPUProc->apply(desc, descDst); bool ret = true; - for (auto i = 0; i < dst.size()/2; i++ ) + for (auto i = 0; i < dst.size(); i++ ) { ret &= EqualWithAbsError(dst[i]*64.f, dst[i+3], 1e-5f); + if (((i+1) % 3) == 0) + { + // Go to next RGB pair. + i += 3; + } } return ret; }; ConstTransformRcPtr transformToReference = cs->getTransform(COLORSPACE_DIR_TO_REFERENCE); ConstTransformRcPtr transformFromReference = cs->getTransform(COLORSPACE_DIR_FROM_REFERENCE); - if (transformToReference && transformFromReference || transformToReference) + if ((transformToReference && transformFromReference) || transformToReference) { - // Color space has transforms for to-reference direction. + // Color space has a transform for the to-reference direction, or both directions. return evaluate(transformToReference); } else if (transformFromReference) { - // Color space has transforms for from-reference direction. + // Color space only has a transform for the from-reference direction. return evaluate(transformFromReference); } - return true; + return false; } /////////////////////////////////////////////////////////////////////////// diff --git a/tests/cpu/ColorSpace_tests.cpp b/tests/cpu/ColorSpace_tests.cpp index 8a3141cefb..7fcb712a1e 100644 --- a/tests/cpu/ColorSpace_tests.cpp +++ b/tests/cpu/ColorSpace_tests.cpp @@ -6,7 +6,9 @@ #include "ColorSpace.cpp" +#include #include "testutils/UnitTest.h" +#include "UnitTestUtils.h" namespace OCIO = OCIO_NAMESPACE; @@ -719,25 +721,211 @@ active_views: [] OCIO_ADD_TEST(Config, is_colorspaces_linear) { + + constexpr const char * TEST_CONFIG { R"(ocio_profile_version: 2 + +description: Test config for the isColorSpaceLinear method. + +environment: + {} +search_path: "non_existing_path" +roles: + aces_interchange: scene_linear-trans + cie_xyz_d65_interchange: display_linear-enc + color_timing: scene_linear-trans + compositing_log: scene_log-enc + default: display_data + scene_linear: scene_linear-trans + +displays: + generic display: + - ! {name: Raw, colorspace: scene_data} + +# Make a few of the color spaces inactive, this should not affect the result. +inactive_colorspaces: [display_linear-trans, scene_linear-trans] + +view_transforms: + - ! + name: view_transform + from_scene_reference: ! {} + +# Display-referred color spaces. + +display_colorspaces: + - ! + name: display_data + description: | + Data space. + Has a linear transform, which should never happen, but this will be ignored since + isdata is true. + isdata: true + encoding: data + from_display_reference: ! {matrix: [ 3.240969941905, -1.537383177570, -0.498610760293, 0, -0.969243636281, 1.875967501508, 0.041555057407, 0, 0.055630079697, -0.203976958889, 1.056971514243, 0, 0, 0, 0, 1 ]} + + - ! + name: display_linear-enc + description: | + Encoding set to display-linear. + Has a non-existent transform, but this should be ignored since the encoding takes precedence. + isdata: false + encoding: display-linear + from_display_reference: ! {src: does-not-exist.lut} + + - ! + name: display_wrong-linear-enc + description: | + Encoding set to scene-linear. This should never happen for a display space, but test it. + isdata: false + encoding: scene-linear + + - ! + name: display_video-enc + description: | + Encoding set to sdr-video. + Has a linear transform, but this should be ignored since the encoding takes precedence. + isdata: false + encoding: sdr-video + from_display_reference: ! {matrix: [ 3.240969941905, -1.537383177570, -0.498610760293, 0, -0.969243636281, 1.875967501508, 0.041555057407, 0, 0.055630079697, -0.203976958889, 1.056971514243, 0, 0, 0, 0, 1 ]} + + - ! + name: display_linear-trans + description: | + No encoding. Transform is linear. + isdata: false + from_display_reference: ! + children: + - ! {matrix: [ 3.240969941905, -1.537383177570, -0.498610760293, 0, -0.969243636281, 1.875967501508, 0.041555057407, 0, 0.055630079697, -0.203976958889, 1.056971514243, 0, 0, 0, 0, 1 ]} + - ! {slope: [0.1, 2, 3], style: noclamp} + + - ! + name: display_video-trans + description: | + No encoding. Transform is non-linear. + isdata: false + from_display_reference: ! {style: DISPLAY - CIE-XYZ-D65_to_sRGB} + +# Scene-referred color spaces. + +colorspaces: + - ! + name: scene_data + description: | + Data space. + Has a linear transform, which should never happen, but this will be ignored + since isdata is true. + isdata: true + encoding: data + from_scene_reference: ! {matrix: [ 3.240969941905, -1.537383177570, -0.498610760293, 0, -0.969243636281, 1.875967501508, 0.041555057407, 0, 0.055630079697, -0.203976958889, 1.056971514243, 0, 0, 0, 0, 1 ]} + + - ! + name: scene_linear-enc + description: | + Encoding set to scene-linear. + Has a non-linear transform, but this will be ignored since the encoding takes precedence. + isdata: false + encoding: scene-linear + from_scene_reference: ! {style: DISPLAY - CIE-XYZ-D65_to_sRGB} + + - ! + name: scene_wrong-linear-enc + description: | + Encoding set to display-linear. This should never happen for a scene space, but test it. + isdata: false + encoding: display-linear + + - ! + name: scene_log-enc + description: | + Encoding set to log. + Has a linear transform, but this will be ignored since the encoding takes precedence. + isdata: false + encoding: log + from_scene_reference: ! {matrix: [ 3.240969941905, -1.537383177570, -0.498610760293, 0, -0.969243636281, 1.875967501508, 0.041555057407, 0, 0.055630079697, -0.203976958889, 1.056971514243, 0, 0, 0, 0, 1 ]} + + - ! + name: scene_linear-trans + aliases: [scene_linear-trans-alias] + description: | + No encoding. Transform is linear. + isdata: false + to_scene_reference: ! + children: + - ! {style: UTILITY - ACES-AP0_to_CIE-XYZ-D65_BFD} + - ! {matrix: [ 3.240969941905, -1.537383177570, -0.498610760293, 0, -0.969243636281, 1.875967501508, 0.041555057407, 0, 0.055630079697, -0.203976958889, 1.056971514243, 0, 0, 0, 0, 1 ]} + - ! {matrix: [ 3.240969941905, -1.537383177570, -0.498610760293, 0, -0.969243636281, 1.875967501508, 0.041555057407, 0, 0.055630079697, -0.203976958889, 1.056971514243, 0, 0, 0, 0, 1 ]} + + - ! + name: scene_nonlin-trans + description: | + No encoding. Transform is non-linear because it clamps values outside [0,1]. + isdata: false + to_scene_reference: ! + children: + - ! {matrix: [ 3.240969941905, -1.537383177570, -0.498610760293, 0, -0.969243636281, 1.875967501508, 0.041555057407, 0, 0.055630079697, -0.203976958889, 1.056971514243, 0, 0, 0, 0, 1 ]} + - ! {min_in_value: 0., min_out_value: 0., max_in_value: 1., max_out_value: 1.} +)" }; + // Load config. + std::istringstream is; + is.str(TEST_CONFIG); OCIO::ConstConfigRcPtr config; - OCIO_CHECK_NO_THROW(config = OCIO::Config::CreateFromFile("ocio://default")); + + OCIO_CHECK_NO_THROW(config = OCIO::Config::CreateFromStream(is)); OCIO_REQUIRE_ASSERT(config); OCIO_CHECK_NO_THROW(config->validate()); - auto numberOfColorspaces = config->getNumColorSpaces(); - for (int i = 0; i < numberOfColorspaces; i++) + auto testSceneReferred = [&config](const char * csName, bool bSceneExpected, int line) { - auto cs = config->getColorSpace(config->getColorSpaceNameByIndex(i)); - bool isLinearToSceneReference = config->isColorSpaceLinear(config->getColorSpaceNameByIndex(i), OCIO::REFERENCE_SPACE_SCENE); - bool isLinearToDisplayReference = config->isColorSpaceLinear(config->getColorSpaceNameByIndex(i), OCIO::REFERENCE_SPACE_DISPLAY); - std::cout << "[" << cs->getName() << "] " - << "Scene-ref. [" - << (isLinearToSceneReference ? "Linear" : "Non-linear") - << "]" - << ", Display-ref. [" - << (isLinearToSceneReference ? "Linear" : "Non-linear") - << "]" - << std::endl; + auto cs = config->getColorSpace(csName); + OCIO_REQUIRE_ASSERT(cs); + + bool isLinearToSceneReference = config->isColorSpaceLinear(csName, OCIO::REFERENCE_SPACE_SCENE); + bool isLinearToDisplayReference = config->isColorSpaceLinear(csName, OCIO::REFERENCE_SPACE_DISPLAY); + OCIO_CHECK_EQUAL_FROM(isLinearToSceneReference, bSceneExpected, line); + }; + + auto testDisplayReferred = [&config](const char * csName, bool bDisplayExpected, int line) + { + auto cs = config->getColorSpace(csName); + OCIO_REQUIRE_ASSERT(cs); + + bool isLinearToDisplayReference = config->isColorSpaceLinear(csName, OCIO::REFERENCE_SPACE_DISPLAY); + OCIO_CHECK_EQUAL_FROM(isLinearToDisplayReference, bDisplayExpected, line); + }; + + { + testSceneReferred("display_data", false, __LINE__); + testSceneReferred("display_linear-enc", false, __LINE__); + testSceneReferred("display_wrong-linear-enc", false, __LINE__); + testSceneReferred("display_video-enc", false, __LINE__); + testSceneReferred("display_linear-trans", false, __LINE__); + //("display_video-trans", false, __LINE__); + + testSceneReferred("scene_data", false, __LINE__); + testSceneReferred("scene_linear-enc", true, __LINE__); + testSceneReferred("scene_wrong-linear-enc", false, __LINE__); + testSceneReferred("scene_log-enc", false, __LINE__); + testSceneReferred("scene_linear-trans", true, __LINE__); + testSceneReferred("scene_nonlin-trans", false, __LINE__); + testSceneReferred("scene_linear-trans-alias", true, __LINE__); } + + { + testDisplayReferred("display_data", false, __LINE__); + testDisplayReferred("display_linear-enc", true, __LINE__); + testDisplayReferred("display_wrong-linear-enc", false, __LINE__); + testDisplayReferred("display_video-enc", false, __LINE__); + testDisplayReferred("display_linear-trans", true, __LINE__); + testDisplayReferred("display_video-trans", false, __LINE__); + + testDisplayReferred("scene_data", false, __LINE__); + testDisplayReferred("scene_linear-enc", false, __LINE__); + testDisplayReferred("scene_wrong-linear-enc", false, __LINE__); + testDisplayReferred("scene_log-enc", false, __LINE__); + testDisplayReferred("scene_linear-trans", false, __LINE__); + testDisplayReferred("scene_nonlin-trans", false, __LINE__); + testDisplayReferred("scene_linear-trans-alias", false, __LINE__); + } + + } From ab0a8ce8cad7226612fa0c7df7f59c09529e2712 Mon Sep 17 00:00:00 2001 From: Cedrik Fuoco Date: Wed, 19 Oct 2022 15:36:22 -0400 Subject: [PATCH 3/6] - Passing in the config reference instead of using this in the capture clause of the lambda function as this was causing issue on other platforms than Windows. - Remove unused variable in unit test. - other minors changes Signed-off-by: Cedrik Fuoco --- include/OpenColorIO/OpenColorIO.h | 2 - src/OpenColorIO/Config.cpp | 97 ++++++++++++++++++------------- tests/cpu/ColorSpace_tests.cpp | 5 +- 3 files changed, 60 insertions(+), 44 deletions(-) diff --git a/include/OpenColorIO/OpenColorIO.h b/include/OpenColorIO/OpenColorIO.h index f484805827..cbfaaddd31 100644 --- a/include/OpenColorIO/OpenColorIO.h +++ b/include/OpenColorIO/OpenColorIO.h @@ -591,11 +591,9 @@ class OCIOEXPORT Config * * -- If the reference space type of the color space differs from the requested reference * space type, return false. - * * -- If the color space's encoding attribute is present, return true if it matches the * expected reference space type (i.e., "scene-linear" for REFERENCE_SPACE_SCENE or * "display-linear" for REFERENCE_SPACE_DISPLAY) and false otherwise. - * * -- Evaluate several points through the color space's transform and check if the output only * differs by a scale factor (which may be different per channel, e.g. allowing an arbitrary * matrix transform, with no offset). diff --git a/src/OpenColorIO/Config.cpp b/src/OpenColorIO/Config.cpp index 06f333602f..60b546b2bc 100644 --- a/src/OpenColorIO/Config.cpp +++ b/src/OpenColorIO/Config.cpp @@ -914,6 +914,31 @@ class Config::Impl m_cacheFlags = flags; m_processorCache.enable((m_cacheFlags & PROCESSOR_CACHE_ENABLED) == PROCESSOR_CACHE_ENABLED); } + + ConstProcessorRcPtr getProcessorWithoutCaching( + const Config & config, + const ConstTransformRcPtr & transform, + TransformDirection direction) const + { + if (!transform) + { + throw Exception("Config::GetProcessor failed. Transform is null."); + } + + // Create helper method. + auto CreateProcessor = [](const Config & config, + const ConstContextRcPtr & context, + const ConstTransformRcPtr & transform, + TransformDirection direction) -> ProcessorRcPtr + { + ProcessorRcPtr processor = Processor::Create(); + processor->getImpl()->setProcessorCacheFlags(PROCESSOR_CACHE_OFF); + processor->getImpl()->setTransform(config, context, transform, direction); + return processor; + }; + + return CreateProcessor(config, m_context, transform, direction); + } int instantiateDisplay(const std::string & monitorName, const std::string & monitorDescription, @@ -1070,31 +1095,6 @@ class Config::Impl // That should never happen. return -1; } - - ConstProcessorRcPtr getProcessorWithoutCaching( - const Config & config, - const ConstTransformRcPtr & transform, - TransformDirection direction) const - { - if (!transform) - { - throw Exception("Config::GetProcessor failed. Transform is null."); - } - - // Create helper method. - auto CreateProcessor = [](const Config & config, - const ConstContextRcPtr & context, - const ConstTransformRcPtr & transform, - TransformDirection direction) -> ProcessorRcPtr - { - ProcessorRcPtr processor = Processor::Create(); - processor->getImpl()->setProcessorCacheFlags(PROCESSOR_CACHE_OFF); - processor->getImpl()->setTransform(config, context, transform, direction); - return processor; - }; - - return CreateProcessor(config, m_context, transform, direction); - } }; @@ -2595,7 +2595,7 @@ bool Config::isColorSpaceLinear(const char * colorSpace, ReferenceSpaceType refe // We want to assess linearity over at least a reasonable range of values, so use a very dark // value and a very bright value. Test neutral, red, green, and blue points to detect situations // where the neutral may be linear but there is non-linearity off the neutral axis. - auto evaluate = [this](ConstTransformRcPtr &t) -> bool + auto evaluate = [](const Config & config, ConstTransformRcPtr &t) -> bool { std::vector img = { @@ -2615,20 +2615,39 @@ bool Config::isColorSpaceLinear(const char * colorSpace, ReferenceSpaceType refe PackedImageDesc desc(&img[0], 8, 1, CHANNEL_ORDERING_RGB); PackedImageDesc descDst(&dst[0], 8, 1, CHANNEL_ORDERING_RGB); - auto procToReference = getImpl()->getProcessorWithoutCaching(*this, t, TRANSFORM_DIR_FORWARD); + auto procToReference = config.getImpl()->getProcessorWithoutCaching( + config, t, TRANSFORM_DIR_FORWARD + ); auto optCPUProc = procToReference->getOptimizedCPUProcessor(OPTIMIZATION_LOSSLESS); optCPUProc->apply(desc, descDst); - bool ret = true; - for (auto i = 0; i < dst.size(); i++ ) - { - ret &= EqualWithAbsError(dst[i]*64.f, dst[i+3], 1e-5f); - if (((i+1) % 3) == 0) - { - // Go to next RGB pair. - i += 3; - } - } + + float absError = 1e-5f; + float multiplier = 64.f; + bool ret = true; + + // Not using loop for readability. + + // Test the first RGB pair. + ret &= EqualWithAbsError(dst[0]*multiplier, dst[3], absError); + ret &= EqualWithAbsError(dst[1]*multiplier, dst[4], absError); + ret &= EqualWithAbsError(dst[2]*multiplier, dst[5], absError); + + // Test the second RGB pair. + ret &= EqualWithAbsError(dst[6]*multiplier, dst[9], absError); + ret &= EqualWithAbsError(dst[7]*multiplier, dst[10], absError); + ret &= EqualWithAbsError(dst[8]*multiplier, dst[11], absError); + + // Test the third RGB pair. + ret &= EqualWithAbsError(dst[12]*multiplier, dst[15], absError); + ret &= EqualWithAbsError(dst[13]*multiplier, dst[16], absError); + ret &= EqualWithAbsError(dst[14]*multiplier, dst[17], absError); + + // Test the fourth RGB pair. + ret &= EqualWithAbsError(dst[18]*multiplier, dst[21], absError); + ret &= EqualWithAbsError(dst[19]*multiplier, dst[22], absError); + ret &= EqualWithAbsError(dst[20]*multiplier, dst[23], absError); + return ret; }; @@ -2637,12 +2656,12 @@ bool Config::isColorSpaceLinear(const char * colorSpace, ReferenceSpaceType refe if ((transformToReference && transformFromReference) || transformToReference) { // Color space has a transform for the to-reference direction, or both directions. - return evaluate(transformToReference); + return evaluate(*this, transformToReference); } else if (transformFromReference) { // Color space only has a transform for the from-reference direction. - return evaluate(transformFromReference); + return evaluate(*this, transformFromReference); } return false; diff --git a/tests/cpu/ColorSpace_tests.cpp b/tests/cpu/ColorSpace_tests.cpp index 7fcb712a1e..1f28b020c8 100644 --- a/tests/cpu/ColorSpace_tests.cpp +++ b/tests/cpu/ColorSpace_tests.cpp @@ -719,7 +719,7 @@ active_views: [] "colorspace"); } -OCIO_ADD_TEST(Config, is_colorspaces_linear) +OCIO_ADD_TEST(Config, is_colorspace_linear) { constexpr const char * TEST_CONFIG { R"(ocio_profile_version: 2 @@ -880,7 +880,6 @@ inactive_colorspaces: [display_linear-trans, scene_linear-trans] OCIO_REQUIRE_ASSERT(cs); bool isLinearToSceneReference = config->isColorSpaceLinear(csName, OCIO::REFERENCE_SPACE_SCENE); - bool isLinearToDisplayReference = config->isColorSpaceLinear(csName, OCIO::REFERENCE_SPACE_DISPLAY); OCIO_CHECK_EQUAL_FROM(isLinearToSceneReference, bSceneExpected, line); }; @@ -899,7 +898,7 @@ inactive_colorspaces: [display_linear-trans, scene_linear-trans] testSceneReferred("display_wrong-linear-enc", false, __LINE__); testSceneReferred("display_video-enc", false, __LINE__); testSceneReferred("display_linear-trans", false, __LINE__); - //("display_video-trans", false, __LINE__); + testSceneReferred("display_video-trans", false, __LINE__); testSceneReferred("scene_data", false, __LINE__); testSceneReferred("scene_linear-enc", true, __LINE__); From 403102400ac157e0ab07c518596103766a728e44 Mon Sep 17 00:00:00 2001 From: Cedrik Fuoco Date: Wed, 19 Oct 2022 15:57:04 -0400 Subject: [PATCH 4/6] Removing a comment and removing the helper function as it is not needed. Signed-off-by: Cedrik Fuoco --- include/OpenColorIO/OpenColorIO.h | 1 - src/OpenColorIO/Config.cpp | 19 ++++--------------- 2 files changed, 4 insertions(+), 16 deletions(-) diff --git a/include/OpenColorIO/OpenColorIO.h b/include/OpenColorIO/OpenColorIO.h index cbfaaddd31..7276bd1060 100644 --- a/include/OpenColorIO/OpenColorIO.h +++ b/include/OpenColorIO/OpenColorIO.h @@ -588,7 +588,6 @@ class OCIOEXPORT Config * * The algorithm proceeds as follows: * -- If the color space isdata attribute is true, return false. - * * -- If the reference space type of the color space differs from the requested reference * space type, return false. * -- If the color space's encoding attribute is present, return true if it matches the diff --git a/src/OpenColorIO/Config.cpp b/src/OpenColorIO/Config.cpp index 60b546b2bc..9232f044d2 100644 --- a/src/OpenColorIO/Config.cpp +++ b/src/OpenColorIO/Config.cpp @@ -924,20 +924,11 @@ class Config::Impl { throw Exception("Config::GetProcessor failed. Transform is null."); } - - // Create helper method. - auto CreateProcessor = [](const Config & config, - const ConstContextRcPtr & context, - const ConstTransformRcPtr & transform, - TransformDirection direction) -> ProcessorRcPtr - { - ProcessorRcPtr processor = Processor::Create(); - processor->getImpl()->setProcessorCacheFlags(PROCESSOR_CACHE_OFF); - processor->getImpl()->setTransform(config, context, transform, direction); - return processor; - }; - return CreateProcessor(config, m_context, transform, direction); + ProcessorRcPtr processor = Processor::Create(); + processor->getImpl()->setProcessorCacheFlags(PROCESSOR_CACHE_OFF); + processor->getImpl()->setTransform(config, m_context, transform, direction); + return processor; } int instantiateDisplay(const std::string & monitorName, @@ -2626,8 +2617,6 @@ bool Config::isColorSpaceLinear(const char * colorSpace, ReferenceSpaceType refe float multiplier = 64.f; bool ret = true; - // Not using loop for readability. - // Test the first RGB pair. ret &= EqualWithAbsError(dst[0]*multiplier, dst[3], absError); ret &= EqualWithAbsError(dst[1]*multiplier, dst[4], absError); From 7cfce93ce86769355b4311184030aabba92c2ee1 Mon Sep 17 00:00:00 2001 From: Cedrik Fuoco Date: Thu, 20 Oct 2022 09:35:50 -0400 Subject: [PATCH 5/6] - Tweaking algorithm. Returns true at the end since the color space matches the desired reference space type, is not a data space, and has no transforms, so it is equivalent to the reference space and hence linear. - Added a color space in the test config to cover that. Signed-off-by: Cedrik Fuoco --- include/OpenColorIO/OpenColorIO.h | 1 + src/OpenColorIO/Config.cpp | 4 +++- tests/cpu/ColorSpace_tests.cpp | 8 ++++++++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/include/OpenColorIO/OpenColorIO.h b/include/OpenColorIO/OpenColorIO.h index 7276bd1060..451a0e301b 100644 --- a/include/OpenColorIO/OpenColorIO.h +++ b/include/OpenColorIO/OpenColorIO.h @@ -593,6 +593,7 @@ class OCIOEXPORT Config * -- If the color space's encoding attribute is present, return true if it matches the * expected reference space type (i.e., "scene-linear" for REFERENCE_SPACE_SCENE or * "display-linear" for REFERENCE_SPACE_DISPLAY) and false otherwise. + * -- If the color space has no to_reference or from_reference transform, return true. * -- Evaluate several points through the color space's transform and check if the output only * differs by a scale factor (which may be different per channel, e.g. allowing an arbitrary * matrix transform, with no offset). diff --git a/src/OpenColorIO/Config.cpp b/src/OpenColorIO/Config.cpp index 9232f044d2..1a1bd23193 100644 --- a/src/OpenColorIO/Config.cpp +++ b/src/OpenColorIO/Config.cpp @@ -2653,7 +2653,9 @@ bool Config::isColorSpaceLinear(const char * colorSpace, ReferenceSpaceType refe return evaluate(*this, transformFromReference); } - return false; + // Color space matches the desired reference space type, is not a data space, and has no + // transforms, so it is equivalent to the reference space and hence linear. + return true; } /////////////////////////////////////////////////////////////////////////// diff --git a/tests/cpu/ColorSpace_tests.cpp b/tests/cpu/ColorSpace_tests.cpp index 1f28b020c8..93a618b274 100644 --- a/tests/cpu/ColorSpace_tests.cpp +++ b/tests/cpu/ColorSpace_tests.cpp @@ -863,6 +863,12 @@ inactive_colorspaces: [display_linear-trans, scene_linear-trans] children: - ! {matrix: [ 3.240969941905, -1.537383177570, -0.498610760293, 0, -0.969243636281, 1.875967501508, 0.041555057407, 0, 0.055630079697, -0.203976958889, 1.056971514243, 0, 0, 0, 0, 1 ]} - ! {min_in_value: 0., min_out_value: 0., max_in_value: 1., max_out_value: 1.} + + - ! + name: scene_ref + description: | + No encoding. Considered linear since it is equivalent to the reference space. + isdata: false )" }; // Load config. @@ -907,6 +913,7 @@ inactive_colorspaces: [display_linear-trans, scene_linear-trans] testSceneReferred("scene_linear-trans", true, __LINE__); testSceneReferred("scene_nonlin-trans", false, __LINE__); testSceneReferred("scene_linear-trans-alias", true, __LINE__); + testSceneReferred("scene_ref", true, __LINE__); } { @@ -924,6 +931,7 @@ inactive_colorspaces: [display_linear-trans, scene_linear-trans] testDisplayReferred("scene_linear-trans", false, __LINE__); testDisplayReferred("scene_nonlin-trans", false, __LINE__); testDisplayReferred("scene_linear-trans-alias", false, __LINE__); + testDisplayReferred("scene_ref", false, __LINE__); } From 4ebeff471affae32f6e77ddd402fe51020ed3706 Mon Sep 17 00:00:00 2001 From: Cedrik Fuoco Date: Wed, 26 Oct 2022 13:12:38 -0400 Subject: [PATCH 6/6] Adding python binding for isColorSpaceLinear and python unit test. Signed-off-by: Cedrik Fuoco --- src/bindings/python/PyConfig.cpp | 2 + tests/cpu/ColorSpace_tests.cpp | 2 - tests/python/ColorSpaceTest.py | 205 +++++++++++++++++++++++++++++++ 3 files changed, 207 insertions(+), 2 deletions(-) diff --git a/src/bindings/python/PyConfig.cpp b/src/bindings/python/PyConfig.cpp index 2eae7a8764..18a3de927a 100644 --- a/src/bindings/python/PyConfig.cpp +++ b/src/bindings/python/PyConfig.cpp @@ -316,6 +316,8 @@ void bindPyConfig(py::module & m) DOC(Config, addColorSpace)) .def("removeColorSpace", &Config::removeColorSpace, "name"_a, DOC(Config, removeColorSpace)) + .def("isColorSpaceLinear", &Config::isColorSpaceLinear, "colorSpace"_a, "referenceSpaceType"_a, + DOC(Config, isColorSpaceLinear)) .def("isColorSpaceUsed", &Config::isColorSpaceUsed, "name"_a, DOC(Config, isColorSpaceUsed)) .def("clearColorSpaces", &Config::clearColorSpaces, diff --git a/tests/cpu/ColorSpace_tests.cpp b/tests/cpu/ColorSpace_tests.cpp index 93a618b274..2e46fc58c8 100644 --- a/tests/cpu/ColorSpace_tests.cpp +++ b/tests/cpu/ColorSpace_tests.cpp @@ -933,6 +933,4 @@ inactive_colorspaces: [display_linear-trans, scene_linear-trans] testDisplayReferred("scene_linear-trans-alias", false, __LINE__); testDisplayReferred("scene_ref", false, __LINE__); } - - } diff --git a/tests/python/ColorSpaceTest.py b/tests/python/ColorSpaceTest.py index 483e338d2a..57fafa544b 100644 --- a/tests/python/ColorSpaceTest.py +++ b/tests/python/ColorSpaceTest.py @@ -407,3 +407,208 @@ def test_aliases(self): cs.clearAliases() aliases = cs.getAliases() self.assertEqual(len(aliases), 0) + + def test_is_colorspace_linear(self): + """ + Test isColorSpaceLinear. + """ + SIMPLE_PROFILE = """ocio_profile_version: 2 + +description: Test config for the isColorSpaceLinear method. + +environment: + {} +search_path: "non_existing_path" +roles: + aces_interchange: scene_linear-trans + cie_xyz_d65_interchange: display_linear-enc + color_timing: scene_linear-trans + compositing_log: scene_log-enc + default: display_data + scene_linear: scene_linear-trans + +displays: + generic display: + - ! {name: Raw, colorspace: scene_data} + +# Make a few of the color spaces inactive, this should not affect the result. +inactive_colorspaces: [display_linear-trans, scene_linear-trans] + +view_transforms: + - ! + name: view_transform + from_scene_reference: ! {} + +# Display-referred color spaces. + +display_colorspaces: + - ! + name: display_data + description: | + Data space. + Has a linear transform, which should never happen, but this will be ignored since + isdata is true. + isdata: true + encoding: data + from_display_reference: ! {matrix: [ 3.240969941905, -1.537383177570, -0.498610760293, 0, -0.969243636281, 1.875967501508, 0.041555057407, 0, 0.055630079697, -0.203976958889, 1.056971514243, 0, 0, 0, 0, 1 ]} + + - ! + name: display_linear-enc + description: | + Encoding set to display-linear. + Has a non-existent transform, but this should be ignored since the encoding takes precedence. + isdata: false + encoding: display-linear + from_display_reference: ! {src: does-not-exist.lut} + + - ! + name: display_wrong-linear-enc + description: | + Encoding set to scene-linear. This should never happen for a display space, but test it. + isdata: false + encoding: scene-linear + + - ! + name: display_video-enc + description: | + Encoding set to sdr-video. + Has a linear transform, but this should be ignored since the encoding takes precedence. + isdata: false + encoding: sdr-video + from_display_reference: ! {matrix: [ 3.240969941905, -1.537383177570, -0.498610760293, 0, -0.969243636281, 1.875967501508, 0.041555057407, 0, 0.055630079697, -0.203976958889, 1.056971514243, 0, 0, 0, 0, 1 ]} + + - ! + name: display_linear-trans + description: | + No encoding. Transform is linear. + isdata: false + from_display_reference: ! + children: + - ! {matrix: [ 3.240969941905, -1.537383177570, -0.498610760293, 0, -0.969243636281, 1.875967501508, 0.041555057407, 0, 0.055630079697, -0.203976958889, 1.056971514243, 0, 0, 0, 0, 1 ]} + - ! {slope: [0.1, 2, 3], style: noclamp} + + - ! + name: display_video-trans + description: | + No encoding. Transform is non-linear. + isdata: false + from_display_reference: ! {style: DISPLAY - CIE-XYZ-D65_to_sRGB} + +# Scene-referred color spaces. + +colorspaces: + - ! + name: scene_data + description: | + Data space. + Has a linear transform, which should never happen, but this will be ignored + since isdata is true. + isdata: true + encoding: data + from_scene_reference: ! {matrix: [ 3.240969941905, -1.537383177570, -0.498610760293, 0, -0.969243636281, 1.875967501508, 0.041555057407, 0, 0.055630079697, -0.203976958889, 1.056971514243, 0, 0, 0, 0, 1 ]} + + - ! + name: scene_linear-enc + description: | + Encoding set to scene-linear. + Has a non-linear transform, but this will be ignored since the encoding takes precedence. + isdata: false + encoding: scene-linear + from_scene_reference: ! {style: DISPLAY - CIE-XYZ-D65_to_sRGB} + + - ! + name: scene_wrong-linear-enc + description: | + Encoding set to display-linear. This should never happen for a scene space, but test it. + isdata: false + encoding: display-linear + + - ! + name: scene_log-enc + description: | + Encoding set to log. + Has a linear transform, but this will be ignored since the encoding takes precedence. + isdata: false + encoding: log + from_scene_reference: ! {matrix: [ 3.240969941905, -1.537383177570, -0.498610760293, 0, -0.969243636281, 1.875967501508, 0.041555057407, 0, 0.055630079697, -0.203976958889, 1.056971514243, 0, 0, 0, 0, 1 ]} + + - ! + name: scene_linear-trans + aliases: [scene_linear-trans-alias] + description: | + No encoding. Transform is linear. + isdata: false + to_scene_reference: ! + children: + - ! {style: UTILITY - ACES-AP0_to_CIE-XYZ-D65_BFD} + - ! {matrix: [ 3.240969941905, -1.537383177570, -0.498610760293, 0, -0.969243636281, 1.875967501508, 0.041555057407, 0, 0.055630079697, -0.203976958889, 1.056971514243, 0, 0, 0, 0, 1 ]} + - ! {matrix: [ 3.240969941905, -1.537383177570, -0.498610760293, 0, -0.969243636281, 1.875967501508, 0.041555057407, 0, 0.055630079697, -0.203976958889, 1.056971514243, 0, 0, 0, 0, 1 ]} + + - ! + name: scene_nonlin-trans + description: | + No encoding. Transform is non-linear because it clamps values outside [0,1]. + isdata: false + to_scene_reference: ! + children: + - ! {matrix: [ 3.240969941905, -1.537383177570, -0.498610760293, 0, -0.969243636281, 1.875967501508, 0.041555057407, 0, 0.055630079697, -0.203976958889, 1.056971514243, 0, 0, 0, 0, 1 ]} + - ! {min_in_value: 0., min_out_value: 0., max_in_value: 1., max_out_value: 1.} + + - ! + name: scene_ref + description: | + No encoding. Considered linear since it is equivalent to the reference space. + isdata: false +""" + # Create a config. + cfg = OCIO.Config.CreateFromStream(SIMPLE_PROFILE) + + def test_scene_referred(self, cfg, cs_name, expected_value): + cs = cfg.getColorSpace(cs_name) + is_linear_to_scene_reference = cfg.isColorSpaceLinear( + cs_name, + OCIO.REFERENCE_SPACE_SCENE + ) + self.assertEqual(is_linear_to_scene_reference, expected_value) + + def test_display_referred(self, cfg, cs_name, expected_value): + cs = cfg.getColorSpace(cs_name) + is_linear_to_display_reference = cfg.isColorSpaceLinear( + cs_name, + OCIO.REFERENCE_SPACE_DISPLAY + ) + self.assertEqual(is_linear_to_display_reference, expected_value) + + # Test the scene referred color spaces. + test_scene_referred(self, cfg, "display_data", False) + test_scene_referred(self, cfg, "display_linear-enc", False) + test_scene_referred(self, cfg, "display_wrong-linear-enc", False) + test_scene_referred(self, cfg, "display_video-enc", False) + test_scene_referred(self, cfg, "display_linear-trans", False) + test_scene_referred(self, cfg, "display_video-trans", False) + + test_scene_referred(self, cfg, "scene_data", False) + test_scene_referred(self, cfg, "scene_linear-enc", True) + test_scene_referred(self, cfg, "scene_wrong-linear-enc", False) + test_scene_referred(self, cfg, "scene_log-enc", False) + test_scene_referred(self, cfg, "scene_linear-trans", True) + test_scene_referred(self, cfg, "scene_nonlin-trans", False) + test_scene_referred(self, cfg, "scene_linear-trans-alias", True) + test_scene_referred(self, cfg, "scene_ref", True) + + # Test the display referred color spaces. + test_display_referred(self, cfg, "display_data", False) + test_display_referred(self, cfg, "display_linear-enc", True) + test_display_referred(self, cfg, "display_wrong-linear-enc", False) + test_display_referred(self, cfg, "display_video-enc", False) + test_display_referred(self, cfg, "display_linear-trans", True) + test_display_referred(self, cfg, "display_video-trans", False) + + test_display_referred(self, cfg, "scene_data", False) + test_display_referred(self, cfg, "scene_linear-enc", False) + test_display_referred(self, cfg, "scene_wrong-linear-enc", False) + test_display_referred(self, cfg, "scene_log-enc", False) + test_display_referred(self, cfg, "scene_linear-trans", False) + test_display_referred(self, cfg, "scene_nonlin-trans", False) + test_display_referred(self, cfg, "scene_linear-trans-alias", False) + test_display_referred(self, cfg, "scene_ref", False)