Skip to content

Commit 8b4b874

Browse files
committed
Take into account OCIO config interop_id for mapping to CICP on write
1 parent 2e55121 commit 8b4b874

File tree

8 files changed

+77
-11
lines changed

8 files changed

+77
-11
lines changed

src/include/OpenImageIO/color.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,12 @@ class OIIO_API ColorConfig {
408408
/// @version 3.1
409409
cspan<int> get_cicp(string_view colorspace) const;
410410

411+
/// Find color interop ID for the given colorspace.
412+
/// Returns empty string if not found.
413+
///
414+
/// @version 3.1
415+
string_view get_color_interop_id(string_view colorspace) const;
416+
411417
/// Find color interop ID corresponding to the CICP code.
412418
/// Returns empty string if not found.
413419
///

src/libOpenImageIO/color_ocio.cpp

Lines changed: 54 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2033,38 +2033,56 @@ enum class CICPRange : int {
20332033
};
20342034

20352035
struct ColorInteropID {
2036+
constexpr ColorInteropID(const char* interop_id)
2037+
: interop_id(interop_id)
2038+
, cicp({ 0, 0, 0, 0 })
2039+
, has_cicp(false)
2040+
{
2041+
}
2042+
20362043
constexpr ColorInteropID(const char* interop_id, CICPPrimaries primaries,
20372044
CICPTransfer transfer, CICPMatrix matrix)
20382045
: interop_id(interop_id)
20392046
, cicp({ int(primaries), int(transfer), int(matrix),
20402047
int(CICPRange::Full) })
2048+
, has_cicp(true)
20412049
{
20422050
}
20432051

20442052
const char* interop_id;
20452053
std::array<int, 4> cicp;
2054+
bool has_cicp;
20462055
};
20472056

20482057
// Mapping between color interop ID and CICP, based on Color Interop Forum
20492058
// recommendations.
20502059
constexpr ColorInteropID color_interop_ids[] = {
20512060
// Scene referred interop IDs first so they are the default in automatic
2052-
// conversion from CICP to interop ID.
2053-
{ "srgb_rec709_scene", CICPPrimaries::Rec709, CICPTransfer::sRGB,
2054-
CICPMatrix::BT709 },
2055-
{ "srgb_p3d65_scene", CICPPrimaries::P3D65, CICPTransfer::sRGB,
2056-
CICPMatrix::BT709 },
2057-
{ "g22_rec709_scene", CICPPrimaries::Rec709, CICPTransfer::Gamma22,
2058-
CICPMatrix::BT709 },
2059-
// These are not display color spaces at all, but can be represented by CICP.
2061+
// conversion from CICP to interop ID. Some are not display color spaces
2062+
// at all, but can be represented by CICP anyway.
2063+
{ "lin_ap1_scene" },
2064+
{ "lin_ap0_scene" },
20602065
{ "lin_rec709_scene", CICPPrimaries::Rec709, CICPTransfer::Linear,
20612066
CICPMatrix::BT709 },
20622067
{ "lin_p3d65_scene", CICPPrimaries::P3D65, CICPTransfer::Linear,
20632068
CICPMatrix::BT709 },
20642069
{ "lin_rec2020_scene", CICPPrimaries::Rec2020, CICPTransfer::Linear,
20652070
CICPMatrix::Rec2020_CL },
2071+
{ "lin_adobergb_scene" },
20662072
{ "lin_ciexyzd65_scene", CICPPrimaries::XYZD65, CICPTransfer::Linear,
20672073
CICPMatrix::Unspecified },
2074+
{ "srgb_rec709_scene", CICPPrimaries::Rec709, CICPTransfer::sRGB,
2075+
CICPMatrix::BT709 },
2076+
{ "g22_rec709_scene", CICPPrimaries::Rec709, CICPTransfer::Gamma22,
2077+
CICPMatrix::BT709 },
2078+
{ "g18_rec709_scene" },
2079+
{ "srgb_ap1_scene" },
2080+
{ "g22_ap1_scene" },
2081+
{ "srgb_p3d65_scene", CICPPrimaries::P3D65, CICPTransfer::sRGB,
2082+
CICPMatrix::BT709 },
2083+
{ "g22_adobergb_scene" },
2084+
{ "data" },
2085+
{ "unknown" },
20682086

20692087
// Display referred interop IDs.
20702088
{ "srgb_rec709_display", CICPPrimaries::Rec709, CICPTransfer::sRGB,
@@ -2084,7 +2102,7 @@ constexpr ColorInteropID color_interop_ids[] = {
20842102
{ "g22_rec709_display", CICPPrimaries::Rec709, CICPTransfer::Gamma22,
20852103
CICPMatrix::BT709 },
20862104
// No CICP code for Adobe RGB primaries.
2087-
// { "g22_adobergb_display" }
2105+
{ "g22_adobergb_display" },
20882106
{ "g26_p3d65_display", CICPPrimaries::P3D65, CICPTransfer::Gamma26,
20892107
CICPMatrix::BT709 },
20902108
{ "g26_xyzd65_display", CICPPrimaries::XYZD65, CICPTransfer::Gamma26,
@@ -2094,11 +2112,35 @@ constexpr ColorInteropID color_interop_ids[] = {
20942112
};
20952113
} // namespace
20962114

2115+
string_view
2116+
ColorConfig::get_color_interop_id(string_view colorspace) const
2117+
{
2118+
if (colorspace.empty())
2119+
return "";
2120+
#if OCIO_VERSION_HEX >= MAKE_OCIO_VERSION_HEX(2, 5, 0)
2121+
if (getImpl()->config_ && !disable_ocio) {
2122+
OCIO::ConstColorSpaceRcPtr c = getImpl()->config_->getColorSpace(
2123+
std::string(resolve(colorspace)).c_str());
2124+
const char* interop_id = (c) ? c->getInteropID() : nullptr;
2125+
if (interop_id) {
2126+
return interop_id;
2127+
}
2128+
}
2129+
#endif
2130+
for (const ColorInteropID& interop : color_interop_ids) {
2131+
if (equivalent(colorspace, interop.interop_id)) {
2132+
return interop.interop_id;
2133+
}
2134+
}
2135+
return "";
2136+
}
2137+
20972138
string_view
20982139
ColorConfig::get_color_interop_id(const int cicp[4]) const
20992140
{
21002141
for (const ColorInteropID& interop : color_interop_ids) {
2101-
if (interop.cicp[0] == cicp[0] && interop.cicp[1] == cicp[1]) {
2142+
if (interop.has_cicp && interop.cicp[0] == cicp[0]
2143+
&& interop.cicp[1] == cicp[1]) {
21022144
return interop.interop_id;
21032145
}
21042146
}
@@ -2110,7 +2152,8 @@ ColorConfig::get_cicp(string_view colorspace) const
21102152
{
21112153
if (!colorspace.empty()) {
21122154
for (const ColorInteropID& interop : color_interop_ids) {
2113-
if (equivalent(colorspace, interop.interop_id)) {
2155+
if (interop.has_cicp
2156+
&& equivalent(colorspace, interop.interop_id)) {
21142157
return interop.cicp;
21152158
}
21162159
}

src/python/py_colorconfig.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,10 @@ declare_colorconfig(py::module& m)
161161
return self.equivalent(color_space, other_color_space);
162162
},
163163
"color_space"_a, "other_color_space"_a)
164+
.def("get_color_interop_id",
165+
[](const ColorConfig& self, const std::string& colorspace) {
166+
return std::string(self.get_color_interop_id(colorspace));
167+
})
164168
.def("get_color_interop_id",
165169
[](const ColorConfig& self, const std::array<int, 4> cicp) {
166170
return std::string(self.get_color_interop_id(cicp.data()));

testsuite/python-colorconfig/ref/out-ocio23.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ equivalent('linear', 'lin_srgb'): False
2626
equivalent('scene_linear', 'lin_srgb'): False
2727
equivalent('ACEScg', 'scene_linear'): True
2828
equivalent('lnf', 'scene_linear'): False
29+
get_color_interop_id('ACEScg') = lin_ap1_scene
30+
get_color_interop_id('lin_srgb') = lin_rec709_scene
2931
get_color_interop_id([1, 13, 1, 1]) = srgb_rec709_scene
3032
get_cicp('pq_rec2020_display') = [9, 16, 9, 1]
3133
get_cicp('unknown_interop_id') = None

testsuite/python-colorconfig/ref/out-ocio24.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ equivalent('linear', 'lin_srgb'): False
2626
equivalent('scene_linear', 'lin_srgb'): False
2727
equivalent('ACEScg', 'scene_linear'): True
2828
equivalent('lnf', 'scene_linear'): False
29+
get_color_interop_id('ACEScg') = lin_ap1_scene
30+
get_color_interop_id('lin_srgb') = lin_rec709_scene
2931
get_color_interop_id([1, 13, 1, 1]) = srgb_rec709_scene
3032
get_cicp('pq_rec2020_display') = [9, 16, 9, 1]
3133
get_cicp('unknown_interop_id') = None

testsuite/python-colorconfig/ref/out-ocio25.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ equivalent('linear', 'lin_srgb'): False
2626
equivalent('scene_linear', 'lin_srgb'): False
2727
equivalent('ACEScg', 'scene_linear'): True
2828
equivalent('lnf', 'scene_linear'): False
29+
get_color_interop_id('ACEScg') = lin_ap1_scene
30+
get_color_interop_id('lin_srgb') = lin_rec709_scene
2931
get_color_interop_id([1, 13, 1, 1]) = srgb_rec709_scene
3032
get_cicp('pq_rec2020_display') = [9, 16, 9, 1]
3133
get_cicp('unknown_interop_id') = None

testsuite/python-colorconfig/ref/out.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@ equivalent('linear', 'lin_srgb'): False
2626
equivalent('scene_linear', 'lin_srgb'): False
2727
equivalent('ACEScg', 'scene_linear'): True
2828
equivalent('lnf', 'scene_linear'): False
29+
get_color_interop_id('ACEScg') = lin_ap1_scene
30+
get_color_interop_id('lin_srgb') = lin_rec709_scene
31+
get_color_interop_id([1, 13, 1, 1]) = srgb_rec709_scene
32+
get_cicp('pq_rec2020_display') = [9, 16, 9, 1]
33+
get_cicp('unknown_interop_id') = None
2934

3035
Loaded test OCIO config: oiio_test_v0.9.2.ocio
3136
Parsed color space for filepath 'foo_lin_ap1.exr': ACEScg

testsuite/python-colorconfig/src/test_colorconfig.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@
4848
print ("equivalent('scene_linear', 'lin_srgb'):", config.equivalent("scene_linear", "lin_srgb"))
4949
print ("equivalent('ACEScg', 'scene_linear'):", config.equivalent("ACEScg", "scene_linear"))
5050
print ("equivalent('lnf', 'scene_linear'):", config.equivalent("lnf", "scene_linear"))
51+
print ("get_color_interop_id('ACEScg') = ", config.get_color_interop_id("ACEScg"))
52+
print ("get_color_interop_id('lin_srgb') = ", config.get_color_interop_id("lin_srgb"))
5153
print ("get_color_interop_id([1, 13, 1, 1]) = ", config.get_color_interop_id([1, 13, 1, 1]))
5254
print ("get_cicp('pq_rec2020_display') = ", config.get_cicp("pq_rec2020_display"))
5355
print ("get_cicp('unknown_interop_id') = ", config.get_cicp("unknown_interop_id"))

0 commit comments

Comments
 (0)