KGuiAddons

kcolorutils.cpp
1 /* This file is part of the KDE project
2  SPDX-FileCopyrightText: 2007 Matthew Woehlke <[email protected]>
3  SPDX-FileCopyrightText: 2007 Thomas Zander <[email protected]>
4  SPDX-FileCopyrightText: 2007 Zack Rusin <[email protected]>
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
19 static inline qreal mixQreal(qreal a, qreal b, qreal bias)
20 {
21  return a + (b - a) * bias;
22 }
23 // END internal helper functions
24 
25 qreal KColorUtils::hue(const QColor &color)
26 {
27  return KColorSpaces::KHCY::hue(color);
28 }
29 
30 qreal KColorUtils::chroma(const QColor &color)
31 {
32  return KColorSpaces::KHCY::chroma(color);
33 }
34 
35 qreal KColorUtils::luma(const QColor &color)
36 {
37  return KColorSpaces::KHCY::luma(color);
38 }
39 
40 void 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 
54 QColor KColorUtils::hcyColor(qreal h, qreal c, qreal y, qreal a)
55 {
56  return KColorSpaces::KHCY(h, c, y, a).qColor();
57 }
58 
59 static 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 
68 qreal KColorUtils::contrastRatio(const QColor &c1, const QColor &c2)
69 {
70  return contrastRatioForLuma(luma(c1), luma(c2));
71 }
72 
73 QColor 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 
81 QColor 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 
89 QColor 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 
97 static QColor 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.qColor();
103 }
104 
105 QColor KColorUtils::tint(const QColor &base, const QColor &color, qreal amount)
106 {
107  if (amount <= 0.0) {
108  return base;
109  }
110  if (amount >= 1.0) {
111  return color;
112  }
113  if (qIsNaN(amount)) {
114  return base;
115  }
116 
117  qreal baseLuma = luma(base); // cache value because luma call is expensive
118  double ri = contrastRatioForLuma(baseLuma, luma(color));
119  double rg = 1.0 + ((ri + 1.0) * amount * amount * amount);
120  double u = 1.0;
121  double l = 0.0;
122  QColor result;
123  for (int i = 12; i; --i) {
124  double a = 0.5 * (l + u);
125  result = tintHelper(base, baseLuma, color, a);
126  double ra = contrastRatioForLuma(baseLuma, luma(result));
127  if (ra > rg) {
128  u = a;
129  } else {
130  l = a;
131  }
132  }
133  return result;
134 }
135 
136 QColor KColorUtils::mix(const QColor &c1, const QColor &c2, qreal bias)
137 {
138  if (bias <= 0.0) {
139  return c1;
140  }
141  if (bias >= 1.0) {
142  return c2;
143  }
144  if (qIsNaN(bias)) {
145  return c1;
146  }
147 
148  qreal r = mixQreal(c1.redF(), c2.redF(), bias);
149  qreal g = mixQreal(c1.greenF(), c2.greenF(), bias);
150  qreal b = mixQreal(c1.blueF(), c2.blueF(), bias);
151  qreal a = mixQreal(c1.alphaF(), c2.alphaF(), bias);
152 
153  return QColor::fromRgbF(r, g, b, a);
154 }
155 
157 {
158  // This isn't the fastest way, but should be "fast enough".
159  // It's also the only safe way to use QPainter::CompositionMode
161  QPainter p(&img);
162  QColor start = base;
163  start.setAlpha(255); // opaque
164  p.fillRect(0, 0, 1, 1, start);
165  p.setCompositionMode(comp);
166  p.fillRect(0, 0, 1, 1, paint);
167  p.end();
168  return img.pixel(0, 0);
169 }
KGUIADDONS_EXPORT qreal chroma(const QColor &)
Calculate the chroma of a color.
Definition: kcolorutils.cpp:30
KGUIADDONS_EXPORT qreal hue(const QColor &)
Calculate the hue of a color.
Definition: kcolorutils.cpp:25
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.
Definition: kcolorutils.cpp:81
bool end()
void fillRect(const QRectF &rectangle, const QBrush &brush)
void setCompositionMode(QPainter::CompositionMode mode)
qreal alphaF() const const
Format_ARGB32_Premultiplied
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.
Definition: kcolorutils.cpp:40
KGUIADDONS_EXPORT qreal contrastRatio(const QColor &, const QColor &)
Calculate the contrast ratio between two colors, according to the W3C/WCAG2.0 algorithm, (Lmax + 0.05)/(Lmin + 0.05), where Lmax and Lmin are the luma values of the lighter color and the darker color, respectively.
Definition: kcolorutils.cpp:68
qreal redF() const const
qreal blueF() const const
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 mix(const QColor &c1, const QColor &c2, qreal bias=0.5)
Blend two colors into a new color by linear combination.
void setAlpha(int alpha)
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.
Definition: kcolorutils.cpp:73
KGUIADDONS_EXPORT qreal luma(const QColor &)
Calculate the luma of a color.
Definition: kcolorutils.cpp:35
QRgb pixel(int x, int y) const const
qreal greenF() const const
KGUIADDONS_EXPORT QColor shade(const QColor &, qreal lumaAmount, qreal chromaAmount=0.0)
Adjust the luma and chroma components of a color.
Definition: kcolorutils.cpp:89
QColor fromRgbF(qreal r, qreal g, qreal b, qreal a)
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 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.
Definition: kcolorutils.cpp:54
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Mon Dec 6 2021 22:50:43 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.