Get large avatar images as scale and crop locally (#1107)

Resolves #1069

The Matrix spec requires servers to provide thumbnails at (96x96, crop) and (320x240, scale) among others. [1] The avatars in Nheko's global/room profile and room settings are sized 130x130 on normal scaling and 260x260 on 2x scaling like on a HiDPI device. In both cases the avatar is requested as cropped and that way displayed at 96x96, making it look blurry.

This can be solved by requesting scaled avatars rather than cropped where appropriate, and cropping to the requested size afterwards.

HiDPI can be simulated in Qt by setting QT_SCALE_FACTOR=2.

[1] https://spec.matrix.org/v1.3/client-server-api/#thumbnails
This commit is contained in:
brausepulver 2022-06-26 20:32:43 +02:00 committed by GitHub
parent e16d297d0c
commit 98de51042a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -110,6 +110,12 @@ MxcImageProvider::download(const QString &id,
return; return;
} }
bool cropLocally = false;
if (crop && requestedSize.width() > 96) {
crop = false;
cropLocally = true;
}
std::optional<mtx::crypto::EncryptedFile> encryptionInfo; std::optional<mtx::crypto::EncryptedFile> encryptionInfo;
auto temp = infos.find("mxc://" + id); auto temp = infos.find("mxc://" + id);
if (temp != infos.end()) if (temp != infos.end())
@ -126,7 +132,7 @@ MxcImageProvider::download(const QString &id,
.arg(requestedSize.width()) .arg(requestedSize.width())
.arg(requestedSize.height()) .arg(requestedSize.height())
.arg(crop ? "crop" : "scale") .arg(crop ? "crop" : "scale")
.arg(radius); .arg(cropLocally ? 0 : radius);
QFileInfo fileInfo(QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + QFileInfo fileInfo(QStandardPaths::writableLocation(QStandardPaths::CacheLocation) +
"/media_cache", "/media_cache",
fileName); fileName);
@ -138,8 +144,16 @@ MxcImageProvider::download(const QString &id,
if (requestedSize.width() <= 0) { if (requestedSize.width() <= 0) {
image = image.scaledToHeight(requestedSize.height(), Qt::SmoothTransformation); image = image.scaledToHeight(requestedSize.height(), Qt::SmoothTransformation);
} else { } else {
image = image = image.scaled(requestedSize,
image.scaled(requestedSize, Qt::KeepAspectRatio, Qt::SmoothTransformation); cropLocally ? Qt::KeepAspectRatioByExpanding
: Qt::KeepAspectRatio,
Qt::SmoothTransformation);
if (cropLocally) {
image = image.copy((image.width() - requestedSize.width()) / 2,
(image.height() - requestedSize.height()) / 2,
requestedSize.width(),
requestedSize.height());
}
} }
if (radius != 0) { if (radius != 0) {
@ -160,8 +174,8 @@ MxcImageProvider::download(const QString &id,
opts.method = crop ? "crop" : "scale"; opts.method = crop ? "crop" : "scale";
http::client()->get_thumbnail( http::client()->get_thumbnail(
opts, opts,
[fileInfo, requestedSize, radius, then, id, crop](const std::string &res, [fileInfo, requestedSize, radius, then, id, crop, cropLocally](
mtx::http::RequestErr err) { const std::string &res, mtx::http::RequestErr err) {
if (err || res.empty()) { if (err || res.empty()) {
download(id, QSize(), then, crop, radius); download(id, QSize(), then, crop, radius);
return; return;
@ -174,8 +188,16 @@ MxcImageProvider::download(const QString &id,
image = image =
image.scaledToHeight(requestedSize.height(), Qt::SmoothTransformation); image.scaledToHeight(requestedSize.height(), Qt::SmoothTransformation);
} else { } else {
image = image = image.scaled(requestedSize,
image.scaled(requestedSize, Qt::KeepAspectRatio, Qt::SmoothTransformation); cropLocally ? Qt::KeepAspectRatioByExpanding
: Qt::KeepAspectRatio,
Qt::SmoothTransformation);
if (cropLocally) {
image = image.copy((image.width() - requestedSize.width()) / 2,
(image.height() - requestedSize.height()) / 2,
requestedSize.width(),
requestedSize.height());
}
} }
if (radius != 0) { if (radius != 0) {