Kirigami2

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

KDE's Doxygen guidelines are available online.