diff --git a/src/colors/kcolorspaces.cpp b/src/colors/kcolorspaces.cpp --- a/src/colors/kcolorspaces.cpp +++ b/src/colors/kcolorspaces.cpp @@ -156,6 +156,16 @@ } } +qreal KHCY::hue(const QColor &color) +{ + return wrap(KHCY(color).h); +} + +qreal KHCY::chroma(const QColor &color) +{ + return KHCY(color).c; +} + qreal KHCY::luma(const QColor &color) { return lumag(gamma(color.redF()), diff --git a/src/colors/kcolorspaces_p.h b/src/colors/kcolorspaces_p.h --- a/src/colors/kcolorspaces_p.h +++ b/src/colors/kcolorspaces_p.h @@ -38,6 +38,8 @@ explicit KHCY(qreal h_, qreal c_, qreal y_, qreal a_ = 1.0); QColor qColor() const; qreal h, c, y, a; + static qreal hue(const QColor &); + static qreal chroma(const QColor &); static qreal luma(const QColor &); private: static qreal gamma(qreal); diff --git a/src/colors/kcolorutils.h b/src/colors/kcolorutils.h --- a/src/colors/kcolorutils.h +++ b/src/colors/kcolorutils.h @@ -32,10 +32,32 @@ */ namespace KColorUtils { +/** + * Calculate the hue of a color. The range is from 0.0 (red) to almost 1.0 (slightly blue-ish red). + * + * The result is computed in linear (not sRGB) color space and may differ slightly from QColor::hue(). + * + * @see https://en.wikipedia.org/wiki/Hue + * @since 5.68 + */ +KGUIADDONS_EXPORT qreal hue(const QColor &); + +/** + * Calculate the chroma of a color. The range is from 0.0 (none) to 1.0 (full). + * + * The result is computed in linear (not sRGB) color space. + * + * @see https://en.wikipedia.org/wiki/Colorfulness + * @since 5.68 + */ +KGUIADDONS_EXPORT qreal chroma(const QColor &); + /** * Calculate the luma of a color. Luma is weighted sum of gamma-adjusted * R'G'B' components of a color. The result is similar to qGray. The range * is from 0.0 (black) to 1.0 (white). + * + * The result is computed in linear (not sRGB) color space. * * KColorUtils::darken(), KColorUtils::lighten() and KColorUtils::shade() * operate on the luma of a color. @@ -46,10 +68,30 @@ /** * Calculate hue, chroma and luma of a color in one call. + * + * The range of hue is from 0.0 (red) to almost 1.0 (slightly blue-ish red). + * The range of chroma is from 0.0 (none) to 1.0 (full). + * The range of luma is from 0.0 (black) to 1.0 (white). + * + * The hue, chroma and luma values are computed in linear (not sRGB) color space. + * * @since 5.0 */ KGUIADDONS_EXPORT void getHcy(const QColor &, qreal *hue, qreal *chroma, qreal *luma, qreal *alpha = nullptr); +/** + * Return a QColor based on the given hue, chroma, luma and alpha values. + * + * The range of hue is cyclical. For example, 0.0 and 1.0 are both red while -0.166667 and 0.833333 are both magenta. + * The range of chroma is from 0.0 (none) to 1.0 (full). Out of range values will be clamped. + * The range of luma is from 0.0 (black) to 1.0 (white). Out of range values will be clamped. + * + * The hue, chroma and luma values are computed in linear (not sRGB) color space. + * + * @since 5.68 + */ +KGUIADDONS_EXPORT QColor hcyColor(qreal hue, qreal chroma, qreal luma, qreal alpha = 1.0); + /** * Calculate the contrast ratio between two colors, according to the * W3C/WCAG2.0 algorithm, (Lmax + 0.05)/(Lmin + 0.05), where Lmax and Lmin diff --git a/src/colors/kcolorutils.cpp b/src/colors/kcolorutils.cpp --- a/src/colors/kcolorutils.cpp +++ b/src/colors/kcolorutils.cpp @@ -35,6 +35,16 @@ } // END internal helper functions +qreal KColorUtils::hue(const QColor &color) +{ + return KColorSpaces::KHCY::hue(color); +} + +qreal KColorUtils::chroma(const QColor &color) +{ + return KColorSpaces::KHCY::chroma(color); +} + qreal KColorUtils::luma(const QColor &color) { return KColorSpaces::KHCY::luma(color); @@ -47,13 +57,18 @@ } KColorSpaces::KHCY khcy(color); *c = khcy.c; - *h = khcy.h; + *h = khcy.h + (khcy.h < 0.0 ? 1.0 : 0.0); *y = khcy.y; if (a) { *a = khcy.a; } } +QColor KColorUtils::hcyColor(qreal h, qreal c, qreal y, qreal a) +{ + return KColorSpaces::KHCY(h, c, y, a).qColor(); +} + static qreal contrastRatioForLuma(qreal y1, qreal y2) { if (y1 > y2) {