Skip to content

Commit 4dff29e

Browse files
remiamichdolan
andauthored
Baking crosstalk and NamedTransform support fix (#1693)
* Check for channel crosstalk on optimised processors when baking Signed-off-by: Rémi Achard <[email protected]> * Use lossless optimization Signed-off-by: Rémi Achard <[email protected]> * Handle NamedTransform used in Baker shaper space Signed-off-by: Rémi Achard <[email protected]> Signed-off-by: Rémi Achard <[email protected]> Co-authored-by: Michael Dolan <[email protected]>
1 parent c897bd3 commit 4dff29e

File tree

5 files changed

+187
-47
lines changed

5 files changed

+187
-47
lines changed

include/OpenColorIO/OpenColorIO.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2648,10 +2648,10 @@ class OCIOEXPORT Baker
26482648

26492649
const char * getShaperSpace() const;
26502650
/**
2651-
* Set an *optional* ColorSpace to shape the incoming values of the LUT.
2652-
* When baking 3DLUT, this will correspond to the 1D shaper used to
2653-
* normalise incoming values to the unit range. When baking 1D LUT, this
2654-
* will be used to determine the input range of the LUT.
2651+
* Set an *optional* ColorSpace or NamedTransform to shape the incoming
2652+
* values of the LUT. When baking 3DLUT, this will correspond to the 1D
2653+
* shaper used to normalise incoming values to the unit range. When baking
2654+
* 1D LUT, this will be used to determine the input range of the LUT.
26552655
*/
26562656
void setShaperSpace(const char * shaperSpace);
26572657

src/OpenColorIO/Baker.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -376,10 +376,8 @@ void Baker::bake(std::ostream & os) const
376376

377377
if(!shaperSpace.empty())
378378
{
379-
ConstProcessorRcPtr inputToShaper = getConfig()->getProcessor(
380-
inputSpace.c_str(), shaperSpace.c_str());
381-
ConstProcessorRcPtr shaperToInput = getConfig()->getProcessor(
382-
shaperSpace.c_str(), inputSpace.c_str());
379+
ConstCPUProcessorRcPtr inputToShaper = GetInputToShaperProcessor(*this);
380+
ConstCPUProcessorRcPtr shaperToInput = GetShaperToInputProcessor(*this);
383381

384382
if(inputToShaper->hasChannelCrosstalk() || shaperToInput->hasChannelCrosstalk())
385383
{

src/OpenColorIO/BakingUtils.cpp

Lines changed: 43 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -8,41 +8,46 @@ namespace OCIO_NAMESPACE
88

99
namespace
1010
{
11-
ConstCPUProcessorRcPtr GetSrcToTargetProcessor(const Baker & baker,
12-
const char * src)
11+
GroupTransformRcPtr GetInputToTargetTransform(const Baker & baker)
1312
{
14-
ConstProcessorRcPtr processor;
15-
13+
const std::string input = baker.getInputSpace();
1614
const std::string looks = baker.getLooks();
1715
const std::string display = baker.getDisplay();
1816
const std::string view = baker.getView();
1917

18+
GroupTransformRcPtr group = GroupTransform::Create();
19+
2020
if (!display.empty() && !view.empty())
2121
{
22-
DisplayViewTransformRcPtr transform = DisplayViewTransform::Create();
23-
transform->setSrc(src);
24-
transform->setDisplay(display.c_str());
25-
transform->setView(view.c_str());
26-
27-
LegacyViewingPipelineRcPtr vp = LegacyViewingPipeline::Create();
28-
vp->setDisplayViewTransform(transform);
29-
vp->setLooksOverrideEnabled(!looks.empty());
30-
vp->setLooksOverride(looks.c_str());
31-
32-
processor = vp->getProcessor(baker.getConfig());
22+
if (!looks.empty())
23+
{
24+
LookTransformRcPtr look = LookTransform::Create();
25+
look->setLooks(looks.c_str());
26+
look->setSrc(input.c_str());
27+
look->setDst(input.c_str());
28+
29+
group->appendTransform(look);
30+
}
31+
32+
DisplayViewTransformRcPtr disp = DisplayViewTransform::Create();
33+
disp->setSrc(input.c_str());
34+
disp->setDisplay(display.c_str());
35+
disp->setView(view.c_str());
36+
disp->setLooksBypass(!looks.empty());
37+
38+
group->appendTransform(disp);
3339
}
3440
else
3541
{
36-
LookTransformRcPtr transform = LookTransform::Create();
37-
transform->setLooks(!looks.empty() ? looks.c_str() : "");
38-
transform->setSrc(src);
39-
transform->setDst(baker.getTargetSpace());
40-
processor = baker.getConfig()->getProcessor(
41-
transform, TRANSFORM_DIR_FORWARD
42-
);
42+
LookTransformRcPtr look = LookTransform::Create();
43+
look->setLooks(!looks.empty() ? looks.c_str() : "");
44+
look->setSrc(input.c_str());
45+
look->setDst(baker.getTargetSpace());
46+
47+
group->appendTransform(look);
4348
}
4449

45-
return processor->getOptimizedCPUProcessor(OPTIMIZATION_LOSSLESS);
50+
return group;
4651
}
4752

4853
void GetSrcRange(const Baker & baker,
@@ -86,7 +91,10 @@ ConstCPUProcessorRcPtr GetInputToTargetProcessor(const Baker & baker)
8691
{
8792
if (baker.getInputSpace() && *baker.getInputSpace())
8893
{
89-
return GetSrcToTargetProcessor(baker, baker.getInputSpace());
94+
ConstProcessorRcPtr processor = baker.getConfig()->getProcessor(
95+
GetInputToTargetTransform(baker), TRANSFORM_DIR_FORWARD
96+
);
97+
return processor->getOptimizedCPUProcessor(OPTIMIZATION_LOSSLESS);
9098
}
9199

92100
throw Exception("Input space is empty.");
@@ -96,7 +104,17 @@ ConstCPUProcessorRcPtr GetShaperToTargetProcessor(const Baker & baker)
96104
{
97105
if (baker.getShaperSpace() && *baker.getShaperSpace())
98106
{
99-
return GetSrcToTargetProcessor(baker, baker.getShaperSpace());
107+
ColorSpaceTransformRcPtr csc = ColorSpaceTransform::Create();
108+
csc->setSrc(baker.getShaperSpace());
109+
csc->setDst(baker.getInputSpace());
110+
111+
GroupTransformRcPtr group = GetInputToTargetTransform(baker);
112+
group->prependTransform(csc);
113+
114+
ConstProcessorRcPtr processor = baker.getConfig()->getProcessor(
115+
group, TRANSFORM_DIR_FORWARD
116+
);
117+
return processor->getOptimizedCPUProcessor(OPTIMIZATION_LOSSLESS);
100118
}
101119

102120
throw Exception("Shaper space is empty.");

src/apps/ociobakelut/main.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,11 @@ int main (int argc, const char* argv[])
312312
return 1;
313313
}
314314

315+
if(!shaperspace.empty())
316+
{
317+
std::cerr << "WARNING: shaperspace is ignored when generating ICC profiles.\n";
318+
}
319+
315320
if(cubesize<2) cubesize = 32; // default
316321

317322
OCIO::ConstProcessorRcPtr processor;

tests/cpu/Baker_tests.cpp

Lines changed: 133 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -36,33 +36,52 @@ void CompareFloats(const std::string& floats1, const std::string& floats2)
3636
OCIO_ADD_TEST(Baker, bake_3dlut)
3737
{
3838
constexpr const char * myProfile =
39-
"ocio_profile_version: 1\n"
39+
"ocio_profile_version: 2\n"
4040
"\n"
41-
"strictparsing: false\n"
41+
"file_rules:\n"
42+
" - !<Rule> {name: Default, colorspace: lnh}\n"
4243
"\n"
4344
"displays:\n"
4445
" display1:\n"
45-
" - !<View> {name: view1, colorspace: test}\n"
46+
" - !<View> {name: view1, colorspace: gamma22}\n"
47+
" - !<View> {name: view2, looks: satlook, colorspace: gamma22}\n"
4648
"\n"
4749
"looks:\n"
4850
" - !<Look>\n"
49-
" name : mylook\n"
51+
" name : contrastlook\n"
5052
" process_space : lnh\n"
5153
" transform : !<ExponentTransform> {value: [2.2, 2.2, 2.2, 1]}\n"
54+
" - !<Look>\n"
55+
" name : satlook\n"
56+
" process_space : lnh\n"
57+
" transform : !<CDLTransform> {sat: 2}\n"
5258
"\n"
53-
"colorspaces :\n"
59+
"colorspaces:\n"
5460
" - !<ColorSpace>\n"
5561
" name : lnh\n"
5662
" bitdepth : 16f\n"
5763
" isdata : false\n"
5864
" allocation : lg2\n"
5965
"\n"
6066
" - !<ColorSpace>\n"
61-
" name : test\n"
67+
" name : gamma22\n"
6268
" bitdepth : 8ui\n"
6369
" isdata : false\n"
6470
" allocation : uniform\n"
65-
" to_reference : !<ExponentTransform> {value: [2.2, 2.2, 2.2, 1]}\n";
71+
" to_reference : !<ExponentTransform> {value: [2.2, 2.2, 2.2, 1]}\n"
72+
"\n"
73+
"named_transforms:\n"
74+
"- !<NamedTransform>\n"
75+
" name: logcnt\n"
76+
" transform: !<LogCameraTransform>\n"
77+
" log_side_slope: 0.247189638318671\n"
78+
" log_side_offset: 0.385536998692443\n"
79+
" lin_side_slope: 5.55555555555556\n"
80+
" lin_side_offset: 0.0522722750251688\n"
81+
" lin_side_break: 0.0105909904954696\n"
82+
" base: 10\n"
83+
" direction: inverse\n"
84+
"\n";
6685

6786
constexpr const char * expectedLut =
6887
"CSPLUTV100\n"
@@ -96,7 +115,9 @@ OCIO_ADD_TEST(Baker, bake_3dlut)
96115
std::istringstream is(myProfile);
97116
OCIO::ConstConfigRcPtr config;
98117
OCIO_CHECK_NO_THROW(config = OCIO::Config::CreateFromStream(is));
118+
OCIO_CHECK_NO_THROW(config->validate());
99119
OCIO_REQUIRE_EQUAL(config->getNumColorSpaces(), 2);
120+
OCIO_REQUIRE_EQUAL(config->getNumNamedTransforms(), 1);
100121

101122
{
102123
OCIO::BakerRcPtr bake = OCIO::Baker::Create();
@@ -117,8 +138,8 @@ OCIO_ADD_TEST(Baker, bake_3dlut)
117138
bake->setLooks("foo, +bar");
118139
OCIO_CHECK_EQUAL("foo, +bar", std::string(bake->getLooks()));
119140
bake->setLooks("");
120-
bake->setTargetSpace("test");
121-
OCIO_CHECK_EQUAL("test", std::string(bake->getTargetSpace()));
141+
bake->setTargetSpace("gamma22");
142+
OCIO_CHECK_EQUAL("gamma22", std::string(bake->getTargetSpace()));
122143
bake->setShaperSize(4);
123144
OCIO_CHECK_EQUAL(4, bake->getShaperSize());
124145
bake->setCubeSize(2);
@@ -153,7 +174,7 @@ OCIO_ADD_TEST(Baker, bake_3dlut)
153174
bake->setConfig(config);
154175
bake->setFormat("resolve_cube");
155176
bake->setInputSpace("lnh");
156-
bake->setLooks("mylook");
177+
bake->setLooks("contrastlook");
157178
bake->setDisplayView("display1", "view1");
158179
bake->setCubeSize(10);
159180
std::ostringstream os;
@@ -171,14 +192,54 @@ R"(LUT_1D_SIZE 10
171192
0.777778 0.777778 0.777778
172193
0.888889 0.888889 0.888889
173194
1.000000 1.000000 1.000000
195+
)"};
196+
197+
OCIO_CHECK_EQUAL(expectedCube.size(), os.str().size());
198+
OCIO_CHECK_EQUAL(expectedCube, os.str());
199+
}
200+
201+
{
202+
OCIO::BakerRcPtr bake = OCIO::Baker::Create();
203+
bake->setConfig(config);
204+
bake->setFormat("resolve_cube");
205+
bake->setInputSpace("lnh");
206+
bake->setShaperSpace("logcnt");
207+
bake->setDisplayView("display1", "view2");
208+
bake->setShaperSize(10);
209+
bake->setCubeSize(2);
210+
std::ostringstream os;
211+
OCIO_CHECK_NO_THROW(bake->bake(os));
212+
213+
const std::string expectedCube{
214+
R"(LUT_1D_SIZE 10
215+
LUT_1D_INPUT_RANGE -0.017290 55.080036
216+
LUT_3D_SIZE 2
217+
0.000000 0.000000 0.000000
218+
0.763998 0.763998 0.763998
219+
0.838479 0.838479 0.838479
220+
0.882030 0.882030 0.882030
221+
0.912925 0.912925 0.912925
222+
0.936887 0.936887 0.936887
223+
0.956464 0.956464 0.956464
224+
0.973016 0.973016 0.973016
225+
0.987354 0.987354 0.987354
226+
1.000000 1.000000 1.000000
227+
0.000000 0.000000 0.000000
228+
8.054426 0.000000 0.000000
229+
0.000000 6.931791 0.000000
230+
6.384501 6.384501 0.000000
231+
0.000000 0.000000 8.336130
232+
7.904850 0.000000 7.904850
233+
0.000000 6.751890 6.751890
234+
6.185304 6.185304 6.185304
174235
)"};
175236

176237
OCIO_CHECK_EQUAL(expectedCube.size(), os.str().size());
177238
OCIO_CHECK_EQUAL(expectedCube, os.str());
178239
}
179240
}
180241

181-
OCIO_ADD_TEST(Baker, baking_config)
242+
OCIO_ADD_TEST(Baker, baking_validation)
182243
{
183244
OCIO::BakerRcPtr bake;
184245
std::ostringstream os;
@@ -232,10 +293,18 @@ OCIO_ADD_TEST(Baker, baking_config)
232293
to_reference: !<LogTransform> {}
233294
234295
- !<ColorSpace>
235-
name : Crosstalk
296+
name : Saturation
236297
isdata : false
237298
to_reference: !<CDLTransform> {sat: 0.5}
238299
300+
- !<ColorSpace>
301+
name : Log2sRGB
302+
isdata : false
303+
to_reference: !<GroupTransform>
304+
children:
305+
- !<LogTransform> {base: 2, direction: inverse}
306+
- !<MatrixTransform> {matrix: [3.2409, -1.5373, -0.4986, 0, -0.9692, 1.8759, 0.0415, 0, 0.0556, -0.2039, 1.0569, 0, 0, 0, 0, 1 ], direction: inverse}
307+
239308
- !<ColorSpace>
240309
name : sRGB
241310
isdata : false
@@ -249,6 +318,12 @@ OCIO_ADD_TEST(Baker, baking_config)
249318
isdata : false
250319
from_reference : !<ExponentTransform> {value: [2.2, 2.2, 2.2, 1], direction: inverse}
251320
321+
named_transforms:
322+
323+
- !<NamedTransform>
324+
name: Log2NT
325+
transform: !<LogTransform> {base: 2}
326+
252327
inactive_colorspaces: [RawInactive]
253328
)";
254329

@@ -450,12 +525,56 @@ OCIO_ADD_TEST(Baker, baking_config)
450525
bake->setConfig(config);
451526
bake->setInputSpace("Raw");
452527
bake->setTargetSpace("sRGB");
453-
bake->setShaperSpace("Crosstalk");
528+
bake->setShaperSpace("Saturation");
454529
bake->setFormat("cinespace");
455530

456531
os.str("");
457532
OCIO_CHECK_THROW_WHAT(bake->bake(os), OCIO::Exception,
458-
"The specified shaper space, 'Crosstalk' has channel crosstalk, which "
533+
"The specified shaper space, 'Saturation' has channel crosstalk, which "
459534
"is not appropriate for shapers. Please select an alternate shaper "
460535
"space or omit this option.");
536+
537+
// Using shaper space without Crosstalk (after optimization).
538+
bake = OCIO::Baker::Create();
539+
bake->setConfig(config);
540+
bake->setInputSpace("sRGB");
541+
bake->setTargetSpace("Raw");
542+
bake->setShaperSpace("Log2sRGB");
543+
bake->setFormat("cinespace");
544+
545+
os.str("");
546+
OCIO_CHECK_NO_THROW(bake->bake(os));
547+
548+
// Using NamedTransform as shaper space.
549+
bake = OCIO::Baker::Create();
550+
bake->setConfig(config);
551+
bake->setInputSpace("sRGB");
552+
bake->setTargetSpace("Raw");
553+
bake->setShaperSpace("Log2NT");
554+
bake->setFormat("cinespace");
555+
556+
os.str("");
557+
OCIO_CHECK_NO_THROW(bake->bake(os));
558+
559+
// Using NamedTransform as input space is not supported.
560+
bake = OCIO::Baker::Create();
561+
bake->setConfig(config);
562+
bake->setInputSpace("Log2NT");
563+
bake->setTargetSpace("sRGB");
564+
bake->setFormat("cinespace");
565+
566+
os.str("");
567+
OCIO_CHECK_THROW_WHAT(bake->bake(os), OCIO::Exception,
568+
"Could not find input colorspace 'Log2NT'.");
569+
570+
// Using NamedTransform as target space is not supported.
571+
bake = OCIO::Baker::Create();
572+
bake->setConfig(config);
573+
bake->setInputSpace("sRGB");
574+
bake->setTargetSpace("Log2NT");
575+
bake->setFormat("cinespace");
576+
577+
os.str("");
578+
OCIO_CHECK_THROW_WHAT(bake->bake(os), OCIO::Exception,
579+
"Could not find target colorspace 'Log2NT'.");
461580
}

0 commit comments

Comments
 (0)