Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/OpenColorIO/Config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5234,6 +5234,8 @@ void Config::Impl::checkVersionConsistency(ConstTransformRcPtr & transform) cons
if (m_majorVersion == 2 && m_minorVersion < 4
&& ( 0 == Platform::Strcasecmp(blt->getStyle(), "APPLE_LOG_to_ACES2065-1")
|| 0 == Platform::Strcasecmp(blt->getStyle(), "CURVE - APPLE_LOG_to_LINEAR")
|| 0 == Platform::Strcasecmp(blt->getStyle(), "DISPLAY - CIE-XYZ-D65_to_DCDM-D65")
|| 0 == Platform::Strcasecmp(blt->getStyle(), "DISPLAY - CIE-XYZ-D65_to_ST2084-DCDM-D65")
|| 0 == Platform::Strcasecmp(blt->getStyle(), "ACES-OUTPUT - ACES2065-1_to_CIE-XYZ-D65 - SDR-100nit-REC709_2.0")
|| 0 == Platform::Strcasecmp(blt->getStyle(), "ACES-OUTPUT - ACES2065-1_to_CIE-XYZ-D65 - SDR-100nit-P3-D65_2.0")
|| 0 == Platform::Strcasecmp(blt->getStyle(), "ACES-OUTPUT - ACES2065-1_to_CIE-XYZ-D65 - HDR-108nit-P3-D65_2.0")
Expand Down
29 changes: 16 additions & 13 deletions src/OpenColorIO/ops/fixedfunction/FixedFunctionOpCPU.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,7 @@ class Renderer_REC2100_Surround : public OpCPU

protected:
float m_gamma;
float m_minLum;
};

class Renderer_RGB_TO_HSV : public OpCPU
Expand Down Expand Up @@ -1171,7 +1172,11 @@ Renderer_REC2100_Surround::Renderer_REC2100_Surround(ConstFixedFunctionOpDataRcP
: OpCPU()
{
const auto fwd = FixedFunctionOpData::REC2100_SURROUND_FWD == data->getStyle();
const float gamma = fwd ? (float)data->getParams()[0] : (float)(1. / data->getParams()[0]);
float gamma = (float)data->getParams()[0];

m_minLum = fwd ? 1e-4f : powf(1e-4f, gamma);

gamma = fwd ? gamma : 1.f / gamma;

m_gamma = gamma - 1.f; // compute Y^gamma / Y
}
Expand All @@ -1187,22 +1192,20 @@ void Renderer_REC2100_Surround::apply(const void * inImg, void * outImg, long nu
const float grn = in[1];
const float blu = in[2];

// Calculate luminance assuming input is Rec.2100 RGB.
float Y = 0.2627f * red + 0.6780f * grn + 0.0593f * blu;

// Mirror the function around the origin.
Y = std::abs(Y);

// Since the slope may approach infinity as Y approaches 0, limit the min value
// to avoid gaining up the RGB values (which may not be as close to 0).
//
// This threshold needs to be bigger than 1e-10 (used above) to prevent extreme
// gain in dark colors, yet smaller than 1e-2 to prevent distorting the shape of
// the HLG EOTF curve. Max gain = 1e-4 ** (0.78-1) = 7.6 for HLG min gamma of 0.78.
//
// TODO: Should have forward & reverse versions of this so the threshold can be
// adjusted correctly for the reverse direction.
constexpr float minLum = 1e-4f;
Y = std::max(m_minLum, Y);

// Calculate luminance assuming input is Rec.2100 RGB.
// TODO: Add another parameter to allow using other primaries.
const float Y = std::max( minLum, ( 0.2627f * red +
0.6780f * grn +
0.0593f * blu ) );

// TODO: Currently our fast approx. requires SSE registers.
// Either make this whole routine SSE or make fast scalar pow.
const float Ypow_over_Y = powf(Y, m_gamma);

out[0] = red * Ypow_over_Y;
Expand Down
25 changes: 18 additions & 7 deletions src/OpenColorIO/ops/fixedfunction/FixedFunctionOpGPU.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1663,15 +1663,24 @@ void Add_Surround_10_Fwd_Shader(GpuShaderCreatorRcPtr & shaderCreator, GpuShader
ss.newLine() << pxl << ".rgb = " << pxl << ".rgb * Ypow_over_Y;";
}

void Add_Surround_Shader(GpuShaderCreatorRcPtr & shaderCreator, GpuShaderText & ss, float gamma)
void Add_Rec2100_Surround_Shader(GpuShaderCreatorRcPtr & shaderCreator, GpuShaderText & ss,
float gamma, bool isForward)
{
const std::string pxl(shaderCreator->getPixelName());

// TODO: -- add vector inner product to GPUShaderUtils
float minLum = 1e-4f;
if (!isForward)
{
minLum = powf(minLum, gamma);
gamma = 1.f / gamma;
}

ss.newLine() << ss.floatDecl("Y")
<< " = max( 1e-4, 0.2627 * " << pxl << ".rgb.r + "
<< "0.6780 * " << pxl << ".rgb.g + "
<< "0.0593 * " << pxl << ".rgb.b );";
<< " = 0.2627 * " << pxl << ".rgb.r + "
<< "0.6780 * " << pxl << ".rgb.g + "
<< "0.0593 * " << pxl << ".rgb.b;";

ss.newLine() << "Y = max( " << minLum << ", abs(Y) );";

ss.newLine() << ss.floatDecl("Ypow_over_Y") << " = pow( Y, " << (gamma - 1.f) << ");";

Expand Down Expand Up @@ -1965,12 +1974,14 @@ void GetFixedFunctionGPUShaderProgram(GpuShaderCreatorRcPtr & shaderCreator,
}
case FixedFunctionOpData::REC2100_SURROUND_FWD:
{
Add_Surround_Shader(shaderCreator, ss, (float) func->getParams()[0]);
Add_Rec2100_Surround_Shader(shaderCreator, ss,
(float) func->getParams()[0], true);
break;
}
case FixedFunctionOpData::REC2100_SURROUND_INV:
{
Add_Surround_Shader(shaderCreator, ss, (float)(1. / func->getParams()[0]));
Add_Rec2100_Surround_Shader(shaderCreator, ss,
(float) func->getParams()[0], false);
break;
}
case FixedFunctionOpData::RGB_TO_HSV:
Expand Down
30 changes: 30 additions & 0 deletions src/OpenColorIO/transforms/builtins/Displays.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,25 @@ void RegisterAll(BuiltinTransformRegistryImpl & registry) noexcept
CIE_XYZ_D65_to_P3_D60_BFD_Functor);
}

{
auto CIE_XYZ_D65_to_DCDM_D65_Functor = [](OpRcPtrVec & ops)
{
const double scale = 48.0 / 52.37;
const double scale4[4] = { scale, scale, scale, 1. };
CreateScaleOp(ops, scale4, TRANSFORM_DIR_FORWARD);

const GammaOpData::Params rgbParams = { 2.6 };
const GammaOpData::Params alphaParams = { 1.0 };
auto gammaData = std::make_shared<GammaOpData>(GammaOpData::BASIC_REV,
rgbParams, rgbParams, rgbParams, alphaParams);
CreateGammaOp(ops, gammaData, TRANSFORM_DIR_FORWARD);
};

registry.addBuiltin("DISPLAY - CIE-XYZ-D65_to_DCDM-D65",
"Convert CIE XYZ (D65 white) to Gamma 2.6 (D65 white in XYZ-E encoding)",
CIE_XYZ_D65_to_DCDM_D65_Functor);
}

{
auto CIE_XYZ_D65_to_DisplayP3_Functor = [](OpRcPtrVec & ops)
{
Expand Down Expand Up @@ -285,6 +304,17 @@ void RegisterAll(BuiltinTransformRegistryImpl & registry) noexcept
CIE_XYZ_D65_to_ST2084_P3_D65_Functor);
}

{
auto CIE_XYZ_D65_to_ST2084_DCDM_D65_Functor = [](OpRcPtrVec & ops)
{
ST_2084::GenerateLinearToPQOps(ops);
};

registry.addBuiltin("DISPLAY - CIE-XYZ-D65_to_ST2084-DCDM-D65",
"Convert CIE XYZ (D65 white) to ST-2084 (PQ) (D65 white in XYZ-E encoding)",
CIE_XYZ_D65_to_ST2084_DCDM_D65_Functor);
}

{
auto CIE_XYZ_D65_to_REC2100_HLG_1000nit_Functor = [](OpRcPtrVec & ops)
{
Expand Down
97 changes: 68 additions & 29 deletions tests/cpu/ops/fixedfunction/FixedFunctionOpCPU_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -927,44 +927,83 @@ OCIO_ADD_TEST(FixedFunctionOpCPU, aces_gamut_map_20)

OCIO_ADD_TEST(FixedFunctionOpCPU, rec2100_surround)
{
const unsigned num_samples = 4;
const unsigned num_samples = 5;

float input_32f[num_samples*4] = {
0.11f, 0.02f, 0.04f, 0.5f,
0.71f, 0.51f, 0.81f, 1.0f,
0.43f, 0.82f, 0.71f, 0.0f,
-1.0f, -0.001f, 1.2f, 0.0f
8.4e-5f, 2.4e-5f, 1.4e-4f, 0.1f,
0.11f, 0.02f, 0.04f, 0.5f,
0.71f, 0.51f, 0.81f, 1.0f,
0.43f, 0.82f, 0.71f, 0.0f,
-1.00f, -0.001f, 1.2f, 0.0f
};
{
OCIO::FixedFunctionOpData::Params params = { 0.78 };

float input2_32f[num_samples * 4];
memcpy(&input2_32f[0], &input_32f[0], sizeof(float)*num_samples * 4);
float output_32f[num_samples * 4];
memcpy(&output_32f[0], &input_32f[0], sizeof(float)*num_samples * 4);

const float expected_32f[num_samples*4] = {
0.21779590f, 0.03959925f, 0.07919850f, 0.5f,
0.80029451f, 0.57485944f, 0.91301214f, 1.0f,
0.46350446f, 0.88389223f, 0.76532131f, 0.0f,
-7.58577776f, -0.00758577f, 9.10293388f, 0.0f,
};
const float expected_32f[num_samples*4] = {
0.000637205163f, 0.000182058618f, 0.001062008605f, 0.1f,
0.21779590f, 0.03959925f, 0.07919850f, 0.5f,
0.80029451f, 0.57485944f, 0.91301214f, 1.0f,
0.46350446f, 0.88389223f, 0.76532131f, 0.0f,
-1.43735918f, -0.00143735918f, 1.72483102f, 0.0f
};

OCIO::FixedFunctionOpData::Params params = { 0.78 };
OCIO::ConstFixedFunctionOpDataRcPtr funcData
= std::make_shared<OCIO::FixedFunctionOpData>(OCIO::FixedFunctionOpData::REC2100_SURROUND_FWD,
params);
// Forward transform -- input to expected.
OCIO::ConstFixedFunctionOpDataRcPtr funcData
= std::make_shared<OCIO::FixedFunctionOpData>(OCIO::FixedFunctionOpData::REC2100_SURROUND_FWD,
params);

ApplyFixedFunction(&input_32f[0], &expected_32f[0], num_samples,
funcData,
1e-7f,
__LINE__);
ApplyFixedFunction(&output_32f[0], &expected_32f[0], num_samples,
funcData,
4e-7f,
__LINE__);

OCIO::FixedFunctionOpData::Params params_inv = { 1 / 0.78 };
OCIO::ConstFixedFunctionOpDataRcPtr funcData2
= std::make_shared<OCIO::FixedFunctionOpData>(OCIO::FixedFunctionOpData::REC2100_SURROUND_INV,
params_inv);
// Inverse transform -- output back to original.
OCIO::ConstFixedFunctionOpDataRcPtr funcDataInv
= std::make_shared<OCIO::FixedFunctionOpData>(OCIO::FixedFunctionOpData::REC2100_SURROUND_INV,
params);

ApplyFixedFunction(&input2_32f[0], &expected_32f[0], num_samples,
funcData2,
1e-7f,
__LINE__);
ApplyFixedFunction(&output_32f[0], &input_32f[0], num_samples,
funcDataInv,
3e-7f,
__LINE__);
}
{
OCIO::FixedFunctionOpData::Params params = { 1.2 };

float output_32f[num_samples * 4];
memcpy(&output_32f[0], &input_32f[0], sizeof(float)*num_samples * 4);

const float expected_32f[num_samples*4] = {
1.331310281667e-05f, 3.803743661907e-06f, 2.218850469446e-05f, 0.1f,
0.059115925805f, 0.010748350146f, 0.021496700293f, 0.5f,
0.636785774786f, 0.457409500198f, 0.726473912080f, 1.0f,
0.401647721515f, 0.765932864285f, 0.663185772735f, 0.0f,
-7.190495367684e-01f, -7.190495367684e-04f, 8.628594441221e-01f, 0.0f
};

// Forward transform -- input to expected.
OCIO::ConstFixedFunctionOpDataRcPtr funcData
= std::make_shared<OCIO::FixedFunctionOpData>(OCIO::FixedFunctionOpData::REC2100_SURROUND_FWD,
params);

ApplyFixedFunction(&output_32f[0], &expected_32f[0], num_samples,
funcData,
2e-7f,
__LINE__);

// Inverse transform -- output back to original.
OCIO::ConstFixedFunctionOpDataRcPtr funcDataInv
= std::make_shared<OCIO::FixedFunctionOpData>(OCIO::FixedFunctionOpData::REC2100_SURROUND_INV,
params);

ApplyFixedFunction(&output_32f[0], &input_32f[0], num_samples,
funcDataInv,
2e-7f,
__LINE__);
}
}

OCIO_ADD_TEST(FixedFunctionOpCPU, RGB_TO_HSV)
Expand Down
8 changes: 8 additions & 0 deletions tests/cpu/transforms/BuiltinTransform_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -538,6 +538,8 @@ AllValues UnitTestValues
{ { 0.5f, 0.4f, 0.3f }, { 0.896805202281f, 0.627254277624f, 0.608228132100f } } },
{ "DISPLAY - CIE-XYZ-D65_to_G2.6-P3-D60-BFD",
{ { 0.5f, 0.4f, 0.3f }, { 0.892433142142f, 0.627011653770f, 0.608093643982f } } },
{ "DISPLAY - CIE-XYZ-D65_to_DCDM-D65",
{ { 0.5f, 0.4f, 0.3f }, { 0.740738422348f, 0.679816639411f, 0.608609083713f } } },
{ "DISPLAY - CIE-XYZ-D65_to_DisplayP3",
{ { 0.5f, 0.4f, 0.3f }, { 0.882580907776f, 0.581526360743f, 0.5606367050000f } } },

Expand All @@ -549,6 +551,8 @@ AllValues UnitTestValues
{ { 0.5f, 0.4f, 0.3f }, { 0.464008302136f, 0.398157119110f, 0.384828370950f } } },
{ "DISPLAY - CIE-XYZ-D65_to_ST2084-P3-D65",
{ { 0.5f, 0.4f, 0.3f }, { 0.479939091128f, 0.392091860770f, 0.384886051856f } } },
{ "DISPLAY - CIE-XYZ-D65_to_ST2084-DCDM-D65",
{ { 0.5f, 0.4f, 0.3f }, { 0.440281573420f, 0.419284117712f, 0.392876186489f } } },
{ "DISPLAY - CIE-XYZ-D65_to_REC.2100-HLG-1000nit",
{ { 0.5f, 0.4f, 0.3f }, { 0.5649694f, 0.4038837f, 0.3751478f } } }
};
Expand Down Expand Up @@ -589,4 +593,8 @@ OCIO_ADD_TEST(Builtins, validate)
ValidateBuiltinTransform(name, values.first, values.second, __LINE__);
}
}

// The above checks if a test values is missing, but not if there are test values
// that don't have an associated built-in.
OCIO_CHECK_EQUAL(UnitTestValues.size(), reg->getNumBuiltins());
}