KGuiAddons

kcolorutils.cpp
1/* This file is part of the KDE project
2 SPDX-FileCopyrightText: 2007 Matthew Woehlke <mw_triad@users.sourceforge.net>
3 SPDX-FileCopyrightText: 2007 Thomas Zander <zander@kde.org>
4 SPDX-FileCopyrightText: 2007 Zack Rusin <zack@kde.org>
5
6 SPDX-License-Identifier: LGPL-2.0-or-later
7*/
8#include "kcolorspaces_p.h"
9#include "kguiaddons_colorhelpers_p.h"
10#include <kcolorutils.h>
11
12#include <QColor>
13#include <QImage>
14#include <QtNumeric> // qIsNaN
15
16#include <math.h>
17
18// BEGIN internal helper functions
19static inline qreal mixQreal(qreal a, qreal b, qreal bias)
20{
21 return a + (b - a) * bias;
22}
23// END internal helper functions
24
25qreal KColorUtils::hue(const QColor &color)
26{
27 return KColorSpaces::KHCY::hue(color);
28}
29
30qreal KColorUtils::chroma(const QColor &color)
31{
32 return KColorSpaces::KHCY::chroma(color);
33}
34
35qreal KColorUtils::luma(const QColor &color)
36{
37 return KColorSpaces::KHCY::luma(color);
38}
39
40void KColorUtils::getHcy(const QColor &color, qreal *h, qreal *c, qreal *y, qreal *a)
41{
42 if (!c || !h || !y) {
43 return;
44 }
45 KColorSpaces::KHCY khcy(color);
46 *c = khcy.c;
47 *h = khcy.h + (khcy.h < 0.0 ? 1.0 : 0.0);
48 *y = khcy.y;
49 if (a) {
50 *a = khcy.a;
51 }
52}
53
54QColor KColorUtils::hcyColor(qreal h, qreal c, qreal y, qreal a)
55{
56 return KColorSpaces::KHCY(h, c, y, a).qColor();
57}
58
59static qreal contrastRatioForLuma(qreal y1, qreal y2)
60{
61 if (y1 > y2) {
62 return (y1 + 0.05) / (y2 + 0.05);
63 } else {
64 return (y2 + 0.05) / (y1 + 0.05);
65 }
66}
67
68qreal KColorUtils::contrastRatio(const QColor &c1, const QColor &c2)
69{
70 return contrastRatioForLuma(luma(c1), luma(c2));
71}
72
73QColor KColorUtils::lighten(const QColor &color, qreal ky, qreal kc)
74{
75 KColorSpaces::KHCY c(color);
76 c.y = 1.0 - normalize((1.0 - c.y) * (1.0 - ky));
77 c.c = 1.0 - normalize((1.0 - c.c) * kc);
78 return c.qColor();
79}
80
81QColor KColorUtils::darken(const QColor &color, qreal ky, qreal kc)
82{
83 KColorSpaces::KHCY c(color);
84 c.y = normalize(c.y * (1.0 - ky));
85 c.c = normalize(c.c * kc);
86 return c.qColor();
87}
88
89QColor KColorUtils::shade(const QColor &color, qreal ky, qreal kc)
90{
91 KColorSpaces::KHCY c(color);
92 c.y = normalize(c.y + ky);
93 c.c = normalize(c.c + kc);
94 return c.qColor();
95}
96
97static KColorSpaces::KHCY tintHelper(const QColor &base, qreal baseLuma, const QColor &color, qreal amount)
98{
99 KColorSpaces::KHCY result(KColorUtils::mix(base, color, pow(amount, 0.3)));
100 result.y = mixQreal(baseLuma, result.y, amount);
101
102 return result;
103}
104
105static qreal tintHelperLuma(const QColor &base, qreal baseLuma, const QColor &color, qreal amount)
106{
107 qreal result(KColorUtils::luma(KColorUtils::mix(base, color, pow(amount, 0.3))));
108 result = mixQreal(baseLuma, result, amount);
109
110 return result;
111}
112
113QColor KColorUtils::tint(const QColor &base, const QColor &color, qreal amount)
114{
115 if (amount <= 0.0) {
116 return base;
117 }
118 if (amount >= 1.0) {
119 return color;
120 }
121 if (qIsNaN(amount)) {
122 return base;
123 }
124
125 qreal baseLuma = luma(base); // cache value because luma call is expensive
126 double ri = contrastRatioForLuma(baseLuma, luma(color));
127 double rg = 1.0 + ((ri + 1.0) * amount * amount * amount);
128 double u = 1.0;
129 double l = 0.0;
130 double a = 0.5;
131 for (int i = 12; i; --i) {
132 a = 0.5 * (l + u);
133 qreal resultLuma = tintHelperLuma(base, baseLuma, color, a);
134 double ra = contrastRatioForLuma(baseLuma, resultLuma);
135 if (ra > rg) {
136 u = a;
137 } else {
138 l = a;
139 }
140 }
141 return tintHelper(base, baseLuma, color, a).qColor();
142}
143
144QColor KColorUtils::mix(const QColor &c1, const QColor &c2, qreal bias)
145{
146 if (bias <= 0.0) {
147 return c1;
148 }
149 if (bias >= 1.0) {
150 return c2;
151 }
152 if (qIsNaN(bias)) {
153 return c1;
154 }
155
156 qreal a = mixQreal(c1.alphaF(), c2.alphaF(), bias);
157 if (a <= 0.0) {
158 return Qt::transparent;
159 }
160
161 qreal r = qBound(0.0, mixQreal(c1.redF() * c1.alphaF(), c2.redF() * c2.alphaF(), bias), 1.0) / a;
162 qreal g = qBound(0.0, mixQreal(c1.greenF() * c1.alphaF(), c2.greenF() * c2.alphaF(), bias), 1.0) / a;
163 qreal b = qBound(0.0, mixQreal(c1.blueF() * c1.alphaF(), c2.blueF() * c2.alphaF(), bias), 1.0) / a;
164
165 return QColor::fromRgbF(r, g, b, a);
166}
167
169{
170 // This isn't the fastest way, but should be "fast enough".
171 // It's also the only safe way to use QPainter::CompositionMode
173 QPainter p(&img);
174 QColor start = base;
175 start.setAlpha(255); // opaque
176 p.fillRect(0, 0, 1, 1, start);
177 p.setCompositionMode(comp);
178 p.fillRect(0, 0, 1, 1, paint);
179 p.end();
180 return img.pixel(0, 0);
181}
Q_SCRIPTABLE Q_NOREPLY void start()
KGUIADDONS_EXPORT qreal chroma(const QColor &)
Calculate the chroma of a color.
KGUIADDONS_EXPORT QColor darken(const QColor &, qreal amount=0.5, qreal chromaGain=1.0)
Adjust the luma of a color by changing its distance from black.
KGUIADDONS_EXPORT QColor overlayColors(const QColor &base, const QColor &paint, QPainter::CompositionMode comp=QPainter::CompositionMode_SourceOver)
Blend two colors into a new color by painting the second color over the first using the specified com...
KGUIADDONS_EXPORT void getHcy(const QColor &, qreal *hue, qreal *chroma, qreal *luma, qreal *alpha=nullptr)
Calculate hue, chroma and luma of a color in one call.
KGUIADDONS_EXPORT qreal luma(const QColor &)
Calculate the luma of a color.
KGUIADDONS_EXPORT QColor shade(const QColor &, qreal lumaAmount, qreal chromaAmount=0.0)
Adjust the luma and chroma components of a color.
KGUIADDONS_EXPORT QColor mix(const QColor &c1, const QColor &c2, qreal bias=0.5)
Blend two colors into a new color by linear combination.
KGUIADDONS_EXPORT QColor tint(const QColor &base, const QColor &color, qreal amount=0.3)
Create a new color by tinting one color with another.
KGUIADDONS_EXPORT QColor lighten(const QColor &, qreal amount=0.5, qreal chromaInverseGain=1.0)
Adjust the luma of a color by changing its distance from white.
KGUIADDONS_EXPORT qreal contrastRatio(const QColor &, const QColor &)
Calculate the contrast ratio between two colors, according to the W3C/WCAG2.0 algorithm,...
KGUIADDONS_EXPORT qreal hue(const QColor &)
Calculate the hue of a color.
KGUIADDONS_EXPORT QColor hcyColor(qreal hue, qreal chroma, qreal luma, qreal alpha=1.0)
Return a QColor based on the given hue, chroma, luma and alpha values.
float alphaF() const const
float blueF() const const
QColor fromRgbF(float r, float g, float b, float a)
float greenF() const const
float redF() const const
void setAlpha(int alpha)
Format_ARGB32_Premultiplied
QRgb pixel(const QPoint &position) const const
bool end()
void fillRect(const QRect &rectangle, QGradient::Preset preset)
void setCompositionMode(CompositionMode mode)
transparent
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:14:40 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.