plugin: add getDominantColour
Replaces wack canvas stuff for ColouredIcon
This commit is contained in:
parent
573423742a
commit
258feae3d7
3 changed files with 79 additions and 58 deletions
|
|
@ -1,5 +1,6 @@
|
||||||
pragma ComponentBehavior: Bound
|
pragma ComponentBehavior: Bound
|
||||||
|
|
||||||
|
import Caelestia
|
||||||
import Quickshell.Widgets
|
import Quickshell.Widgets
|
||||||
import QtQuick
|
import QtQuick
|
||||||
|
|
||||||
|
|
@ -7,77 +8,23 @@ IconImage {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
required property color colour
|
required property color colour
|
||||||
property color sourceColour
|
property color dominantColour
|
||||||
property url lastSource
|
|
||||||
|
|
||||||
asynchronous: true
|
asynchronous: true
|
||||||
|
|
||||||
layer.enabled: true
|
layer.enabled: true
|
||||||
layer.effect: Colouriser {
|
layer.effect: Colouriser {
|
||||||
sourceColor: root.sourceColour
|
sourceColor: root.dominantColour
|
||||||
colorizationColor: root.colour
|
colorizationColor: root.colour
|
||||||
}
|
}
|
||||||
|
|
||||||
layer.onEnabledChanged: {
|
layer.onEnabledChanged: {
|
||||||
if (layer.enabled)
|
if (layer.enabled)
|
||||||
canvas.requestPaint();
|
CUtils.getDominantColour(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
onStatusChanged: {
|
onStatusChanged: {
|
||||||
if (layer.enabled && status === Image.Ready)
|
if (layer.enabled && status === Image.Ready)
|
||||||
canvas.requestPaint();
|
CUtils.getDominantColour(this);
|
||||||
}
|
|
||||||
|
|
||||||
Canvas {
|
|
||||||
id: canvas
|
|
||||||
|
|
||||||
property int retryCount
|
|
||||||
|
|
||||||
implicitWidth: 32
|
|
||||||
implicitHeight: 32
|
|
||||||
visible: false
|
|
||||||
|
|
||||||
onPaint: {
|
|
||||||
if (!root.layer.enabled)
|
|
||||||
return;
|
|
||||||
|
|
||||||
const ctx = getContext("2d");
|
|
||||||
ctx.reset();
|
|
||||||
ctx.drawImage(root.backer, 0, 0, width, height);
|
|
||||||
|
|
||||||
const colours = {} as Object;
|
|
||||||
const data = ctx.getImageData(0, 0, width, height).data;
|
|
||||||
|
|
||||||
for (let i = 0; i < data.length; i += 4) {
|
|
||||||
if (data[i + 3] === 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
const c = `${data[i]},${data[i + 1]},${data[i + 2]}`;
|
|
||||||
if (colours.hasOwnProperty(c))
|
|
||||||
colours[c]++;
|
|
||||||
else
|
|
||||||
colours[c] = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Canvas is empty, try again next frame
|
|
||||||
if (retryCount < 5 && !Object.keys(colours).length) {
|
|
||||||
retryCount++;
|
|
||||||
Qt.callLater(() => requestPaint());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let max = 0;
|
|
||||||
let maxColour = "0,0,0";
|
|
||||||
for (const [colour, occurences] of Object.entries(colours)) {
|
|
||||||
if (occurences > max) {
|
|
||||||
max = occurences;
|
|
||||||
maxColour = colour;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const [r, g, b] = maxColour.split(",");
|
|
||||||
root.sourceColour = Qt.rgba(r / 255, g / 255, b / 255, 1);
|
|
||||||
retryCount = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -90,3 +90,74 @@ bool CUtils::copyFile(const QUrl& source, const QUrl& target, bool overwrite) co
|
||||||
|
|
||||||
return QFile::copy(source.toLocalFile(), target.toLocalFile());
|
return QFile::copy(source.toLocalFile(), target.toLocalFile());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CUtils::getDominantColour(QQuickItem* item) const {
|
||||||
|
this->getDominantColour(item, 128, 128);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CUtils::getDominantColour(QQuickItem* item, int width, int height) const {
|
||||||
|
if (!item) {
|
||||||
|
qWarning() << "CUtils::getDominantColour: an item is required";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!item->window()) {
|
||||||
|
// Fail silently to avoid warning
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QSharedPointer<QQuickItemGrabResult> grabResult = item->grabToImage(QSize(width, height));
|
||||||
|
|
||||||
|
QObject::connect(grabResult.data(), &QQuickItemGrabResult::ready, this,
|
||||||
|
[grabResult, item, this]() {
|
||||||
|
QImage image = grabResult->image();
|
||||||
|
|
||||||
|
if (image.format() != QImage::Format_ARGB32) {
|
||||||
|
image = image.convertToFormat(QImage::Format_ARGB32);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unordered_map<uint32_t, int> colours;
|
||||||
|
const uchar* data = image.bits();
|
||||||
|
int width = image.width();
|
||||||
|
int height = image.height();
|
||||||
|
int bytesPerLine = image.bytesPerLine();
|
||||||
|
|
||||||
|
for (int y = 0; y < height; ++y) {
|
||||||
|
const uchar* line = data + y * bytesPerLine;
|
||||||
|
for (int x = 0; x < width; ++x) {
|
||||||
|
const uchar* pixel = line + x * 4;
|
||||||
|
uchar r = pixel[0];
|
||||||
|
uchar g = pixel[1];
|
||||||
|
uchar b = pixel[2];
|
||||||
|
uchar a = pixel[3];
|
||||||
|
|
||||||
|
if (a == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
r &= 0xF8;
|
||||||
|
g &= 0xF8;
|
||||||
|
b &= 0xF8;
|
||||||
|
|
||||||
|
uint32_t colour = (r << 16) | (g << 8) | b;
|
||||||
|
++colours[colour];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t dominantColour = 0;
|
||||||
|
int maxCount = 0;
|
||||||
|
for (const auto& [colour, count] : colours) {
|
||||||
|
if (count > maxCount) {
|
||||||
|
dominantColour = colour;
|
||||||
|
maxCount = count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const QColor colour = QColor((0xFF << 24) | dominantColour);
|
||||||
|
|
||||||
|
QMetaObject::invokeMethod(item, [item, colour]() {
|
||||||
|
item->setProperty("dominantColour", colour);
|
||||||
|
}, Qt::QueuedConnection);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,4 +19,7 @@ public:
|
||||||
|
|
||||||
Q_INVOKABLE bool copyFile(const QUrl& source, const QUrl& target) const;
|
Q_INVOKABLE bool copyFile(const QUrl& source, const QUrl& target) const;
|
||||||
Q_INVOKABLE bool copyFile(const QUrl& source, const QUrl& target, bool overwrite) const;
|
Q_INVOKABLE bool copyFile(const QUrl& source, const QUrl& target, bool overwrite) const;
|
||||||
|
|
||||||
|
Q_INVOKABLE void getDominantColour(QQuickItem* item) const;
|
||||||
|
Q_INVOKABLE void getDominantColour(QQuickItem* item, int width, int height) const;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue