QML Shader Effect blur behind an item
Asked Answered
S

2

6

Is it possible to make a blur of an item which is behind another item?

Example: blur a part of image (like in qml - parent.centerIn: image)

Blur example

I want something like:

Image { id: img
    anchors.fill: parent
    source: "bug.png"

    Item { id: info
        anchors.centerIn: parent
        height: 200
        width: 200

        Text {
            text: "HAMMER TIME"
            color: "white"
        }

        /* BLUR CODE HERE TO BLUR BACKGROUND OF THIS ITEM */
        /* which is a part of "bug.png" image with 200x200 size */
        /* and offset equals to "info.x" and "info.y" */
    }
}

This question affects any shader effect because official docs dont have an answer for the question and all of my attempts are unsuccessfull - it is only possible to blur WHOLE ITEM but not a part of it.

Studding answered 19/1, 2015 at 19:41 Comment(0)
J
10

Here is my solution. This version is just applicable to Rectangles. The Item ShaderEffectSource helps with creating such a source rectangle.

enter image description here

import QtQuick 2.3
import QtQuick.Window 2.2
import QtGraphicalEffects 1.0

Window {
    visible: true
    width: 600
    height:600

    Image {
        id: image_bug

        anchors.fill: parent
        source: "images/Original_bug.png"
    }

    ShaderEffectSource {
        id: effectSource

        sourceItem: image_bug
        anchors.centerIn: image_bug
        width: 400
        height: 400
        sourceRect: Qt.rect(x,y, width, height)
    }

    FastBlur{
        id: blur
        anchors.fill: effectSource

        source: effectSource
        radius: 100
    }
}

If you need other shapes, I think you might need to apply a mask-shader, cutting out the relevant parts first and then apply the blur.

Japha answered 27/1, 2016 at 12:41 Comment(2)
Fortunately, I was able to fix this problem by myself a halfyear ago and my solution is almost the same as yours. So, I will not post answer and accept it but just accept yours.Studding
Note, in many use cases it's required to set recursive: true. Also make sure to set ShaderEffectSource visible: false. FastBlur is what actually renders. 100 is WAY too high, starting with 16-20 is a better number.Iodism
C
0

Not the prettiest solution but I afraid there is no such Qml mechanism.
You could apply on your image second image with same source and clip it to your needs, like below:

Image {
    id: img
    anchors.fill: parent
    source: "bug.png"

    Item { id: info
        anchors.centerIn: parent
        height: 200
        width: 200

    Text {
        text: "HAMMER TIME"
        color: "white"
    }

    /* BLUR CODE HERE TO BLUR BACKGROUND OF THIS ITEM */
    /* which is a part of "bug.png" image with 200x200 size */
    /* and offset equals to "info.x" and "info.y" */

    clip:true
    Image {
        id: img2
        x: -info.x
        y: -info.y
        width: img.width
        height: img.height
        source: img.source
    }
    FastBlur {
        anchors.fill: img2
        source: img2
        radius: 32
    }
}
Cindycine answered 20/1, 2015 at 10:5 Comment(3)
I believe your code may work but I was asking for a universal solution because the question does not affect only images but any qml type (which can be layered and be used as source for ShaderEffect). Anyway, thank you. Also, here is one more problem - in qml2 your code will be buggy if item that you use as effect source will have an animation.Studding
As for possible problem when animating source let say on width property: Why would you expect something in item info with strict size==200 will adjust its size to scaled image? If you really want such effect just make dependence bindings on animated properties.Cindycine
As for more universal solution I believe it could be done by applying custom shader and passing to it property values (x,y, width, height) of image. Maybe I could do an example for you later.Cindycine

© 2022 - 2024 — McMap. All rights reserved.