File indexing completed on 2024-05-12 15:59:31
0001 /* 0002 * SPDX-FileCopyrightText: 2007 Cyrille Berger <cberger@cberger.net> 0003 * 0004 * SPDX-License-Identifier: LGPL-2.1-or-later 0005 */ 0006 0007 #include "KoColorConversionAlphaTransformation.h" 0008 0009 #include "KoColorSpace.h" 0010 #include "KoIntegerMaths.h" 0011 #include "KoColorSpaceTraits.h" 0012 #include "KoColorModelStandardIds.h" 0013 #include "KoColorModelStandardIdsUtils.h" 0014 0015 /** 0016 * Converter from the alpha color space to any color space 0017 */ 0018 template <typename alpha_channel_type> 0019 class KoColorConversionFromAlphaTransformation : public KoColorConversionTransformation 0020 { 0021 public: 0022 KoColorConversionFromAlphaTransformation(const KoColorSpace* srcCs, const KoColorSpace* dstCs, 0023 Intent renderingIntent, 0024 KoColorConversionTransformation::ConversionFlags conversionFlags) 0025 : KoColorConversionTransformation(srcCs, dstCs, renderingIntent, conversionFlags) 0026 { 0027 } 0028 0029 void transform(const quint8 *src, quint8 *dst, qint32 nPixels) const override 0030 { 0031 const alpha_channel_type *srcPtr = reinterpret_cast<const alpha_channel_type*>(src); 0032 0033 quint16 data[4]; 0034 const qint32 pixelSize = dstColorSpace()->pixelSize(); 0035 0036 data[1] = UINT16_MAX / 2; // a 0037 data[2] = UINT16_MAX / 2; // b 0038 data[3] = UINT16_MAX; // A 0039 0040 while (nPixels > 0) { 0041 data[0] = KoColorSpaceMaths<alpha_channel_type, quint16>::scaleToA(*srcPtr); // L 0042 dstColorSpace()->fromLabA16((quint8*)data, dst, 1); 0043 0044 srcPtr++; 0045 dst += pixelSize; 0046 nPixels--; 0047 } 0048 } 0049 }; 0050 0051 template <typename alpha_channel_type> 0052 class KoColorConversionAlphaToLab16Transformation : public KoColorConversionTransformation 0053 { 0054 public: 0055 KoColorConversionAlphaToLab16Transformation(const KoColorSpace* srcCs, const KoColorSpace* dstCs, 0056 Intent renderingIntent, 0057 KoColorConversionTransformation::ConversionFlags conversionFlags) 0058 : KoColorConversionTransformation(srcCs, dstCs, renderingIntent, conversionFlags) 0059 { 0060 } 0061 0062 void transform(const quint8 *src, quint8 *dst, qint32 nPixels) const override 0063 { 0064 const alpha_channel_type *srcPtr = reinterpret_cast<const alpha_channel_type*>(src); 0065 quint16 *dstPtr = reinterpret_cast<quint16*>(dst); 0066 0067 while (nPixels > 0) { 0068 dstPtr[0] = KoColorSpaceMaths<alpha_channel_type, quint16>::scaleToA(*srcPtr); // L 0069 dstPtr[1] = UINT16_MAX / 2; // a 0070 dstPtr[2] = UINT16_MAX / 2; // b 0071 dstPtr[3] = UINT16_MAX; // A 0072 0073 srcPtr++; 0074 dstPtr += 4; 0075 nPixels--; 0076 } 0077 } 0078 }; 0079 0080 0081 template <typename alpha_channel_type, typename gray_channel_type> 0082 class KoColorConversionGrayAFromAlphaTransformation : public KoColorConversionTransformation 0083 { 0084 public: 0085 KoColorConversionGrayAFromAlphaTransformation(const KoColorSpace* srcCs, 0086 const KoColorSpace* dstCs, 0087 Intent renderingIntent, 0088 KoColorConversionTransformation::ConversionFlags conversionFlags) 0089 : KoColorConversionTransformation(srcCs, dstCs, renderingIntent, conversionFlags) 0090 { 0091 } 0092 void transform(const quint8 *src, quint8 *dst, qint32 nPixels) const override { 0093 const alpha_channel_type *srcPtr = reinterpret_cast<const alpha_channel_type*>(src); 0094 gray_channel_type *dstPtr = reinterpret_cast<gray_channel_type*>(dst); 0095 0096 while (nPixels > 0) { 0097 dstPtr[0] = KoColorSpaceMaths<alpha_channel_type, gray_channel_type>::scaleToA(*srcPtr); 0098 dstPtr[1] = KoColorSpaceMathsTraits<gray_channel_type>::unitValue; 0099 0100 srcPtr++; 0101 dstPtr += 2; 0102 nPixels--; 0103 } 0104 } 0105 }; 0106 0107 //------ KoColorConversionFromAlphaTransformationFactoryImpl ------// 0108 0109 template<typename alpha_channel_type> 0110 KoColorConversionFromAlphaTransformationFactoryImpl<alpha_channel_type>:: 0111 KoColorConversionFromAlphaTransformationFactoryImpl(const QString& _dstModelId, const QString& _dstDepthId, const QString& _dstProfileName) 0112 : KoColorConversionTransformationFactory(AlphaColorModelID.id(), 0113 colorDepthIdForChannelType<alpha_channel_type>().id(), 0114 "default", 0115 _dstModelId, _dstDepthId, _dstProfileName) 0116 { 0117 } 0118 0119 template<typename alpha_channel_type> 0120 KoColorConversionTransformation* 0121 KoColorConversionFromAlphaTransformationFactoryImpl<alpha_channel_type>:: 0122 createColorTransformation(const KoColorSpace* srcColorSpace, 0123 const KoColorSpace* dstColorSpace, 0124 KoColorConversionTransformation::Intent renderingIntent, 0125 KoColorConversionTransformation::ConversionFlags conversionFlags) const 0126 { 0127 Q_ASSERT(canBeSource(srcColorSpace)); 0128 Q_ASSERT(canBeDestination(dstColorSpace)); 0129 0130 if (dstColorSpace->colorModelId() == GrayAColorModelID && 0131 dstColorSpace->colorDepthId() == Integer8BitsColorDepthID) { 0132 return new KoColorConversionGrayAFromAlphaTransformation<alpha_channel_type, quint8>(srcColorSpace, dstColorSpace, renderingIntent, conversionFlags); 0133 0134 } else if (dstColorSpace->colorModelId() == GrayAColorModelID && 0135 dstColorSpace->colorDepthId() == Integer16BitsColorDepthID) { 0136 return new KoColorConversionGrayAFromAlphaTransformation<alpha_channel_type, quint16>(srcColorSpace, dstColorSpace, renderingIntent, conversionFlags); 0137 0138 #ifdef HAVE_OPENEXR 0139 } else if (dstColorSpace->colorModelId() == GrayAColorModelID && 0140 dstColorSpace->colorDepthId() == Float16BitsColorDepthID) { 0141 return new KoColorConversionGrayAFromAlphaTransformation<alpha_channel_type, half>(srcColorSpace, dstColorSpace, renderingIntent, conversionFlags); 0142 #endif 0143 0144 } else if (dstColorSpace->colorModelId() == GrayAColorModelID && 0145 dstColorSpace->colorDepthId() == Float32BitsColorDepthID) { 0146 return new KoColorConversionGrayAFromAlphaTransformation<alpha_channel_type, float>(srcColorSpace, dstColorSpace, renderingIntent, conversionFlags); 0147 0148 } else if (dstColorSpace->colorModelId() == LABAColorModelID && 0149 dstColorSpace->colorDepthId() == Integer16BitsColorDepthID) { 0150 return new KoColorConversionAlphaToLab16Transformation<alpha_channel_type>(srcColorSpace, dstColorSpace, renderingIntent, conversionFlags); 0151 0152 } else { 0153 return new KoColorConversionFromAlphaTransformation<alpha_channel_type>(srcColorSpace, dstColorSpace, renderingIntent, conversionFlags); 0154 } 0155 } 0156 0157 template class KoColorConversionFromAlphaTransformationFactoryImpl<quint8>; 0158 template class KoColorConversionFromAlphaTransformationFactoryImpl<quint16>; 0159 #ifdef HAVE_OPENEXR 0160 template class KoColorConversionFromAlphaTransformationFactoryImpl<half>; 0161 #endif 0162 template class KoColorConversionFromAlphaTransformationFactoryImpl<float>; 0163 0164 //------ KoColorConversionToAlphaTransformation ------// 0165 0166 /** 0167 * Converter to the alpha color space to any color space 0168 */ 0169 template <typename alpha_channel_type> 0170 class KoColorConversionToAlphaTransformation : public KoColorConversionTransformation 0171 { 0172 public: 0173 KoColorConversionToAlphaTransformation(const KoColorSpace* srcCs, const KoColorSpace* dstCs, Intent renderingIntent, ConversionFlags conversionFlags) 0174 : KoColorConversionTransformation(srcCs, dstCs, renderingIntent, conversionFlags) 0175 { 0176 } 0177 0178 void transform(const quint8 *src, quint8 *dst, qint32 nPixels) const override { 0179 alpha_channel_type *dstPtr = reinterpret_cast<alpha_channel_type*>(dst); 0180 0181 quint16 data[4]; 0182 qint32 pixelSize = srcColorSpace()->pixelSize(); 0183 0184 while (nPixels > 0) { 0185 srcColorSpace()->toLabA16(src, (quint8*)data, 1); 0186 *dstPtr = KoColorSpaceMaths<quint16, alpha_channel_type>::scaleToA(UINT16_MULT(data[0], data[3])); // L * A 0187 0188 src += pixelSize; 0189 dstPtr ++; 0190 nPixels --; 0191 0192 } 0193 } 0194 }; 0195 0196 template <typename alpha_channel_type> 0197 class KoColorConversionLab16ToAlphaTransformation : public KoColorConversionTransformation 0198 { 0199 public: 0200 KoColorConversionLab16ToAlphaTransformation(const KoColorSpace* srcCs, const KoColorSpace* dstCs, 0201 Intent renderingIntent, 0202 KoColorConversionTransformation::ConversionFlags conversionFlags) 0203 : KoColorConversionTransformation(srcCs, dstCs, renderingIntent, conversionFlags) 0204 { 0205 } 0206 0207 void transform(const quint8 *src, quint8 *dst, qint32 nPixels) const override 0208 { 0209 const quint16 *srcPtr = reinterpret_cast<const quint16*>(src); 0210 alpha_channel_type *dstPtr = reinterpret_cast<alpha_channel_type*>(dst); 0211 0212 while (nPixels > 0) { 0213 *dstPtr = KoColorSpaceMaths<quint16, alpha_channel_type>::scaleToA(UINT16_MULT(srcPtr[0], srcPtr[3])); // L * A 0214 0215 srcPtr += 4; 0216 dstPtr++; 0217 nPixels--; 0218 } 0219 } 0220 }; 0221 0222 0223 //------ KoColorConversionGrayAU8ToAlphaTransformation ------// 0224 0225 template <typename gray_channel_type, typename alpha_channel_type> 0226 class KoColorConversionGrayAToAlphaTransformation : public KoColorConversionTransformation 0227 { 0228 public: 0229 KoColorConversionGrayAToAlphaTransformation(const KoColorSpace* srcCs, 0230 const KoColorSpace* dstCs, 0231 Intent renderingIntent, 0232 ConversionFlags conversionFlags) 0233 : KoColorConversionTransformation(srcCs, dstCs, renderingIntent, conversionFlags) 0234 { 0235 } 0236 0237 void transform(const quint8 *src, quint8 *dst, qint32 nPixels) const override 0238 { 0239 const gray_channel_type *srcPtr = reinterpret_cast<const gray_channel_type*>(src); 0240 alpha_channel_type *dstPtr = reinterpret_cast<alpha_channel_type*>(dst); 0241 0242 while (nPixels > 0) { 0243 *dstPtr = KoColorSpaceMaths<gray_channel_type, alpha_channel_type>::scaleToA( 0244 KoColorSpaceMaths<gray_channel_type>::multiply(srcPtr[0], srcPtr[1])); 0245 0246 srcPtr += 2; 0247 dstPtr++; 0248 nPixels --; 0249 } 0250 } 0251 }; 0252 0253 //------ KoColorConversionToAlphaTransformationFactoryImpl ------// 0254 0255 template <typename alpha_channel_type> 0256 KoColorConversionToAlphaTransformationFactoryImpl<alpha_channel_type>:: 0257 KoColorConversionToAlphaTransformationFactoryImpl(const QString& _srcModelId, const QString& _srcDepthId, const QString& _srcProfileName) 0258 : KoColorConversionTransformationFactory(_srcModelId, _srcDepthId, _srcProfileName, 0259 AlphaColorModelID.id(), colorDepthIdForChannelType<alpha_channel_type>().id(), "default") 0260 { 0261 } 0262 0263 template <typename alpha_channel_type> 0264 KoColorConversionTransformation* 0265 KoColorConversionToAlphaTransformationFactoryImpl<alpha_channel_type>:: 0266 createColorTransformation(const KoColorSpace* srcColorSpace, 0267 const KoColorSpace* dstColorSpace, 0268 KoColorConversionTransformation::Intent renderingIntent, 0269 KoColorConversionTransformation::ConversionFlags conversionFlags) const 0270 { 0271 Q_ASSERT(canBeSource(srcColorSpace)); 0272 Q_ASSERT(canBeDestination(dstColorSpace)); 0273 0274 if (srcColorSpace->colorModelId() == GrayAColorModelID && 0275 srcColorSpace->colorDepthId() == Integer8BitsColorDepthID) { 0276 return new KoColorConversionGrayAToAlphaTransformation<quint8, alpha_channel_type>(srcColorSpace, dstColorSpace, renderingIntent, conversionFlags); 0277 0278 } else if (srcColorSpace->colorModelId() == GrayAColorModelID && 0279 srcColorSpace->colorDepthId() == Integer16BitsColorDepthID) { 0280 return new KoColorConversionGrayAToAlphaTransformation<quint16, alpha_channel_type>(srcColorSpace, dstColorSpace, renderingIntent, conversionFlags); 0281 0282 #ifdef HAVE_OPENEXR 0283 } else if (srcColorSpace->colorModelId() == GrayAColorModelID && 0284 srcColorSpace->colorDepthId() == Float16BitsColorDepthID) { 0285 return new KoColorConversionGrayAToAlphaTransformation<half, alpha_channel_type>(srcColorSpace, dstColorSpace, renderingIntent, conversionFlags); 0286 #endif 0287 0288 } else if (srcColorSpace->colorModelId() == GrayAColorModelID && 0289 srcColorSpace->colorDepthId() == Float32BitsColorDepthID) { 0290 return new KoColorConversionGrayAToAlphaTransformation<float, alpha_channel_type>(srcColorSpace, dstColorSpace, renderingIntent, conversionFlags); 0291 0292 } else if (srcColorSpace->colorModelId() == LABAColorModelID && 0293 srcColorSpace->colorDepthId() == Integer16BitsColorDepthID) { 0294 return new KoColorConversionLab16ToAlphaTransformation<alpha_channel_type>(srcColorSpace, dstColorSpace, renderingIntent, conversionFlags); 0295 0296 } else { 0297 return new KoColorConversionToAlphaTransformation<alpha_channel_type>(srcColorSpace, dstColorSpace, renderingIntent, conversionFlags); 0298 } 0299 } 0300 0301 template class KoColorConversionToAlphaTransformationFactoryImpl<quint8>; 0302 template class KoColorConversionToAlphaTransformationFactoryImpl<quint16>; 0303 #ifdef HAVE_OPENEXR 0304 template class KoColorConversionToAlphaTransformationFactoryImpl<half>; 0305 #endif 0306 template class KoColorConversionToAlphaTransformationFactoryImpl<float>;