@@ -1997,6 +1997,173 @@ ColorConfig::parseColorSpaceFromString(string_view str) const
19971997}
19981998
19991999
2000+ // ////////////////////////////////////////////////////////////////////////
2001+ //
2002+ // Color Interop ID
2003+
2004+ namespace {
2005+ enum class CICPPrimaries : int {
2006+ Rec709 = 1 ,
2007+ Rec2020 = 9 ,
2008+ XYZD65 = 10 ,
2009+ P3D65 = 12 ,
2010+ };
2011+
2012+ enum class CICPTransfer : int {
2013+ BT709 = 1 ,
2014+ Gamma22 = 4 ,
2015+ Linear = 8 ,
2016+ sRGB = 13 ,
2017+ PQ = 16 ,
2018+ Gamma26 = 17 ,
2019+ HLG = 18 ,
2020+ };
2021+
2022+ enum class CICPMatrix : int {
2023+ RGB = 0 ,
2024+ BT709 = 1 ,
2025+ Unspecified = 2 ,
2026+ Rec2020_NCL = 9 ,
2027+ Rec2020_CL = 10 ,
2028+ };
2029+
2030+ enum class CICPRange : int {
2031+ Narrow = 0 ,
2032+ Full = 1 ,
2033+ };
2034+
2035+ 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+
2043+ constexpr ColorInteropID (const char * interop_id, CICPPrimaries primaries,
2044+ CICPTransfer transfer, CICPMatrix matrix)
2045+ : interop_id(interop_id)
2046+ , cicp({ int (primaries), int (transfer), int (matrix),
2047+ int (CICPRange::Full) })
2048+ , has_cicp(true )
2049+ {
2050+ }
2051+
2052+ const char * interop_id;
2053+ std::array<int , 4 > cicp;
2054+ bool has_cicp;
2055+ };
2056+
2057+ // Mapping between color interop ID and CICP, based on Color Interop Forum
2058+ // recommendations.
2059+ constexpr ColorInteropID color_interop_ids[] = {
2060+ // Scene referred interop IDs first so they are the default in automatic
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" },
2065+ { " lin_rec709_scene" , CICPPrimaries::Rec709, CICPTransfer::Linear,
2066+ CICPMatrix::BT709 },
2067+ { " lin_p3d65_scene" , CICPPrimaries::P3D65, CICPTransfer::Linear,
2068+ CICPMatrix::BT709 },
2069+ { " lin_rec2020_scene" , CICPPrimaries::Rec2020, CICPTransfer::Linear,
2070+ CICPMatrix::Rec2020_CL },
2071+ { " lin_adobergb_scene" },
2072+ { " lin_ciexyzd65_scene" , CICPPrimaries::XYZD65, CICPTransfer::Linear,
2073+ 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" },
2086+
2087+ // Display referred interop IDs.
2088+ { " srgb_rec709_display" , CICPPrimaries::Rec709, CICPTransfer::sRGB ,
2089+ CICPMatrix::BT709 },
2090+ { " g24_rec709_display" , CICPPrimaries::Rec709, CICPTransfer::BT709,
2091+ CICPMatrix::BT709 },
2092+ { " srgb_p3d65_display" , CICPPrimaries::P3D65, CICPTransfer::sRGB ,
2093+ CICPMatrix::BT709 },
2094+ { " srgbe_p3d65_display" , CICPPrimaries::P3D65, CICPTransfer::sRGB ,
2095+ CICPMatrix::BT709 },
2096+ { " pq_p3d65_display" , CICPPrimaries::P3D65, CICPTransfer::PQ,
2097+ CICPMatrix::Rec2020_NCL },
2098+ { " pq_rec2020_display" , CICPPrimaries::Rec2020, CICPTransfer::PQ,
2099+ CICPMatrix::Rec2020_NCL },
2100+ { " hlg_rec2020_display" , CICPPrimaries::Rec2020, CICPTransfer::HLG,
2101+ CICPMatrix::Rec2020_NCL },
2102+ // No CICP mapping to keep previous behavior unchanged, as Gamma 2.2
2103+ // display is more likely meant to be written as sRGB. On read the
2104+ // scene referred interop ID will be used.
2105+ { " g22_rec709_display" ,
2106+ /* CICPPrimaries::Rec709, CICPTransfer::Gamma22, CICPMatrix::BT709 */ },
2107+ // No CICP code for Adobe RGB primaries.
2108+ { " g22_adobergb_display" },
2109+ { " g26_p3d65_display" , CICPPrimaries::P3D65, CICPTransfer::Gamma26,
2110+ CICPMatrix::BT709 },
2111+ { " g26_xyzd65_display" , CICPPrimaries::XYZD65, CICPTransfer::Gamma26,
2112+ CICPMatrix::Unspecified },
2113+ { " pq_xyzd65_display" , CICPPrimaries::XYZD65, CICPTransfer::PQ,
2114+ CICPMatrix::Unspecified },
2115+ };
2116+ } // namespace
2117+
2118+ string_view
2119+ ColorConfig::get_color_interop_id (string_view colorspace) const
2120+ {
2121+ if (colorspace.empty ())
2122+ return " " ;
2123+ #if OCIO_VERSION_HEX >= MAKE_OCIO_VERSION_HEX(2, 5, 0)
2124+ if (getImpl ()->config_ && !disable_ocio) {
2125+ OCIO::ConstColorSpaceRcPtr c = getImpl ()->config_ ->getColorSpace (
2126+ std::string (resolve (colorspace)).c_str ());
2127+ const char * interop_id = (c) ? c->getInteropID () : nullptr ;
2128+ if (interop_id) {
2129+ return interop_id;
2130+ }
2131+ }
2132+ #endif
2133+ for (const ColorInteropID& interop : color_interop_ids) {
2134+ if (equivalent (colorspace, interop.interop_id )) {
2135+ return interop.interop_id ;
2136+ }
2137+ }
2138+ return " " ;
2139+ }
2140+
2141+ string_view
2142+ ColorConfig::get_color_interop_id (const int cicp[4 ]) const
2143+ {
2144+ for (const ColorInteropID& interop : color_interop_ids) {
2145+ if (interop.has_cicp && interop.cicp [0 ] == cicp[0 ]
2146+ && interop.cicp [1 ] == cicp[1 ]) {
2147+ return interop.interop_id ;
2148+ }
2149+ }
2150+ return " " ;
2151+ }
2152+
2153+ cspan<int >
2154+ ColorConfig::get_cicp (string_view colorspace) const
2155+ {
2156+ string_view interop_id = get_color_interop_id (colorspace);
2157+ if (!interop_id.empty ()) {
2158+ for (const ColorInteropID& interop : color_interop_ids) {
2159+ if (interop.has_cicp && interop_id == interop.interop_id ) {
2160+ return interop.cicp ;
2161+ }
2162+ }
2163+ }
2164+ return cspan<int >();
2165+ }
2166+
20002167
20012168// ////////////////////////////////////////////////////////////////////////
20022169//
0 commit comments