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 LCMSRGBP2020PQCOLORSPACETRANSFORMATION_H 0008 #define LCMSRGBP2020PQCOLORSPACETRANSFORMATION_H 0009 0010 #include "KoAlwaysInline.h" 0011 #include "KoColorModelStandardIds.h" 0012 #include "KoColorSpaceMaths.h" 0013 #include "KoColorModelStandardIdsUtils.h" 0014 #include "KoColorConversionTransformationFactory.h" 0015 #include "KoColorTransferFunctions.h" 0016 0017 #include <colorspaces/rgb_u8/RgbU8ColorSpace.h> 0018 #include <colorspaces/rgb_u16/RgbU16ColorSpace.h> 0019 #ifdef HAVE_OPENEXR 0020 #include <colorspaces/rgb_f16/RgbF16ColorSpace.h> 0021 #endif 0022 #include <colorspaces/rgb_f32/RgbF32ColorSpace.h> 0023 0024 0025 namespace 0026 { 0027 0028 template <class T> 0029 struct DstTraitsForSource { 0030 typedef KoRgbF32Traits result; 0031 }; 0032 0033 /** 0034 * If half format is present, we use it instead 0035 */ 0036 #ifdef HAVE_OPENEXR 0037 template <> 0038 struct DstTraitsForSource<KoBgrU16Traits> { 0039 typedef KoRgbF16Traits result; 0040 }; 0041 0042 template <> 0043 struct DstTraitsForSource<KoBgrU8Traits> { 0044 typedef KoRgbF16Traits result; 0045 }; 0046 #endif 0047 0048 template <typename src_channel_type, 0049 typename dst_channel_type> 0050 struct RemoveSmpte2048Policy { 0051 static ALWAYS_INLINE dst_channel_type process(src_channel_type value) { 0052 return 0053 KoColorSpaceMaths<float, dst_channel_type>::scaleToA( 0054 removeSmpte2048Curve( 0055 KoColorSpaceMaths<src_channel_type, float>::scaleToA( 0056 value))); 0057 } 0058 }; 0059 0060 template <typename src_channel_type, 0061 typename dst_channel_type> 0062 struct ApplySmpte2048Policy { 0063 static ALWAYS_INLINE dst_channel_type process(src_channel_type value) { 0064 return 0065 KoColorSpaceMaths<float, dst_channel_type>::scaleToA( 0066 applySmpte2048Curve( 0067 KoColorSpaceMaths<src_channel_type, float>::scaleToA( 0068 value))); 0069 } 0070 }; 0071 0072 template <typename src_channel_type, 0073 typename dst_channel_type> 0074 struct NoopPolicy { 0075 static ALWAYS_INLINE dst_channel_type process(src_channel_type value) { 0076 return KoColorSpaceMaths<src_channel_type, dst_channel_type>::scaleToA(value); 0077 } 0078 }; 0079 0080 } 0081 0082 template<typename SrcCSTraits, 0083 typename DstCSTraits, 0084 template<typename, typename> class Policy> 0085 struct ApplyRgbShaper : public KoColorConversionTransformation 0086 { 0087 ApplyRgbShaper(const KoColorSpace* srcCs, 0088 const KoColorSpace* dstCs, 0089 Intent renderingIntent, 0090 ConversionFlags conversionFlags) 0091 : KoColorConversionTransformation(srcCs, 0092 dstCs, 0093 renderingIntent, 0094 conversionFlags) 0095 { 0096 } 0097 0098 void transform(const quint8 *src, quint8 *dst, qint32 nPixels) const override { 0099 KIS_ASSERT(src != dst); 0100 0101 const typename SrcCSTraits::Pixel *srcPixel = reinterpret_cast<const typename SrcCSTraits::Pixel*>(src); 0102 typename DstCSTraits::Pixel *dstPixel = reinterpret_cast<typename DstCSTraits::Pixel*>(dst); 0103 0104 typedef typename SrcCSTraits::channels_type src_channel_type; 0105 typedef typename DstCSTraits::channels_type dst_channel_type; 0106 typedef Policy<src_channel_type, dst_channel_type> ConcretePolicy; 0107 0108 for (int i = 0; i < nPixels; i++) { 0109 dstPixel->red = ConcretePolicy::process(srcPixel->red); 0110 dstPixel->green = ConcretePolicy::process(srcPixel->green); 0111 dstPixel->blue = ConcretePolicy::process(srcPixel->blue); 0112 dstPixel->alpha = 0113 KoColorSpaceMaths<src_channel_type, dst_channel_type>::scaleToA( 0114 srcPixel->alpha); 0115 0116 srcPixel++; 0117 dstPixel++; 0118 } 0119 } 0120 0121 }; 0122 0123 template<class ParentColorSpace, class DstColorSpaceTraits = typename DstTraitsForSource<typename ParentColorSpace::ColorSpaceTraits>::result> 0124 class LcmsFromRGBP2020PQTransformationFactory : public KoColorConversionTransformationFactory 0125 { 0126 public: 0127 LcmsFromRGBP2020PQTransformationFactory() 0128 : KoColorConversionTransformationFactory(RGBAColorModelID.id(), 0129 colorDepthIdForChannelType<typename ParentColorSpace::ColorSpaceTraits::channels_type>().id(), 0130 "High Dynamic Range UHDTV Wide Color Gamut Display (Rec. 2020) - SMPTE ST 2084 PQ EOTF", 0131 RGBAColorModelID.id(), 0132 colorDepthIdForChannelType<typename DstColorSpaceTraits::channels_type>().id(), 0133 "Rec2020-elle-V4-g10.icc") 0134 { 0135 } 0136 0137 KoColorConversionTransformation* createColorTransformation(const KoColorSpace* srcColorSpace, 0138 const KoColorSpace* dstColorSpace, 0139 KoColorConversionTransformation::Intent renderingIntent, 0140 KoColorConversionTransformation::ConversionFlags conversionFlags) const override 0141 { 0142 return new ApplyRgbShaper< 0143 typename ParentColorSpace::ColorSpaceTraits, 0144 DstColorSpaceTraits, 0145 RemoveSmpte2048Policy>(srcColorSpace, 0146 dstColorSpace, 0147 renderingIntent, 0148 conversionFlags); 0149 } 0150 }; 0151 0152 template<class ParentColorSpace, class DstColorSpaceTraits = typename DstTraitsForSource<typename ParentColorSpace::ColorSpaceTraits>::result> 0153 class LcmsToRGBP2020PQTransformationFactory : public KoColorConversionTransformationFactory 0154 { 0155 public: 0156 LcmsToRGBP2020PQTransformationFactory() 0157 : KoColorConversionTransformationFactory(RGBAColorModelID.id(), 0158 colorDepthIdForChannelType<typename DstColorSpaceTraits::channels_type>().id(), 0159 "Rec2020-elle-V4-g10.icc", 0160 RGBAColorModelID.id(), 0161 colorDepthIdForChannelType<typename ParentColorSpace::ColorSpaceTraits::channels_type>().id(), 0162 "High Dynamic Range UHDTV Wide Color Gamut Display (Rec. 2020) - SMPTE ST 2084 PQ EOTF") 0163 { 0164 } 0165 0166 KoColorConversionTransformation* createColorTransformation(const KoColorSpace* srcColorSpace, 0167 const KoColorSpace* dstColorSpace, 0168 KoColorConversionTransformation::Intent renderingIntent, 0169 KoColorConversionTransformation::ConversionFlags conversionFlags) const override 0170 { 0171 return new ApplyRgbShaper< 0172 DstColorSpaceTraits, 0173 typename ParentColorSpace::ColorSpaceTraits, 0174 ApplySmpte2048Policy>(srcColorSpace, 0175 dstColorSpace, 0176 renderingIntent, 0177 conversionFlags); 0178 } 0179 }; 0180 0181 template<class ParentColorSpace, class DstColorSpaceTraits> 0182 class LcmsScaleRGBP2020PQTransformationFactory : public KoColorConversionTransformationFactory 0183 { 0184 public: 0185 LcmsScaleRGBP2020PQTransformationFactory() 0186 : KoColorConversionTransformationFactory(RGBAColorModelID.id(), 0187 colorDepthIdForChannelType<typename ParentColorSpace::ColorSpaceTraits::channels_type>().id(), 0188 "High Dynamic Range UHDTV Wide Color Gamut Display (Rec. 2020) - SMPTE ST 2084 PQ EOTF", 0189 RGBAColorModelID.id(), 0190 colorDepthIdForChannelType<typename DstColorSpaceTraits::channels_type>().id(), 0191 "High Dynamic Range UHDTV Wide Color Gamut Display (Rec. 2020) - SMPTE ST 2084 PQ EOTF") 0192 { 0193 KIS_SAFE_ASSERT_RECOVER_NOOP(srcColorDepthId() != dstColorDepthId()); 0194 } 0195 0196 KoColorConversionTransformation* createColorTransformation(const KoColorSpace* srcColorSpace, 0197 const KoColorSpace* dstColorSpace, 0198 KoColorConversionTransformation::Intent renderingIntent, 0199 KoColorConversionTransformation::ConversionFlags conversionFlags) const override 0200 { 0201 return new ApplyRgbShaper< 0202 typename ParentColorSpace::ColorSpaceTraits, 0203 DstColorSpaceTraits, 0204 NoopPolicy>(srcColorSpace, 0205 dstColorSpace, 0206 renderingIntent, 0207 conversionFlags); 0208 } 0209 }; 0210 0211 #endif // LCMSRGBP2020PQCOLORSPACETRANSFORMATION_H