I am trying to create an image with a rounded corner for a KDE Plasma Widget I am working on, but the dimensions of the mask don't match with my rounded rectangle. According to the resources I found, I need to use MultiEffects
. Sure enough it works but I need the image to also 1) be resizable in the widget and 2) keep the rounded corners even if the fill setting for Image
changes.
I tried the following:
Image {
id: sourceItem
fillMode: Image.PreserveAspectFit
source: "/home/tjaart/Pictures/Wallpaper/04191_heartlake_1920x1080.jpg"
anchors.fill: parent
visible: false
layer.enabled: true
}
MultiEffect {
source: sourceItem
anchors.fill: sourceItem
maskEnabled: true
maskSource: mask
}
Item {
id: mask
width: sourceItem.paintedWidth
height: sourceItem.paintedHeight
layer.enabled: true
visible: true
anchors.centerIn: sourceItem
Rectangle {
width: sourceItem.paintedWidth
height: sourceItem.paintedHeight
radius: 90
color: "green"
opacity: 0.5
}
}
I tinted the rectangle I used to create the mask in the example image (also in the source). The rounded corner is clipped according the to the size of the Image
element and not the real size of the image on screen. That is why it is clipping the image along dimensions that don't match with the rectangle in green, which is what I want to achieve.
The problem is compounded by the fact that:
fillMode: Image.PreserveAspectFit
A simple solution is to correct your Mask dimensions to match your source Image but adjust the Rectangle to just the dimensions of the aspected fitted image, i.e.
Item {
id: mask
anchors.fill: sourceItem
layer.enabled: true
visible: false
Rectangle {
width: sourceItem.paintedWidth
height: sourceItem.paintedHeight
anchors.centerIn: parent
radius: 90
color: "green"
opacity: 0.5
}
}
However, the sourceItem, the MultiEffect, and the Mask has a lot of wasted space since the preseve aspect fit will mean there could be a large letter box effect which is included in all images.
Instead, you can change how you compute the sourceItem width x height to take into account that you know the aspect ratio of the source image. This will optimize the sizes of the Image, MultiEffect and the mask, i.e.
Image {
id: sourceItem
// manual implementation of 1920:1080 preserve aspect fit ...
width: parent.height * 1920 > parent.width * 1080 ? parent.width : parent.height * 1920 / 1080
height: width * 1080 / 1920
anchors.fill: parent
source: "https://w0.peakpx.com/wallpaper/252/964/HD-wallpaper-heartlake-sunshine-lake-mountains-landscape.jpg"
visible: false
layer.enabled: true
}
MultiEffect {
source: sourceItem
anchors.fill: sourceItem
anchors.centerIn: parent
maskEnabled: true
maskSource: mask
}
Item {
id: mask
anchors.fill: sourceItem
layer.enabled: true
visible: false
Rectangle {
anchors.fill: parent
radius: 90
color: "green"
opacity: 0.5
}
}