Kirigami2

imagecolors.h
1 /*
2  * Copyright 2020 Marco Martin <[email protected]>
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 
32 class QTimer;
33 
34 struct 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 = Qt::transparent;
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  */
65 class ImageColors : public QObject
66 {
67  Q_OBJECT
68  /**
69  * The source from which colors should be extracted from.
70  *
71  * `source` can be one of the following:
72  * * Item
73  * * QImage
74  * * QIcon
75  * * Icon name
76  *
77  * Note that an Item's color palette will only be extracted once unless you * call `update()`, regardless of how the item hanges.
78  */
79  Q_PROPERTY(QVariant source READ source WRITE setSource NOTIFY sourceChanged)
80 
81  /**
82  * A list of colors and related information about then.
83  *
84  * Each list item has the following properties:
85  * * `color`: The color of the list item.
86  * * `ratio`: How dominant the color is in the source image.
87  * * `contrastingColor`: The color from the source image that's closest to the inverse of `color`.
88  *
89  * The list is sorted by `ratio`; the first element is the most
90  * dominant color in the source image and the last element is the
91  * least dominant color of the image.
92  *
93  * \note K-means clustering is used to extract these colors; see https://en.wikipedia.org/wiki/K-means_clustering.
94  */
95  Q_PROPERTY(QVariantList palette READ palette NOTIFY paletteChanged)
96 
97  /**
98  * Information whether the palette is towards a light or dark color
99  * scheme, possible values are:
100  * * ColorUtils.Light
101  * * ColorUtils.Dark
102  */
103  Q_PROPERTY(ColorUtils::Brightness paletteBrightness READ paletteBrightness NOTIFY paletteChanged)
104 
105  /**
106  * The average color of the source image.
107  */
108  Q_PROPERTY(QColor average READ average NOTIFY paletteChanged)
109 
110  /**
111  * The dominant color of the source image.
112  *
113  * The dominant color of the image is the color of the largest
114  * cluster in the image.
115  *
116  * \sa https://en.wikipedia.org/wiki/K-means_clustering
117  */
118  Q_PROPERTY(QColor dominant READ dominant NOTIFY paletteChanged)
119 
120  /**
121  * Suggested "contrasting" color to the dominant one. It's the color in the palette nearest to the negative of the dominant
122  */
124 
125  /**
126  * An accent color extracted from the source image.
127  *
128  * The accent color is the color cluster with the highest CIELAB
129  * chroma in the source image.
130  *
131  * \sa https://en.wikipedia.org/wiki/Colorfulness#Chroma
132  */
133  Q_PROPERTY(QColor highlight READ highlight NOTIFY paletteChanged)
134 
135  /**
136  * A color suitable for rendering text and other foreground
137  * over the source image.
138  *
139  * On dark items, this will be the color closest to white in
140  * the image if it's light enough, or a bright gray otherwise.
141  * On light items, this will be the color closest to black in
142  * the image if it's dark enough, or a dark gray otherwise.
143  */
144  Q_PROPERTY(QColor foreground READ foreground NOTIFY paletteChanged)
145 
146  /**
147  * A color suitable for rendering a background behind the
148  * source image.
149  *
150  * On dark items, this will be the color closest to black in the
151  * image if it's dark enough, or a dark gray otherwise.
152  * On light items, this will be the color closest to white
153  * in the image if it's light enough, or a bright gray otherwise.
154  */
155  Q_PROPERTY(QColor background READ background NOTIFY paletteChanged)
156 
157  /**
158  * The lightest color of the source image.
159  */
160  Q_PROPERTY(QColor closestToWhite READ closestToWhite NOTIFY paletteChanged)
161 
162  /**
163  * The darkest color of the source image.
164  */
165  Q_PROPERTY(QColor closestToBlack READ closestToBlack NOTIFY paletteChanged)
166 
167  /**
168  * The value to return when palette is not available, e.g. when
169  * ImageColors is still computing it or the source is invalid.
170  */
171  Q_PROPERTY(QVariantList fallbackPalette MEMBER m_fallbackPalette NOTIFY fallbackPaletteChanged)
172 
173  /**
174  * The value to return when paletteBrightness is not available, e.g. when
175  * ImageColors is still computing it or the source is invalid.
176  */
177  Q_PROPERTY(ColorUtils::Brightness fallbackPaletteBrightness MEMBER m_fallbackPaletteBrightness NOTIFY fallbackPaletteBrightnessChanged)
178 
179  /**
180  * The value to return when average is not available, e.g. when
181  * ImageColors is still computing it or the source is invalid.
182  */
183  Q_PROPERTY(QColor fallbackAverage MEMBER m_fallbackAverage NOTIFY fallbackAverageChanged)
184 
185  /**
186  * The value to return when dominant is not available, e.g. when
187  * ImageColors is still computing it or the source is invalid.
188  */
189  Q_PROPERTY(QColor fallbackDominant MEMBER m_fallbackDominant NOTIFY fallbackDominantChanged)
190 
191  /**
192  * The value to return when dominantContrasting is not available, e.g. when
193  * ImageColors is still computing it or the source is invalid.
194  */
195  Q_PROPERTY(QColor fallbackDominantContrasting MEMBER m_fallbackDominantContrasting NOTIFY fallbackDominantContrastingChanged)
196 
197  /**
198  * The value to return when highlight is not available, e.g. when
199  * ImageColors is still computing it or the source is invalid.
200  */
201  Q_PROPERTY(QColor fallbackHighlight MEMBER m_fallbackHighlight NOTIFY fallbackHighlightChanged)
202 
203  /**
204  * The value to return when foreground is not available, e.g. when
205  * ImageColors is still computing it or the source is invalid.
206  */
207  Q_PROPERTY(QColor fallbackForeground MEMBER m_fallbackForeground NOTIFY fallbackForegroundChanged)
208 
209  /**
210  * The value to return when background is not available, e.g. when
211  * ImageColors is still computing it or the source is invalid.
212  */
213  Q_PROPERTY(QColor fallbackBackground MEMBER m_fallbackBackground NOTIFY fallbackBackgroundChanged)
214 
215 public:
216  explicit ImageColors(QObject *parent = nullptr);
217  ~ImageColors() override;
218 
219  void setSource(const QVariant &source);
220  QVariant source() const;
221 
222  void setSourceImage(const QImage &image);
223  QImage sourceImage() const;
224 
225  void setSourceItem(QQuickItem *source);
226  QQuickItem *sourceItem() const;
227 
228  Q_INVOKABLE void update();
229 
230  QVariantList palette() const;
231  ColorUtils::Brightness paletteBrightness() const;
232  QColor average() const;
233  QColor dominant() const;
234  QColor dominantContrast() const;
235  QColor highlight() const;
236  QColor foreground() const;
237  QColor background() const;
238  QColor closestToWhite() const;
239  QColor closestToBlack() const;
240 
241 Q_SIGNALS:
242  void sourceChanged();
243  void paletteChanged();
244  void fallbackPaletteChanged();
245  void fallbackPaletteBrightnessChanged();
246  void fallbackAverageChanged();
247  void fallbackDominantChanged();
248  void fallbackDominantContrastingChanged();
249  void fallbackHighlightChanged();
250  void fallbackForegroundChanged();
251  void fallbackBackgroundChanged();
252 
253 private:
254  static inline void positionColor(QRgb rgb, QList<ImageData::colorStat> &clusters);
255  ImageData generatePalette(const QImage &sourceImage) const;
256 
257  double getClusterScore(const ImageData::colorStat &stat) const;
258  void postProcess(ImageData &imageData) const;
259 
260  // Arbitrary number that seems to work well
261  static const int s_minimumSquareDistance = 32000;
262  QPointer<QQuickWindow> m_window;
263  QVariant m_source;
264  QPointer<QQuickItem> m_sourceItem;
265  QSharedPointer<QQuickItemGrabResult> m_grabResult;
266  QImage m_sourceImage;
267  QFutureWatcher<QImage> *m_futureSourceImageData = nullptr;
268 
269  QTimer *m_imageSyncTimer;
270 
271  QFutureWatcher<ImageData> *m_futureImageData = nullptr;
272  ImageData m_imageData;
273 
274  QVariantList m_fallbackPalette;
275  ColorUtils::Brightness m_fallbackPaletteBrightness;
276  QColor m_fallbackAverage;
277  QColor m_fallbackDominant;
278  QColor m_fallbackDominantContrasting;
279  QColor m_fallbackHighlight;
280  QColor m_fallbackForeground;
281  QColor m_fallbackBackground;
282 };
Q_OBJECTQ_OBJECT
QColor dominant
The dominant color of the source image.
Definition: imagecolors.h:118
Q_PROPERTY(...)
QColor closestToWhite
The lightest color of the source image.
Definition: imagecolors.h:160
QColor closestToBlack
The darkest color of the source image.
Definition: imagecolors.h:165
QColor fallbackDominant
The value to return when dominant is not available, e.g.
Definition: imagecolors.h:189
QColor fallbackAverage
The value to return when average is not available, e.g.
Definition: imagecolors.h:183
Utilities for processing items to obtain colors and information useful for UIs that need to adjust to...
Definition: colorutils.h:18
QColor average
The average color of the source image.
Definition: imagecolors.h:108
QColor fallbackBackground
The value to return when background is not available, e.g.
Definition: imagecolors.h:213
QColor fallbackDominantContrasting
The value to return when dominantContrasting is not available, e.g.
Definition: imagecolors.h:195
QColor dominantContrast
Suggested "contrasting" color to the dominant one.
Definition: imagecolors.h:123
QVariantList fallbackPalette
The value to return when palette is not available, e.g.
Definition: imagecolors.h:171
Extracts the dominant colors from an element or an image and exports it to a color palette.
Definition: imagecolors.h:65
QColor background
A color suitable for rendering a background behind the source image.
Definition: imagecolors.h:155
Q_INVOKABLEQ_INVOKABLE
Q_SIGNALSQ_SIGNALS
QColor foreground
A color suitable for rendering text and other foreground over the source image.
Definition: imagecolors.h:144
QVariant source
The source from which colors should be extracted from.
Definition: imagecolors.h:79
QColor fallbackForeground
The value to return when foreground is not available, e.g.
Definition: imagecolors.h:207
QColor highlight
An accent color extracted from the source image.
Definition: imagecolors.h:133
ColorUtils::Brightness paletteBrightness
Information whether the palette is towards a light or dark color scheme, possible values are:
Definition: imagecolors.h:103
ColorUtils::Brightness fallbackPaletteBrightness
The value to return when paletteBrightness is not available, e.g.
Definition: imagecolors.h:177
QColor fallbackHighlight
The value to return when highlight is not available, e.g.
Definition: imagecolors.h:201
QVariantList palette
A list of colors and related information about then.
Definition: imagecolors.h:95
QObject * parent() const const
transparent
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Tue Feb 7 2023 04:14:23 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.