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
3 changes: 3 additions & 0 deletions src/include/OpenImageIO/color.h
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,9 @@ class OIIO_API ColorConfig {
/// will return false if it's not sure.
bool isColorSpaceLinear(string_view name) const;

/// Is the color space non-color-managed "data"?
bool isData(string_view name) const;

/// Retrieve the full list of aliases for the named color space.
std::vector<std::string> getAliases(string_view color_space) const;

Expand Down
38 changes: 37 additions & 1 deletion src/libOpenImageIO/color_ocio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ struct CSInfo {
is_lin_srgb = 8, // sRGB/Rec709 primaries, linear response
is_ACEScg = 16, // ACEScg
is_Rec709 = 32, // Rec709 primaries and transfer function
is_data = 64, // Non-color-managed data
is_known = is_srgb | is_lin_srgb | is_ACEScg | is_Rec709
};
int m_flags = 0;
Expand Down Expand Up @@ -341,6 +342,8 @@ class ColorConfig::Impl {

bool isColorSpaceLinear(string_view name) const;

bool isData(string_view name) const;

private:
// Return the CSInfo flags for the given color space name
int flags(string_view name)
Expand Down Expand Up @@ -607,6 +610,8 @@ ColorConfig::Impl::classify_by_name(CSInfo& cs)
ACEScg_alias);
} else if (Strutil::iequals(cs.name, "Rec709")) {
cs.setflag(CSInfo::is_Rec709, Rec709_alias);
} else if (Strutil::iequals(cs.name, "Raw")) {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not in favor of these string-based assumptions. Aren't we catching these cases with OCIO's API in a subsequent classification stage anyway?

In any case, if you do want to have a fast path to selecting color spaces we know are data spaces, without having to actually inspect them, you can try looking up the "data" role, which is MUCH more likely to point to a data color space than assuming the current config has a color space named "Raw", and that "Raw" is a data color space.

You can try Config::getCanonicalColorSpaceName("data"), which will either return the name of a color space that can be mapped to the "data" colorInteropID (or any other data color space needs); or it will return something falsey if the "data" role isn't set (I think it usually is -- IIRC, configs fail to validate otherwise).

cs.setflag(CSInfo::is_data);
}
#ifdef OIIO_SITE_spi
// Ugly SPI-specific hacks, so sorry
Expand All @@ -619,6 +624,9 @@ ColorConfig::Impl::classify_by_name(CSInfo& cs)
} else if (cs.name == "srgblnf" || cs.name == "srgblnh"
|| cs.name == "srgbln16" || cs.name == "srgbln8") {
cs.setflag(CSInfo::is_lin_srgb, lin_srgb_alias);
} else if (Strutil::starts_with(cs.name, "nc")) {
cs.setflag(CSInfo::is_data);
DBG("Classifying {} as data based on SPI name\n", cs.name);
}
#endif

Expand Down Expand Up @@ -649,6 +657,10 @@ ColorConfig::Impl::classify_by_conversions(CSInfo& cs)

if (isColorSpaceLinear(cs.name))
cs.setflag(CSInfo::is_linear_response);
if (cs.ocio_cs && cs.ocio_cs->isData()) {
cs.setflag(CSInfo::is_data);
DBG("Classifying {} as data isData() [1]\n", cs.name);
}

// If the name didn't already tell us what it is, and we have a new enough
// OCIO that has built-in configs, test whether this color space is
Expand Down Expand Up @@ -683,7 +695,12 @@ ColorConfig::Impl::classify_by_conversions(CSInfo& cs)
cs.setflag(CSInfo::is_ACEScg | CSInfo::is_linear_response,
ACEScg_alias);
}
} catch (...) {
if (cs.ocio_cs->isData()) {
cs.setflag(CSInfo::is_data);
DBG("Classifying {} as data isData() [2]\n", cs.name);
}
} catch (OCIO::Exception& e) {
DBG("OCIO exception in classify_by_conversions: {}", e.what());
}
}

Expand Down Expand Up @@ -1067,6 +1084,25 @@ ColorConfig::Impl::isColorSpaceLinear(string_view name) const



bool
ColorConfig::isData(string_view name) const
{
return getImpl()->isData(name);
}



bool
ColorConfig::Impl::isData(string_view name) const
{
if (const CSInfo* cs = find(name)) {
return cs->flags() & CSInfo::is_data;
}
return false;
}



std::vector<std::string>
ColorConfig::getAliases(string_view color_space) const
{
Expand Down
12 changes: 12 additions & 0 deletions src/python/py_colorconfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,18 @@ declare_colorconfig(py::module& m)
[](const ColorConfig& self, const std::string& named_transform) {
return self.getNamedTransformAliases(named_transform);
})
.def(
"isColorSpaceLinear",
[](const ColorConfig& self, const std::string& name) {
return self.isColorSpaceLinear(name);
},
"name"_a)
.def(
"isData",
[](const ColorConfig& self, const std::string& name) {
return self.isData(name);
},
"name"_a)
.def(
"getColorSpaceFromFilepath",
[](const ColorConfig& self, const std::string& filepath) {
Expand Down
4 changes: 4 additions & 0 deletions testsuite/python-colorconfig/ref/out-ocio23.txt
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ get_color_interop_id('lin_srgb') = lin_rec709_scene
get_color_interop_id([1, 13, 1, 1]) = srgb_rec709_scene
get_cicp('pq_rec2020_display') = [9, 16, 9, 1]
get_cicp('unknown_interop_id') = None
isColorSpaceLinear('scene_linear') = True
isColorSpaceLinear('srgb') = False
isData('scene_linear') = False
isData('Raw') = True

Loaded test OCIO config: oiio_test_v0.9.2.ocio
Parsed color space for filepath 'foo_lin_ap1.exr': ACEScg
Expand Down
4 changes: 4 additions & 0 deletions testsuite/python-colorconfig/ref/out-ocio24.txt
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ get_color_interop_id('lin_srgb') = lin_rec709_scene
get_color_interop_id([1, 13, 1, 1]) = srgb_rec709_scene
get_cicp('pq_rec2020_display') = [9, 16, 9, 1]
get_cicp('unknown_interop_id') = None
isColorSpaceLinear('scene_linear') = True
isColorSpaceLinear('srgb') = False
isData('scene_linear') = False
isData('Raw') = True

Loaded test OCIO config: oiio_test_v0.9.2.ocio
Parsed color space for filepath 'foo_lin_ap1.exr': ACEScg
Expand Down
4 changes: 4 additions & 0 deletions testsuite/python-colorconfig/ref/out-ocio25.txt
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ get_color_interop_id('lin_srgb') = lin_rec709_scene
get_color_interop_id([1, 13, 1, 1]) = srgb_rec709_scene
get_cicp('pq_rec2020_display') = [9, 16, 9, 1]
get_cicp('unknown_interop_id') = None
isColorSpaceLinear('scene_linear') = True
isColorSpaceLinear('srgb') = False
isData('scene_linear') = False
isData('Raw') = True

Loaded test OCIO config: oiio_test_v0.9.2.ocio
Parsed color space for filepath 'foo_lin_ap1.exr': ACEScg
Expand Down
4 changes: 4 additions & 0 deletions testsuite/python-colorconfig/ref/out.txt
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ get_color_interop_id('lin_srgb') = lin_rec709_scene
get_color_interop_id([1, 13, 1, 1]) = srgb_rec709_scene
get_cicp('pq_rec2020_display') = [9, 16, 9, 1]
get_cicp('unknown_interop_id') = None
isColorSpaceLinear('scene_linear') = True
isColorSpaceLinear('srgb') = False
isData('scene_linear') = False
isData('Raw') = True

Loaded test OCIO config: oiio_test_v0.9.2.ocio
Parsed color space for filepath 'foo_lin_ap1.exr': ACEScg
Expand Down
4 changes: 4 additions & 0 deletions testsuite/python-colorconfig/src/test_colorconfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@
print ("get_color_interop_id([1, 13, 1, 1]) = ", config.get_color_interop_id([1, 13, 1, 1]))
print ("get_cicp('pq_rec2020_display') = ", config.get_cicp("pq_rec2020_display"))
print ("get_cicp('unknown_interop_id') = ", config.get_cicp("unknown_interop_id"))
print ("isColorSpaceLinear('scene_linear') = ", config.isColorSpaceLinear('scene_linear'))
print ("isColorSpaceLinear('srgb') = ", config.isColorSpaceLinear('srgb'))
print ("isData('scene_linear') = ", config.isData('scene_linear'))
print ("isData('Raw') = ", config.isData('Raw'))
print ("")

config = oiio.ColorConfig(str(TEST_CONFIG_PATH))
Expand Down
Loading