Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
b5d8bbe
Add view helper functions to Config class
annieln Sep 28, 2024
143aa90
add view helper functions to Config class and unit tests
annieln Oct 17, 2024
6b3e4b6
add view helper functions as python bindings
annieln Oct 17, 2024
6959ebc
add unit tests for view helper py bindings
annieln Oct 17, 2024
a1f2168
update with style changes and comments
annieln Oct 18, 2024
d76c9cb
comprehensive unit tests for ViewsAreEqual and displayHasView
annieln Feb 1, 2025
d338c94
improved in-line comments for unit tests
annieln Feb 1, 2025
41805a2
test suite for comparing virtual displays, fix to getVirtualDisplayVi…
annieln Feb 17, 2025
1681a8e
update briefs for ViewsAreEqual + VirtualViewsAreEqual, remove reduna…
annieln May 16, 2025
a15e9de
move virtual_display_exceptions test from tests/cpu/Config_tests.cpp …
annieln May 16, 2025
9e83598
move display_view_order test from tests/cpu/Config_tests.cpp to tests…
annieln May 16, 2025
0918ff4
add usage of viewIsShared to compare_displays test
annieln May 16, 2025
9f2ab62
add test of clearSharedViews to basic test module in tests/cpu/Displa…
annieln May 16, 2025
990fd73
change configs for compare_virtual_displays in tests/cpu/Config_tests…
annieln May 16, 2025
ecc7323
improve test cases for python config tests
annieln May 16, 2025
99d973e
restore old tests to Config_tests.cpp and move new tests compare_disp…
annieln May 17, 2025
75ae64a
add null/empty view name handling to viewIsShared and virtualViewIsSh…
annieln May 24, 2025
8fc9745
Merge branch 'main' into viewHelpers
doug-walker May 26, 2025
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
64 changes: 64 additions & 0 deletions include/OpenColorIO/OpenColorIO.h
Original file line number Diff line number Diff line change
Expand Up @@ -852,13 +852,20 @@ class OCIOEXPORT Config
* \ref Config::validate will throw if the config does not contain
* the matching display color space.
*/

/// Check if a view within a given display is referencing one of the config's shared views.
bool viewIsShared(const char * dispName, const char * viewName) const;

/// Will throw if view or colorSpaceName are null or empty.
void addSharedView(const char * view, const char * viewTransformName,
const char * colorSpaceName, const char * looks,
const char * ruleName, const char * description);
/// Remove a shared view. Will throw if the view does not exist.
void removeSharedView(const char * view);

/// Clear all shared views. This will throw if any displays are still using the shared views.
void clearSharedViews();

const char * getDefaultDisplay() const;
int getNumDisplays() const;
/// Will return "" if the index is invalid.
Expand All @@ -883,6 +890,23 @@ class OCIOEXPORT Config
int getNumViews(const char * display, const char * colorspaceName) const;
const char * getView(const char * display, const char * colorspaceName, int index) const;

/**
* \brief Compare views in a pair of configs.
*
* Will return false if either of the views does not exist. This will return true even
* if the view is display-defined in one config and a reference to a shared view in the
* other config (both within the same display), as long as the contents match. The
* description text (if any) is ignored, since it is not a functional difference.
*
* Note that the comparison is only on the strings contained in the view definition,
* the function does not attempt to compare that the color spaces or view transforms
* being referenced are identical (only that they have the same name).
*/
static bool ViewsAreEqual(const ConstConfigRcPtr & first,
const ConstConfigRcPtr & second,
const char * dispName,
const char * viewName);

/**
* Returns the view_transform attribute of the (display, view) pair. View can
* be a shared view of the display. If display is null or empty, config shared views are used.
Expand All @@ -900,6 +924,17 @@ class OCIOEXPORT Config
/// Returns the description attribute of a (display, view) pair.
const char * getDisplayViewDescription(const char * display, const char * view) const noexcept;

/**
* \brief Determine if a display and view exist.
*
* This returns false if either the display or view doesn't exist. It works regardless
* of whether the display or view are active, and it works regardless of whether the
* view is display-defined or if the display has this as a shared view. It will only
* check config-level shared views if dispName is null. It will not check config level
* shared views if dispName is not null.
*/
bool displayHasView(const char * dispName, const char * viewName) const;

/**
* For the (display, view) pair, specify which color space and look to use.
* If a look is not desired, then just pass a null or empty string.
Expand Down Expand Up @@ -963,6 +998,18 @@ class OCIOEXPORT Config
*
*/

/**
* \brief Determine if a virtual view exists.
*
* This returns false if the virtual view doesn't exist. It works regardless of
* whether the virtual view is active, and it works regardless of whether the virtual
* view is display-defined or if the display has this as a shared virtual view.
*/
bool hasVirtualView(const char * viewName) const;

/// Check if a given virtual view is referencing one of the config's shared views.
bool virtualViewIsShared(const char * viewName) const;

void addVirtualDisplayView(const char * view,
const char * viewTransformName,
const char * colorSpaceName,
Expand All @@ -977,6 +1024,23 @@ class OCIOEXPORT Config
/// Get the view name at a specific index.
const char * getVirtualDisplayView(ViewType type, int index) const noexcept;

/**
* \brief Compare virtual views in a pair of configs.
*
* Will return false if either of the virtual views does not exist. This will return true
* even if the virtual view is display-defined in one config and a reference to a shared
* virtual view in the other config, as long as the contents match.
*
* The description text (if any) is ignored, since it is not a functional difference.
*
* Note that the comparison is only on the strings contained in the view definition,
* the function does not attempt to compare that the color spaces or view transforms
* being referenced are identical (only that they have the same name).
*/
static bool VirtualViewsAreEqual(const ConstConfigRcPtr & first,
const ConstConfigRcPtr & second,
const char * viewName);

const char * getVirtualDisplayViewTransformName(const char * view) const noexcept;
const char * getVirtualDisplayViewColorSpaceName(const char * view) const noexcept;
const char * getVirtualDisplayViewLooks(const char * view) const noexcept;
Expand Down
163 changes: 163 additions & 0 deletions src/OpenColorIO/Config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3305,6 +3305,22 @@ void Config::setViewingRules(ConstViewingRulesRcPtr viewingRules)
getImpl()->resetCacheIDs();
}

bool Config::viewIsShared(const char * dispName, const char * viewName) const
{
if (!viewName || !*viewName) return false;

for (int v = 0; v < getNumViews(VIEW_SHARED, dispName); v++)
{
const char * sharedViewName = getView(VIEW_SHARED, dispName, v);
if (sharedViewName && *sharedViewName && Platform::Strcasecmp(sharedViewName, viewName) == 0)
{
return true;
}
}

return false;
}

void Config::addSharedView(const char * view, const char * viewTransform,
const char * colorSpace, const char * looks,
const char * rule, const char * description)
Expand Down Expand Up @@ -3358,6 +3374,19 @@ void Config::removeSharedView(const char * view)
}
}

void Config::clearSharedViews()
{
int numViews = getNumViews(VIEW_SHARED, nullptr);
for (int v = numViews - 1; v >= 0; v--)
{
const char * sharedViewName = getView(VIEW_SHARED, nullptr, v);
if (sharedViewName && *sharedViewName)
{
removeSharedView(sharedViewName);
}
}
}

const char * Config::getDefaultDisplay() const
{
return getDisplay(0);
Expand Down Expand Up @@ -3487,6 +3516,43 @@ const char * Config::getView(const char * display, const char * colorspace, int
return "";
}


bool Config::ViewsAreEqual(const ConstConfigRcPtr & first,
const ConstConfigRcPtr & second,
const char * dispName, // may be empty or nullptr for shared views
const char * viewName)
{
// It's ok to call this even for displays/views that don't exist, it will simply return false.

// Note that this will return true even if the view is display-defined in one config and a reference
// to a shared view in the other config (both within the same display), as long as the contents match.

// These calls return null if either the display or view doesn't exist (regardless if it's active).
const char * cs1 = first->getDisplayViewColorSpaceName(dispName, viewName);
const char * cs2 = second->getDisplayViewColorSpaceName(dispName, viewName);

// If the color space is not null, the display and view exist.
if (cs1 && *cs1 && cs2 && *cs2)
{
// Both configs have a display and view by this name, now check the contents.
if (Platform::Strcasecmp(cs1, cs2) == 0)
{
// Note the remaining strings may be empty in a valid view.
// Intentionally not checking the description since it is not a functional difference.
if ( (Platform::Strcasecmp(first->getDisplayViewLooks(dispName, viewName),
second->getDisplayViewLooks(dispName, viewName)) == 0) &&
(Platform::Strcasecmp(first->getDisplayViewTransformName(dispName, viewName),
second->getDisplayViewTransformName(dispName, viewName)) == 0) &&
(Platform::Strcasecmp(first->getDisplayViewRule(dispName, viewName),
second->getDisplayViewRule(dispName, viewName)) == 0) )
{
return true;
}
}
}
return false;
}

const char * Config::getDisplayViewTransformName(const char * display, const char * view) const
{
const View * viewPtr = getImpl()->getView(display, view);
Expand Down Expand Up @@ -3525,6 +3591,21 @@ const char * Config::getDisplayViewDescription(const char * display, const char
return viewPtr ? viewPtr->m_description.c_str() : "";
}

bool Config::displayHasView(const char * dispName, const char * viewName) const
{
// This returns null if either the display or view doesn't exist.
// It works regardless of whether the display or view are active,
// and it works regardless of whether the view is display-defined
// or if the display has this as a shared view.
//
// It will only check config level shared views if dispName is null.
// It will not check config level shared views if dispName is not null.
const char * cs = getDisplayViewColorSpaceName(dispName, viewName);

// All views must have a color space, so if it's not empty, the view exists.
return (cs && *cs);
}

void Config::addDisplaySharedView(const char * display, const char * sharedView)
{
if (!display || !*display)
Expand Down Expand Up @@ -3695,6 +3776,30 @@ void Config::clearDisplays()
getImpl()->resetCacheIDs();
}

bool Config::hasVirtualView(const char * viewName) const
{
const char * cs = getVirtualDisplayViewColorSpaceName(viewName);

// All views must have a color space, so if it's not empty, the view exists.
return (cs && *cs);
}

bool Config::virtualViewIsShared(const char * viewName) const
{
if (!viewName || !*viewName) return false;

for (int v = 0; v < getVirtualDisplayNumViews(VIEW_SHARED); v++)
{
const char * sharedViewName = getVirtualDisplayView(VIEW_SHARED, v);
if (sharedViewName && *sharedViewName && Platform::Strcasecmp(sharedViewName, viewName) == 0)
{
return true;
}
}

return false;
}

void Config::addVirtualDisplayView(const char * view,
const char * viewTransform,
const char * colorSpace,
Expand Down Expand Up @@ -3795,10 +3900,44 @@ const char * Config::getVirtualDisplayView(ViewType type, int index) const noexc
return "";
}

bool Config::VirtualViewsAreEqual(const ConstConfigRcPtr & first,
const ConstConfigRcPtr & second,
const char * viewName)
{
const char * cs1 = first->getVirtualDisplayViewColorSpaceName(viewName);
const char * cs2 = second->getVirtualDisplayViewColorSpaceName(viewName);

// If the color space is not null, the display and view exist.
if (cs1 && *cs1 && cs2 && *cs2)
{
if (Platform::Strcasecmp(cs1, cs2) == 0)
{
// Note the remaining strings may be empty in a valid view.
// Intentionally not checking the description since it is not a functional difference.
if ( (Platform::Strcasecmp(first->getVirtualDisplayViewLooks(viewName),
second->getVirtualDisplayViewLooks(viewName)) == 0) &&
(Platform::Strcasecmp(first->getVirtualDisplayViewTransformName(viewName),
second->getVirtualDisplayViewTransformName(viewName)) == 0) &&
(Platform::Strcasecmp(first->getVirtualDisplayViewRule(viewName),
second->getVirtualDisplayViewRule(viewName)) == 0) )
{
return true;
}
}
}
return false;
}

const char * Config::getVirtualDisplayViewTransformName(const char * view) const noexcept
{
if (!view) return "";

// Get the view transform name for the case where a virtual view is shared.
if (virtualViewIsShared(view))
{
return getDisplayViewTransformName(nullptr, view);
}

ViewVec::const_iterator iter = FindView(getImpl()->m_virtualDisplay.m_views, view);
if (iter != getImpl()->m_virtualDisplay.m_views.end())
{
Expand All @@ -3812,6 +3951,12 @@ const char * Config::getVirtualDisplayViewColorSpaceName(const char * view) cons
{
if (!view) return "";

// Get the colorspace name for the case where a virtual view is shared.
if (virtualViewIsShared(view))
{
return getDisplayViewColorSpaceName(nullptr, view);
}

ViewVec::const_iterator iter = FindView(getImpl()->m_virtualDisplay.m_views, view);
if (iter != getImpl()->m_virtualDisplay.m_views.end())
{
Expand All @@ -3825,6 +3970,12 @@ const char * Config::getVirtualDisplayViewLooks(const char * view) const noexcep
{
if (!view) return "";

// Get the view looks for the case where a virtual view is shared
if (virtualViewIsShared(view))
{
return getDisplayViewLooks(nullptr, view);
}

ViewVec::const_iterator iter = FindView(getImpl()->m_virtualDisplay.m_views, view);
if (iter != getImpl()->m_virtualDisplay.m_views.end())
{
Expand All @@ -3838,6 +3989,12 @@ const char * Config::getVirtualDisplayViewRule(const char * view) const noexcept
{
if (!view) return "";

// Get the view rule for the case where a virtual view is shared
if (virtualViewIsShared(view))
{
return getDisplayViewRule(nullptr, view);
}

ViewVec::const_iterator iter = FindView(getImpl()->m_virtualDisplay.m_views, view);
if (iter != getImpl()->m_virtualDisplay.m_views.end())
{
Expand All @@ -3851,6 +4008,12 @@ const char * Config::getVirtualDisplayViewDescription(const char * view) const n
{
if (!view) return "";

// Get the view description for the case where a virtual view is shared
if (virtualViewIsShared(view))
{
return getDisplayViewDescription(nullptr, view);
}

ViewVec::const_iterator iter = FindView(getImpl()->m_virtualDisplay.m_views, view);
if (iter != getImpl()->m_virtualDisplay.m_views.end())
{
Expand Down
Loading
Loading