From 7fc59f80e67dc4defaada03cfcf3a89105c66693 Mon Sep 17 00:00:00 2001 From: Annie Lin <63685774+annieln@users.noreply.github.com> Date: Thu, 26 Sep 2024 18:22:53 -0700 Subject: [PATCH] Add hasAlias method to ColorSpace and NamedTransform classes (#2059) * Add hasAlias method to ColorSpace and NamedTransform classes Signed-off-by: annie * minor style changes Signed-off-by: annie * Update Python binding to include hasAlias method with unit tests Signed-off-by: annie --------- Signed-off-by: annie --- include/OpenColorIO/OpenColorIO.h | 4 ++++ src/OpenColorIO/ColorSpace.cpp | 13 +++++++++++++ src/OpenColorIO/NamedTransform.cpp | 13 +++++++++++++ src/OpenColorIO/NamedTransform.h | 1 + src/bindings/python/PyColorSpace.cpp | 2 ++ src/bindings/python/PyNamedTransform.cpp | 2 ++ tests/cpu/ColorSpace_tests.cpp | 14 ++++++++++++++ tests/cpu/NamedTransform_tests.cpp | 14 ++++++++++++++ tests/python/ColorSpaceTest.py | 11 ++++++++++- tests/python/NamedTransformTest.py | 9 +++++++++ 10 files changed, 82 insertions(+), 1 deletion(-) diff --git a/include/OpenColorIO/OpenColorIO.h b/include/OpenColorIO/OpenColorIO.h index 5f11ec9eb9..b7183ce77f 100644 --- a/include/OpenColorIO/OpenColorIO.h +++ b/include/OpenColorIO/OpenColorIO.h @@ -1879,6 +1879,8 @@ class OCIOEXPORT ColorSpace size_t getNumAliases() const noexcept; /// Return empty string if idx is out of range. const char * getAlias(size_t idx) const noexcept; + /// Return true if alias exists. + bool hasAlias(const char * alias) const noexcept; /** * Add an alias for the color space name (the aliases may be used as a synonym for the * name). Nothing will be added if the alias is already the color space name, one of its @@ -2301,6 +2303,8 @@ class OCIOEXPORT NamedTransform virtual size_t getNumAliases() const noexcept = 0; /// Return empty string if idx is out of range. virtual const char * getAlias(size_t idx) const noexcept = 0; + /// Return true if alias exists. + virtual bool hasAlias(const char* alias) const noexcept = 0; /** * Nothing is done if alias is NULL or empty, if it is already there, or if it is already * the named transform name. diff --git a/src/OpenColorIO/ColorSpace.cpp b/src/OpenColorIO/ColorSpace.cpp index ef51458698..4b7ecb25d0 100644 --- a/src/OpenColorIO/ColorSpace.cpp +++ b/src/OpenColorIO/ColorSpace.cpp @@ -8,6 +8,7 @@ #include #include "TokensManager.h" +#include "Platform.h" #include "PrivateTypes.h" #include "utils/StringUtils.h" @@ -147,6 +148,18 @@ const char * ColorSpace::getAlias(size_t idx) const noexcept return ""; } +bool ColorSpace::hasAlias(const char * alias) const noexcept +{ + for (size_t idx = 0; idx < getImpl()->m_aliases.size(); ++idx) + { + if (0 == Platform::Strcasecmp(getImpl()->m_aliases[idx].c_str(), alias)) + { + return true; + } + } + return false; +} + void ColorSpace::addAlias(const char * alias) noexcept { if (alias && *alias) diff --git a/src/OpenColorIO/NamedTransform.cpp b/src/OpenColorIO/NamedTransform.cpp index 56a3a9c099..2eb8f53b19 100644 --- a/src/OpenColorIO/NamedTransform.cpp +++ b/src/OpenColorIO/NamedTransform.cpp @@ -5,6 +5,7 @@ #include #include "NamedTransform.h" +#include "Platform.h" namespace OCIO_NAMESPACE { @@ -64,6 +65,18 @@ const char * NamedTransformImpl::getAlias(size_t idx) const noexcept return ""; } +bool NamedTransformImpl::hasAlias(const char * alias) const noexcept +{ + for (size_t idx = 0; idx < m_aliases.size(); ++idx) + { + if (0 == Platform::Strcasecmp(m_aliases[idx].c_str(), alias)) + { + return true; + } + } + return false; +} + void NamedTransformImpl::addAlias(const char * alias) noexcept { if (alias && *alias) diff --git a/src/OpenColorIO/NamedTransform.h b/src/OpenColorIO/NamedTransform.h index 34f8a1b97b..f0f6ef4663 100644 --- a/src/OpenColorIO/NamedTransform.h +++ b/src/OpenColorIO/NamedTransform.h @@ -27,6 +27,7 @@ class NamedTransformImpl : public NamedTransform size_t getNumAliases() const noexcept override; const char * getAlias(size_t idx) const noexcept override; + bool hasAlias(const char * alias) const noexcept override; void addAlias(const char * alias) noexcept override; void removeAlias(const char * alias) noexcept override; void clearAliases() noexcept override; diff --git a/src/bindings/python/PyColorSpace.cpp b/src/bindings/python/PyColorSpace.cpp index ee72784f8b..6827943bc0 100644 --- a/src/bindings/python/PyColorSpace.cpp +++ b/src/bindings/python/PyColorSpace.cpp @@ -164,6 +164,8 @@ void bindPyColorSpace(py::module & m) DOC(ColorSpace, setName)) // Aliases. + .def("hasAlias", &ColorSpace::hasAlias, "alias"_a, + DOC(ColorSpace, hasAlias)) .def("addAlias", &ColorSpace::addAlias, "alias"_a.none(false), DOC(ColorSpace, addAlias)) .def("removeAlias", &ColorSpace::removeAlias, "alias"_a.none(false), diff --git a/src/bindings/python/PyNamedTransform.cpp b/src/bindings/python/PyNamedTransform.cpp index 963bdf41d6..10205a88f2 100644 --- a/src/bindings/python/PyNamedTransform.cpp +++ b/src/bindings/python/PyNamedTransform.cpp @@ -130,6 +130,8 @@ void bindPyNamedTransform(py::module & m) DOC(NamedTransform, setName)) // Aliases. + .def("hasAlias", &NamedTransform::hasAlias, "alias"_a, + DOC(NamedTransform, hasAlias)) .def("addAlias", &NamedTransform::addAlias, "alias"_a.none(false), DOC(NamedTransform, addAlias)) .def("removeAlias", &NamedTransform::removeAlias, "alias"_a.none(false), diff --git a/tests/cpu/ColorSpace_tests.cpp b/tests/cpu/ColorSpace_tests.cpp index 20d026de4d..54521be171 100644 --- a/tests/cpu/ColorSpace_tests.cpp +++ b/tests/cpu/ColorSpace_tests.cpp @@ -79,10 +79,14 @@ OCIO_ADD_TEST(ColorSpace, alias) constexpr char AliasB[]{ "aliasB" }; cs->addAlias(AliasA); OCIO_CHECK_EQUAL(cs->getNumAliases(), 1); + OCIO_CHECK_ASSERT(cs->hasAlias(AliasA)); + OCIO_CHECK_ASSERT(cs->hasAlias(AliasAAlt)); + OCIO_CHECK_ASSERT(!cs->hasAlias(AliasB)); cs->addAlias(AliasB); OCIO_CHECK_EQUAL(cs->getNumAliases(), 2); OCIO_CHECK_EQUAL(std::string(cs->getAlias(0)), AliasA); OCIO_CHECK_EQUAL(std::string(cs->getAlias(1)), AliasB); + OCIO_CHECK_ASSERT(cs->hasAlias(AliasB)); // Alias with same name (different case) already exists, do nothing. @@ -96,6 +100,8 @@ OCIO_ADD_TEST(ColorSpace, alias) cs->removeAlias(AliasAAlt); OCIO_CHECK_EQUAL(cs->getNumAliases(), 1); OCIO_CHECK_EQUAL(std::string(cs->getAlias(0)), AliasB); + OCIO_CHECK_ASSERT(!cs->hasAlias(AliasA)); + OCIO_CHECK_ASSERT(!cs->hasAlias(AliasAAlt)); // Add with new case. @@ -103,6 +109,8 @@ OCIO_ADD_TEST(ColorSpace, alias) OCIO_CHECK_EQUAL(cs->getNumAliases(), 2); OCIO_CHECK_EQUAL(std::string(cs->getAlias(0)), AliasB); OCIO_CHECK_EQUAL(std::string(cs->getAlias(1)), AliasAAlt); + OCIO_CHECK_ASSERT(cs->hasAlias(AliasA)); + OCIO_CHECK_ASSERT(cs->hasAlias(AliasAAlt)); // Setting the name of the color space to one of its aliases removes the alias. @@ -110,6 +118,8 @@ OCIO_ADD_TEST(ColorSpace, alias) OCIO_CHECK_EQUAL(std::string(cs->getName()), AliasA); OCIO_CHECK_EQUAL(cs->getNumAliases(), 1); OCIO_CHECK_EQUAL(std::string(cs->getAlias(0)), AliasB); + OCIO_CHECK_ASSERT(!cs->hasAlias(AliasA)); + OCIO_CHECK_ASSERT(!cs->hasAlias(AliasAAlt)); // Alias is not added if it is already the color space name. @@ -117,13 +127,17 @@ OCIO_ADD_TEST(ColorSpace, alias) OCIO_CHECK_EQUAL(std::string(cs->getName()), AliasA); OCIO_CHECK_EQUAL(cs->getNumAliases(), 1); OCIO_CHECK_EQUAL(std::string(cs->getAlias(0)), AliasB); + OCIO_CHECK_ASSERT(!cs->hasAlias(AliasAAlt)); // Remove all aliases. cs->addAlias("other"); OCIO_CHECK_EQUAL(cs->getNumAliases(), 2); + OCIO_CHECK_ASSERT(cs->hasAlias("other")); cs->clearAliases(); OCIO_CHECK_EQUAL(cs->getNumAliases(), 0); + OCIO_CHECK_ASSERT(!cs->hasAlias(AliasB)); + OCIO_CHECK_ASSERT(!cs->hasAlias("other")); } OCIO_ADD_TEST(ColorSpace, category) diff --git a/tests/cpu/NamedTransform_tests.cpp b/tests/cpu/NamedTransform_tests.cpp index 3730fd046a..2d2b5e810d 100644 --- a/tests/cpu/NamedTransform_tests.cpp +++ b/tests/cpu/NamedTransform_tests.cpp @@ -71,10 +71,14 @@ OCIO_ADD_TEST(NamedTransform, alias) constexpr char AliasB[]{ "aliasB" }; nt->addAlias(AliasA); OCIO_CHECK_EQUAL(nt->getNumAliases(), 1); + OCIO_CHECK_ASSERT(nt->hasAlias(AliasA)); + OCIO_CHECK_ASSERT(nt->hasAlias(AliasAAlt)); + OCIO_CHECK_ASSERT(!nt->hasAlias(AliasB)); nt->addAlias(AliasB); OCIO_CHECK_EQUAL(nt->getNumAliases(), 2); OCIO_CHECK_EQUAL(std::string(nt->getAlias(0)), AliasA); OCIO_CHECK_EQUAL(std::string(nt->getAlias(1)), AliasB); + OCIO_CHECK_ASSERT(nt->hasAlias(AliasB)); // Alias with same name (different case) already exists, do nothing. { @@ -89,6 +93,8 @@ OCIO_ADD_TEST(NamedTransform, alias) nt->removeAlias(AliasAAlt); OCIO_CHECK_EQUAL(nt->getNumAliases(), 1); OCIO_CHECK_EQUAL(std::string(nt->getAlias(0)), AliasB); + OCIO_CHECK_ASSERT(!nt->hasAlias(AliasA)); + OCIO_CHECK_ASSERT(!nt->hasAlias(AliasAAlt)); } // Add with new case. @@ -97,6 +103,8 @@ OCIO_ADD_TEST(NamedTransform, alias) OCIO_CHECK_EQUAL(nt->getNumAliases(), 2); OCIO_CHECK_EQUAL(std::string(nt->getAlias(0)), AliasB); OCIO_CHECK_EQUAL(std::string(nt->getAlias(1)), AliasAAlt); + OCIO_CHECK_ASSERT(nt->hasAlias(AliasA)); + OCIO_CHECK_ASSERT(nt->hasAlias(AliasAAlt)); } // Setting the name of the named transform to one of its aliases removes the alias. @@ -105,6 +113,8 @@ OCIO_ADD_TEST(NamedTransform, alias) OCIO_CHECK_EQUAL(std::string(nt->getName()), AliasA); OCIO_CHECK_EQUAL(nt->getNumAliases(), 1); OCIO_CHECK_EQUAL(std::string(nt->getAlias(0)), AliasB); + OCIO_CHECK_ASSERT(!nt->hasAlias(AliasA)); + OCIO_CHECK_ASSERT(!nt->hasAlias(AliasAAlt)); } // Alias is not added if it is already the named transform name. @@ -113,14 +123,18 @@ OCIO_ADD_TEST(NamedTransform, alias) OCIO_CHECK_EQUAL(std::string(nt->getName()), AliasA); OCIO_CHECK_EQUAL(nt->getNumAliases(), 1); OCIO_CHECK_EQUAL(std::string(nt->getAlias(0)), AliasB); + OCIO_CHECK_ASSERT(!nt->hasAlias(AliasAAlt)); } // Remove all aliases. { nt->addAlias("other"); OCIO_CHECK_EQUAL(nt->getNumAliases(), 2); + OCIO_CHECK_ASSERT(nt->hasAlias("other")); nt->clearAliases(); OCIO_CHECK_EQUAL(nt->getNumAliases(), 0); + OCIO_CHECK_ASSERT(!nt->hasAlias(AliasB)); + OCIO_CHECK_ASSERT(!nt->hasAlias("other")); } // diff --git a/tests/python/ColorSpaceTest.py b/tests/python/ColorSpaceTest.py index a78dcb7503..0860e7a3f0 100644 --- a/tests/python/ColorSpaceTest.py +++ b/tests/python/ColorSpaceTest.py @@ -356,7 +356,7 @@ def test_transform(self): def test_aliases(self): """ - Test NamedTransform aliases. + Test ColorSpace aliases. """ cs = OCIO.ColorSpace() @@ -368,12 +368,16 @@ def test_aliases(self): aliases = cs.getAliases() self.assertEqual(len(aliases), 1) self.assertEqual(aliases[0], 'alias1') + self.assertTrue(cs.hasAlias('alias1')) + self.assertTrue(cs.hasAlias('aLiaS1')) + self.assertFalse(cs.hasAlias('alias2')) cs.addAlias('alias2') aliases = cs.getAliases() self.assertEqual(len(aliases), 2) self.assertEqual(aliases[0], 'alias1') self.assertEqual(aliases[1], 'alias2') + self.assertTrue(cs.hasAlias('alias2')) # Alias is already there, not added. @@ -393,12 +397,15 @@ def test_aliases(self): aliases = cs.getAliases() self.assertEqual(len(aliases), 1) self.assertEqual(aliases[0], 'alias1') + self.assertFalse(cs.hasAlias('alias2')) # Removing an alias. cs.addAlias('to remove') aliases = cs.getAliases() self.assertEqual(len(aliases), 2) + self.assertTrue(cs.hasAlias('to remove')) + self.assertTrue(cs.hasAlias('to REMOVE')) cs.removeAlias('not found') aliases = cs.getAliases() @@ -407,10 +414,12 @@ def test_aliases(self): cs.removeAlias('to REMOVE') aliases = cs.getAliases() self.assertEqual(len(aliases), 1) + self.assertFalse(cs.hasAlias('to remove')) cs.clearAliases() aliases = cs.getAliases() self.assertEqual(len(aliases), 0) + self.assertFalse(cs.hasAlias('alias1')) def test_is_colorspace_linear(self): """ diff --git a/tests/python/NamedTransformTest.py b/tests/python/NamedTransformTest.py index 4e8b8e153a..abeb577964 100644 --- a/tests/python/NamedTransformTest.py +++ b/tests/python/NamedTransformTest.py @@ -485,12 +485,16 @@ def test_aliases(self): aliases = named_tr.getAliases() self.assertEqual(len(aliases), 1) self.assertEqual(aliases[0], 'alias1') + self.assertTrue(named_tr.hasAlias('alias1')) + self.assertTrue(named_tr.hasAlias('aLiAs1')) + self.assertFalse(named_tr.hasAlias('alias2')) named_tr.addAlias('alias2') aliases = named_tr.getAliases() self.assertEqual(len(aliases), 2) self.assertEqual(aliases[0], 'alias1') self.assertEqual(aliases[1], 'alias2') + self.assertTrue(named_tr.hasAlias('alias2')) # Alias is already there, not added. @@ -510,12 +514,15 @@ def test_aliases(self): aliases = named_tr.getAliases() self.assertEqual(len(aliases), 1) self.assertEqual(aliases[0], 'alias1') + self.assertFalse(named_tr.hasAlias('alias2')) # Removing an alias. named_tr.addAlias('to remove') aliases = named_tr.getAliases() self.assertEqual(len(aliases), 2) + self.assertTrue(named_tr.hasAlias('to remove')) + self.assertTrue(named_tr.hasAlias('to REMOVE')) named_tr.removeAlias('not found') aliases = named_tr.getAliases() @@ -524,7 +531,9 @@ def test_aliases(self): named_tr.removeAlias('to REMOVE') aliases = named_tr.getAliases() self.assertEqual(len(aliases), 1) + self.assertFalse(named_tr.hasAlias('to remove')) named_tr.clearAliases() aliases = named_tr.getAliases() self.assertEqual(len(aliases), 0) + self.assertFalse(named_tr.hasAlias('alias1'))