forked from quickshell/quickshell
		
	core/colorquant: add ColorQuantizer
This commit is contained in:
		
							parent
							
								
									fb343ab639
								
							
						
					
					
						commit
						a813a51a12
					
				
					 4 changed files with 360 additions and 0 deletions
				
			
		| 
						 | 
					@ -37,6 +37,7 @@ qt_add_library(quickshell-core STATIC
 | 
				
			||||||
	common.cpp
 | 
						common.cpp
 | 
				
			||||||
	iconprovider.cpp
 | 
						iconprovider.cpp
 | 
				
			||||||
	scriptmodel.cpp
 | 
						scriptmodel.cpp
 | 
				
			||||||
 | 
						colorquantizer.cpp
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
qt_add_qml_module(quickshell-core
 | 
					qt_add_qml_module(quickshell-core
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										230
									
								
								src/core/colorquantizer.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										230
									
								
								src/core/colorquantizer.cpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,230 @@
 | 
				
			||||||
 | 
					#include "colorquantizer.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <qcolor.h>
 | 
				
			||||||
 | 
					#include <qlogging.h>
 | 
				
			||||||
 | 
					#include <qloggingcategory.h>
 | 
				
			||||||
 | 
					#include <qobject.h>
 | 
				
			||||||
 | 
					#include <qqmllist.h>
 | 
				
			||||||
 | 
					#include <qthreadpool.h>
 | 
				
			||||||
 | 
					#include <qtypes.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace {
 | 
				
			||||||
 | 
					Q_LOGGING_CATEGORY(logColorQuantizer, "quickshell.colorquantizer", QtWarningMsg);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ColorQuantizerOperation::ColorQuantizerOperation(QUrl* source, qreal depth, qreal rescaleSize)
 | 
				
			||||||
 | 
					    : source(source)
 | 
				
			||||||
 | 
					    , maxDepth(depth)
 | 
				
			||||||
 | 
					    , rescaleSize(rescaleSize) {
 | 
				
			||||||
 | 
						setAutoDelete(false);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ColorQuantizerOperation::quantizeImage(const QAtomicInteger<bool>& shouldCancel) {
 | 
				
			||||||
 | 
						if (shouldCancel.loadAcquire() || source->isEmpty()) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						colors.clear();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						auto image = QImage(source->toLocalFile());
 | 
				
			||||||
 | 
						if ((image.width() > rescaleSize || image.height() > rescaleSize) && rescaleSize > 0) {
 | 
				
			||||||
 | 
							image = image.scaled(
 | 
				
			||||||
 | 
							    static_cast<int>(rescaleSize),
 | 
				
			||||||
 | 
							    static_cast<int>(rescaleSize),
 | 
				
			||||||
 | 
							    Qt::KeepAspectRatio,
 | 
				
			||||||
 | 
							    Qt::SmoothTransformation
 | 
				
			||||||
 | 
							);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (image.isNull()) {
 | 
				
			||||||
 | 
							qCWarning(logColorQuantizer) << "Failed to load image from" << source;
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						QList<QColor> pixels;
 | 
				
			||||||
 | 
						for (int y = 0; y != image.height(); ++y) {
 | 
				
			||||||
 | 
							for (int x = 0; x != image.width(); ++x) {
 | 
				
			||||||
 | 
								auto pixel = image.pixel(x, y);
 | 
				
			||||||
 | 
								if (qAlpha(pixel) == 0) continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								pixels.append(QColor::fromRgb(pixel));
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						auto startTime = QDateTime::currentDateTime();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						colors = quantization(pixels, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						auto endTime = QDateTime::currentDateTime();
 | 
				
			||||||
 | 
						auto milliseconds = startTime.msecsTo(endTime);
 | 
				
			||||||
 | 
						qCDebug(logColorQuantizer) << "Color Quantization took: " << milliseconds << "ms";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					QList<QColor> ColorQuantizerOperation::quantization(
 | 
				
			||||||
 | 
					    QList<QColor>& rgbValues,
 | 
				
			||||||
 | 
					    qreal depth,
 | 
				
			||||||
 | 
					    const QAtomicInteger<bool>& shouldCancel
 | 
				
			||||||
 | 
					) {
 | 
				
			||||||
 | 
						if (shouldCancel.loadAcquire()) return QList<QColor>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (depth >= maxDepth || rgbValues.isEmpty()) {
 | 
				
			||||||
 | 
							if (rgbValues.isEmpty()) return QList<QColor>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							auto totalR = 0;
 | 
				
			||||||
 | 
							auto totalG = 0;
 | 
				
			||||||
 | 
							auto totalB = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							for (const auto& color: rgbValues) {
 | 
				
			||||||
 | 
								if (shouldCancel.loadAcquire()) return QList<QColor>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								totalR += color.red();
 | 
				
			||||||
 | 
								totalG += color.green();
 | 
				
			||||||
 | 
								totalB += color.blue();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							auto avgColor = QColor(
 | 
				
			||||||
 | 
							    qRound(totalR / static_cast<double>(rgbValues.size())),
 | 
				
			||||||
 | 
							    qRound(totalG / static_cast<double>(rgbValues.size())),
 | 
				
			||||||
 | 
							    qRound(totalB / static_cast<double>(rgbValues.size()))
 | 
				
			||||||
 | 
							);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return QList<QColor>() << avgColor;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						auto dominantChannel = findBiggestColorRange(rgbValues);
 | 
				
			||||||
 | 
						std::ranges::sort(rgbValues, [dominantChannel](const auto& a, const auto& b) {
 | 
				
			||||||
 | 
							if (dominantChannel == 'r') return a.red() < b.red();
 | 
				
			||||||
 | 
							else if (dominantChannel == 'g') return a.green() < b.green();
 | 
				
			||||||
 | 
							return a.blue() < b.blue();
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						auto mid = rgbValues.size() / 2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						auto leftHalf = rgbValues.mid(0, mid);
 | 
				
			||||||
 | 
						auto rightHalf = rgbValues.mid(mid);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						QList<QColor> result;
 | 
				
			||||||
 | 
						result.append(quantization(leftHalf, depth + 1));
 | 
				
			||||||
 | 
						result.append(quantization(rightHalf, depth + 1));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					char ColorQuantizerOperation::findBiggestColorRange(const QList<QColor>& rgbValues) {
 | 
				
			||||||
 | 
						if (rgbValues.isEmpty()) return 'r';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						auto rMin = 255;
 | 
				
			||||||
 | 
						auto gMin = 255;
 | 
				
			||||||
 | 
						auto bMin = 255;
 | 
				
			||||||
 | 
						auto rMax = 0;
 | 
				
			||||||
 | 
						auto gMax = 0;
 | 
				
			||||||
 | 
						auto bMax = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (const auto& color: rgbValues) {
 | 
				
			||||||
 | 
							rMin = qMin(rMin, color.red());
 | 
				
			||||||
 | 
							gMin = qMin(gMin, color.green());
 | 
				
			||||||
 | 
							bMin = qMin(bMin, color.blue());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							rMax = qMax(rMax, color.red());
 | 
				
			||||||
 | 
							gMax = qMax(gMax, color.green());
 | 
				
			||||||
 | 
							bMax = qMax(bMax, color.blue());
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						auto rRange = rMax - rMin;
 | 
				
			||||||
 | 
						auto gRange = gMax - gMin;
 | 
				
			||||||
 | 
						auto bRange = bMax - bMin;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						auto biggestRange = qMax(rRange, qMax(gRange, bRange));
 | 
				
			||||||
 | 
						if (biggestRange == rRange) {
 | 
				
			||||||
 | 
							return 'r';
 | 
				
			||||||
 | 
						} else if (biggestRange == gRange) {
 | 
				
			||||||
 | 
							return 'g';
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							return 'b';
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ColorQuantizerOperation::finishRun() {
 | 
				
			||||||
 | 
						QMetaObject::invokeMethod(this, &ColorQuantizerOperation::finished, Qt::QueuedConnection);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ColorQuantizerOperation::finished() {
 | 
				
			||||||
 | 
						emit this->done(colors);
 | 
				
			||||||
 | 
						delete this;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ColorQuantizerOperation::run() {
 | 
				
			||||||
 | 
						if (!this->shouldCancel) {
 | 
				
			||||||
 | 
							this->quantizeImage();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (this->shouldCancel.loadAcquire()) {
 | 
				
			||||||
 | 
								qCDebug(logColorQuantizer) << "Color quantization" << this << "cancelled";
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						this->finishRun();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ColorQuantizerOperation::tryCancel() { this->shouldCancel.storeRelease(true); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ColorQuantizer::componentComplete() {
 | 
				
			||||||
 | 
						componentCompleted = true;
 | 
				
			||||||
 | 
						if (!mSource.isEmpty()) quantizeAsync();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ColorQuantizer::setSource(const QUrl& source) {
 | 
				
			||||||
 | 
						if (mSource != source) {
 | 
				
			||||||
 | 
							mSource = source;
 | 
				
			||||||
 | 
							emit this->sourceChanged();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (this->componentCompleted && !mSource.isEmpty()) quantizeAsync();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ColorQuantizer::setDepth(qreal depth) {
 | 
				
			||||||
 | 
						if (mDepth != depth) {
 | 
				
			||||||
 | 
							mDepth = depth;
 | 
				
			||||||
 | 
							emit this->depthChanged();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (this->componentCompleted) quantizeAsync();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ColorQuantizer::setRescaleSize(int rescaleSize) {
 | 
				
			||||||
 | 
						if (mRescaleSize != rescaleSize) {
 | 
				
			||||||
 | 
							mRescaleSize = rescaleSize;
 | 
				
			||||||
 | 
							emit this->rescaleSizeChanged();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (this->componentCompleted) quantizeAsync();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ColorQuantizer::operationFinished(const QList<QColor>& result) {
 | 
				
			||||||
 | 
						bColors = result;
 | 
				
			||||||
 | 
						this->liveOperation = nullptr;
 | 
				
			||||||
 | 
						emit this->colorsChanged();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ColorQuantizer::quantizeAsync() {
 | 
				
			||||||
 | 
						if (this->liveOperation) this->cancelAsync();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						qCDebug(logColorQuantizer) << "Starting color quantization asynchronously";
 | 
				
			||||||
 | 
						this->liveOperation = new ColorQuantizerOperation(&mSource, mDepth, mRescaleSize);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						QObject::connect(
 | 
				
			||||||
 | 
						    this->liveOperation,
 | 
				
			||||||
 | 
						    &ColorQuantizerOperation::done,
 | 
				
			||||||
 | 
						    this,
 | 
				
			||||||
 | 
						    &ColorQuantizer::operationFinished
 | 
				
			||||||
 | 
						);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						QThreadPool::globalInstance()->start(this->liveOperation);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ColorQuantizer::cancelAsync() {
 | 
				
			||||||
 | 
						if (!this->liveOperation) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						this->liveOperation->tryCancel();
 | 
				
			||||||
 | 
						QThreadPool::globalInstance()->waitForDone();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						QObject::disconnect(this->liveOperation, nullptr, this, nullptr);
 | 
				
			||||||
 | 
						this->liveOperation = nullptr;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										128
									
								
								src/core/colorquantizer.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										128
									
								
								src/core/colorquantizer.hpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,128 @@
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <qlist.h>
 | 
				
			||||||
 | 
					#include <qobject.h>
 | 
				
			||||||
 | 
					#include <qproperty.h>
 | 
				
			||||||
 | 
					#include <qqmlintegration.h>
 | 
				
			||||||
 | 
					#include <qqmlparserstatus.h>
 | 
				
			||||||
 | 
					#include <qrunnable.h>
 | 
				
			||||||
 | 
					#include <qtmetamacros.h>
 | 
				
			||||||
 | 
					#include <qtypes.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ColorQuantizerOperation
 | 
				
			||||||
 | 
					    : public QObject
 | 
				
			||||||
 | 
					    , public QRunnable {
 | 
				
			||||||
 | 
						Q_OBJECT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
						explicit ColorQuantizerOperation(QUrl* source, qreal depth, qreal rescaleSize);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						void run() override;
 | 
				
			||||||
 | 
						void tryCancel();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					signals:
 | 
				
			||||||
 | 
						void done(QList<QColor> colors);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private slots:
 | 
				
			||||||
 | 
						void finished();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
						static char findBiggestColorRange(const QList<QColor>& rgbValues);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						void quantizeImage(const QAtomicInteger<bool>& shouldCancel = false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						QList<QColor> quantization(
 | 
				
			||||||
 | 
						    QList<QColor>& rgbValues,
 | 
				
			||||||
 | 
						    qreal depth,
 | 
				
			||||||
 | 
						    const QAtomicInteger<bool>& shouldCancel = false
 | 
				
			||||||
 | 
						);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						void finishRun();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						QAtomicInteger<bool> shouldCancel = false;
 | 
				
			||||||
 | 
						QList<QColor> colors;
 | 
				
			||||||
 | 
						QUrl* source;
 | 
				
			||||||
 | 
						qreal maxDepth;
 | 
				
			||||||
 | 
						qreal rescaleSize;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					///! Color Quantization Utility
 | 
				
			||||||
 | 
					/// A color quantization utility used for getting prevalent colors in an image, by
 | 
				
			||||||
 | 
					/// averaging out the image's color data recursively.
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					/// #### Example
 | 
				
			||||||
 | 
					/// ```qml
 | 
				
			||||||
 | 
					/// ColorQuantizer {
 | 
				
			||||||
 | 
					///   id: colorQuantizer
 | 
				
			||||||
 | 
					///   source: Qt.resolvedUrl("./yourImage.png")
 | 
				
			||||||
 | 
					///   depth: 3 // Will produce 8 colors (2³)
 | 
				
			||||||
 | 
					///   rescaleSize: 64 // Rescale to 64x64 for faster processing
 | 
				
			||||||
 | 
					/// }
 | 
				
			||||||
 | 
					/// ```
 | 
				
			||||||
 | 
					class ColorQuantizer
 | 
				
			||||||
 | 
					    : public QObject
 | 
				
			||||||
 | 
					    , public QQmlParserStatus {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Q_OBJECT;
 | 
				
			||||||
 | 
						QML_ELEMENT;
 | 
				
			||||||
 | 
						Q_INTERFACES(QQmlParserStatus);
 | 
				
			||||||
 | 
						/// Access the colors resulting from the color quantization performed.
 | 
				
			||||||
 | 
						/// > [!NOTE] The amount of colors returned from the quantization is determined by
 | 
				
			||||||
 | 
						/// > the property depth, specifically 2ⁿ where n is the depth.
 | 
				
			||||||
 | 
						Q_PROPERTY(QList<QColor> colors READ default NOTIFY colorsChanged BINDABLE bindableColors);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/// Path to the image you'd like to run the color quantization on.
 | 
				
			||||||
 | 
						Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/// Max depth for the color quantization. Each level of depth represents another
 | 
				
			||||||
 | 
						/// binary split of the color space
 | 
				
			||||||
 | 
						Q_PROPERTY(qreal depth READ depth WRITE setDepth NOTIFY depthChanged);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/// The size to rescale the image to, when rescaleSize is 0 then no scaling will be done.
 | 
				
			||||||
 | 
						/// > [!NOTE] Results from color quantization doesn't suffer much when rescaling, it's
 | 
				
			||||||
 | 
						/// > reccommended to rescale, otherwise the quantization process will take much longer.
 | 
				
			||||||
 | 
						Q_PROPERTY(qreal rescaleSize READ rescaleSize WRITE setRescaleSize NOTIFY rescaleSizeChanged);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
						explicit ColorQuantizer(QObject* parent = nullptr): QObject(parent) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						void componentComplete() override;
 | 
				
			||||||
 | 
						void classBegin() override {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						[[nodiscard]] QBindable<QList<QColor>> bindableColors() { return &this->bColors; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						[[nodiscard]] QUrl source() const { return mSource; }
 | 
				
			||||||
 | 
						void setSource(const QUrl& source);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						[[nodiscard]] qreal depth() const { return mDepth; }
 | 
				
			||||||
 | 
						void setDepth(qreal depth);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						[[nodiscard]] qreal rescaleSize() const { return mRescaleSize; }
 | 
				
			||||||
 | 
						void setRescaleSize(int rescaleSize);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					signals:
 | 
				
			||||||
 | 
						void colorsChanged();
 | 
				
			||||||
 | 
						void sourceChanged();
 | 
				
			||||||
 | 
						void depthChanged();
 | 
				
			||||||
 | 
						void rescaleSizeChanged();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public slots:
 | 
				
			||||||
 | 
						void operationFinished(const QList<QColor>& result);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
						void quantizeAsync();
 | 
				
			||||||
 | 
						void cancelAsync();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bool componentCompleted = false;
 | 
				
			||||||
 | 
						ColorQuantizerOperation* liveOperation = nullptr;
 | 
				
			||||||
 | 
						QUrl mSource;
 | 
				
			||||||
 | 
						qreal mDepth = 0;
 | 
				
			||||||
 | 
						qreal mRescaleSize = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Q_OBJECT_BINDABLE_PROPERTY(
 | 
				
			||||||
 | 
						    ColorQuantizer,
 | 
				
			||||||
 | 
						    QList<QColor>,
 | 
				
			||||||
 | 
						    bColors,
 | 
				
			||||||
 | 
						    &ColorQuantizer::colorsChanged
 | 
				
			||||||
 | 
						);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
| 
						 | 
					@ -29,5 +29,6 @@ headers = [
 | 
				
			||||||
	"qsmenuanchor.hpp",
 | 
						"qsmenuanchor.hpp",
 | 
				
			||||||
	"clock.hpp",
 | 
						"clock.hpp",
 | 
				
			||||||
	"scriptmodel.hpp",
 | 
						"scriptmodel.hpp",
 | 
				
			||||||
 | 
						"colorquantizer.hpp",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
-----
 | 
					-----
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue