Skip to content

Commit ebebc25

Browse files
LegacyViewingPipeline and ColorSpaceMenuHelper (#1252)
Signed-off-by: Bernard Lefebvre <bernard.lefebvre@autodesk.com>
1 parent cfc2068 commit ebebc25

File tree

4 files changed

+250
-131
lines changed

4 files changed

+250
-131
lines changed

src/OpenColorIO/apphelpers/CategoryHelpers.cpp

Lines changed: 121 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -345,158 +345,165 @@ Infos FindColorSpaceInfos(ConstConfigRcPtr config,
345345

346346
LogMessageHelper log;
347347

348-
ColorSpaceVec appCS;
349-
NamedTransformVec appNT;
350-
ColorSpaceVec appCSNoEncodings;
351-
NamedTransformVec appNTNoEncodings;
352-
bool appNoEncodingsComputed{ false };
348+
// V1 does not have categories and encodings, skip them.
349+
if (config->getMajorVersion() >= 2)
350+
{
351+
ColorSpaceVec appCS;
352+
NamedTransformVec appNT;
353+
ColorSpaceVec appCSNoEncodings;
354+
NamedTransformVec appNTNoEncodings;
355+
bool appNoEncodingsComputed{ false };
353356

354-
size_t appSize{ 0 };
357+
size_t appSize{ 0 };
355358

356-
bool encsIgnored = encodings.empty();
359+
bool encsIgnored = encodings.empty();
357360

358-
if (!appCategories.empty())
359-
{
360-
// 3a) Use categories and encodings, fallback to only categories, fallback to only
361-
// encodings.
361+
if (!appCategories.empty())
362+
{
363+
// 3a) Use categories and encodings, fallback to only categories, fallback to only
364+
// encodings.
362365

363-
log.m_appCats = SHOULD_BE_USED;
366+
log.m_appCats = SHOULD_BE_USED;
364367

365-
// Use categories and encodings.
368+
// Use categories and encodings.
366369

367-
if (!encsIgnored)
368-
{
369-
appCS = GetColorSpaces(config, includeColorSpaces, colorSpaceType,
370-
appCategories, encodings);
371-
appNT = GetNamedTransforms(config, includeNamedTransforms, appCategories, encodings);
372-
appSize = appCS.size() + appNT.size();
373-
}
370+
if (!encsIgnored)
371+
{
372+
appCS = GetColorSpaces(config, includeColorSpaces, colorSpaceType,
373+
appCategories, encodings);
374+
appNT = GetNamedTransforms(config, includeNamedTransforms, appCategories,
375+
encodings);
376+
appSize = appCS.size() + appNT.size();
377+
}
374378

375-
// Do not use encodings if empty or drop them if no result is found with them.
376-
if (appSize == 0)
377-
{
378-
encsIgnored = true;
379-
log.m_ignoreEncodings = !encodings.empty();
380-
appCS = GetColorSpaces(config, includeColorSpaces, colorSpaceType, appCategories);
381-
appNT = GetNamedTransforms(config, includeNamedTransforms, appCategories);
382-
appSize = appCS.size() + appNT.size();
379+
// Do not use encodings if empty or drop them if no result is found with them.
380+
if (appSize == 0)
381+
{
382+
encsIgnored = true;
383+
log.m_ignoreEncodings = !encodings.empty();
384+
appCS = GetColorSpaces(config, includeColorSpaces, colorSpaceType, appCategories);
385+
appNT = GetNamedTransforms(config, includeNamedTransforms, appCategories);
386+
appSize = appCS.size() + appNT.size();
387+
388+
// Keep these results in case we need them later.
389+
appNoEncodingsComputed = true;
390+
appCSNoEncodings = appCS;
391+
appNTNoEncodings = appNT;
392+
}
383393

384-
// Keep these results in case we need them later.
385-
appNoEncodingsComputed = true;
386-
appCSNoEncodings = appCS;
387-
appNTNoEncodings = appNT;
388-
}
394+
// Drop app categories and use encoding if no results.
395+
if (appSize == 0 && !encodings.empty())
396+
{
397+
encsIgnored = false;
398+
log.m_ignoreEncodings = false;
399+
log.m_appCats = NONE_FOUND;
400+
appCS = GetColorSpacesFromEncodings(config, includeColorSpaces, colorSpaceType,
401+
encodings);
402+
appNT = GetNamedTransformsFromEncodings(config, includeNamedTransforms, encodings);
403+
appSize = appCS.size() + appNT.size();
404+
}
389405

390-
// Drop app categories and use encoding if no results.
391-
if (appSize == 0 && !encodings.empty())
406+
if (appSize == 0)
407+
{
408+
log.m_appCats = NONE_FOUND;
409+
}
410+
}
411+
else if (!encsIgnored)
392412
{
393-
encsIgnored = false;
394-
log.m_ignoreEncodings = false;
395-
log.m_appCats = NONE_FOUND;
396413
appCS = GetColorSpacesFromEncodings(config, includeColorSpaces, colorSpaceType,
397414
encodings);
398415
appNT = GetNamedTransformsFromEncodings(config, includeNamedTransforms, encodings);
399416
appSize = appCS.size() + appNT.size();
400417
}
401418

402-
if (appSize == 0)
403-
{
404-
log.m_appCats = NONE_FOUND;
405-
}
406-
}
407-
else if (!encsIgnored)
408-
{
409-
appCS = GetColorSpacesFromEncodings(config, includeColorSpaces, colorSpaceType,
410-
encodings);
411-
appNT = GetNamedTransformsFromEncodings(config, includeNamedTransforms, encodings);
412-
appSize = appCS.size() + appNT.size();
413-
}
414-
415-
ColorSpaceVec userCS;
416-
NamedTransformVec userNT;
417-
size_t userSize{ 0 };
418-
419-
if (!userCategories.empty())
420-
{
421-
// 3b) Items using user categories.
419+
ColorSpaceVec userCS;
420+
NamedTransformVec userNT;
421+
size_t userSize{ 0 };
422422

423-
userCS = GetColorSpaces(config, includeColorSpaces, colorSpaceType, userCategories);
424-
userNT = GetNamedTransforms(config, includeNamedTransforms, userCategories);
425-
userSize = userCS.size() + userNT.size();
426-
if (userSize == 0)
423+
if (!userCategories.empty())
427424
{
428-
log.m_userCats = NONE_FOUND;
429-
}
430-
}
431-
432-
if (appSize != 0 && userSize != 0)
433-
{
434-
// 3c) and 3d) Use intersection of app and user categories.
425+
// 3b) Items using user categories.
435426

436-
ColorSpaceVec * appCSTest = &appCS;
437-
NamedTransformVec * appNTTest = &appNT;
438-
const auto encsIgnoredBack = encsIgnored;
439-
const auto ignoreEncodingsBack = log.m_ignoreEncodings;
427+
userCS = GetColorSpaces(config, includeColorSpaces, colorSpaceType, userCategories);
428+
userNT = GetNamedTransforms(config, includeNamedTransforms, userCategories);
429+
userSize = userCS.size() + userNT.size();
430+
if (userSize == 0)
431+
{
432+
log.m_userCats = NONE_FOUND;
433+
}
434+
}
440435

441-
// Allow to run twice, with and without encodings.
442-
while (1)
436+
if (appSize != 0 && userSize != 0)
443437
{
444-
const auto css = Intersection(*appCSTest, userCS);
445-
const auto nts = Intersection(*appNTTest, userNT);
438+
// 3c) and 3d) Use intersection of app and user categories.
446439

447-
if (!css.empty() || !nts.empty())
448-
{
449-
// 3c) or 3d) Intersection is not empty.
450-
return GetInfos(config, css, nts);
451-
}
440+
ColorSpaceVec * appCSTest = &appCS;
441+
NamedTransformVec * appNTTest = &appNT;
442+
const auto encsIgnoredBack = encsIgnored;
443+
const auto ignoreEncodingsBack = log.m_ignoreEncodings;
452444

453-
if (!encsIgnored && !encodings.empty())
445+
// Allow to run twice, with and without encodings.
446+
while (1)
454447
{
455-
// Intersection is empty, but encodings can be dropped if they were not dropped
456-
// already.
457-
encsIgnored = true;
458-
log.m_ignoreEncodings = true;
459-
if (!appNoEncodingsComputed)
448+
const auto css = Intersection(*appCSTest, userCS);
449+
const auto nts = Intersection(*appNTTest, userNT);
450+
451+
if (!css.empty() || !nts.empty())
452+
{
453+
// 3c) or 3d) Intersection is not empty.
454+
return GetInfos(config, css, nts);
455+
}
456+
457+
if (!encsIgnored && !encodings.empty())
460458
{
461-
// If not already computed, compute list with app categories and no encodings.
462-
appCSNoEncodings = GetColorSpaces(config, includeColorSpaces, colorSpaceType,
463-
appCategories);
464-
appNTNoEncodings = GetNamedTransforms(config, includeNamedTransforms,
465-
appCategories);
459+
// Intersection is empty, but encodings can be dropped if they were not dropped
460+
// already.
461+
encsIgnored = true;
462+
log.m_ignoreEncodings = true;
463+
if (!appNoEncodingsComputed)
464+
{
465+
// If not already computed, compute list with app categories and no
466+
// encodings.
467+
appCSNoEncodings = GetColorSpaces(config, includeColorSpaces,
468+
colorSpaceType, appCategories);
469+
appNTNoEncodings = GetNamedTransforms(config, includeNamedTransforms,
470+
appCategories);
471+
}
472+
appCSTest = &appCSNoEncodings;
473+
appNTTest = &appNTNoEncodings;
474+
}
475+
else
476+
{
477+
break;
466478
}
467-
appCSTest = &appCSNoEncodings;
468-
appNTTest = &appNTNoEncodings;
469479
}
470-
else
480+
log.m_emptyIntersection = true;
481+
encsIgnored = encsIgnoredBack;
482+
log.m_ignoreEncodings = ignoreEncodingsBack;
483+
}
484+
485+
if (appSize)
486+
{
487+
// 3e) Only use app categories. Use the result of 3a).
488+
if (!userCategories.empty() && log.m_userCats != NONE_FOUND)
471489
{
472-
break;
490+
log.m_userCats = IGNORED;
473491
}
492+
return GetInfos(config, appCS, appNT);
474493
}
475-
log.m_emptyIntersection = true;
476-
encsIgnored = encsIgnoredBack;
477-
log.m_ignoreEncodings = ignoreEncodingsBack;
478-
}
479494

480-
if (appSize)
481-
{
482-
// 3e) Only use app categories. Use the result of 3a).
483-
if (!userCategories.empty() && log.m_userCats != NONE_FOUND)
495+
if (userSize)
484496
{
485-
log.m_userCats = IGNORED;
497+
// 3f) Only use user categories.
498+
return GetInfos(config, userCS, userNT);
486499
}
487-
return GetInfos(config, appCS, appNT);
488-
}
489500

490-
if (userSize)
491-
{
492-
// 3f) Only use user categories.
493-
return GetInfos(config, userCS, userNT);
501+
// Fallback to ignoring categories and encodings.
502+
log.m_ignoreCategories = !appCategories.empty() || !userCategories.empty();
494503
}
495504

496505
// 3g) Ignore all categories and encodings and return all items.
497506

498-
log.m_ignoreCategories = !appCategories.empty() || !userCategories.empty();
499-
500507
Infos allInfos;
501508
const auto numCS = config->getNumColorSpaces(colorSpaceType, COLORSPACE_ACTIVE);
502509
for (int idx = 0; idx < numCS; ++idx)

src/OpenColorIO/apphelpers/LegacyViewingPipeline.cpp

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -224,24 +224,13 @@ ConstProcessorRcPtr LegacyViewingPipelineImpl::getProcessor(const ConstConfigRcP
224224
const bool nameFromDisplay = (0 == strcmp(name.c_str(), OCIO_VIEW_USE_DISPLAY_NAME));
225225
const std::string displayColorSpaceName{ nameFromDisplay ? display : name };
226226
ConstColorSpaceRcPtr displayColorSpace = config->getColorSpace(displayColorSpaceName.c_str());
227-
if (!displayColorSpace)
228-
{
229-
std::ostringstream os;
230-
os << "DisplayViewTransform error: ";
231-
if (displayColorSpaceName.empty())
232-
{
233-
os << "DisplayColorSpaceName is unspecified.";
234-
}
235-
else
236-
{
237-
os << "Cannot find display colorspace, '" << displayColorSpaceName << "'.";
238-
}
239-
throw Exception(os.str().c_str());
240-
}
227+
// If this is not a color space it can be a named transform. Error handling (missing color
228+
// space or named transform) is handled by display view transform.
241229

242230
const bool dataBypass = m_displayViewTransform->getDataBypass();
243-
bool skipColorSpaceConversions = dataBypass &&
244-
(inputColorSpace->isData() || displayColorSpace->isData());
231+
const bool displayData = (!displayColorSpace ||
232+
(displayColorSpace && displayColorSpace->isData())) ? true : false;
233+
bool skipColorSpaceConversions = dataBypass && (inputColorSpace->isData() || displayData);
245234

246235
if (dataBypass)
247236
{
@@ -372,7 +361,8 @@ ConstProcessorRcPtr LegacyViewingPipelineImpl::getProcessor(const ConstConfigRcP
372361
group->appendTransform(m_channelView);
373362
}
374363

375-
if (!skipColorSpaceConversions)
364+
// If there is no displayColorSpace it should be a named transform and it has to be applied.
365+
if (!skipColorSpaceConversions || !displayColorSpace)
376366
{
377367
group->appendTransform(dt);
378368
}

tests/cpu/apphelpers/ColorSpaceHelpers_tests.cpp

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -653,6 +653,63 @@ OCIO_ADD_TEST(ColorSpaceMenuHelper, encodings)
653653
OCIO_REQUIRE_EQUAL(menuHelper->getNumColorSpaces(), 2);
654654
}
655655

656+
OCIO_ADD_TEST(ColorSpaceMenuHelper, no_category)
657+
{
658+
std::istringstream is{ R"(ocio_profile_version: 1
659+
660+
environment:
661+
{}
662+
663+
search_path: luts
664+
strictparsing: true
665+
666+
roles:
667+
rendering: test_1
668+
default: raw
669+
670+
displays:
671+
DISP_1:
672+
- !<View> {name: VIEW_1, colorspace: test_1}
673+
- !<View> {name: VIEW_2, colorspace: test_2}
674+
675+
active_displays: []
676+
active_views: []
677+
678+
colorspaces:
679+
- !<ColorSpace>
680+
name: raw
681+
family: Raw
682+
description: A raw color space. Conversions to and from this space are no-ops.
683+
isdata: true
684+
allocation: uniform
685+
686+
- !<ColorSpace>
687+
name: test_1
688+
689+
- !<ColorSpace>
690+
name: test_2
691+
)" };
692+
693+
OCIO::ConstConfigRcPtr config;
694+
OCIO_CHECK_NO_THROW(config = OCIO::Config::CreateFromStream(is));
695+
OCIO_CHECK_NO_THROW(config->validate());
696+
697+
OCIO::ColorSpaceMenuHelperRcPtr menuHelper;
698+
auto params = OCIO::ColorSpaceMenuParameters::Create(config);
699+
700+
// Categories are ignored when config is version 1 and no message is logged.
701+
{
702+
OCIO::LogGuard guard;
703+
704+
params->setAppCategories("file-io");
705+
706+
// Return all the color spaces.
707+
OCIO_CHECK_NO_THROW(menuHelper = OCIO::ColorSpaceMenuHelper::Create(params));
708+
OCIO_CHECK_EQUAL(guard.output(), "");
709+
OCIO_CHECK_EQUAL(menuHelper->getNumColorSpaces(), 3);
710+
}
711+
}
712+
656713
OCIO_ADD_TEST(ColorSpaceMenuHelper, input_color_transformation)
657714
{
658715
std::istringstream is(category_test_config);

0 commit comments

Comments
 (0)