Reputation: 54517
Using QtQuick, is it possible to take an existing color defined by RGB and desaturate it without resorting to Javascript?
Upvotes: 1
Views: 2076
Reputation: 1103
function desaturate(colorString)
{
let c = Qt.darker(colorString, 1.0);
return Qt.hsla(c.hslHue, 0.0, c.hslLightness, c.a);
}
Upvotes: 3
Reputation: 63
Just modify the color's hsvSaturation
, or hslSaturation
property, depending on your color model.
Example Test.qml
that de-saturates a blue rectangle gradually every second (runs with qmlscene Test.qml
):
import QtQuick 2.7
Item {
width: 100
height: 100
Rectangle {
anchors.fill: parent
objectName: "precious"
color: "#0000FF"
Timer {
running: true
repeat: true
onTriggered: parent.color.hslSaturation *= 0.8;
}
}
}
Hidden in a lot of text, between two blocks of code, these properties are actually documented in color QML Basic Type. They appear to correspond to the qreal
versions of color component properties in C++ (names ending in ...F()
).
As @dtech states, the onTriggered:...
is legally already a line of JavaScript. If you must, you can also walk down the line in C++, find the element's attribute, and modify the property there.
Example main.cpp
, showing the above Test.qml
, that starts with an already very de-saturated (purely in C++) blue rectangle, then gradually de-saturating it (still done in QML/JavaScript):
#include <QGuiApplication>
#include <QQuickView>
#include <QQuickItem>
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QQuickView view(QUrl(QLatin1String("qrc:/Test.qml")));
view.show();
if ( QObject * rectangle = view.rootObject()->findChild<QObject*>("precious") )
{
qreal h, s, l, a;
rectangle->property("color").value<QColor>().getHslF( &h, &s, &l, &a );
s *= 0.2;
rectangle->setProperty( "color", QVariant::fromValue(QColor::fromHsvF( h, s, l, a )) );
}
return app.exec();
}
Now you could remove the apparent line of JavaScript from Test.qml
.
Note that I demonstrate a very crude color animation. There is a special ColorAnimation
tool to do better.
Upvotes: 1
Reputation: 49319
Seeing how QtQuick runs on top of a Javascript engine, I'd say it is not possible to do anything in QML without resorting to Javascript.
In order to adjust the saturation you will have to convert RGB to HSL color and then back to RGB. QML has Qt.hsla()
for the latter, but last time I checked it didn't provide a conversion from RGB to HSL, so I ended up using this:
function rgbToHsl(r, g, b) {
r /= 255
g /= 255
b /= 255
var max = Math.max(r, g, b), min = Math.min(r, g, b)
var h, s, l = (max + min) / 2
if (max == min) {
h = s = 0
} else {
var d = max - min
s = l > 0.5 ? d / (2 - max - min) : d / (max + min)
switch (max) {
case r:
h = (g - b) / d + (g < b ? 6 : 0)
break
case g:
h = (b - r) / d + 2
break
case b:
h = (r - g) / d + 4
break
}
h /= 6;
}
return {"h":h, "s":s, "l":l};
}
So you basically:
var ic = yourRGBColor.toString()
var r = parseInt(ic.substr(1, 2), 16)
var g = parseInt(ic.substr(3, 2), 16)
var b = parseInt(ic.substr(5, 2), 16)
var hsl = rgbToHsl(r, g, b)
hsl.s *= .5 // desaturate 50%
yourRGBColor = Qt.hsla(hsl.h, hsl.s, hsl.l, 1)
Upvotes: 1