From 50cdf9886803c0279aafa43d0b590abdc34f5766 Mon Sep 17 00:00:00 2001 From: HigherOrderLogic <73709188+HigherOrderLogic@users.noreply.github.com> Date: Fri, 29 Aug 2025 11:50:13 +0000 Subject: [PATCH] core/colorquant: add imageRect option for cropping image --- CMakeLists.txt | 5 ++++- changelog/next.md | 1 + src/core/colorquantizer.cpp | 38 ++++++++++++++++++++++++++++++++----- src/core/colorquantizer.hpp | 17 ++++++++++++++++- 4 files changed, 54 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b02b3d8..966e8c3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,10 @@ cmake_minimum_required(VERSION 3.20) project(quickshell VERSION "0.2.1" LANGUAGES CXX C) -set(UNRELEASED_FEATURES "network.2") +set(UNRELEASED_FEATURES + "network.2" + "colorquant-imagerect" +) set(QT_MIN_VERSION "6.6.0") set(CMAKE_CXX_STANDARD 20) diff --git a/changelog/next.md b/changelog/next.md index 17b8cd4..8b22d07 100644 --- a/changelog/next.md +++ b/changelog/next.md @@ -29,6 +29,7 @@ set shell id. - Added generic WindowManager interface implementing ext-workspace. - Added ext-background-effect window blur support. - Added per-corner radius support to Region. +- Added ColorQuantizer region selection. ## Other Changes diff --git a/src/core/colorquantizer.cpp b/src/core/colorquantizer.cpp index 4ac850b..d983f76 100644 --- a/src/core/colorquantizer.cpp +++ b/src/core/colorquantizer.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -24,9 +25,15 @@ namespace { QS_LOGGING_CATEGORY(logColorQuantizer, "quickshell.colorquantizer", QtWarningMsg); } -ColorQuantizerOperation::ColorQuantizerOperation(QUrl* source, qreal depth, qreal rescaleSize) +ColorQuantizerOperation::ColorQuantizerOperation( + QUrl* source, + qreal depth, + QRect imageRect, + qreal rescaleSize +) : source(source) , maxDepth(depth) + , imageRect(imageRect) , rescaleSize(rescaleSize) { this->setAutoDelete(false); } @@ -37,6 +44,11 @@ void ColorQuantizerOperation::quantizeImage(const QAtomicInteger& shouldCa this->colors.clear(); auto image = QImage(this->source->toLocalFile()); + + if (this->imageRect.isValid()) { + image = image.copy(this->imageRect); + } + if ((image.width() > this->rescaleSize || image.height() > this->rescaleSize) && this->rescaleSize > 0) { @@ -198,16 +210,27 @@ void ColorQuantizer::setDepth(qreal depth) { this->mDepth = depth; emit this->depthChanged(); - if (this->componentCompleted) this->quantizeAsync(); + if (this->componentCompleted && !this->mSource.isEmpty()) this->quantizeAsync(); } } +void ColorQuantizer::setImageRect(QRect imageRect) { + if (this->mImageRect != imageRect) { + this->mImageRect = imageRect; + emit this->imageRectChanged(); + + if (this->componentCompleted && !this->mSource.isEmpty()) this->quantizeAsync(); + } +} + +void ColorQuantizer::resetImageRect() { this->setImageRect(QRect()); } + void ColorQuantizer::setRescaleSize(int rescaleSize) { if (this->mRescaleSize != rescaleSize) { this->mRescaleSize = rescaleSize; emit this->rescaleSizeChanged(); - if (this->componentCompleted) this->quantizeAsync(); + if (this->componentCompleted && !this->mSource.isEmpty()) this->quantizeAsync(); } } @@ -221,8 +244,13 @@ void ColorQuantizer::quantizeAsync() { if (this->liveOperation) this->cancelAsync(); qCDebug(logColorQuantizer) << "Starting color quantization asynchronously"; - this->liveOperation = - new ColorQuantizerOperation(&this->mSource, this->mDepth, this->mRescaleSize); + + this->liveOperation = new ColorQuantizerOperation( + &this->mSource, + this->mDepth, + this->mImageRect, + this->mRescaleSize + ); QObject::connect( this->liveOperation, diff --git a/src/core/colorquantizer.hpp b/src/core/colorquantizer.hpp index f6e158d..0159181 100644 --- a/src/core/colorquantizer.hpp +++ b/src/core/colorquantizer.hpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -16,7 +17,7 @@ class ColorQuantizerOperation Q_OBJECT; public: - explicit ColorQuantizerOperation(QUrl* source, qreal depth, qreal rescaleSize); + explicit ColorQuantizerOperation(QUrl* source, qreal depth, QRect imageRect, qreal rescaleSize); void run() override; void tryCancel(); @@ -44,6 +45,7 @@ private: QList colors; QUrl* source; qreal maxDepth; + QRect imageRect; qreal rescaleSize; }; @@ -78,6 +80,13 @@ class ColorQuantizer /// binary split of the color space Q_PROPERTY(qreal depth READ depth WRITE setDepth NOTIFY depthChanged); + // clang-format off + /// Rectangle that the source image is cropped to. + /// + /// Can be set to `undefined` to reset. + Q_PROPERTY(QRect imageRect READ imageRect WRITE setImageRect RESET resetImageRect NOTIFY imageRectChanged); + // clang-format on + /// 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. @@ -97,6 +106,10 @@ public: [[nodiscard]] qreal depth() const { return this->mDepth; } void setDepth(qreal depth); + [[nodiscard]] QRect imageRect() const { return this->mImageRect; } + void setImageRect(QRect imageRect); + void resetImageRect(); + [[nodiscard]] qreal rescaleSize() const { return this->mRescaleSize; } void setRescaleSize(int rescaleSize); @@ -104,6 +117,7 @@ signals: void colorsChanged(); void sourceChanged(); void depthChanged(); + void imageRectChanged(); void rescaleSizeChanged(); public slots: @@ -117,6 +131,7 @@ private: ColorQuantizerOperation* liveOperation = nullptr; QUrl mSource; qreal mDepth = 0; + QRect mImageRect; qreal mRescaleSize = 0; Q_OBJECT_BINDABLE_PROPERTY(