在QML中为图像的一部分添加模糊效果

Adding blur effect on a part of image in QML

提问人:LeXela-ED 提问时间:10/15/2023 更新时间:10/16/2023 访问量:66

问:

我正在尝试在我的 QtQucick 应用程序中为图像添加一些模糊效果。下面是一个简单的片段,可以加载图像,并在其上放置一个自定义多边形。我应该在我的代码中添加什么才能使多边形内部看起来模糊!

提前致谢。

import QtQuick 2.15
import QtQuick.Window 2.15

Window
{
    id: main_window

    width: 640
    height: 480
    visible: true
    title: qsTr("Hello World")

    property var mpoints: [Qt.point(20, 20), Qt.point(20, 300), Qt.point(300, 300), Qt.point(300, 20)]

    Image
    {
        id: m_image

        anchors.fill: parent

        source: "file:///C:/Users/LeXela/Pictures/test.jpg"
        cache: false
    }

    Canvas
    {
        anchors.fill: parent

        onPaint:
        {
            var ctx = getContext("2d");
            ctx.clearRect(0, 0, main_window.width, main_window.height);

            ctx.globalCompositeOperation = "source-over";

            ctx.fillStyle = "white";
            ctx.globalAlpha = 0.6;

            ctx.beginPath();
            ctx.moveTo(mpoints[0].x, mpoints[0].y)
            for(let i = 1; i < mpoints.length; i++)
                ctx.lineTo(mpoints[i].x, mpoints[i].y);
            ctx.closePath();

            ctx.fill();
            ctx.stroke();
        }
    }
}
QML QTQUICK2 模糊

评论

0赞 JarMan 10/16/2023
如果您使用的是 Qt5,请使用 FastBlur。如果您使用的是 Qt6,请尝试 MultiEffect

答:

1赞 Stephen Quan 10/16/2023 #1

您可以通过设置 (2) 来渲染图像两次,第二个实例 (1) 以较低的分辨率采样,然后,您可以通过定义多边形来渲染较低分辨率图像的剪裁版本,并使用 :sourceSizeShapePathOpacityMask

import QtQuick
import QtQuick.Controls
import QtQuick.Shapes
import Qt5Compat.GraphicalEffects
Page {
    property list<point> mpoints: [Qt.point(100, 150), Qt.point(300, 150), Qt.point(200, 250)]

    Image
    {
        id: img
        width: 400
        height: 350
        source: "butterfly.png"
    }
    
    Image {
        id: blur
        width: img.width
        height: img.height
        source: img.source
        sourceSize: Qt.size(32, 32)
        visible: false
    }

    Item {
        id: mask
        width: img.width
        height: img.height
        Shape {
            id: polygon
            ShapePath {
                fillColor: "red"
                strokeColor: "red"
                startX: mpoints[0].x; startY: mpoints[0].y
                PathLine { x: mpoints[1].x; y: mpoints[1].y }
                PathLine { x: mpoints[2].x; y: mpoints[2].y }
            }
        }
        visible: false
    }
    
    OpacityMask {
        anchors.fill: mask
        source: blur
        maskSource: mask
    }
}

// butterfly.png : https://raw.githubusercontent.com/stephenquan/stephenquan.github.io/master/images/qt/Original_butterfly.png

您可以在线试用!

下面是多边形顶点可以移动的版本:

import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import QtQuick.Shapes
import Qt5Compat.GraphicalEffects

Page {
    property list<point> mpoints: [Qt.point(100, 150), Qt.point(200, 50), Qt.point(300, 150), Qt.point(200, 250)]
    property int msize: 20
    
    Image
    {
        id: img
        width: 400
        height: 350
        source: "butterfly.png"
    }
    
    Item {
        id: blur
        anchors.fill: parent
        Image {
            width: img.width
            height: img.height
            source: img.source
            sourceSize: Qt.size(img.width / blurSlider.value, img.height / blurSlider.value)
        }
        visible: false
    }
    
    Item {
        id: polygon
        anchors.fill: parent
        visible: false
        Repeater {
            model: mpoints.length - 2
            Shape {
                property point firstPoint: mpoints[index]
                property point secondPoint: mpoints[index+1]
                property point lastPoint: mpoints[mpoints.length - 1]
                ShapePath {
                    strokeColor: "orange"
                    fillColor: "orange"
                    startX: firstPoint.x; startY: firstPoint.y
                    PathLine { x: secondPoint.x; y: secondPoint.y }
                    PathLine { x: lastPoint.x; y: lastPoint.y }
                }
            }
        }
    }
    
    Repeater {
        model: mpoints.length
        Shape {
            property point thisPoint: mpoints[index]
            property point nextPoint: mpoints[(index + 1) % mpoints.length]
            ShapePath {
                strokeColor: "blue"
                strokeWidth: 2
                startX: thisPoint.x; startY: thisPoint.y
                PathLine { x: nextPoint.x; y: nextPoint.y }
            }
        }
    }
    
    OpacityMask {
        anchors.fill: parent
        source: blur
        maskSource: polygon
        invert: invertCheckBox.checked
    }
    
    Repeater {
        model: mpoints
        Rectangle {
            x: modelData.x -msize / 2
            y: modelData.y -msize / 2
            width: msize
            height: msize
            color: "transparent"
            border.color: "red"
            border.width: 2
            DragHandler {
                onGrabChanged: {
                    switch (transition) {
                        case 1:
                        break;
                        case 2:
                        Qt.callLater(movePoint, index, parent.x + msize / 2, parent.y + msize / 2);
                        parent.x = -msize / 2;
                        parent.y = -msize / 2;
                        break;
                    }
                }
            }
        }
    }
    
    footer: Frame {
        RowLayout {
            CheckBox { id: invertCheckBox; text: "Invert" }
            Slider { id: blurSlider; from: 1; to: 10; value: 10 }
            Label { text: "Blur %1".arg(blurSlider.value.toFixed(1)) }
        }
    }
    
    function movePoint(index, newx, newy) {
        mpoints[index] = Qt.point(newx, newy);
    }    
}

// butterfly.png : https://raw.githubusercontent.com/stephenquan/stephenquan.github.io/master/images/qt/Original_butterfly.png

您可以在线试用!

评论

0赞 LeXela-ED 10/16/2023
聪明的方法!干的好。非常感谢。:-)