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
108 changes: 73 additions & 35 deletions src/libOpenImageIO/color_ocio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -159,14 +159,17 @@ struct CSInfo {
int index; // More than one can have the same index -- aliases
enum Flags {
none = 0,
is_linear_response = 1, // any cs with linear transfer function
is_scene_linear = 2, // equivalent to scene_linear
is_srgb = 4, // sRGB (primaries, and transfer function)
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
is_linear_response = 1, // any cs with linear transfer function
is_scene_linear = 2, // equivalent to scene_linear
is_srgb_display = 4, // sRGB (primaries, and transfer function) display
is_srgb_scene = 8, // sRGB (primaries, and transfer function) scene
is_lin_srgb = 16, // sRGB/Rec709 primaries, linear response
is_ACEScg = 32, // ACEScg
is_Rec709 = 64, // Rec709 primaries and transfer function
is_data = 128, // Non-color-managed data
is_known = is_srgb_display | is_srgb_scene | is_lin_srgb | is_ACEScg
| is_Rec709

};
int m_flags = 0;
bool examined = false;
Expand Down Expand Up @@ -208,7 +211,8 @@ class ColorConfig::Impl {
std::vector<CSInfo> colorspaces;
std::string scene_linear_alias; // Alias for a scene-linear color space
std::string lin_srgb_alias;
std::string srgb_alias;
std::string srgb_display_alias;
std::string srgb_scene_alias;
std::string ACEScg_alias;
std::string Rec709_alias;
mutable spin_rw_mutex m_mutex;
Expand Down Expand Up @@ -406,9 +410,9 @@ class ColorConfig::Impl {

void debug_print_aliases()
{
DBG("Aliases: scene_linear={} lin_srgb={} srgb={} ACEScg={} Rec709={}\n",
scene_linear_alias, lin_srgb_alias, srgb_alias, ACEScg_alias,
Rec709_alias);
DBG("Aliases: scene_linear={} lin_srgb={} srgb_display={} srgb_scene={} ACEScg={} Rec709={}\n",
scene_linear_alias, lin_srgb_alias, srgb_display_alias,
srgb_scene_alias, ACEScg_alias, Rec709_alias);
}

// For OCIO 2.3+, we can ask for the equivalent of some built-in
Expand All @@ -426,7 +430,7 @@ class ColorConfig::Impl {


// ColorConfig utility to take inventory of the color spaces available.
// It sets up knowledge of "linear", "srgb_rec709_scene", "Rec709", etc,
// It sets up knowledge of "linear", "srgb_rec709_display", "Rec709", etc,
// even if the underlying OCIO configuration lacks them.
void
ColorConfig::Impl::inventory()
Expand Down Expand Up @@ -474,8 +478,9 @@ ColorConfig::Impl::inventory()
add("lin_rec709_scene", 0, linflags);
add("lin_srgb", 0, linflags);
add("lin_rec709", 0, linflags);
add("srgb_rec709_scene", 1, CSInfo::is_srgb);
add("sRGB", 1, CSInfo::is_srgb);
add("srgb_rec709_display", 1, CSInfo::is_srgb_display);
add("srgb_rec709_scene", 1, CSInfo::is_srgb_scene);
add("sRGB", 1, CSInfo::is_srgb_scene);
add("Rec709", 2, CSInfo::is_Rec709);

for (auto&& cs : colorspaces)
Expand Down Expand Up @@ -589,14 +594,17 @@ ColorConfig::Impl::classify_by_name(CSInfo& cs)
// General heuristics based on the names -- for a few canonical names,
// believe them! Woe be unto the poor soul who names a color space "sRGB"
// or "ACEScg" and it's really something entirely different.
if (Strutil::iequals(cs.name, "srgb_rec709_scene")
|| Strutil::iequals(cs.name, "srgb_tx")
|| Strutil::iequals(cs.name, "srgb_texture")
|| Strutil::iequals(cs.name, "srgb texture")
|| Strutil::iequals(cs.name, "srgb_rec709_scene")
|| Strutil::iequals(cs.name, "sRGB - Texture")
|| Strutil::iequals(cs.name, "sRGB")) {
cs.setflag(CSInfo::is_srgb, srgb_alias);
if (Strutil::iequals(cs.name, "srgb_rec709_display")
|| Strutil::iequals(cs.name, "srgb_display")
|| Strutil::iequals(cs.name, "sRGB - Display")) {
cs.setflag(CSInfo::is_srgb_display, srgb_display_alias);
} else if (Strutil::iequals(cs.name, "srgb_rec709_scene")
|| Strutil::iequals(cs.name, "srgb_tx")
|| Strutil::iequals(cs.name, "srgb_texture")
|| Strutil::iequals(cs.name, "srgb texture")
|| Strutil::iequals(cs.name, "sRGB - Texture")
|| Strutil::iequals(cs.name, "sRGB")) {
cs.setflag(CSInfo::is_srgb_scene, srgb_scene_alias);
} else if (Strutil::iequals(cs.name, "lin_rec709_scene")
|| Strutil::iequals(cs.name, "lin_rec709")
|| Strutil::iequals(cs.name, "Linear Rec.709 (sRGB)")
Expand All @@ -622,7 +630,7 @@ ColorConfig::Impl::classify_by_name(CSInfo& cs)
ACEScg_alias);
} else if (cs.name == "srgbf" || cs.name == "srgbh" || cs.name == "srgb16"
|| cs.name == "srgb8") {
cs.setflag(CSInfo::is_srgb, srgb_alias);
cs.setflag(CSInfo::is_srgb_scene, srgb_scene_alias);
} else if (cs.name == "srgblnf" || cs.name == "srgblnh"
|| cs.name == "srgbln16" || cs.name == "srgbln8") {
cs.setflag(CSInfo::is_lin_srgb, lin_srgb_alias);
Expand All @@ -633,7 +641,9 @@ ColorConfig::Impl::classify_by_name(CSInfo& cs)
#endif

// Set up some canonical names
if (cs.flags() & CSInfo::is_srgb)
if (cs.flags() & CSInfo::is_srgb_display)
cs.canonical = "srgb_rec709_display";
else if (cs.flags() & CSInfo::is_srgb_scene)
cs.canonical = "srgb_rec709_scene";
else if (cs.flags() & CSInfo::is_lin_srgb)
cs.canonical = "lin_rec709_scene";
Expand Down Expand Up @@ -685,9 +695,12 @@ ColorConfig::Impl::classify_by_conversions(CSInfo& cs)
// inversion costs, and they're not gonna be our favourite
// canonical spaces anyway.
// DBG("{} has LUT3\n", cs.name);
} else if (check_same_as_builtin_transform(cs.name.c_str(),
"srgb_display")) {
cs.setflag(CSInfo::is_srgb_display, srgb_display_alias);
} else if (check_same_as_builtin_transform(cs.name.c_str(),
"srgb_tx")) {
cs.setflag(CSInfo::is_srgb, srgb_alias);
cs.setflag(CSInfo::is_srgb_scene, srgb_scene_alias);
} else if (check_same_as_builtin_transform(cs.name.c_str(),
"lin_srgb")) {
cs.setflag(CSInfo::is_lin_srgb | CSInfo::is_linear_response,
Expand All @@ -707,7 +720,9 @@ ColorConfig::Impl::classify_by_conversions(CSInfo& cs)
}

// Set up some canonical names
if (cs.flags() & CSInfo::is_srgb)
if (cs.flags() & CSInfo::is_srgb_display)
cs.canonical = "srgb_rec709_display";
else if (cs.flags() & CSInfo::is_srgb_scene)
cs.canonical = "srgb_rec709_scene";
else if (cs.flags() & CSInfo::is_lin_srgb)
cs.canonical = "lin_rec709_scene";
Expand Down Expand Up @@ -738,6 +753,9 @@ ColorConfig::Impl::reclassify_heuristics(CSInfo& cs)
// If there is a known srgb space, and transforming our test
// colors from "this cs" to srgb gives us what we expect for a
// lin_srgb->srgb, then guess what? -- this is lin_srgb!
const std::string& srgb_alias = srgb_scene_alias.size()
? srgb_scene_alias
: srgb_display_alias;
if (srgb_alias.size()
&& test_conversion_yields(cs.name.c_str(), srgb_alias.c_str(),
test_colors, lin_srgb_to_srgb_results)) {
Expand All @@ -757,14 +775,23 @@ ColorConfig::Impl::identify_builtin_equivalents()
if (disable_builtin_configs)
return;
Timer timer;
if (auto n = IdentifyBuiltinColorSpace("srgb_display")) {
if (CSInfo* cs = find(n)) {
cs->setflag(CSInfo::is_srgb_display, srgb_display_alias);
DBG("Identified {} = builtin '{}'\n", "srgb_rec709_display",
cs->name);
}
} else {
DBG("No config space identified as srgb_display\n");
}
if (auto n = IdentifyBuiltinColorSpace("srgb_tx")) {
if (CSInfo* cs = find(n)) {
cs->setflag(CSInfo::is_srgb, srgb_alias);
cs->setflag(CSInfo::is_srgb_scene, srgb_scene_alias);
DBG("Identified {} = builtin '{}'\n", "srgb_rec709_scene",
cs->name);
}
} else {
DBG("No config space identified as srgb\n");
DBG("No config space identified as srgb_scene\n");
}
DBG("identify_builtin_equivalents srgb took {:0.2f}s\n", timer.lap());
if (auto n = IdentifyBuiltinColorSpace("lin_srgb")) {
Expand Down Expand Up @@ -921,8 +948,10 @@ ColorConfig::Impl::init(string_view filename)
for (auto&& cs : colorspaces) {
// examine(&cs);
DBG("Color space '{}':\n", cs.name);
if (cs.flags() & CSInfo::is_srgb)
DBG("'{}' is srgb\n", cs.name);
if (cs.flags() & CSInfo::is_srgb_display)
DBG("'{}' is srgb_display\n", cs.name);
if (cs.flags() & CSInfo::is_srgb_scene)
DBG("'{}' is srgb_scene\n", cs.name);
if (cs.flags() & CSInfo::is_lin_srgb)
DBG("'{}' is lin_srgb\n", cs.name);
if (cs.flags() & CSInfo::is_ACEScg)
Expand Down Expand Up @@ -1529,8 +1558,11 @@ ColorConfig::Impl::resolve(string_view name) const
spin_rw_write_lock lock(m_mutex);
if ((Strutil::iequals(name, "sRGB")
|| Strutil::iequals(name, "srgb_rec709_scene"))
&& !srgb_alias.empty())
return srgb_alias;
&& !srgb_scene_alias.empty())
return srgb_scene_alias;
if (Strutil::iequals(name, "srgb_rec709_display")
&& !srgb_display_alias.empty())
return srgb_display_alias;
if ((Strutil::iequals(name, "lin_srgb")
|| Strutil::iequals(name, "lin_rec709")
|| Strutil::iequals(name, "lin_rec709_scene")
Expand Down Expand Up @@ -1574,7 +1606,8 @@ ColorConfig::equivalent(string_view color_space1,

// If the color spaces' flags (when masking only the bits that refer to
// specific known color spaces) match, consider them equivalent.
const int mask = CSInfo::is_srgb | CSInfo::is_lin_srgb | CSInfo::is_ACEScg
const int mask = CSInfo::is_srgb_display | CSInfo::is_srgb_scene
| CSInfo::is_lin_srgb | CSInfo::is_ACEScg
| CSInfo::is_Rec709;
const CSInfo* csi1 = getImpl()->find(color_space1);
const CSInfo* csi2 = getImpl()->find(color_space2);
Expand Down Expand Up @@ -2321,6 +2354,11 @@ constexpr ColorInteropID color_interop_ids[] = {
CICPMatrix::Unspecified },
{ "pq_xyzd65_display", CICPPrimaries::XYZD65, CICPTransfer::PQ,
CICPMatrix::Unspecified },

// OpenColorIO interop IDs, last so that the official ones above take
// priority when converting a CICP to an interop ID.
{ "ocio:lin_ciexyzd65_display", CICPPrimaries::XYZD65, CICPTransfer::Linear,
CICPMatrix::Unspecified },
};
} // namespace

Expand All @@ -2340,7 +2378,7 @@ ColorConfig::get_color_interop_id(string_view colorspace) const
} catch (...) {
interop_id = nullptr;
}
if (interop_id) {
if (interop_id && interop_id[0]) {
return interop_id;
}
}
Expand Down
3 changes: 3 additions & 0 deletions testsuite/python-colorconfig/ref/out-ocio230.txt
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ equivalent('lnf', 'scene_linear'): False
get_color_interop_id('ACEScg') = lin_ap1_scene
get_color_interop_id('lin_srgb') = lin_rec709_scene
get_color_interop_id([1, 13, 1, 1]) = srgb_rec709_scene
resolve('srgb_rec709_display'): srgb_rec709_display
equivalent('srgb_rec709_display', 'srgb_rec709_scene'): False
get_color_interop_id('sRGB - Display') = ''
get_cicp('pq_rec2020_display') = [9, 16, 9, 1]
get_cicp('unknown_interop_id') = None
isColorSpaceLinear('scene_linear') = True
Expand Down
3 changes: 3 additions & 0 deletions testsuite/python-colorconfig/ref/out-ocio230b.txt
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ equivalent('lnf', 'scene_linear'): False
get_color_interop_id('ACEScg') = lin_ap1_scene
get_color_interop_id('lin_srgb') = lin_rec709_scene
get_color_interop_id([1, 13, 1, 1]) = srgb_rec709_scene
resolve('srgb_rec709_display'): srgb_rec709_display
equivalent('srgb_rec709_display', 'srgb_rec709_scene'): False
get_color_interop_id('sRGB - Display') = ''
get_cicp('pq_rec2020_display') = [9, 16, 9, 1]
get_cicp('unknown_interop_id') = None
isColorSpaceLinear('scene_linear') = True
Expand Down
3 changes: 3 additions & 0 deletions testsuite/python-colorconfig/ref/out-ocio232.txt
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ equivalent('lnf', 'scene_linear'): False
get_color_interop_id('ACEScg') = lin_ap1_scene
get_color_interop_id('lin_srgb') = lin_rec709_scene
get_color_interop_id([1, 13, 1, 1]) = srgb_rec709_scene
resolve('srgb_rec709_display'): srgb_rec709_display
equivalent('srgb_rec709_display', 'srgb_rec709_scene'): False
get_color_interop_id('sRGB - Display') = ''
get_cicp('pq_rec2020_display') = [9, 16, 9, 1]
get_cicp('unknown_interop_id') = None
isColorSpaceLinear('scene_linear') = True
Expand Down
3 changes: 3 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,9 @@ equivalent('lnf', 'scene_linear'): False
get_color_interop_id('ACEScg') = lin_ap1_scene
get_color_interop_id('lin_srgb') = lin_rec709_scene
get_color_interop_id([1, 13, 1, 1]) = srgb_rec709_scene
resolve('srgb_rec709_display'): sRGB - Display
equivalent('srgb_rec709_display', 'srgb_rec709_scene'): False
get_color_interop_id('sRGB - Display') = 'srgb_rec709_display'
get_cicp('pq_rec2020_display') = [9, 16, 9, 1]
get_cicp('unknown_interop_id') = None
isColorSpaceLinear('scene_linear') = True
Expand Down
3 changes: 3 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,9 @@ equivalent('lnf', 'scene_linear'): False
get_color_interop_id('ACEScg') = lin_ap1_scene
get_color_interop_id('lin_srgb') = lin_rec709_scene
get_color_interop_id([1, 13, 1, 1]) = srgb_rec709_scene
resolve('srgb_rec709_display'): sRGB - Display
equivalent('srgb_rec709_display', 'srgb_rec709_scene'): False
get_color_interop_id('sRGB - Display') = 'srgb_rec709_display'
get_cicp('pq_rec2020_display') = [9, 16, 9, 1]
get_cicp('unknown_interop_id') = None
isColorSpaceLinear('scene_linear') = True
Expand Down
3 changes: 3 additions & 0 deletions testsuite/python-colorconfig/ref/out.txt
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ equivalent('lnf', 'scene_linear'): False
get_color_interop_id('ACEScg') = lin_ap1_scene
get_color_interop_id('lin_srgb') = lin_rec709_scene
get_color_interop_id([1, 13, 1, 1]) = srgb_rec709_scene
resolve('srgb_rec709_display'): srgb_rec709_display
equivalent('srgb_rec709_display', 'srgb_rec709_scene'): False
get_color_interop_id('sRGB - Display') = ''
get_cicp('pq_rec2020_display') = [9, 16, 9, 1]
get_cicp('unknown_interop_id') = None
isColorSpaceLinear('scene_linear') = True
Expand Down
3 changes: 3 additions & 0 deletions testsuite/python-colorconfig/src/test_colorconfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@
print ("get_color_interop_id('ACEScg') = ", config.get_color_interop_id("ACEScg"))
print ("get_color_interop_id('lin_srgb') = ", config.get_color_interop_id("lin_srgb"))
print ("get_color_interop_id([1, 13, 1, 1]) = ", config.get_color_interop_id([1, 13, 1, 1]))
print ("resolve('srgb_rec709_display'):", config.resolve("srgb_rec709_display"))
print ("equivalent('srgb_rec709_display', 'srgb_rec709_scene'):", config.equivalent("srgb_rec709_display", "srgb_rec709_scene"))
print (f"get_color_interop_id('sRGB - Display') = '{config.get_color_interop_id('sRGB - Display')}'")
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'))
Expand Down
Loading