Reputation: 1251
I searched for how to colorize an image (with the format svg or png ...).
I tried covering my image with a rectangle that fills the image, but as my image is not a rectangle it colorizes the whole rectangle and not just the image.
Is it possible to change image color with qml? Alternatively, is it possible to change the color on qt (with C++) with QPixmap then integrate the QPixmap on QML Item?
Thank you for your help. (If there is no solution, I will have to load a different image to the same basic image with different color.)
Upvotes: 29
Views: 28335
Reputation: 41
Work around is using IconImage
. It has color:
I Found it in Qt 6.5.0
IconImage{
source: "qrc:/yourImage.svg"
color: "red"
}
Upvotes: 4
Reputation: 25871
I also went looking for a non-QtGraphicalEffects solution and found a solution by using the icon
property as follows:
icon.source
- for setting the SVG imageicon.color
- for changing the color of the SVG imageicon.width
- for changing the width of the SVG imageicon.height
- for changing the height of the SVG imageSome controls have the icon
property such as Button
, ItemDelegate
and MenuItem
.
In the following code, we implement AppIcon
as a customized version of Button
so that the only thing that remains is the icon
rendering. We remove the button styling and the button size, it is clipped to just render the icon itself. Because we have customized the Button
we can expose the clicked
signal and the pressed
property.
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
Page {
ColumnLayout {
anchors.centerIn: parent
AppIcon {
Layout.alignment: Qt.AlignHCenter
icon.source: "biking-32.svg"
icon.color: pressed ? "orange" : "red"
onClicked: status.text = "red clicked"
}
AppIcon {
Layout.alignment: Qt.AlignHCenter
Layout.preferredWidth: 64
Layout.preferredHeight: 64
icon.source: "biking-32.svg"
icon.color: pressed ? "orange" : "blue"
onClicked: status.text = "blue clicked"
}
AppIcon {
Layout.alignment: Qt.AlignHCenter
Layout.preferredWidth: 96
Layout.preferredHeight: 96
icon.source: "biking-32.svg"
icon.color: pressed ? "orange" : "green"
onClicked: status.text = "green clicked"
}
Text {
id: status
text: "click on an image"
}
}
}
//AppIcon.qml
import QtQuick
import QtQuick.Controls
Item {
id: appIcon
implicitWidth: 32
implicitHeight: 32
property alias icon: btn.icon
property alias pressed: btn.pressed
signal clicked()
Button {
id: btn
anchors.centerIn: parent
background: Item { }
icon.width: parent.width
icon.height: parent.height
onClicked: appIcon.clicked()
}
}
//biking-32.svg
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><path d="M16 5.5A2.5 2.5 0 1 1 18.5 8 2.498 2.498 0 0 1 16 5.5zm-1.042 19.02a1.545 1.545 0 0 0 1.021 1.688c.73.104 1.23-.25 1.452-1.211.034-.145 1.173-6.518 1.173-6.518l-3.979-2.146 2.823-4.087L19.498 15H24a1 1 0 0 0 0-2h-3.498l-2.434-3.27a1.63 1.63 0 0 0-.48-.551.995.995 0 0 0-.11-.083l-1.107-.765a1.685 1.685 0 0 0-2.194.595l-4.09 6.534a1 1 0 0 0 .367 1.408l5.114 2.8zM29.8 24.5a5.3 5.3 0 1 1-5.3-5.3 5.3 5.3 0 0 1 5.3 5.3zm-1.8 0a3.5 3.5 0 1 0-3.5 3.5 3.504 3.504 0 0 0 3.5-3.5zm-15.2 0a5.3 5.3 0 1 1-5.3-5.3 5.3 5.3 0 0 1 5.3 5.3zm-1.8 0A3.5 3.5 0 1 0 7.5 28a3.504 3.504 0 0 0 3.5-3.5z"/><path fill="none" d="M0 0h32v32H0z"/></svg>
You can Try it Online!
Upvotes: 3
Reputation: 1708
In Qt 5 (from 5.2) you may use ColorOverlay
as follows:
import QtQuick 2.0
import QtGraphicalEffects 1.0
Item {
width: 300
height: 300
Image {
id: bug
source: "images/butterfly.png"
sourceSize: Qt.size(parent.width, parent.height)
smooth: true
visible: false
}
ColorOverlay {
anchors.fill: bug
source: bug
color: "#ff0000" // make image like it lays under red glass
}
}
In Qt 6 module QtGraphicalEffects
(which includes ColorOverlay
) was removed because of licensing issues.
In Qt 6.1 GraphicalEffects is now available again, as @SCP3008 commented below
Upvotes: 37
Reputation: 135
You can also use Colorize
And the difference with ColorOverlay is: Colorize can really change the color of a image with HSL, it is more suitable for me. ColorOverlay is similar to what happens when a colorized glass is put on top of a grayscale image with RGBA.
import QtQuick 2.12
import QtGraphicalEffects 1.12
Item {
width: 300
height: 300
Image {
id: bug
source: "images/bug.jpg"
sourceSize: Qt.size(parent.width, parent.height)
smooth: true
visible: false
}
Colorize {
anchors.fill: bug
source: bug
hue: 0.0
saturation: 0.5
lightness: -0.2
}
}
Upvotes: 7
Reputation: 368
You can replace your image color using ShaderEffect.
ShaderEffect {
property variant src: yourImage
property real r: yourColor.r * yourColor.a
property real g: yourColor.g * yourColor.a
property real b: yourColor.b * yourColor.a
width: yourImage.width
height: yourImage.height
vertexShader: "
uniform highp mat4 qt_Matrix;
attribute highp vec4 qt_Vertex;
attribute highp vec2 qt_MultiTexCoord0;
varying highp vec2 coord;
void main() {
coord = qt_MultiTexCoord0;
gl_Position = qt_Matrix * qt_Vertex;
}
"
fragmentShader: "
varying highp vec2 coord;
uniform sampler2D src;
uniform lowp float r;
uniform lowp float g;
uniform lowp float b;
void main() {
lowp vec4 clr = texture2D(src, coord);
lowp float avg = (clr.r + clr.g + clr.b) / 3.;
gl_FragColor = vec4(r * avg, g * avg, b * avg, clr.a);
}
"
}
The above code turns your image into the grayscaled one and then applies your color.
Upvotes: 8