core/colorquant: add imageRect option for cropping image

This commit is contained in:
HigherOrderLogic 2025-08-29 11:50:13 +00:00 committed by outfoxxed
parent 4b751ccb0d
commit 50cdf98868
No known key found for this signature in database
GPG key ID: 4C88A185FB89301E
4 changed files with 54 additions and 7 deletions

View file

@ -1,7 +1,10 @@
cmake_minimum_required(VERSION 3.20) cmake_minimum_required(VERSION 3.20)
project(quickshell VERSION "0.2.1" LANGUAGES CXX C) 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(QT_MIN_VERSION "6.6.0")
set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD 20)

View file

@ -29,6 +29,7 @@ set shell id.
- Added generic WindowManager interface implementing ext-workspace. - Added generic WindowManager interface implementing ext-workspace.
- Added ext-background-effect window blur support. - Added ext-background-effect window blur support.
- Added per-corner radius support to Region. - Added per-corner radius support to Region.
- Added ColorQuantizer region selection.
## Other Changes ## Other Changes

View file

@ -13,6 +13,7 @@
#include <qnumeric.h> #include <qnumeric.h>
#include <qobject.h> #include <qobject.h>
#include <qqmllist.h> #include <qqmllist.h>
#include <qrect.h>
#include <qrgb.h> #include <qrgb.h>
#include <qthreadpool.h> #include <qthreadpool.h>
#include <qtmetamacros.h> #include <qtmetamacros.h>
@ -24,9 +25,15 @@ namespace {
QS_LOGGING_CATEGORY(logColorQuantizer, "quickshell.colorquantizer", QtWarningMsg); 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) : source(source)
, maxDepth(depth) , maxDepth(depth)
, imageRect(imageRect)
, rescaleSize(rescaleSize) { , rescaleSize(rescaleSize) {
this->setAutoDelete(false); this->setAutoDelete(false);
} }
@ -37,6 +44,11 @@ void ColorQuantizerOperation::quantizeImage(const QAtomicInteger<bool>& shouldCa
this->colors.clear(); this->colors.clear();
auto image = QImage(this->source->toLocalFile()); auto image = QImage(this->source->toLocalFile());
if (this->imageRect.isValid()) {
image = image.copy(this->imageRect);
}
if ((image.width() > this->rescaleSize || image.height() > this->rescaleSize) if ((image.width() > this->rescaleSize || image.height() > this->rescaleSize)
&& this->rescaleSize > 0) && this->rescaleSize > 0)
{ {
@ -198,16 +210,27 @@ void ColorQuantizer::setDepth(qreal depth) {
this->mDepth = depth; this->mDepth = depth;
emit this->depthChanged(); 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) { void ColorQuantizer::setRescaleSize(int rescaleSize) {
if (this->mRescaleSize != rescaleSize) { if (this->mRescaleSize != rescaleSize) {
this->mRescaleSize = rescaleSize; this->mRescaleSize = rescaleSize;
emit this->rescaleSizeChanged(); 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(); if (this->liveOperation) this->cancelAsync();
qCDebug(logColorQuantizer) << "Starting color quantization asynchronously"; 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( QObject::connect(
this->liveOperation, this->liveOperation,

View file

@ -5,6 +5,7 @@
#include <qproperty.h> #include <qproperty.h>
#include <qqmlintegration.h> #include <qqmlintegration.h>
#include <qqmlparserstatus.h> #include <qqmlparserstatus.h>
#include <qrect.h>
#include <qrunnable.h> #include <qrunnable.h>
#include <qtmetamacros.h> #include <qtmetamacros.h>
#include <qtypes.h> #include <qtypes.h>
@ -16,7 +17,7 @@ class ColorQuantizerOperation
Q_OBJECT; Q_OBJECT;
public: public:
explicit ColorQuantizerOperation(QUrl* source, qreal depth, qreal rescaleSize); explicit ColorQuantizerOperation(QUrl* source, qreal depth, QRect imageRect, qreal rescaleSize);
void run() override; void run() override;
void tryCancel(); void tryCancel();
@ -44,6 +45,7 @@ private:
QList<QColor> colors; QList<QColor> colors;
QUrl* source; QUrl* source;
qreal maxDepth; qreal maxDepth;
QRect imageRect;
qreal rescaleSize; qreal rescaleSize;
}; };
@ -78,6 +80,13 @@ class ColorQuantizer
/// binary split of the color space /// binary split of the color space
Q_PROPERTY(qreal depth READ depth WRITE setDepth NOTIFY depthChanged); 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. /// 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 /// > [!NOTE] Results from color quantization doesn't suffer much when rescaling, it's
/// > reccommended to rescale, otherwise the quantization process will take much longer. /// > reccommended to rescale, otherwise the quantization process will take much longer.
@ -97,6 +106,10 @@ public:
[[nodiscard]] qreal depth() const { return this->mDepth; } [[nodiscard]] qreal depth() const { return this->mDepth; }
void setDepth(qreal depth); void setDepth(qreal depth);
[[nodiscard]] QRect imageRect() const { return this->mImageRect; }
void setImageRect(QRect imageRect);
void resetImageRect();
[[nodiscard]] qreal rescaleSize() const { return this->mRescaleSize; } [[nodiscard]] qreal rescaleSize() const { return this->mRescaleSize; }
void setRescaleSize(int rescaleSize); void setRescaleSize(int rescaleSize);
@ -104,6 +117,7 @@ signals:
void colorsChanged(); void colorsChanged();
void sourceChanged(); void sourceChanged();
void depthChanged(); void depthChanged();
void imageRectChanged();
void rescaleSizeChanged(); void rescaleSizeChanged();
public slots: public slots:
@ -117,6 +131,7 @@ private:
ColorQuantizerOperation* liveOperation = nullptr; ColorQuantizerOperation* liveOperation = nullptr;
QUrl mSource; QUrl mSource;
qreal mDepth = 0; qreal mDepth = 0;
QRect mImageRect;
qreal mRescaleSize = 0; qreal mRescaleSize = 0;
Q_OBJECT_BINDABLE_PROPERTY( Q_OBJECT_BINDABLE_PROPERTY(