@@ -1997,6 +1997,127 @@ 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, CICPPrimaries primaries,
2037+ CICPTransfer transfer, CICPMatrix matrix)
2038+ : interop_id(interop_id)
2039+ , cicp({ int (primaries), int (transfer), int (matrix),
2040+ int (CICPRange::Full) })
2041+ {
2042+ }
2043+
2044+ const char * interop_id;
2045+ std::array<int , 4 > cicp;
2046+ };
2047+
2048+ // Mapping between color interop ID and CICP, based on Color Interop Forum
2049+ // recommendations.
2050+ constexpr ColorInteropID color_interop_ids[] = {
2051+ // 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.
2060+ { " lin_rec709_scene" , CICPPrimaries::Rec709, CICPTransfer::Linear,
2061+ CICPMatrix::BT709 },
2062+ { " lin_p3d65_scene" , CICPPrimaries::P3D65, CICPTransfer::Linear,
2063+ CICPMatrix::BT709 },
2064+ { " lin_rec2020_scene" , CICPPrimaries::Rec2020, CICPTransfer::Linear,
2065+ CICPMatrix::Rec2020_CL },
2066+ { " lin_ciexyzd65_scene" , CICPPrimaries::XYZD65, CICPTransfer::Linear,
2067+ CICPMatrix::Unspecified },
2068+
2069+ // Display referred interop IDs.
2070+ { " srgb_rec709_display" , CICPPrimaries::Rec709, CICPTransfer::sRGB ,
2071+ CICPMatrix::BT709 },
2072+ { " g24_rec709_display" , CICPPrimaries::Rec709, CICPTransfer::BT709,
2073+ CICPMatrix::BT709 },
2074+ { " srgb_p3d65_display" , CICPPrimaries::P3D65, CICPTransfer::sRGB ,
2075+ CICPMatrix::BT709 },
2076+ { " srgbe_p3d65_display" , CICPPrimaries::P3D65, CICPTransfer::sRGB ,
2077+ CICPMatrix::BT709 },
2078+ { " pq_p3d65_display" , CICPPrimaries::P3D65, CICPTransfer::PQ,
2079+ CICPMatrix::Rec2020_NCL },
2080+ { " pq_rec2020_display" , CICPPrimaries::Rec2020, CICPTransfer::PQ,
2081+ CICPMatrix::Rec2020_NCL },
2082+ { " hlg_rec2020_display" , CICPPrimaries::Rec2020, CICPTransfer::HLG,
2083+ CICPMatrix::Rec2020_NCL },
2084+ { " g22_rec709_display" , CICPPrimaries::Rec709, CICPTransfer::Gamma22,
2085+ CICPMatrix::BT709 },
2086+ // No CICP code for Adobe RGB primaries.
2087+ // { "g22_adobergb_display" }
2088+ { " g26_p3d65_display" , CICPPrimaries::P3D65, CICPTransfer::Gamma26,
2089+ CICPMatrix::BT709 },
2090+ { " g26_xyzd65_display" , CICPPrimaries::XYZD65, CICPTransfer::Gamma26,
2091+ CICPMatrix::Unspecified },
2092+ { " pq_xyzd65_display" , CICPPrimaries::XYZD65, CICPTransfer::PQ,
2093+ CICPMatrix::Unspecified },
2094+ };
2095+ } // namespace
2096+
2097+ string_view
2098+ ColorConfig::getColorInteropID (const int cicp[4 ]) const
2099+ {
2100+ for (const ColorInteropID& interop : color_interop_ids) {
2101+ if (interop.cicp [0 ] == cicp[0 ] && interop.cicp [1 ] == cicp[1 ]) {
2102+ return interop.interop_id ;
2103+ }
2104+ }
2105+ return " " ;
2106+ }
2107+
2108+ const int *
2109+ ColorConfig::getCICP (string_view colorspace) const
2110+ {
2111+ if (!colorspace.empty ()) {
2112+ for (const ColorInteropID& interop : color_interop_ids) {
2113+ if (equivalent (colorspace, interop.interop_id )) {
2114+ return interop.cicp .data ();
2115+ }
2116+ }
2117+ }
2118+ return nullptr ;
2119+ }
2120+
20002121
20012122// ////////////////////////////////////////////////////////////////////////
20022123//
@@ -2655,134 +2776,6 @@ ColorConfig::set_colorspace_rec709_gamma(ImageSpec& spec, float gamma) const
26552776 }
26562777}
26572778
2658- namespace {
2659- enum class CICPPrimaries {
2660- Rec709 = 1 ,
2661- Rec2020 = 9 ,
2662- XYZD65 = 10 ,
2663- P3D65 = 12 ,
2664- };
2665- enum class CICPTransfer {
2666- BT709 = 1 ,
2667- Gamma22 = 4 ,
2668- Linear = 8 ,
2669- sRGB = 13 ,
2670- PQ = 16 ,
2671- Gamma26 = 17 ,
2672- HLG = 18 ,
2673- };
2674- enum class CICPMatrix {
2675- RGB = 0 ,
2676- BT709 = 1 ,
2677- Unspecified = 2 ,
2678- Rec2020_NCL = 9 ,
2679- Rec2020_CL = 10 ,
2680- };
2681- enum class CICPRange {
2682- Narrow = 0 ,
2683- Full = 1 ,
2684- };
2685-
2686- // Mapping between color interop ID and CICP, based on Color Interop Forum
2687- // recommendations.
2688- struct ColorSpaceCICP {
2689- const char * interop_id;
2690- CICPPrimaries primaries;
2691- CICPTransfer transfer;
2692- CICPMatrix matrix;
2693- };
2694-
2695- constexpr ColorSpaceCICP color_space_cicp[] = {
2696- // Scene referred interop IDs first so they are the default in automatic
2697- // conversion from CICP to interop ID.
2698- { " srgb_rec709_scene" , CICPPrimaries::Rec709, CICPTransfer::sRGB ,
2699- CICPMatrix::BT709 },
2700- { " srgb_rec709_scene" , CICPPrimaries::Rec709, CICPTransfer::sRGB ,
2701- CICPMatrix::BT709 },
2702- { " srgb_p3d65_scene" , CICPPrimaries::P3D65, CICPTransfer::sRGB ,
2703- CICPMatrix::BT709 },
2704- // These are not display color spaces at all, but can be represented by CICP.
2705- { " lin_rec709_scene" , CICPPrimaries::Rec709, CICPTransfer::Linear,
2706- CICPMatrix::BT709 },
2707- { " lin_p3d65_scene" , CICPPrimaries::P3D65, CICPTransfer::Linear,
2708- CICPMatrix::BT709 },
2709- { " lin_rec2020_scene" , CICPPrimaries::Rec2020, CICPTransfer::Linear,
2710- CICPMatrix::Rec2020_CL },
2711- { " lin_ciexyzd65_scene" , CICPPrimaries::XYZD65, CICPTransfer::Linear,
2712- CICPMatrix::Unspecified },
2713-
2714- // Display referred interop IDs.
2715- { " srgb_rec709_display" , CICPPrimaries::Rec709, CICPTransfer::sRGB ,
2716- CICPMatrix::BT709 },
2717- { " g24_rec709_display" , CICPPrimaries::Rec709, CICPTransfer::BT709,
2718- CICPMatrix::BT709 },
2719- { " srgb_p3d65_display" , CICPPrimaries::P3D65, CICPTransfer::sRGB ,
2720- CICPMatrix::BT709 },
2721- { " srgbe_p3d65_display" , CICPPrimaries::P3D65, CICPTransfer::sRGB ,
2722- CICPMatrix::BT709 },
2723- { " pq_p3d65_display" , CICPPrimaries::P3D65, CICPTransfer::PQ,
2724- CICPMatrix::Rec2020_NCL },
2725- { " pq_rec2020_display" , CICPPrimaries::Rec2020, CICPTransfer::PQ,
2726- CICPMatrix::Rec2020_NCL },
2727- { " hlg_rec2020_display" , CICPPrimaries::Rec2020, CICPTransfer::HLG,
2728- CICPMatrix::Rec2020_NCL },
2729- { " g22_rec709_display" , CICPPrimaries::Rec709, CICPTransfer::Gamma22,
2730- CICPMatrix::BT709 },
2731- // No CICP code for Adobe RGB primaries.
2732- // { "g22_adobergb_display" }
2733- { " g26_p3d65_display" , CICPPrimaries::P3D65, CICPTransfer::Gamma26,
2734- CICPMatrix::BT709 },
2735- { " g26_xyzd65_display" , CICPPrimaries::XYZD65, CICPTransfer::Gamma26,
2736- CICPMatrix::Unspecified },
2737- { " pq_xyzd65_display" , CICPPrimaries::XYZD65, CICPTransfer::PQ,
2738- CICPMatrix::Unspecified },
2739- };
2740- } // namespace
2741-
2742- void
2743- ColorConfig::set_colorspace_cicp (ImageSpec& spec, const int cicp[4 ]) const
2744- {
2745- spec.attribute (" CICP" , TypeDesc (TypeDesc::INT, 4 ), cicp);
2746-
2747- for (const ColorSpaceCICP& space : color_space_cicp) {
2748- if (int (space.primaries ) == cicp[0 ] && int (space.transfer ) == cicp[1 ]) {
2749- set_colorspace (spec, space.interop_id );
2750- return ;
2751- }
2752- }
2753- }
2754-
2755- bool
2756- ColorConfig::get_colorspace_cicp (ImageSpec& spec, bool auto_cicp,
2757- int cicp[4 ]) const
2758- {
2759- const ParamValue* p = spec.find_attribute (" CICP" ,
2760- TypeDesc (TypeDesc::INT, 4 ));
2761- if (p) {
2762- std::copy_n (static_cast <const int *>(p->data ()), 4 , cicp);
2763- return true ;
2764- }
2765-
2766- if (!auto_cicp) {
2767- return false ;
2768- }
2769-
2770- string_view colorspace = spec.get_string_attribute (" oiio:ColorSpace" );
2771- if (!colorspace.empty ()) {
2772- for (const ColorSpaceCICP& space : color_space_cicp) {
2773- if (equivalent (colorspace, space.interop_id )) {
2774- cicp[0 ] = int (space.primaries );
2775- cicp[1 ] = int (space.transfer );
2776- cicp[2 ] = int (space.matrix );
2777- cicp[3 ] = int (CICPRange::Full);
2778- return true ;
2779- }
2780- }
2781- }
2782-
2783- return false ;
2784- }
2785-
27862779void
27872780set_colorspace (ImageSpec& spec, string_view colorspace)
27882781{
0 commit comments