File indexing completed on 2024-05-26 04:32:15
0001 /* 0002 * SPDX-FileCopyrightText: 2019 Dmitry Kazakov <dimula73@gmail.com> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #ifndef LCMSRGBP2020PQCOLORSPACE_H 0008 #define LCMSRGBP2020PQCOLORSPACE_H 0009 0010 0011 #include <colorspaces/rgb_u8/RgbU8ColorSpace.h> 0012 #include <colorspaces/rgb_u16/RgbU16ColorSpace.h> 0013 0014 #ifdef HAVE_OPENEXR 0015 #include <colorspaces/rgb_f16/RgbF16ColorSpace.h> 0016 #endif 0017 0018 #include <colorspaces/rgb_f32/RgbF32ColorSpace.h> 0019 0020 #include "KoColorConversionTransformationFactory.h" 0021 0022 #include <LcmsRGBP2020PQColorSpaceTransformation.h> 0023 0024 template <class T> 0025 struct ColorSpaceFromFactory { 0026 }; 0027 0028 template<> 0029 struct ColorSpaceFromFactory<RgbU8ColorSpaceFactory> { 0030 typedef RgbU8ColorSpace type; 0031 }; 0032 0033 template<> 0034 struct ColorSpaceFromFactory<RgbU16ColorSpaceFactory> { 0035 typedef RgbU16ColorSpace type; 0036 }; 0037 0038 #ifdef HAVE_OPENEXR 0039 template<> 0040 struct ColorSpaceFromFactory<RgbF16ColorSpaceFactory> { 0041 typedef RgbF16ColorSpace type; 0042 }; 0043 #endif 0044 0045 template<> 0046 struct ColorSpaceFromFactory<RgbF32ColorSpaceFactory> { 0047 typedef RgbF32ColorSpace type; 0048 }; 0049 0050 /** 0051 * Define a singly linked list of supported bit depth traits 0052 */ 0053 template<class T> struct NextTrait { using type = void; }; 0054 template<> struct NextTrait<KoBgrU8Traits> { using type = KoBgrU16Traits; }; 0055 0056 #ifdef HAVE_OPENEXR 0057 template<> struct NextTrait<KoBgrU16Traits> { using type = KoRgbF16Traits; }; 0058 template<> struct NextTrait<KoRgbF16Traits> { using type = KoRgbF32Traits; }; 0059 #else 0060 template<> struct NextTrait<KoBgrU16Traits> { using type = KoRgbF32Traits; }; 0061 #endif 0062 0063 /** 0064 * Recursively add bit-depths conversions to the color space. We add only 0065 * **outgoing** conversions for every RGB color space. That is, every color 0066 * space has exactly three outgoing edges for color conversion. 0067 */ 0068 template<typename ParentColorSpace, typename CurrentTraits> 0069 void addInternalConversion(QList<KoColorConversionTransformationFactory*> &list, CurrentTraits*) 0070 { 0071 // general case: add a converter and recurse for the next traits 0072 list << new LcmsScaleRGBP2020PQTransformationFactory<ParentColorSpace, CurrentTraits>(); 0073 0074 using NextTraits = typename NextTrait<CurrentTraits>::type; 0075 addInternalConversion<ParentColorSpace>(list, static_cast<NextTraits*>(0)); 0076 } 0077 0078 template<typename ParentColorSpace> 0079 void addInternalConversion(QList<KoColorConversionTransformationFactory*> &list, typename ParentColorSpace::ColorSpaceTraits*) 0080 { 0081 // exception: skip adding an edge to the same bit depth 0082 0083 using CurrentTraits = typename ParentColorSpace::ColorSpaceTraits; 0084 using NextTraits = typename NextTrait<CurrentTraits>::type; 0085 addInternalConversion<ParentColorSpace>(list, static_cast<NextTraits*>(0)); 0086 } 0087 0088 template<typename ParentColorSpace> 0089 void addInternalConversion(QList<KoColorConversionTransformationFactory*> &, void*) 0090 { 0091 // stop recursion 0092 } 0093 0094 template <class BaseColorSpaceFactory> 0095 class LcmsRGBP2020PQColorSpaceFactoryWrapper : public BaseColorSpaceFactory 0096 { 0097 typedef typename ColorSpaceFromFactory<BaseColorSpaceFactory>::type RelatedColorSpaceType; 0098 0099 KoColorSpace *createColorSpace(const KoColorProfile *p) const override 0100 { 0101 return new RelatedColorSpaceType(this->name(), p->clone()); 0102 } 0103 0104 bool isHdr() const override { 0105 return this->colorDepthId() != Integer8BitsColorDepthID; 0106 } 0107 0108 QList<KoColorConversionTransformationFactory *> colorConversionLinks() const override 0109 { 0110 QList<KoColorConversionTransformationFactory *> list; 0111 0112 /** 0113 * We explicitly disable direct conversions to/from integer color spaces, because 0114 * they may cause the conversion system to choose them as an intermediate 0115 * color space for the conversion chain, e.g. 0116 * p709-g10 F32 -> p2020-g10 U16 -> Rec2020-pq U16, which is incorrect and loses 0117 * all the HDR data 0118 */ 0119 list << new LcmsFromRGBP2020PQTransformationFactory<RelatedColorSpaceType, KoRgbF32Traits>(); 0120 list << new LcmsToRGBP2020PQTransformationFactory<RelatedColorSpaceType, KoRgbF32Traits>(); 0121 #ifdef HAVE_OPENEXR 0122 list << new LcmsFromRGBP2020PQTransformationFactory<RelatedColorSpaceType, KoRgbF16Traits>(); 0123 list << new LcmsToRGBP2020PQTransformationFactory<RelatedColorSpaceType, KoRgbF16Traits>(); 0124 #endif 0125 0126 0127 // internally, we can convert to RGB U8 if needed 0128 addInternalConversion<RelatedColorSpaceType>(list, static_cast<KoBgrU8Traits*>(0)); 0129 0130 return list; 0131 } 0132 }; 0133 0134 #endif // LCMSRGBP2020PQCOLORSPACE_H