Home > Enterprise >  How can I save an image with OpacityMask applied?
How can I save an image with OpacityMask applied?

Time:11-05

I am working on a project where I want to save a thumbnail image of a rendered screen exactly as it's displayed, including with the application of an OpacityMask. The problem is that no matter what I do, it always creates the thumbnail image without it applied.

So even though the screen looks like this:

screen shot of red rectangle with round mask

The created image looks like this:

red rectangle without mask

import QtQuick 2.15
import QtGraphicalEffects 1.12
import QtQuick.Layouts 1.2
import QtQuick.Controls 1.4
import QtQuick.Dialogs 1.1

ApplicationWindow {
    id: root
    width: 640
    property bool round: true

    toolBar: ToolBar {
        RowLayout {
            anchors.fill: parent
            anchors.margins: spacing
            CheckBox {
                id: roundCheckBox
                text: "Round"
                Component.onCompleted: checked = round
                onCheckedChanged: round = checked; 
            }
            Item { Layout.fillWidth: true }
        }
    }

    Rectangle {
        height: 640
        width: 640

        Rectangle {
            id: frame
            anchors.fill: parent
            focus: true
            color: "black"
            Image {
                id: background
                source: "background.jpg"
                anchors.fill: parent
            }
            Rectangle {
                anchors.centerIn: parent
                width: parent.width/2
                height: parent.height/2
                color: "red"
            }

            layer.enabled: round
            layer.effect:  OpacityMask {
                anchors.fill: parent
                source: frame
                maskSource: Rectangle {
                    width: frame.width
                    height: frame.height
                    radius: frame.width/2
                }
            }

            Keys.onReturnPressed: frame.grabToImage(
            function(result) {  
                result.saveToFile("example.jpg") 
            }, Qt.size(320, 320) )

        }
    }
}

CodePudding user response:

This seems to be a scoping problem, where you are grabbing the image at a level where the mask is not applied. Use the grabToImage() function of your frame Rectangle's parent. For example, I have added an id to that parent, and instead call it, and get the proper output:

import QtQuick 2.15
import QtGraphicalEffects 1.12
import QtQuick.Layouts 1.2
import QtQuick.Controls 1.4
import QtQuick.Dialogs 1.1

ApplicationWindow {
    id: root
    width: 640
    property bool round: true

    toolBar: ToolBar {
        RowLayout {
            anchors.fill: parent
            anchors.margins: spacing
            CheckBox {
                id: roundCheckBox
                text: "Round"
                Component.onCompleted: checked = round
                onCheckedChanged: round = checked;
            }
            Item { Layout.fillWidth: true }
        }
    }

    Rectangle {
        id: frameParent // set parent ID here
        height: 640
        width: 640

        Rectangle {
            id: frame
            anchors.fill: parent
            focus: true
            color: "black"
            Image {
                id: background
                source: "background.jpg"
                anchors.fill: parent
            }
            Rectangle {
                anchors.centerIn: parent
                width: parent.width/2
                height: parent.height/2
                color: "red"
            }

            layer.enabled: round
            layer.effect:  OpacityMask {
                anchors.fill: parent
                source: frame
                maskSource: Rectangle {
                    width: frame.width
                    height: frame.height
                    radius: frame.width/2
                }
            }

            Keys.onReturnPressed: frameParent.grabToImage( // use parent ID here
            function(result) {
                result.saveToFile("example.jpg")
            }, Qt.size(320, 320) )

        }
    }
}

Results in the following output example.jpg (using my own random background image): enter image description here

I also was able to semi-successfully get this to work by re-organizing your layer.effect and instead calling the grabToImage() function on the OpacityMask instead. The solution above was much simpler though.

  • Related