Set sourceSize in for images, improving memory usage and smoothing
In some cases (where we don't get a thumbnail) we load the entire image, which might be large. Even when we get a thumbnail, the smoothing we apply doesn't get the best results and the only other option is mipmapping which is more memory intensive - it stores progressively smaller images but keeps all of them in memory. Now the ImageDelegate sets the sourceSize, which helps reduce the memory footprint (since Qt will throw away whatever parts of the image we don't need) and makes the images look smoother when scaled. However, AnimatedImages do not support this so this change introduces a new property to tell if the image could possibly be animated. It will erroneously pick up formats that could support animation (e.g. WebP) but other image formats will still benefit so it's a net positive. The ImageDelegate will load the correct image component depending on this property.
This commit is contained in:
@@ -20,6 +20,7 @@
|
||||
|
||||
#include <QDebug>
|
||||
#include <QGuiApplication>
|
||||
#include <QMovie>
|
||||
#include <QTimeZone>
|
||||
|
||||
#include <KLocalizedString>
|
||||
@@ -969,6 +970,9 @@ QVariantMap MessageEventModel::getMediaInfoFromFileInfo(const EventContent::File
|
||||
mediaInfo["width"] = castInfo->imageSize.width();
|
||||
mediaInfo["height"] = castInfo->imageSize.height();
|
||||
|
||||
// TODO: Images in certain formats (e.g. WebP) will be erroneously marked as animated, even if they are static.
|
||||
mediaInfo["animated"] = QMovie::supportedFormats().contains(mimeType.preferredSuffix().toUtf8());
|
||||
|
||||
if (!isThumbnail) {
|
||||
QVariantMap tempInfo;
|
||||
auto thumbnailInfo = getMediaInfoFromFileInfo(castInfo->thumbnailInfo(), eventId, true);
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
import QtQuick 2.15
|
||||
import QtQuick.Window 2.15
|
||||
import QtQuick.Controls 2.15 as QQC2
|
||||
import QtQuick.Layouts 1.15
|
||||
import QtQml.Models 2.15
|
||||
@@ -55,14 +56,12 @@ TimelineContainer {
|
||||
|
||||
onOpenContextMenu: openFileContext(root)
|
||||
|
||||
innerObject: AnimatedImage {
|
||||
id: img
|
||||
innerObject: Item {
|
||||
id: imageContainer
|
||||
|
||||
property var imageWidth: {
|
||||
if (root.mediaInfo.width > 0) {
|
||||
return root.mediaInfo.width;
|
||||
} else if (sourceSize.width && sourceSize.width > 0) {
|
||||
return sourceSize.width;
|
||||
} else {
|
||||
return root.contentMaxWidth;
|
||||
}
|
||||
@@ -70,8 +69,6 @@ TimelineContainer {
|
||||
property var imageHeight: {
|
||||
if (root.mediaInfo.height > 0) {
|
||||
return root.mediaInfo.height;
|
||||
} else if (sourceSize.height && sourceSize.height > 0) {
|
||||
return sourceSize.height;
|
||||
} else {
|
||||
// Default to a 16:9 placeholder
|
||||
return root.contentMaxWidth / 16 * 9;
|
||||
@@ -103,22 +100,49 @@ TimelineContainer {
|
||||
Layout.maximumHeight: maxSize.height
|
||||
Layout.preferredWidth: imageWidth
|
||||
Layout.preferredHeight: imageHeight
|
||||
source: root.mediaInfo.source
|
||||
|
||||
property var imageItem: root.mediaInfo.animated ? animatedImageLoader.item : imageLoader.item
|
||||
|
||||
Loader {
|
||||
id: imageLoader
|
||||
|
||||
anchors.fill: parent
|
||||
|
||||
active: !root.mediaInfo.animated
|
||||
sourceComponent: Image {
|
||||
source: root.mediaInfo.source
|
||||
sourceSize.width: imageContainer.maxSize.width * Screen.devicePixelRatio
|
||||
sourceSize.height: imageContainer.maxSize.height * Screen.devicePixelRatio
|
||||
|
||||
fillMode: Image.PreserveAspectFit
|
||||
}
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: animatedImageLoader
|
||||
|
||||
anchors.fill: parent
|
||||
|
||||
active: root.mediaInfo.animated
|
||||
sourceComponent: AnimatedImage {
|
||||
source: root.mediaInfo.source
|
||||
|
||||
fillMode: Image.PreserveAspectFit
|
||||
|
||||
paused: !applicationWindow().active
|
||||
}
|
||||
}
|
||||
|
||||
Image {
|
||||
anchors.fill: parent
|
||||
source: root.mediaInfo.tempInfo.source
|
||||
visible: parent.status !== Image.Ready
|
||||
visible: imageContainer.imageItem.status !== Image.Ready
|
||||
}
|
||||
|
||||
fillMode: Image.PreserveAspectFit
|
||||
|
||||
QQC2.ToolTip.text: root.display
|
||||
QQC2.ToolTip.visible: hoverHandler.hovered
|
||||
QQC2.ToolTip.delay: Kirigami.Units.toolTipDelay
|
||||
|
||||
paused: !applicationWindow().active
|
||||
|
||||
HoverHandler {
|
||||
id: hoverHandler
|
||||
}
|
||||
@@ -126,7 +150,7 @@ TimelineContainer {
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
|
||||
visible: root.progressInfo.active && !downloaded
|
||||
visible: (root.progressInfo.active && !downloaded) || imageContainer.imageItem.status !== Image.Ready
|
||||
|
||||
color: "#BB000000"
|
||||
|
||||
@@ -144,8 +168,10 @@ TimelineContainer {
|
||||
TapHandler {
|
||||
acceptedButtons: Qt.LeftButton
|
||||
onTapped: {
|
||||
img.QQC2.ToolTip.hide()
|
||||
img.paused = true
|
||||
imageContainer.QQC2.ToolTip.hide()
|
||||
if (root.mediaInfo.animated) {
|
||||
imageContainer.imageItem.paused = true
|
||||
}
|
||||
root.ListView.view.interactive = false
|
||||
root.ListView.view.showMaximizedMedia(root.index)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user