QML更改图像颜色

27
我搜索了如何为图像(svg或png格式)上色。
我尝试着用一个填满整个图像的矩形来覆盖我的图片,但由于我的图片不是矩形,因此它会将整个矩形着色而不仅仅是图片。
在QML中更改图像颜色是否可行? 或者在Qt(使用C ++)中是否可以通过QPixmap更改颜色,然后将QPixmap集成在QML项目中?
感谢您的帮助。(如果没有解决方案,我将不得不加载不同颜色的相同基本图像。)
5个回答

35

Qt 5中(从5.2开始),您可以按以下方式使用ColorOverlay

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 
    }
 }

由于许可问题Qt 6 模块 QtGraphicalEffects(其中包括 ColorOverlay)已被移除。

如下面的 @SCP3008 评论所述,在 Qt 6.1 中,GraphicalEffects 现在可用了。


1
可用文档:Qt ColorOverlay QML - Rémi
3
QT 6 中不存在 ColorOverlay。 - Amir Saniyan
1
整个QtGraphicalEffects模块已从Qt 6中删除。他们不再继续开发它,并且正在重新授权为BSD。如果需要Qt 6,则ShaderEffects可能是最佳解决方法。@AmirSaniyan - user8104581
1
GraphicalEffects现在在Qt 6.1中再次提供,但现在属于不同的模块:这里。像ColorOverlay这样的组件稍作修改,例如不再具有samples属性。 - SCP3008
警告,我发现在TI AM335x ARM板上将Qt5Compat.GraphicalEffects和Qt6组合使用会导致QSGRenderThread崩溃。因此最好找一些基于Qt6的解决方案。 - Ted Feng

8
您可以使用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);
        }
    "
}

上述代码将您的图像转换为灰度图像,然后应用您的颜色。

7

您还可以使用Colorize

与ColorOverlay不同的是: Colorize可以通过HSL真正改变图像的颜色,更适合我。 而ColorOverlay类似于将着色玻璃覆盖在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
    }
}

2

我也尝试寻找一个非QtGraphicalEffects的解决方案,并使用如下方式通过icon属性找到了一种解决方法:

  • icon.source - 用于设置SVG图片
  • icon.color - 用于更改SVG图片的颜色
  • icon.width - 用于更改SVG图片的宽度
  • icon.height - 用于更改SVG图片的高度

某些控件具有icon属性,例如ButtonItemDelegateMenuItem

在以下代码中,我们将AppIcon实现为Button的定制版本,因此唯一保留的是icon渲染。我们删除了按钮样式和按钮大小,它被剪裁以只呈现图标本身。由于我们已经定制了Button,可以公开clicked信号和pressed属性。

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>

您可以在线尝试!

1

解决方法是使用IconImage。它有color:属性。 我在Qt 6.5.0中找到了它。

IconImage{
     source: "qrc:/yourImage.svg"
     color: "red"
}

1
嗨Saysdf,那是Qt Quick控件吗?我在Qt 6.5文档中没有看到它被提及。 - Surfbutler
1
据我所知,这仍然是一个未记录的功能,这真是令人遗憾,因为它在布局设计方面是最佳解决方案。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接