7#ifndef KOCOLORSPACEMATHS_H_
8#define KOCOLORSPACEMATHS_H_
13#include "kritapigment_export.h"
50 static constexpr quint8 zeroValue = 0;
51 static constexpr quint8 unitValue = 0x00FF;
52 static constexpr quint8 halfValue = 0x00FF / 2;
53 static constexpr quint8 max = 0x00FF;
54 static constexpr quint8 min = 0;
55 static constexpr quint8 epsilon = 1;
56 static constexpr qint8 bits = 8;
66 static constexpr quint16 zeroValue = 0;
67 static constexpr quint16 unitValue = 0xFFFF;
68 static constexpr quint16 halfValue = 0xFFFF / 2;
69 static constexpr quint16 max = 0xFFFF;
70 static constexpr quint16 min = 0;
71 static constexpr quint16 epsilon = 1;
72 static constexpr qint8 bits = 16;
82 static constexpr qint16 zeroValue = 0;
83 static constexpr qint16 unitValue = 32767;
84 static constexpr qint16 halfValue = 32767 / 2;
85 static constexpr qint16 max = 32767;
86 static constexpr qint16 min = -32768;
87 static constexpr qint16 epsilon = 1;
88 static constexpr qint8 bits = 16;
98 static constexpr quint32 zeroValue = 0;
99 static constexpr quint32 unitValue = 0xFFFFFFFF;
100 static constexpr quint32 halfValue = 0xFFFFFFFF / 2;
101 static constexpr quint32 max = 0xFFFFFFFF;
102 static constexpr quint32 min = 0;
103 static constexpr quint32 epsilon = 1;
104 static constexpr qint8 bits = 32;
117 typedef double compositetype;
118 typedef double mixtype;
119 static const half zeroValue;
120 static const half unitValue;
121 static const half halfValue;
122 static const half max;
123 static const half min;
124 static const half epsilon;
125 static constexpr qint8 bits = 16;
142 static constexpr qint8 bits = 32;
158 static constexpr qint8 bits = 64;
170 return int(x + 0.5f);
184template<
typename _T_>
194 static KRITAPIGMENT_EXPORT
const Ko::FullLut< KoIntegerToFloat<quint16>, float, quint16>
Uint16ToFloat;
195 static KRITAPIGMENT_EXPORT
const Ko::FullLut< KoIntegerToFloat<quint8>, float, quint8>
Uint8ToFloat;
207template <
typename _T,
typename _Tdst = _T >
219 inline static _Tdst
multiply(_T a, _Tdst b, _Tdst c) {
237 return (
int (a * std::numeric_limits<int>::max() - traits::epsilon) ^
int (b * std::numeric_limits<int>::max() - traits::epsilon));
241 return (
int (a * std::numeric_limits<int>::max() - traits::epsilon) &
int (b * std::numeric_limits<int>::max() - traits::epsilon));
245 return (
int (a * std::numeric_limits<int>::max() - traits::epsilon) |
int (b * std::numeric_limits<int>::max() - traits::epsilon));
253 return traits::unitValue - a;
262 inline static _T
blend(_T a, _T b, _T alpha) {
279 if constexpr (std::numeric_limits<_T>::is_integer) {
288 if constexpr (std::numeric_limits<_T>::is_integer) {
308 if constexpr (std::numeric_limits<_Tdst>::is_integer) {
316 if constexpr (std::numeric_limits<_Tdst>::is_integer) {
332 static_assert(std::numeric_limits<_Tdst>::is_integer);
337 static_assert(std::numeric_limits<_Tdst>::is_integer);
342 static_assert(std::numeric_limits<_Tdst>::is_integer);
347 static_assert(std::numeric_limits<_Tdst>::is_integer);
352 static_assert(std::numeric_limits<_Tdst>::is_integer);
358 static_assert(std::numeric_limits<_Tdst>::is_integer);
380 double v = a * 0xFFFF;
415 return d <= 0.000000000001;
422 return d > 1.0 - 0.000000000001;
447 float v = a * 0xFFFF;
473 return (a - b) * alpha + b;
501 return f <= 0.00001f;
508 return f > 1.0 - 0.00001f;
548 return (quint8)(
CLAMP(
v, 0, 255));
554 return a *(1.0 / 255.0);
559 double v = a * 0xFFFF;
560 return (quint16)(
CLAMP(
v, 0, 0xFFFF));
566 return a *(1.0 / 0xFFFF);
578 return (a - b) * alpha +
b;
601 return qAbs(
value) < 0.002f;
615 return f > 1.0 - 0.002f;
621 return qAbs(
value - 0.5f) < 0.001f;
722 const static qreal
pi = 3.14159265358979323846;
748 template<
class TRet,
class T>
797 template<class T, typename composite_type = typename KoColorSpaceMathsTraits<T>::compositetype>
802 template<class T, typename composite_type = typename KoColorSpaceMathsTraits<T>::compositetype>
807 template <
typename T>
813 template <
typename T>
819 template <
typename T>
825 template <
typename T>
831 template <
typename T>
837 template <
typename T>
841 template <
typename T>
846 template <
typename T>
848 if constexpr (std::numeric_limits<T>::is_integer) {
854 template <
typename T>
856 if constexpr (std::numeric_limits<T>::is_integer) {
859 return value <= KoColorSpaceMathsTraits<T>::zeroValue;
865 inline T
min(T a, T b, T c) {
867 return (b < c) ? b : c;
871 inline T
max(T a, T b, T c) {
873 return (b > c) ? b : c;
888 return T(composite_type(a) + b -
mul(a,b));
892 inline T
blend(T src, T srcAlpha, T dst, T dstAlpha, T cfValue) {
893 return mul(
inv(srcAlpha), dstAlpha, dst) +
mul(
inv(dstAlpha), srcAlpha, src) +
mul(dstAlpha, srcAlpha, cfValue);
911 template<
class TReal>
913 return TReal(0.299)*r + TReal(0.587)*g + TReal(0.114)*b;
916 template<
class TReal>
926 template<
class TReal>
928 return (r + g + b) * TReal(0.33333333333333333333);
931 template<
class TReal>
935 TReal chroma = max - min;
937 return (chroma > std::numeric_limits<TReal>::epsilon()) ?
938 (TReal(1.0) - min /
getLightness(r, g, b)) : TReal(0.0);
946 template<
class TReal>
950 return (max + min) * TReal(0.5);
953 template<
class TReal>
957 TReal chroma = max - min;
958 TReal light = (max + min) * TReal(0.5);
959 TReal div = TReal(1.0) - std::abs(TReal(2.0)*light - TReal(1.0));
961 if(div > std::numeric_limits<TReal>::epsilon())
972 template<
class TReal>
977 template<
class TReal>
981 return (max > std::numeric_limits<TReal>::epsilon()) ? (max - min) / max : TReal(0.0);
991 TReal chroma = max - min;
993 TReal hue = TReal(-1.0);
995 if(chroma > std::numeric_limits<TReal>::epsilon()) {
1000 hue = (g - b) / chroma;
1002 hue = TReal(2.0) + (b - r) / chroma;
1004 hue = TReal(4.0) + (r - g) / chroma;
1006 if(hue < -std::numeric_limits<TReal>::epsilon())
1017template<
class TReal>
1018void getRGB(TReal& r, TReal& g, TReal& b, TReal hue) {
1027 if(hue < -std::numeric_limits<TReal>::epsilon()) {
1028 r = g = b = TReal(0.0);
1032 int i = int(hue * TReal(6.0));
1033 TReal x = hue * TReal(6.0) - i;
1034 TReal y = TReal(1.0) - x;
1037 case 0: { r=TReal(1.0), g=x , b=TReal(0.0); }
break;
1038 case 1: { r=y , g=TReal(1.0), b=TReal(0.0); }
break;
1039 case 2: { r=TReal(0.0), g=TReal(1.0), b=x ; }
break;
1040 case 3: { r=TReal(0.0), g=y , b=TReal(1.0); }
break;
1041 case 4: { r=x , g=TReal(0.0), b=TReal(1.0); }
break;
1042 case 5: { r=TReal(1.0), g=TReal(0.0), b=y ; }
break;
1046template<
class HSXType,
class TReal>
1048 return HSXType::getLightness(r, g, b);
1051template<
class HSXType,
class TReal>
1057 TReal l = HSXType::getLightness(r, g, b);
1058 TReal n = min(r, g, b);
1059 TReal x = max(r, g, b);
1061 if(n < TReal(0.0)) {
1062 if (isZeroValueClampedFuzzy<float>(l)) {
1070 r = g = b = TReal(0.0);
1072 const TReal stretch = l - n;
1074 if (stretch < std::numeric_limits<TReal>::epsilon()) {
1075 r = g = b = TReal(0.0);
1077 TReal iln = TReal(1.0) / stretch;
1078 r = l + ((r-l) * l) * iln;
1079 g = l + ((g-l) * l) * iln;
1080 b = l + ((b-l) * l) * iln;
1085 if(x > TReal(1.0)) {
1086 auto setFallbackValues = [&] () {
1087 if constexpr (HSXType::lightnessIsAverage) {
1088 r = g = b = TReal(1.0);
1090 r = qMin(r, TReal(1.0));
1091 g = qMin(g, TReal(1.0));
1092 b = qMin(b, TReal(1.0));
1096 if (l > TReal(1.0)) {
1104 setFallbackValues();
1106 const TReal stretch = x - l;
1108 if (stretch < std::numeric_limits<TReal>::epsilon()) {
1109 setFallbackValues();
1111 TReal il = TReal(1.0) - l;
1112 TReal ixl = TReal(1.0) / stretch;
1114 r = l + ((r-l) * il) * ixl;
1115 g = l + ((g-l) * il) * ixl;
1116 b = l + ((b-l) * il) * ixl;
1122template<
class HSXType,
class TReal>
1131 ToneMapping<HSXType, TReal>(r, g, b);
1134template<
class HSXType,
class TReal>
1137 addLightness<HSXType>(r,g,b, light - HSXType::getLightness(r,g,b));
1140template<
class HSXType,
class TReal>
1142 return HSXType::getSaturation(r, g, b);
1145template<
class HSXType,
class TReal>
1151 TReal rgb[3] = {r, g, b};
1153 if(rgb[mid] < rgb[min]) {
1159 if(rgb[max] < rgb[mid]) {
1165 if(rgb[mid] < rgb[min]) {
1171 if((rgb[max] - rgb[min]) > std::numeric_limits<TReal>::epsilon()) {
1172 rgb[mid] = ((rgb[mid]-rgb[min]) * sat) / (rgb[max]-rgb[min]);
1174 rgb[min] = TReal(0.0);
1180 else r = g = b = TReal(0.0);
float value(const T *src, size_t ch)
static TReal getLightness(TReal r, TReal g, TReal b)
void setLightness(TReal &r, TReal &g, TReal &b, TReal light)
void getRGB(TReal &r, TReal &g, TReal &b, TReal hue)
TReal getHue(TReal r, TReal g, TReal b)
void setSaturation(TReal &r, TReal &g, TReal &b, TReal sat)
static TReal getSaturation(TReal r, TReal g, TReal b)
void addLightness(TReal &r, TReal &g, TReal &b, TReal light)
void ToneMapping(TReal &r, TReal &g, TReal &b)
uint UINT8_MULT(uint a, uint b)
uint UINT8_BLEND(uint a, uint b, uint alpha)
uint UINT16_MULT(uint a, uint b)
uint UINT8_TO_UINT16(uint c)
uint UINT16_DIVIDE(uint a, uint b)
uint UINT16_TO_UINT8(uint c)
uint UINT8_DIVIDE(uint a, uint b)
uint UINT8_MULT3(uint a, uint b, uint c)
Approximation of (a * b * c + 32512) / 65025.0.
enumChannelValueType
enum to define the value of the channel
static const double zeroValue
static const double halfValue
static const double epsilon
static const double unitValue
static const KoChannelInfo::enumChannelValueType channelValueType
static const float halfValue
static const float unitValue
static const float epsilon
static const KoChannelInfo::enumChannelValueType channelValueType
static const float zeroValue
static const KoChannelInfo::enumChannelValueType channelValueType
static const KoChannelInfo::enumChannelValueType channelValueType
static const KoChannelInfo::enumChannelValueType channelValueType
static const KoChannelInfo::enumChannelValueType channelValueType
KoColorSpaceMathsTraits< _Tdst >::compositetype dst_compositetype
static _T blend(_T a, _T b, _T alpha)
static dst_compositetype xor(_T a, _Tdst b)
static dst_compositetype clamp(dst_compositetype val)
static dst_compositetype clampToSDR(dst_compositetype val)
static dst_compositetype or(_T a, _Tdst b)
static dst_compositetype divideInCompositeSpace(dst_compositetype a, dst_compositetype b)
static _T isUnsafeAsDivisor(_T value)
static dst_compositetype clampToSDRBottom(dst_compositetype val)
static bool isUnitValueFuzzy(_T value)
static dst_compositetype multiplyInCompositeSpace(dst_compositetype a, dst_compositetype b)
static _T clampChannelToSDR(_T val)
static bool isZeroValueFuzzy(_T value)
static dst_compositetype and(_T a, _Tdst b)
static _Tdst multiply(_T a, _Tdst b)
static _T clampChannelToSDRBottom(_T val)
static _Tdst clampAfterScale(dst_compositetype val)
static bool isUnitValueClampedFuzzy(_T v)
static dst_compositetype clampToSDRTop(dst_compositetype val)
static bool isHalfValueFuzzy(_T v)
static _Tdst multiply(_T a, _Tdst b, _Tdst c)
static _Tdst scaleToA(_T a)
traits::compositetype src_compositetype
static bool isZeroValueClampedFuzzy(_T v)
KoColorSpaceMathsTraits< _T > traits
static dst_compositetype modulus(_T a, _Tdst b)
static dst_compositetype divide(_T a, _Tdst b)
static bool qFuzzyCompare(half p1, half p2)
static bool qFuzzyIsNull(half h)
bool isUnitValueStrict(T value)
bool isUnitValueClampedStrict(T value)
static bool isHalfValueFuzzy(T v)
T clamp(typename KoColorSpaceMathsTraits< T >::compositetype a)
static bool isUnitValueClampedFuzzy(T v)
composite_type multiplyInCompositeSpace(composite_type a, composite_type b)
T blend(T src, T srcAlpha, T dst, T dstAlpha, T cfValue)
T lerp(T a, T b, T alpha)
bool isZeroValueStrict(T value)
T clampChannelToSDRBottom(T a)
bool isZeroValueClampedStrict(T value)
T clampToSDRBottom(typename KoColorSpaceMathsTraits< T >::compositetype a)
T clampToSDR(typename KoColorSpaceMathsTraits< T >::compositetype a)
T isUnsafeAsDivisor(T value)
T unionShapeOpacity(T a, T b)
KoColorSpaceMathsTraits< T >::compositetype xor(T a, T b)
composite_type divideInCompositeSpace(composite_type a, composite_type b)
KoColorSpaceMathsTraits< T >::compositetype div(T a, T b)
static bool isZeroValueClampedFuzzy(T v)
KoColorSpaceMathsTraits< T >::compositetype or(T a, T b)
KoColorSpaceMathsTraits< T >::compositetype mod(T a, T b)
KoColorSpaceMathsTraits< T >::compositetype and(T a, T b)
static bool isZeroValueFuzzy(T v)
static bool isUnitValueFuzzy(T v)
T clampToSDRTop(typename KoColorSpaceMathsTraits< T >::compositetype a)
static TReal getSaturation(TReal r, TReal g, TReal b)
static constexpr bool lightnessIsAverage
static TReal getLightness(TReal r, TReal g, TReal b)
static TReal getLightness(TReal r, TReal g, TReal b)
static TReal getSaturation(TReal r, TReal g, TReal b)
static constexpr bool lightnessIsAverage
static TReal getSaturation(TReal r, TReal g, TReal b)
static constexpr bool lightnessIsAverage
static TReal getLightness(TReal r, TReal g, TReal b)
static TReal getSaturation(TReal r, TReal g, TReal b)
static TReal getLightness(TReal r, TReal g, TReal b)
static constexpr bool lightnessIsAverage
float operator()(_T_ f) const
static KRITAPIGMENT_EXPORT const Ko::FullLut< KoIntegerToFloat< quint16 >, float, quint16 > Uint16ToFloat
static KRITAPIGMENT_EXPORT const Ko::FullLut< KoIntegerToFloat< quint8 >, float, quint8 > Uint8ToFloat