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:
The created image looks like this:
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) )
}
}
}
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):
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.