File indexing completed on 2024-12-08 06:39:04
0001 /* This file is part of the KDE project 0002 SPDX-FileCopyrightText: 2007 Matthew Woehlke <mw_triad@users.sourceforge.net> 0003 SPDX-FileCopyrightText: 2007 Olaf Schmidt <ojschmidt@kde.org> 0004 0005 SPDX-License-Identifier: LGPL-2.0-or-later 0006 */ 0007 #include "kcolorspaces_p.h" 0008 #include "kguiaddons_colorhelpers_p.h" 0009 0010 #include <QColor> 0011 0012 #include <math.h> 0013 0014 using namespace KColorSpaces; 0015 0016 static inline qreal wrap(qreal a, qreal d = 1.0) 0017 { 0018 qreal r = fmod(a, d); 0019 return (r < 0.0 ? d + r : (r > 0.0 ? r : 0.0)); 0020 } 0021 0022 /////////////////////////////////////////////////////////////////////////////// 0023 // HCY color space 0024 0025 #define HCY_REC 709 // use 709 for now 0026 #if HCY_REC == 601 0027 static const qreal yc[3] = {0.299, 0.587, 0.114}; 0028 #elif HCY_REC == 709 0029 static const qreal yc[3] = {0.2126, 0.7152, 0.0722}; 0030 #else // use Qt values 0031 static const qreal yc[3] = {0.34375, 0.5, 0.15625}; 0032 #endif 0033 0034 qreal KHCY::gamma(qreal n) 0035 { 0036 return pow(normalize(n), 2.2); 0037 } 0038 0039 qreal KHCY::igamma(qreal n) 0040 { 0041 return pow(normalize(n), 1.0 / 2.2); 0042 } 0043 0044 qreal KHCY::lumag(qreal r, qreal g, qreal b) 0045 { 0046 return r * yc[0] + g * yc[1] + b * yc[2]; 0047 } 0048 0049 KHCY::KHCY(qreal h_, qreal c_, qreal y_, qreal a_) 0050 { 0051 h = h_; 0052 c = c_; 0053 y = y_; 0054 a = a_; 0055 } 0056 0057 KHCY::KHCY(const QColor &color) 0058 { 0059 qreal r = gamma(color.redF()); 0060 qreal g = gamma(color.greenF()); 0061 qreal b = gamma(color.blueF()); 0062 a = color.alphaF(); 0063 0064 // luma component 0065 y = lumag(r, g, b); 0066 0067 // hue component 0068 qreal p = qMax(qMax(r, g), b); 0069 qreal n = qMin(qMin(r, g), b); 0070 qreal d = 6.0 * (p - n); 0071 if (n == p) { 0072 h = 0.0; 0073 } else if (r == p) { 0074 h = ((g - b) / d); 0075 } else if (g == p) { 0076 h = ((b - r) / d) + (1.0 / 3.0); 0077 } else { 0078 h = ((r - g) / d) + (2.0 / 3.0); 0079 } 0080 0081 // chroma component 0082 if (r == g && g == b) { 0083 c = 0.0; 0084 } else { 0085 c = qMax((y - n) / y, (p - y) / (1 - y)); 0086 } 0087 } 0088 0089 QColor KHCY::qColor() const 0090 { 0091 // start with sane component values 0092 qreal _h = wrap(h); 0093 qreal _c = normalize(c); 0094 qreal _y = normalize(y); 0095 0096 // calculate some needed variables 0097 qreal _hs = _h * 6.0; 0098 qreal th; 0099 qreal tm; 0100 if (_hs < 1.0) { 0101 th = _hs; 0102 tm = yc[0] + yc[1] * th; 0103 } else if (_hs < 2.0) { 0104 th = 2.0 - _hs; 0105 tm = yc[1] + yc[0] * th; 0106 } else if (_hs < 3.0) { 0107 th = _hs - 2.0; 0108 tm = yc[1] + yc[2] * th; 0109 } else if (_hs < 4.0) { 0110 th = 4.0 - _hs; 0111 tm = yc[2] + yc[1] * th; 0112 } else if (_hs < 5.0) { 0113 th = _hs - 4.0; 0114 tm = yc[2] + yc[0] * th; 0115 } else { 0116 th = 6.0 - _hs; 0117 tm = yc[0] + yc[2] * th; 0118 } 0119 0120 // calculate RGB channels in sorted order 0121 qreal tn; 0122 qreal to; 0123 qreal tp; 0124 if (tm >= _y) { 0125 tp = _y + _y * _c * (1.0 - tm) / tm; 0126 to = _y + _y * _c * (th - tm) / tm; 0127 tn = _y - (_y * _c); 0128 } else { 0129 tp = _y + (1.0 - _y) * _c; 0130 to = _y + (1.0 - _y) * _c * (th - tm) / (1.0 - tm); 0131 tn = _y - (1.0 - _y) * _c * tm / (1.0 - tm); 0132 } 0133 0134 // return RGB channels in appropriate order 0135 if (_hs < 1.0) { 0136 return QColor::fromRgbF(igamma(tp), igamma(to), igamma(tn), a); 0137 } else if (_hs < 2.0) { 0138 return QColor::fromRgbF(igamma(to), igamma(tp), igamma(tn), a); 0139 } else if (_hs < 3.0) { 0140 return QColor::fromRgbF(igamma(tn), igamma(tp), igamma(to), a); 0141 } else if (_hs < 4.0) { 0142 return QColor::fromRgbF(igamma(tn), igamma(to), igamma(tp), a); 0143 } else if (_hs < 5.0) { 0144 return QColor::fromRgbF(igamma(to), igamma(tn), igamma(tp), a); 0145 } else { 0146 return QColor::fromRgbF(igamma(tp), igamma(tn), igamma(to), a); 0147 } 0148 } 0149 0150 qreal KHCY::hue(const QColor &color) 0151 { 0152 return wrap(KHCY(color).h); 0153 } 0154 0155 qreal KHCY::chroma(const QColor &color) 0156 { 0157 return KHCY(color).c; 0158 } 0159 0160 qreal KHCY::luma(const QColor &color) 0161 { 0162 return lumag(gamma(color.redF()), gamma(color.greenF()), gamma(color.blueF())); 0163 }