File indexing completed on 2024-05-12 15:59:37
0001 /* 0002 * SPDX-FileCopyrightText: 2006, 2007, 2010 Cyrille Berger <cberger@cberger.net> 0003 * SPDX-FileCopyrightText: 2017, 2020 L. E. Segovia <amy@amyspark.me> 0004 * 0005 * SPDX-License-Identifier: LGPL-2.1-or-later 0006 */ 0007 0008 #ifndef KOLABCOLORSPACEMATHS_H_ 0009 #define KOLABCOLORSPACEMATHS_H_ 0010 0011 #include <cmath> 0012 #include <limits> 0013 0014 #include "kritapigment_export.h" 0015 #include <KoIntegerMaths.h> 0016 #include "KoChannelInfo.h" 0017 #include "KoLut.h" 0018 0019 #include <KoColorSpaceMaths.h> 0020 0021 #undef _T 0022 0023 /** 0024 * This is an empty mainWindow that needs to be "specialized" for each possible 0025 * numerical type (quint8, quint16...). 0026 * 0027 * It needs to defines some static constant fields : 0028 * - zeroValue : the zero for this numerical type 0029 * - unitValue : the maximum value of the normal dynamic range 0030 * - max : the maximum value 0031 * - min : the minimum value 0032 * - epsilon : a value close to zero but different of zero 0033 * - bits : the bit depth 0034 * 0035 * And some types : 0036 * - compositetype the type used for composite operations (usually one with 0037 * a higher bit depth) 0038 * 0039 * This class is specialized to handle the floating point bounds of the Lab color space. 0040 */ 0041 0042 template<typename _T> 0043 class KoLabColorSpaceMathsTraits 0044 { 0045 public: 0046 }; 0047 0048 template<> 0049 class KRITAPIGMENT_EXPORT KoLabColorSpaceMathsTraits<quint8> : public KoColorSpaceMathsTraits<quint8> 0050 { 0051 public: 0052 static const quint8 zeroValueL = 0; 0053 static const quint8 unitValueL = 0x00FF; 0054 static const quint8 halfValueL = 0x00FF / 2; 0055 static const quint8 zeroValueAB = 0; 0056 static const quint8 unitValueAB = 0x00FF; 0057 static const quint8 halfValueAB = 0x0080; 0058 }; 0059 0060 template<> 0061 class KRITAPIGMENT_EXPORT KoLabColorSpaceMathsTraits<quint16> : public KoColorSpaceMathsTraits<quint16> 0062 { 0063 public: 0064 static const quint16 zeroValueL = 0; 0065 static const quint16 unitValueL = 0xFFFF; 0066 static const quint16 halfValueL = 0xFFFF / 2; 0067 static const quint16 zeroValueAB = 0; 0068 static const quint16 unitValueAB = 0xFFFF; 0069 static const quint16 halfValueAB = 0x8080; 0070 }; 0071 0072 template<> 0073 class KRITAPIGMENT_EXPORT KoLabColorSpaceMathsTraits<qint16> : public KoColorSpaceMathsTraits<qint16> 0074 { 0075 public: 0076 static const qint16 zeroValueL = 0; 0077 static const qint16 unitValueL = 32767; 0078 static const qint16 halfValueL = 32767 / 2; 0079 static const qint16 zeroValueAB = 0; 0080 static const qint16 unitValueAB = 32767; 0081 static const qint16 halfValueAB = 19549; 0082 }; 0083 0084 template<> 0085 class KRITAPIGMENT_EXPORT KoLabColorSpaceMathsTraits<quint32> : public KoColorSpaceMathsTraits<quint32> 0086 { 0087 public: 0088 static const quint32 zeroValueL = 0; 0089 static const quint32 unitValueL = 0xFFFFFFFF; 0090 static const quint32 halfValueL = 0xFFFFFFFF / 2; 0091 static const quint32 zeroValueAB = 0; 0092 static const quint32 unitValueAB = 0xFFFFFFFF; 0093 static const quint32 halfValueAB = 0x80808080; 0094 }; 0095 0096 #include <KoConfig.h> 0097 #ifdef HAVE_OPENEXR 0098 #include <half.h> 0099 0100 template<> 0101 class KRITAPIGMENT_EXPORT KoLabColorSpaceMathsTraits<half> : public KoColorSpaceMathsTraits<half> 0102 { 0103 public: 0104 static const half zeroValueL; 0105 static const half unitValueL; 0106 static const half halfValueL; 0107 static const half zeroValueAB; 0108 static const half unitValueAB; 0109 static const half halfValueAB; 0110 }; 0111 #endif 0112 0113 template<> 0114 class KRITAPIGMENT_EXPORT KoLabColorSpaceMathsTraits<float> : public KoColorSpaceMathsTraits<float> 0115 { 0116 public: 0117 static const float zeroValueL; 0118 static const float unitValueL; 0119 static const float halfValueL; 0120 static const float zeroValueAB; 0121 static const float unitValueAB; 0122 static const float halfValueAB; 0123 }; 0124 0125 template<> 0126 class KRITAPIGMENT_EXPORT KoLabColorSpaceMathsTraits<double> : public KoColorSpaceMathsTraits<double> 0127 { 0128 public: 0129 static const double zeroValueL; 0130 static const double unitValueL; 0131 static const double halfValueL; 0132 static const double zeroValueAB; 0133 static const double unitValueAB; 0134 static const double halfValueAB; 0135 }; 0136 0137 //template<typename _T_> 0138 //struct KoIntegerToFloat { 0139 // inline float operator()(_T_ f) const 0140 // { 0141 // return f / float(KoColorSpaceMathsTraits<_T_>::max); 0142 // } 0143 //}; 0144 0145 //struct KoLuts { 0146 0147 // static KRITAPIGMENT_EXPORT const Ko::FullLut< KoIntegerToFloat<quint16>, float, quint16> Uint16ToFloat; 0148 // static KRITAPIGMENT_EXPORT const Ko::FullLut< KoIntegerToFloat<quint8>, float, quint8> Uint8ToFloat; 0149 //}; 0150 0151 ///** 0152 // * This class defines some elementary operations used by various color 0153 // * space. It's intended to be generic, but some specialization exists 0154 // * either for optimization or just for being buildable. 0155 // * 0156 // * @param _T some numerical type with an existing trait 0157 // * @param _Tdst some other numerical type with an existing trait, it is 0158 // * only needed if different of _T 0159 // */ 0160 //template < typename _T, typename _Tdst = _T > 0161 //class KoColorSpaceMaths 0162 //{ 0163 // typedef KoColorSpaceMathsTraits<_T> traits; 0164 // typedef typename traits::compositetype src_compositetype; 0165 // typedef typename KoColorSpaceMathsTraits<_Tdst>::compositetype dst_compositetype; 0166 0167 //public: 0168 // inline static _Tdst multiply(_T a, _Tdst b) { 0169 // return (dst_compositetype(a)*b) / KoColorSpaceMathsTraits<_Tdst>::unitValue; 0170 // } 0171 0172 // inline static _Tdst multiply(_T a, _Tdst b, _Tdst c) { 0173 // return (dst_compositetype(a)*b*c) / (dst_compositetype(KoColorSpaceMathsTraits<_Tdst>::unitValue) * KoColorSpaceMathsTraits<_T>::unitValue); 0174 // } 0175 0176 // /** 0177 // * Division : (a * MAX ) / b 0178 // * @param a 0179 // * @param b 0180 // */ 0181 // inline static dst_compositetype divide(_T a, _Tdst b) { 0182 // return (dst_compositetype(a) * KoColorSpaceMathsTraits<_Tdst>::unitValue) / b; 0183 // } 0184 0185 // /** 0186 // * Inversion : unitValue - a 0187 // * @param a 0188 // */ 0189 // inline static _T invert(_T a) { 0190 // return traits::unitValue - a; 0191 // } 0192 0193 // /** 0194 // * Blending : (a * alpha) + b * (1 - alpha) 0195 // * @param a 0196 // * @param b 0197 // * @param alpha 0198 // */ 0199 // inline static _T blend(_T a, _T b, _T alpha) { 0200 // src_compositetype c = ((src_compositetype(a) - b) * alpha) / traits::unitValue; 0201 // return c + b; 0202 // } 0203 0204 // /** 0205 // * This function will scale a value of type _T to fit into a _Tdst. 0206 // */ 0207 // inline static _Tdst scaleToA(_T a) { 0208 // return _Tdst(dst_compositetype(a) * KoColorSpaceMathsTraits<_Tdst>::unitValue / KoColorSpaceMathsTraits<_T>::unitValue); 0209 // } 0210 0211 // inline static dst_compositetype clamp(dst_compositetype val) { 0212 // return qBound<dst_compositetype>(KoColorSpaceMathsTraits<_Tdst>::min, val, KoColorSpaceMathsTraits<_Tdst>::max); 0213 // } 0214 0215 // /** 0216 // * Clamps the composite type on higher border only. That is a fast path 0217 // * for scale-only transformations 0218 // */ 0219 // inline static _Tdst clampAfterScale(dst_compositetype val) { 0220 // return qMin<dst_compositetype>(val, KoColorSpaceMathsTraits<_Tdst>::max); 0221 // } 0222 //}; 0223 0224 ////------------------------------ double specialization ------------------------------// 0225 //template<> 0226 //inline quint8 KoColorSpaceMaths<double, quint8>::scaleToA(double a) 0227 //{ 0228 // double v = a * 255; 0229 // return float2int(CLAMP(v, 0, 255)); 0230 //} 0231 0232 //template<> 0233 //inline double KoColorSpaceMaths<quint8, double>::scaleToA(quint8 a) 0234 //{ 0235 // return KoLuts::Uint8ToFloat(a); 0236 //} 0237 0238 //template<> 0239 //inline quint16 KoColorSpaceMaths<double, quint16>::scaleToA(double a) 0240 //{ 0241 // double v = a * 0xFFFF; 0242 // return float2int(CLAMP(v, 0, 0xFFFF)); 0243 //} 0244 0245 //template<> 0246 //inline double KoColorSpaceMaths<quint16, double>::scaleToA(quint16 a) 0247 //{ 0248 // return KoLuts::Uint16ToFloat(a); 0249 //} 0250 0251 //template<> 0252 //inline double KoColorSpaceMaths<double>::clamp(double a) 0253 //{ 0254 // return a; 0255 //} 0256 0257 ////------------------------------ float specialization ------------------------------// 0258 0259 //template<> 0260 //inline float KoColorSpaceMaths<double, float>::scaleToA(double a) 0261 //{ 0262 // return (float)a; 0263 //} 0264 0265 //template<> 0266 //inline double KoColorSpaceMaths<float, double>::scaleToA(float a) 0267 //{ 0268 // return a; 0269 //} 0270 0271 //template<> 0272 //inline quint16 KoColorSpaceMaths<float, quint16>::scaleToA(float a) 0273 //{ 0274 // float v = a * 0xFFFF; 0275 // return (quint16)float2int(CLAMP(v, 0, 0xFFFF)); 0276 //} 0277 0278 //template<> 0279 //inline float KoColorSpaceMaths<quint16, float>::scaleToA(quint16 a) 0280 //{ 0281 // return KoLuts::Uint16ToFloat(a); 0282 //} 0283 0284 //template<> 0285 //inline quint8 KoColorSpaceMaths<float, quint8>::scaleToA(float a) 0286 //{ 0287 // float v = a * 255; 0288 // return (quint8)float2int(CLAMP(v, 0, 255)); 0289 //} 0290 0291 //template<> 0292 //inline float KoColorSpaceMaths<quint8, float>::scaleToA(quint8 a) 0293 //{ 0294 // return KoLuts::Uint8ToFloat(a); 0295 //} 0296 0297 //template<> 0298 //inline float KoColorSpaceMaths<float>::blend(float a, float b, float alpha) 0299 //{ 0300 // return (a - b) * alpha + b; 0301 //} 0302 0303 //template<> 0304 //inline double KoColorSpaceMaths<float>::clamp(double a) 0305 //{ 0306 // return a; 0307 //} 0308 0309 ////------------------------------ half specialization ------------------------------// 0310 0311 //#ifdef HAVE_OPENEXR 0312 0313 //template<> 0314 //inline half KoColorSpaceMaths<double, half>::scaleToA(double a) 0315 //{ 0316 // return (half)a; 0317 //} 0318 0319 //template<> 0320 //inline double KoColorSpaceMaths<half, double>::scaleToA(half a) 0321 //{ 0322 // return a; 0323 //} 0324 0325 //template<> 0326 //inline float KoColorSpaceMaths<half, float>::scaleToA(half a) 0327 //{ 0328 // return a; 0329 //} 0330 0331 //template<> 0332 //inline half KoColorSpaceMaths<float, half>::scaleToA(float a) 0333 //{ 0334 // return (half) a; 0335 //} 0336 0337 //template<> 0338 //inline quint8 KoColorSpaceMaths<half, quint8>::scaleToA(half a) 0339 //{ 0340 // half v = a * 255; 0341 // return (quint8)(CLAMP(v, 0, 255)); 0342 //} 0343 0344 //template<> 0345 //inline half KoColorSpaceMaths<quint8, half>::scaleToA(quint8 a) 0346 //{ 0347 // return a *(1.0 / 255.0); 0348 //} 0349 //template<> 0350 //inline quint16 KoColorSpaceMaths<half, quint16>::scaleToA(half a) 0351 //{ 0352 // double v = a * 0xFFFF; 0353 // return (quint16)(CLAMP(v, 0, 0xFFFF)); 0354 //} 0355 0356 //template<> 0357 //inline half KoColorSpaceMaths<quint16, half>::scaleToA(quint16 a) 0358 //{ 0359 // return a *(1.0 / 0xFFFF); 0360 //} 0361 0362 //template<> 0363 //inline half KoColorSpaceMaths<half, half>::scaleToA(half a) 0364 //{ 0365 // return a; 0366 //} 0367 0368 //template<> 0369 //inline half KoColorSpaceMaths<half>::blend(half a, half b, half alpha) 0370 //{ 0371 // return (a - b) * alpha + b; 0372 //} 0373 0374 //template<> 0375 //inline double KoColorSpaceMaths<half>::clamp(double a) 0376 //{ 0377 // return a; 0378 //} 0379 0380 0381 //#endif 0382 0383 ////------------------------------ quint8 specialization ------------------------------// 0384 0385 //template<> 0386 //inline quint8 KoColorSpaceMaths<quint8>::multiply(quint8 a, quint8 b) 0387 //{ 0388 // return (quint8)UINT8_MULT(a, b); 0389 //} 0390 0391 0392 //template<> 0393 //inline quint8 KoColorSpaceMaths<quint8>::multiply(quint8 a, quint8 b, quint8 c) 0394 //{ 0395 // return (quint8)UINT8_MULT3(a, b, c); 0396 //} 0397 0398 //template<> 0399 //inline KoColorSpaceMathsTraits<quint8>::compositetype 0400 //KoColorSpaceMaths<quint8>::divide(quint8 a, quint8 b) 0401 //{ 0402 // return UINT8_DIVIDE(a, b); 0403 //} 0404 0405 //template<> 0406 //inline quint8 KoColorSpaceMaths<quint8>::invert(quint8 a) 0407 //{ 0408 // return ~a; 0409 //} 0410 0411 //template<> 0412 //inline quint8 KoColorSpaceMaths<quint8>::blend(quint8 a, quint8 b, quint8 c) 0413 //{ 0414 // return UINT8_BLEND(a, b, c); 0415 //} 0416 0417 ////------------------------------ quint16 specialization ------------------------------// 0418 0419 //template<> 0420 //inline quint16 KoColorSpaceMaths<quint16>::multiply(quint16 a, quint16 b) 0421 //{ 0422 // return (quint16)UINT16_MULT(a, b); 0423 //} 0424 0425 //template<> 0426 //inline KoColorSpaceMathsTraits<quint16>::compositetype 0427 //KoColorSpaceMaths<quint16>::divide(quint16 a, quint16 b) 0428 //{ 0429 // return UINT16_DIVIDE(a, b); 0430 //} 0431 0432 //template<> 0433 //inline quint16 KoColorSpaceMaths<quint16>::invert(quint16 a) 0434 //{ 0435 // return ~a; 0436 //} 0437 0438 ////------------------------------ various specialization ------------------------------// 0439 0440 0441 //// TODO: use more functions from KoIntegersMaths to do the computation 0442 0443 ///// This specialization is needed because the default implementation won't work when scaling up 0444 //template<> 0445 //inline quint16 KoColorSpaceMaths<quint8, quint16>::scaleToA(quint8 a) 0446 //{ 0447 // return UINT8_TO_UINT16(a); 0448 //} 0449 0450 //template<> 0451 //inline quint8 KoColorSpaceMaths<quint16, quint8>::scaleToA(quint16 a) 0452 //{ 0453 // return UINT16_TO_UINT8(a); 0454 //} 0455 0456 0457 //// Due to once again a bug in gcc, there is the need for those specialized functions: 0458 0459 //template<> 0460 //inline quint8 KoColorSpaceMaths<quint8, quint8>::scaleToA(quint8 a) 0461 //{ 0462 // return a; 0463 //} 0464 0465 //template<> 0466 //inline quint16 KoColorSpaceMaths<quint16, quint16>::scaleToA(quint16 a) 0467 //{ 0468 // return a; 0469 //} 0470 0471 //template<> 0472 //inline float KoColorSpaceMaths<float, float>::scaleToA(float a) 0473 //{ 0474 // return a; 0475 //} 0476 0477 //namespace Arithmetic 0478 //{ 0479 // const static qreal pi = 3.14159265358979323846; 0480 0481 // template<class T> 0482 // inline T mul(T a, T b) { return KoColorSpaceMaths<T>::multiply(a, b); } 0483 0484 // template<class T> 0485 // inline T mul(T a, T b, T c) { return KoColorSpaceMaths<T>::multiply(a, b, c); } 0486 0487 //// template<class T> 0488 //// inline T mul(T a, T b) { 0489 //// typedef typename KoColorSpaceMathsTraits<T>::compositetype composite_type; 0490 //// return T(composite_type(a) * b / KoColorSpaceMathsTraits<T>::unitValue); 0491 //// } 0492 //// 0493 //// template<class T> 0494 //// inline T mul(T a, T b, T c) { 0495 //// typedef typename KoColorSpaceMathsTraits<T>::compositetype composite_type; 0496 //// return T((composite_type(a) * b * c) / (composite_type(KoColorSpaceMathsTraits<T>::unitValue) * KoColorSpaceMathsTraits<T>::unitValue)); 0497 //// } 0498 0499 // template<class T> 0500 // inline T inv(T a) { return KoColorSpaceMaths<T>::invert(a); } 0501 0502 // template<class T> 0503 // inline T lerp(T a, T b, T alpha) { return KoColorSpaceMaths<T>::blend(b, a, alpha); } 0504 0505 // template<class TRet, class T> 0506 // inline TRet scale(T a) { return KoColorSpaceMaths<T,TRet>::scaleToA(a); } 0507 0508 // template<class T> 0509 // inline typename KoColorSpaceMathsTraits<T>::compositetype 0510 // div(T a, T b) { return KoColorSpaceMaths<T>::divide(a, b); } 0511 0512 // template<class T> 0513 // inline T clamp(typename KoColorSpaceMathsTraits<T>::compositetype a) { 0514 // return KoColorSpaceMaths<T>::clamp(a); 0515 // } 0516 0517 // template<class T> 0518 // inline T min(T a, T b, T c) { 0519 // b = (a < b) ? a : b; 0520 // return (b < c) ? b : c; 0521 // } 0522 0523 // template<class T> 0524 // inline T max(T a, T b, T c) { 0525 // b = (a > b) ? a : b; 0526 // return (b > c) ? b : c; 0527 // } 0528 0529 // template<class T> 0530 // inline T zeroValue() { return KoColorSpaceMathsTraits<T>::zeroValue; } 0531 0532 // template<class T> 0533 // inline T halfValue() { return KoColorSpaceMathsTraits<T>::halfValue; } 0534 0535 // template<class T> 0536 // inline T unitValue() { return KoColorSpaceMathsTraits<T>::unitValue; } 0537 0538 // template<class T> 0539 // inline T unionShapeOpacity(T a, T b) { 0540 // typedef typename KoColorSpaceMathsTraits<T>::compositetype composite_type; 0541 // return T(composite_type(a) + b - mul(a,b)); 0542 // } 0543 0544 // template<class T> 0545 // inline T blend(T src, T srcAlpha, T dst, T dstAlpha, T cfValue) { 0546 // return mul(inv(srcAlpha), dstAlpha, dst) + mul(inv(dstAlpha), srcAlpha, src) + mul(dstAlpha, srcAlpha, cfValue); 0547 // } 0548 //} 0549 0550 //struct HSYType 0551 //{ 0552 // template<class TReal> 0553 // inline static TReal getLightness(TReal r, TReal g, TReal b) { 0554 // return TReal(0.299)*r + TReal(0.587)*g + TReal(0.114)*b; 0555 // } 0556 0557 // template<class TReal> 0558 // inline static TReal getSaturation(TReal r, TReal g, TReal b) { 0559 // return Arithmetic::max(r,g,b) - Arithmetic::min(r,g,b); 0560 // } 0561 //}; 0562 0563 //struct HSIType 0564 //{ 0565 // template<class TReal> 0566 // inline static TReal getLightness(TReal r, TReal g, TReal b) { 0567 // return (r + g + b) * TReal(0.33333333333333333333); // (r + g + b) / 3.0 0568 // } 0569 0570 // template<class TReal> 0571 // inline static TReal getSaturation(TReal r, TReal g, TReal b) { 0572 // TReal max = Arithmetic::max(r, g, b); 0573 // TReal min = Arithmetic::min(r, g, b); 0574 // TReal chroma = max - min; 0575 0576 // return (chroma > std::numeric_limits<TReal>::epsilon()) ? 0577 // (TReal(1.0) - min / getLightness(r, g, b)) : TReal(0.0); 0578 // } 0579 //}; 0580 0581 //struct HSLType 0582 //{ 0583 // template<class TReal> 0584 // inline static TReal getLightness(TReal r, TReal g, TReal b) { 0585 // TReal max = Arithmetic::max(r, g, b); 0586 // TReal min = Arithmetic::min(r, g, b); 0587 // return (max + min) * TReal(0.5); 0588 // } 0589 0590 // template<class TReal> 0591 // inline static TReal getSaturation(TReal r, TReal g, TReal b) { 0592 // TReal max = Arithmetic::max(r, g, b); 0593 // TReal min = Arithmetic::min(r, g, b); 0594 // TReal chroma = max - min; 0595 // TReal light = (max + min) * TReal(0.5); 0596 // TReal div = TReal(1.0) - std::abs(TReal(2.0)*light - TReal(1.0)); 0597 0598 // if(div > std::numeric_limits<TReal>::epsilon()) 0599 // return chroma / div; 0600 0601 // return TReal(1.0); 0602 // } 0603 //}; 0604 0605 //struct HSVType 0606 //{ 0607 // template<class TReal> 0608 // inline static TReal getLightness(TReal r, TReal g, TReal b) { 0609 // return Arithmetic::max(r,g,b); 0610 // } 0611 0612 // template<class TReal> 0613 // inline static TReal getSaturation(TReal r, TReal g, TReal b) { 0614 // TReal max = Arithmetic::max(r, g, b); 0615 // TReal min = Arithmetic::min(r, g, b); 0616 // return (max == TReal(0.0)) ? TReal(0.0) : (max - min) / max; 0617 // } 0618 //}; 0619 0620 //template<class TReal> 0621 //TReal getHue(TReal r, TReal g, TReal b) { 0622 // TReal min = Arithmetic::min(r, g, b); 0623 // TReal max = Arithmetic::max(r, g, b); 0624 // TReal chroma = max - min; 0625 0626 // TReal hue = TReal(-1.0); 0627 0628 // if(chroma > std::numeric_limits<TReal>::epsilon()) { 0629 0630 //// return atan2(TReal(2.0)*r - g - b, TReal(1.73205080756887729353)*(g - b)); 0631 0632 // if(max == r) // between yellow and magenta 0633 // hue = (g - b) / chroma; 0634 // else if(max == g) // between cyan and yellow 0635 // hue = TReal(2.0) + (b - r) / chroma; 0636 // else if(max == b) // between magenta and cyan 0637 // hue = TReal(4.0) + (r - g) / chroma; 0638 0639 // if(hue < -std::numeric_limits<TReal>::epsilon()) 0640 // hue += TReal(6.0); 0641 0642 // hue /= TReal(6.0); 0643 // } 0644 0645 //// hue = (r == max) ? (b-g) : (g == max) ? TReal(2.0)+(r-b) : TReal(4.0)+(g-r); 0646 0647 // return hue; 0648 //} 0649 0650 //template<class TReal> 0651 //void getRGB(TReal& r, TReal& g, TReal& b, TReal hue) { 0652 // // 0 red -> (1,0,0) 0653 // // 1 yellow -> (1,1,0) 0654 // // 2 green -> (0,1,0) 0655 // // 3 cyan -> (0,1,1) 0656 // // 4 blue -> (0,0,1) 0657 // // 5 maenta -> (1,0,1) 0658 // // 6 red -> (1,0,0) 0659 0660 // if(hue < -std::numeric_limits<TReal>::epsilon()) { 0661 // r = g = b = TReal(0.0); 0662 // return; 0663 // } 0664 0665 // int i = int(hue * TReal(6.0)); 0666 // TReal x = hue * TReal(6.0) - i; 0667 // TReal y = TReal(1.0) - x; 0668 0669 // switch(i % 6){ 0670 // case 0: { r=TReal(1.0), g=x , b=TReal(0.0); } break; 0671 // case 1: { r=y , g=TReal(1.0), b=TReal(0.0); } break; 0672 // case 2: { r=TReal(0.0), g=TReal(1.0), b=x ; } break; 0673 // case 3: { r=TReal(0.0), g=y , b=TReal(1.0); } break; 0674 // case 4: { r=x , g=TReal(0.0), b=TReal(1.0); } break; 0675 // case 5: { r=TReal(1.0), g=TReal(0.0), b=y ; } break; 0676 // } 0677 //} 0678 0679 //template<class HSXType, class TReal> 0680 //inline static TReal getLightness(TReal r, TReal g, TReal b) { 0681 // return HSXType::getLightness(r, g, b); 0682 //} 0683 0684 //template<class HSXType, class TReal> 0685 //inline void addLightness(TReal& r, TReal& g, TReal& b, TReal light) 0686 //{ 0687 // using namespace Arithmetic; 0688 0689 // r += light; 0690 // g += light; 0691 // b += light; 0692 0693 // TReal l = HSXType::getLightness(r, g, b); 0694 // TReal n = min(r, g, b); 0695 // TReal x = max(r, g, b); 0696 0697 // if(n < TReal(0.0)) { 0698 // TReal iln = TReal(1.0) / (l-n); 0699 // r = l + ((r-l) * l) * iln; 0700 // g = l + ((g-l) * l) * iln; 0701 // b = l + ((b-l) * l) * iln; 0702 // } 0703 0704 // if(x > TReal(1.0) && (x-l) > std::numeric_limits<TReal>::epsilon()) { 0705 // TReal il = TReal(1.0) - l; 0706 // TReal ixl = TReal(1.0) / (x - l); 0707 // r = l + ((r-l) * il) * ixl; 0708 // g = l + ((g-l) * il) * ixl; 0709 // b = l + ((b-l) * il) * ixl; 0710 // } 0711 //} 0712 0713 //template<class HSXType, class TReal> 0714 //inline void setLightness(TReal& r, TReal& g, TReal& b, TReal light) 0715 //{ 0716 // addLightness<HSXType>(r,g,b, light - HSXType::getLightness(r,g,b)); 0717 //} 0718 0719 //template<class HSXType, class TReal> 0720 //inline static TReal getSaturation(TReal r, TReal g, TReal b) { 0721 // return HSXType::getSaturation(r, g, b); 0722 //} 0723 0724 //template<class HSXType, class TReal> 0725 //inline void setSaturation(TReal& r, TReal& g, TReal& b, TReal sat) 0726 //{ 0727 // int min = 0; 0728 // int mid = 1; 0729 // int max = 2; 0730 // TReal rgb[3] = {r, g, b}; 0731 0732 // if(rgb[mid] < rgb[min]) { 0733 // int tmp = min; 0734 // min = mid; 0735 // mid = tmp; 0736 // } 0737 0738 // if(rgb[max] < rgb[mid]) { 0739 // int tmp = mid; 0740 // mid = max; 0741 // max = tmp; 0742 // } 0743 0744 // if(rgb[mid] < rgb[min]) { 0745 // int tmp = min; 0746 // min = mid; 0747 // mid = tmp; 0748 // } 0749 0750 // if((rgb[max] - rgb[min]) > TReal(0.0)) { 0751 // rgb[mid] = ((rgb[mid]-rgb[min]) * sat) / (rgb[max]-rgb[min]); 0752 // rgb[max] = sat; 0753 // rgb[min] = TReal(0.0); 0754 0755 // r = rgb[0]; 0756 // g = rgb[1]; 0757 // b = rgb[2]; 0758 // } 0759 // else r = g = b = TReal(0.0); 0760 //} 0761 0762 #endif