MauiKit Controls

imagecolors.h
1/*
2 * Copyright 2020 Marco Martin <mart@kde.org>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 2.010-1301, USA.
17 */
18
19#pragma once
20
21#include "colorutils.h"
22
23#include <QColor>
24#include <QFuture>
25#include <QImage>
26#include <QObject>
27#include <QPointer>
28#include <QQuickItem>
29#include <QQuickItemGrabResult>
30#include <QQuickWindow>
31
32class QTimer;
33
34struct ImageData {
35 struct colorStat {
36 QList<QRgb> colors;
37 QRgb centroid = 0;
38 qreal ratio = 0;
39 };
40
41 struct colorSet {
42 QColor average;
43 QColor text;
44 QColor background;
45 QColor highlight;
46 };
47
48 QList<QRgb> m_samples;
49 QList<colorStat> m_clusters;
50 QVariantList m_palette;
51
52 bool m_darkPalette = true;
53 QColor m_dominant;
54 QColor m_dominantContrast;
55 QColor m_average;
56 QColor m_highlight;
57
58 QColor m_closestToBlack;
59 QColor m_closestToWhite;
60};
61
62/**
63 * Extracts the dominant colors from an element or an image and exports it to a color palette.
64 */
65class ImageColors : public QObject
66{
68 QML_ELEMENT
69 /**
70 * The source from which colors should be extracted from.
71 *
72 * `source` can be one of the following:
73 * * Item
74 * * QImage
75 * * QIcon
76 * * Icon name
77 *
78 * Note that an Item's color palette will only be extracted once unless you * call `update()`, regardless of how the item hanges.
79 */
80 Q_PROPERTY(QVariant source READ source WRITE setSource NOTIFY sourceChanged)
81
82 /**
83 * A list of colors and related information about then.
84 *
85 * Each list item has the following properties:
86 * * `color`: The color of the list item.
87 * * `ratio`: How dominant the color is in the source image.
88 * * `contrastingColor`: The color from the source image that's closest to the inverse of `color`.
89 *
90 * The list is sorted by `ratio`; the first element is the most
91 * dominant color in the source image and the last element is the
92 * least dominant color of the image.
93 *
94 * \note K-means clustering is used to extract these colors; see https://en.wikipedia.org/wiki/K-means_clustering.
95 */
96 Q_PROPERTY(QVariantList palette READ palette NOTIFY paletteChanged)
97
98 /**
99 * Information whether the palette is towards a light or dark color
100 * scheme, possible values are:
101 * * ColorUtils.Light
102 * * ColorUtils.Dark
103 */
104 Q_PROPERTY(ColorUtils::Brightness paletteBrightness READ paletteBrightness NOTIFY paletteChanged)
105
106 /**
107 * The average color of the source image.
108 */
109 Q_PROPERTY(QColor average READ average NOTIFY paletteChanged)
110
111 /**
112 * The dominant color of the source image.
113 *
114 * The dominant color of the image is the color of the largest
115 * cluster in the image.
116 *
117 * \sa https://en.wikipedia.org/wiki/K-means_clustering
118 */
119 Q_PROPERTY(QColor dominant READ dominant NOTIFY paletteChanged)
120
121 /**
122 * Suggested "contrasting" color to the dominant one. It's the color in the palette nearest to the negative of the dominant
123 */
125
126 /**
127 * An accent color extracted from the source image.
128 *
129 * The accent color is the color cluster with the highest CIELAB
130 * chroma in the source image.
131 *
132 * \sa https://en.wikipedia.org/wiki/Colorfulness#Chroma
133 */
134 Q_PROPERTY(QColor highlight READ highlight NOTIFY paletteChanged)
135
136 /**
137 * A color suitable for rendering text and other foreground
138 * over the source image.
139 *
140 * On dark items, this will be the color closest to white in
141 * the image if it's light enough, or a bright gray otherwise.
142 * On light items, this will be the color closest to black in
143 * the image if it's dark enough, or a dark gray otherwise.
144 */
145 Q_PROPERTY(QColor foreground READ foreground NOTIFY paletteChanged)
146
147 /**
148 * A color suitable for rendering a background behind the
149 * source image.
150 *
151 * On dark items, this will be the color closest to black in the
152 * image if it's dark enough, or a dark gray otherwise.
153 * On light items, this will be the color closest to white
154 * in the image if it's light enough, or a bright gray otherwise.
155 */
156 Q_PROPERTY(QColor background READ background NOTIFY paletteChanged)
157
158 /**
159 * The lightest color of the source image.
160 */
161 Q_PROPERTY(QColor closestToWhite READ closestToWhite NOTIFY paletteChanged)
162
163 /**
164 * The darkest color of the source image.
165 */
166 Q_PROPERTY(QColor closestToBlack READ closestToBlack NOTIFY paletteChanged)
167
168 /**
169 * The value to return when palette is not available, e.g. when
170 * ImageColors is still computing it or the source is invalid.
171 */
172 Q_PROPERTY(QVariantList fallbackPalette MEMBER m_fallbackPalette NOTIFY fallbackPaletteChanged)
173
174 /**
175 * The value to return when paletteBrightness is not available, e.g. when
176 * ImageColors is still computing it or the source is invalid.
177 */
178 Q_PROPERTY(ColorUtils::Brightness fallbackPaletteBrightness MEMBER m_fallbackPaletteBrightness NOTIFY fallbackPaletteBrightnessChanged)
179
180 /**
181 * The value to return when average is not available, e.g. when
182 * ImageColors is still computing it or the source is invalid.
183 */
184 Q_PROPERTY(QColor fallbackAverage MEMBER m_fallbackAverage NOTIFY fallbackAverageChanged)
185
186 /**
187 * The value to return when dominant is not available, e.g. when
188 * ImageColors is still computing it or the source is invalid.
189 */
190 Q_PROPERTY(QColor fallbackDominant MEMBER m_fallbackDominant NOTIFY fallbackDominantChanged)
191
192 /**
193 * The value to return when dominantContrasting is not available, e.g. when
194 * ImageColors is still computing it or the source is invalid.
195 */
196 Q_PROPERTY(QColor fallbackDominantContrasting MEMBER m_fallbackDominantContrasting NOTIFY fallbackDominantContrastingChanged)
197
198 /**
199 * The value to return when highlight is not available, e.g. when
200 * ImageColors is still computing it or the source is invalid.
201 */
202 Q_PROPERTY(QColor fallbackHighlight MEMBER m_fallbackHighlight NOTIFY fallbackHighlightChanged)
203
204 /**
205 * The value to return when foreground is not available, e.g. when
206 * ImageColors is still computing it or the source is invalid.
207 */
208 Q_PROPERTY(QColor fallbackForeground MEMBER m_fallbackForeground NOTIFY fallbackForegroundChanged)
209
210 /**
211 * The value to return when background is not available, e.g. when
212 * ImageColors is still computing it or the source is invalid.
213 */
214 Q_PROPERTY(QColor fallbackBackground MEMBER m_fallbackBackground NOTIFY fallbackBackgroundChanged)
215
216public:
217 explicit ImageColors(QObject *parent = nullptr);
218 ~ImageColors() override;
219
220 void setSource(const QVariant &source);
221 QVariant source() const;
222
223 void setSourceImage(const QImage &image);
224 QImage sourceImage() const;
225
226 void setSourceItem(QQuickItem *source);
227 QQuickItem *sourceItem() const;
228
229 Q_INVOKABLE void update();
230
231 QVariantList palette() const;
232 ColorUtils::Brightness paletteBrightness() const;
233 QColor average() const;
234 QColor dominant() const;
235 QColor dominantContrast() const;
236 QColor highlight() const;
237 QColor foreground() const;
238 QColor background() const;
239 QColor closestToWhite() const;
240 QColor closestToBlack() const;
241
243 void sourceChanged();
244 void paletteChanged();
245 void fallbackPaletteChanged();
246 void fallbackPaletteBrightnessChanged();
247 void fallbackAverageChanged();
248 void fallbackDominantChanged();
249 void fallbackDominantContrastingChanged();
250 void fallbackHighlightChanged();
251 void fallbackForegroundChanged();
252 void fallbackBackgroundChanged();
253
254private:
255 static inline void positionColor(QRgb rgb, QList<ImageData::colorStat> &clusters);
256 static ImageData generatePalette(const QImage &sourceImage);
257
258 // Arbitrary number that seems to work well
259 static const int s_minimumSquareDistance = 32000;
260 QPointer<QQuickWindow> m_window;
261 QVariant m_source;
262 QPointer<QQuickItem> m_sourceItem;
264 QImage m_sourceImage;
265
266 QTimer *m_imageSyncTimer;
267
268 QFutureWatcher<ImageData> *m_futureImageData = nullptr;
269 ImageData m_imageData;
270
271 QVariantList m_fallbackPalette;
272 ColorUtils::Brightness m_fallbackPaletteBrightness;
273 QColor m_fallbackAverage;
274 QColor m_fallbackDominant;
275 QColor m_fallbackDominantContrasting;
276 QColor m_fallbackHighlight;
277 QColor m_fallbackForeground;
278 QColor m_fallbackBackground;
279};
Utilities for processing items to obtain colors and information useful for UIs that need to adjust to...
Definition colorutils.h:19
QColor fallbackDominant
The value to return when dominant is not available, e.g.
ColorUtils::Brightness fallbackPaletteBrightness
The value to return when paletteBrightness is not available, e.g.
QML_ELEMENTQVariant source
The source from which colors should be extracted from.
Definition imagecolors.h:80
QColor foreground
A color suitable for rendering text and other foreground over the source image.
QVariantList fallbackPalette
The value to return when palette is not available, e.g.
QColor closestToWhite
The lightest color of the source image.
QColor dominant
The dominant color of the source image.
QVariantList palette
A list of colors and related information about then.
Definition imagecolors.h:96
QColor fallbackAverage
The value to return when average is not available, e.g.
QColor closestToBlack
The darkest color of the source image.
QColor fallbackBackground
The value to return when background is not available, e.g.
QColor fallbackForeground
The value to return when foreground is not available, e.g.
QColor dominantContrast
Suggested "contrasting" color to the dominant one.
ColorUtils::Brightness paletteBrightness
Information whether the palette is towards a light or dark color scheme, possible values are:
QColor fallbackDominantContrasting
The value to return when dominantContrasting is not available, e.g.
QColor average
The average color of the source image.
QColor background
A color suitable for rendering a background behind the source image.
QColor highlight
An accent color extracted from the source image.
QColor fallbackHighlight
The value to return when highlight is not available, e.g.
QObject(QObject *parent)
Q_INVOKABLEQ_INVOKABLE
Q_OBJECTQ_OBJECT
Q_PROPERTY(...)
Q_SIGNALSQ_SIGNALS
QObject * parent() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2025 The KDE developers.
Generated on Fri May 2 2025 11:57:11 by doxygen 1.13.2 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.