Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog/next.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
38 changes: 33 additions & 5 deletions src/core/colorquantizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <qnumeric.h>
#include <qobject.h>
#include <qqmllist.h>
#include <qrect.h>
#include <qrgb.h>
#include <qthreadpool.h>
#include <qtmetamacros.h>
Expand All @@ -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);
}
Expand All @@ -37,6 +44,11 @@ void ColorQuantizerOperation::quantizeImage(const QAtomicInteger<bool>& 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)
{
Expand Down Expand Up @@ -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();
}
}

Expand All @@ -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,
Expand Down
17 changes: 16 additions & 1 deletion src/core/colorquantizer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <qproperty.h>
#include <qqmlintegration.h>
#include <qqmlparserstatus.h>
#include <qrect.h>
#include <qrunnable.h>
#include <qtmetamacros.h>
#include <qtypes.h>
Expand All @@ -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();
Expand Down Expand Up @@ -44,6 +45,7 @@ private slots:
QList<QColor> colors;
QUrl* source;
qreal maxDepth;
QRect imageRect;
qreal rescaleSize;
};

Expand Down Expand Up @@ -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.
Expand All @@ -97,13 +106,18 @@ class ColorQuantizer
[[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);

signals:
void colorsChanged();
void sourceChanged();
void depthChanged();
void imageRectChanged();
void rescaleSizeChanged();

public slots:
Expand All @@ -117,6 +131,7 @@ public slots:
ColorQuantizerOperation* liveOperation = nullptr;
QUrl mSource;
qreal mDepth = 0;
QRect mImageRect;
qreal mRescaleSize = 0;

Q_OBJECT_BINDABLE_PROPERTY(
Expand Down
Loading