mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 22:54:01 +02:00
Try using progressive jpeg photo size.
This commit is contained in:
parent
55edb3bdfe
commit
0888901d79
17 changed files with 198 additions and 63 deletions
|
@ -1082,7 +1082,8 @@ void Call::handleControllerError(const QString &error) {
|
||||||
|
|
||||||
void Call::destroyController() {
|
void Call::destroyController() {
|
||||||
if (_instance) {
|
if (_instance) {
|
||||||
_instance->stop();
|
_instance->stop([](tgcalls::FinalState) {
|
||||||
|
});
|
||||||
|
|
||||||
DEBUG_LOG(("Call Info: Destroying call controller.."));
|
DEBUG_LOG(("Call Info: Destroying call controller.."));
|
||||||
_instance.reset();
|
_instance.reset();
|
||||||
|
|
|
@ -160,6 +160,9 @@ void UpdateCloudFile(
|
||||||
Fn<void(FileOrigin)> restartLoader,
|
Fn<void(FileOrigin)> restartLoader,
|
||||||
Fn<void(QImage)> usePreloaded) {
|
Fn<void(QImage)> usePreloaded) {
|
||||||
if (!data.location.valid()) {
|
if (!data.location.valid()) {
|
||||||
|
if (data.progressivePartSize && !file.location.valid()) {
|
||||||
|
file.progressivePartSize = data.progressivePartSize;
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -208,11 +211,18 @@ void LoadCloudFile(
|
||||||
Fn<bool()> finalCheck,
|
Fn<bool()> finalCheck,
|
||||||
Fn<void(CloudFile&)> done,
|
Fn<void(CloudFile&)> done,
|
||||||
Fn<void(bool)> fail,
|
Fn<void(bool)> fail,
|
||||||
Fn<void()> progress) {
|
Fn<void()> progress,
|
||||||
|
int downloadFrontPartSize = 0) {
|
||||||
|
const auto loadSize = downloadFrontPartSize
|
||||||
|
? downloadFrontPartSize
|
||||||
|
: file.byteSize;
|
||||||
if (file.loader) {
|
if (file.loader) {
|
||||||
if (fromCloud == LoadFromCloudOrLocal) {
|
if (fromCloud == LoadFromCloudOrLocal) {
|
||||||
file.loader->permitLoadFromCloud();
|
file.loader->permitLoadFromCloud();
|
||||||
}
|
}
|
||||||
|
if (file.loader->fullSize() < loadSize) {
|
||||||
|
file.loader->increaseLoadSize(loadSize);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
} else if ((file.flags & CloudFile::Flag::Failed)
|
} else if ((file.flags & CloudFile::Flag::Failed)
|
||||||
|| !file.location.valid()
|
|| !file.location.valid()
|
||||||
|
@ -225,7 +235,7 @@ void LoadCloudFile(
|
||||||
file.location.file(),
|
file.location.file(),
|
||||||
origin,
|
origin,
|
||||||
QString(),
|
QString(),
|
||||||
file.byteSize,
|
loadSize,
|
||||||
UnknownFileLocation,
|
UnknownFileLocation,
|
||||||
LoadToCacheAsWell,
|
LoadToCacheAsWell,
|
||||||
fromCloud,
|
fromCloud,
|
||||||
|
@ -275,7 +285,8 @@ void LoadCloudFile(
|
||||||
Fn<bool()> finalCheck,
|
Fn<bool()> finalCheck,
|
||||||
Fn<void(QImage)> done,
|
Fn<void(QImage)> done,
|
||||||
Fn<void(bool)> fail,
|
Fn<void(bool)> fail,
|
||||||
Fn<void()> progress) {
|
Fn<void()> progress,
|
||||||
|
int downloadFrontPartSize) {
|
||||||
const auto callback = [=](CloudFile &file) {
|
const auto callback = [=](CloudFile &file) {
|
||||||
if (auto read = file.loader->imageData(); read.isNull()) {
|
if (auto read = file.loader->imageData(); read.isNull()) {
|
||||||
file.flags |= CloudFile::Flag::Failed;
|
file.flags |= CloudFile::Flag::Failed;
|
||||||
|
@ -296,7 +307,8 @@ void LoadCloudFile(
|
||||||
finalCheck,
|
finalCheck,
|
||||||
callback,
|
callback,
|
||||||
std::move(fail),
|
std::move(fail),
|
||||||
std::move(progress));
|
std::move(progress),
|
||||||
|
downloadFrontPartSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoadCloudFile(
|
void LoadCloudFile(
|
||||||
|
|
|
@ -39,6 +39,7 @@ struct CloudFile final {
|
||||||
ImageLocation location;
|
ImageLocation location;
|
||||||
std::unique_ptr<FileLoader> loader;
|
std::unique_ptr<FileLoader> loader;
|
||||||
int byteSize = 0;
|
int byteSize = 0;
|
||||||
|
int progressivePartSize = 0;
|
||||||
base::flags<Flag> flags;
|
base::flags<Flag> flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -105,7 +106,8 @@ void LoadCloudFile(
|
||||||
Fn<bool()> finalCheck,
|
Fn<bool()> finalCheck,
|
||||||
Fn<void(QImage)> done,
|
Fn<void(QImage)> done,
|
||||||
Fn<void(bool)> fail = nullptr,
|
Fn<void(bool)> fail = nullptr,
|
||||||
Fn<void()> progress = nullptr);
|
Fn<void()> progress = nullptr,
|
||||||
|
int downloadFrontPartSize = 0);
|
||||||
|
|
||||||
void LoadCloudFile(
|
void LoadCloudFile(
|
||||||
not_null<Main::Session*> session,
|
not_null<Main::Session*> session,
|
||||||
|
|
|
@ -82,12 +82,30 @@ int PhotoData::validSizeIndex(PhotoSize size) const {
|
||||||
return PhotoSizeIndex(PhotoSize::Large);
|
return PhotoSizeIndex(PhotoSize::Large);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int PhotoData::existingSizeIndex(PhotoSize size) const {
|
||||||
|
const auto index = PhotoSizeIndex(size);
|
||||||
|
for (auto i = index; i != kPhotoSizeCount; ++i) {
|
||||||
|
if (_images[i].location.valid() || _images[i].progressivePartSize) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return PhotoSizeIndex(PhotoSize::Large);
|
||||||
|
}
|
||||||
|
|
||||||
bool PhotoData::hasExact(PhotoSize size) const {
|
bool PhotoData::hasExact(PhotoSize size) const {
|
||||||
return _images[PhotoSizeIndex(size)].location.valid();
|
return _images[PhotoSizeIndex(size)].location.valid();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PhotoData::loading(PhotoSize size) const {
|
bool PhotoData::loading(PhotoSize size) const {
|
||||||
return (_images[validSizeIndex(size)].loader != nullptr);
|
const auto valid = validSizeIndex(size);
|
||||||
|
const auto existing = existingSizeIndex(size);
|
||||||
|
if (!_images[valid].loader) {
|
||||||
|
return false;
|
||||||
|
} else if (valid == existing) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return (_images[valid].loader->fullSize()
|
||||||
|
>= _images[existing].progressivePartSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PhotoData::failed(PhotoSize size) const {
|
bool PhotoData::failed(PhotoSize size) const {
|
||||||
|
@ -117,6 +135,10 @@ std::optional<QSize> PhotoData::size(PhotoSize size) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
int PhotoData::imageByteSize(PhotoSize size) const {
|
int PhotoData::imageByteSize(PhotoSize size) const {
|
||||||
|
const auto existing = existingSizeIndex(size);
|
||||||
|
if (const auto result = _images[existing].progressivePartSize) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
return _images[validSizeIndex(size)].byteSize;
|
return _images[validSizeIndex(size)].byteSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -235,10 +257,12 @@ void PhotoData::load(
|
||||||
Data::FileOrigin origin,
|
Data::FileOrigin origin,
|
||||||
LoadFromCloudSetting fromCloud,
|
LoadFromCloudSetting fromCloud,
|
||||||
bool autoLoading) {
|
bool autoLoading) {
|
||||||
const auto index = validSizeIndex(size);
|
const auto valid = validSizeIndex(size);
|
||||||
|
const auto existing = existingSizeIndex(size);
|
||||||
|
|
||||||
// Could've changed, if the requested size didn't have a location.
|
// Could've changed, if the requested size didn't have a location.
|
||||||
const auto loadingSize = static_cast<PhotoSize>(index);
|
const auto validSize = static_cast<PhotoSize>(valid);
|
||||||
|
const auto existingSize = static_cast<PhotoSize>(existing);
|
||||||
const auto finalCheck = [=] {
|
const auto finalCheck = [=] {
|
||||||
if (const auto active = activeMediaView()) {
|
if (const auto active = activeMediaView()) {
|
||||||
return !active->image(size);
|
return !active->image(size);
|
||||||
|
@ -247,25 +271,25 @@ void PhotoData::load(
|
||||||
};
|
};
|
||||||
const auto done = [=](QImage result) {
|
const auto done = [=](QImage result) {
|
||||||
if (const auto active = activeMediaView()) {
|
if (const auto active = activeMediaView()) {
|
||||||
active->set(loadingSize, std::move(result));
|
active->set(validSize, existingSize, std::move(result));
|
||||||
}
|
}
|
||||||
if (loadingSize == PhotoSize::Large) {
|
if (validSize == PhotoSize::Large) {
|
||||||
_owner->photoLoadDone(this);
|
_owner->photoLoadDone(this);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const auto fail = [=](bool started) {
|
const auto fail = [=](bool started) {
|
||||||
if (loadingSize == PhotoSize::Large) {
|
if (validSize == PhotoSize::Large) {
|
||||||
_owner->photoLoadFail(this, started);
|
_owner->photoLoadFail(this, started);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const auto progress = [=] {
|
const auto progress = [=] {
|
||||||
if (loadingSize == PhotoSize::Large) {
|
if (validSize == PhotoSize::Large) {
|
||||||
_owner->photoLoadProgress(this);
|
_owner->photoLoadProgress(this);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Data::LoadCloudFile(
|
Data::LoadCloudFile(
|
||||||
&session(),
|
&session(),
|
||||||
_images[index],
|
_images[valid],
|
||||||
origin,
|
origin,
|
||||||
fromCloud,
|
fromCloud,
|
||||||
autoLoading,
|
autoLoading,
|
||||||
|
@ -273,7 +297,8 @@ void PhotoData::load(
|
||||||
finalCheck,
|
finalCheck,
|
||||||
done,
|
done,
|
||||||
fail,
|
fail,
|
||||||
progress);
|
progress,
|
||||||
|
_images[existing].progressivePartSize);
|
||||||
|
|
||||||
if (size == PhotoSize::Large) {
|
if (size == PhotoSize::Large) {
|
||||||
_owner->notifyPhotoLayoutChanged(this);
|
_owner->notifyPhotoLayoutChanged(this);
|
||||||
|
@ -313,7 +338,7 @@ void PhotoData::updateImages(
|
||||||
[=](Data::FileOrigin origin) { load(size, origin); },
|
[=](Data::FileOrigin origin) { load(size, origin); },
|
||||||
[=](QImage preloaded) {
|
[=](QImage preloaded) {
|
||||||
if (const auto media = activeMediaView()) {
|
if (const auto media = activeMediaView()) {
|
||||||
media->set(size, data.preloaded);
|
media->set(size, size, data.preloaded);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -92,6 +92,7 @@ public:
|
||||||
const ImageWithLocation &video,
|
const ImageWithLocation &video,
|
||||||
crl::time videoStartTime);
|
crl::time videoStartTime);
|
||||||
[[nodiscard]] int validSizeIndex(Data::PhotoSize size) const;
|
[[nodiscard]] int validSizeIndex(Data::PhotoSize size) const;
|
||||||
|
[[nodiscard]] int existingSizeIndex(Data::PhotoSize size) const;
|
||||||
|
|
||||||
[[nodiscard]] QByteArray inlineThumbnailBytes() const {
|
[[nodiscard]] QByteArray inlineThumbnailBytes() const {
|
||||||
return _inlineThumbnailBytes;
|
return _inlineThumbnailBytes;
|
||||||
|
|
|
@ -49,29 +49,34 @@ Image *PhotoMedia::thumbnailInline() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
Image *PhotoMedia::image(PhotoSize size) const {
|
Image *PhotoMedia::image(PhotoSize size) const {
|
||||||
if (const auto image = _images[PhotoSizeIndex(size)].get()) {
|
const auto &original = _images[PhotoSizeIndex(size)];
|
||||||
return image;
|
if (const auto image = original.data.get()) {
|
||||||
|
return (original.goodFor >= size) ? image : nullptr;
|
||||||
}
|
}
|
||||||
return _images[_owner->validSizeIndex(size)].get();
|
const auto &valid = _images[_owner->validSizeIndex(size)];
|
||||||
|
if (const auto image = valid.data.get()) {
|
||||||
|
return (valid.goodFor >= size) ? image : nullptr;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PhotoMedia::wanted(PhotoSize size, Data::FileOrigin origin) {
|
void PhotoMedia::wanted(PhotoSize size, Data::FileOrigin origin) {
|
||||||
const auto index = _owner->validSizeIndex(size);
|
const auto index = _owner->validSizeIndex(size);
|
||||||
if (!_images[index]) {
|
if (!_images[index].data || _images[index].goodFor < size) {
|
||||||
_owner->load(size, origin);
|
_owner->load(size, origin);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QSize PhotoMedia::size(PhotoSize size) const {
|
QSize PhotoMedia::size(PhotoSize size) const {
|
||||||
const auto index = PhotoSizeIndex(size);
|
const auto index = PhotoSizeIndex(size);
|
||||||
if (const auto image = _images[index].get()) {
|
if (const auto image = _images[index].data.get()) {
|
||||||
return image->size();
|
return image->size();
|
||||||
}
|
}
|
||||||
const auto &location = _owner->location(size);
|
const auto &location = _owner->location(size);
|
||||||
return { location.width(), location.height() };
|
return { location.width(), location.height() };
|
||||||
}
|
}
|
||||||
|
|
||||||
void PhotoMedia::set(PhotoSize size, QImage image) {
|
void PhotoMedia::set(PhotoSize size, PhotoSize goodFor, QImage image) {
|
||||||
const auto index = PhotoSizeIndex(size);
|
const auto index = PhotoSizeIndex(size);
|
||||||
const auto limit = PhotoData::SideLimit();
|
const auto limit = PhotoData::SideLimit();
|
||||||
if (image.width() > limit || image.height() > limit) {
|
if (image.width() > limit || image.height() > limit) {
|
||||||
|
@ -81,7 +86,10 @@ void PhotoMedia::set(PhotoSize size, QImage image) {
|
||||||
Qt::KeepAspectRatio,
|
Qt::KeepAspectRatio,
|
||||||
Qt::SmoothTransformation);
|
Qt::SmoothTransformation);
|
||||||
}
|
}
|
||||||
_images[index] = std::make_unique<Image>(std::move(image));
|
_images[index] = PhotoImage{
|
||||||
|
.data = std::make_unique<Image>(std::move(image)),
|
||||||
|
.goodFor = goodFor,
|
||||||
|
};
|
||||||
_owner->session().notifyDownloaderTaskFinished();
|
_owner->session().notifyDownloaderTaskFinished();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,7 +114,8 @@ void PhotoMedia::setVideo(QByteArray content) {
|
||||||
|
|
||||||
bool PhotoMedia::loaded() const {
|
bool PhotoMedia::loaded() const {
|
||||||
const auto index = PhotoSizeIndex(PhotoSize::Large);
|
const auto index = PhotoSizeIndex(PhotoSize::Large);
|
||||||
return (_images[index] != nullptr);
|
return (_images[index].data != nullptr)
|
||||||
|
&& (_images[index].goodFor >= PhotoSize::Large);
|
||||||
}
|
}
|
||||||
|
|
||||||
float64 PhotoMedia::progress() const {
|
float64 PhotoMedia::progress() const {
|
||||||
|
@ -136,8 +145,11 @@ void PhotoMedia::collectLocalData(not_null<PhotoMedia*> local) {
|
||||||
_inlineThumbnail = std::make_unique<Image>(image->original());
|
_inlineThumbnail = std::make_unique<Image>(image->original());
|
||||||
}
|
}
|
||||||
for (auto i = 0; i != kPhotoSizeCount; ++i) {
|
for (auto i = 0; i != kPhotoSizeCount; ++i) {
|
||||||
if (const auto image = local->_images[i].get()) {
|
if (const auto image = local->_images[i].data.get()) {
|
||||||
_images[i] = std::make_unique<Image>(image->original());
|
_images[i] = PhotoImage{
|
||||||
|
.data = std::make_unique<Image>(image->original()),
|
||||||
|
.goodFor = local->_images[i].goodFor
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ public:
|
||||||
[[nodiscard]] Image *image(PhotoSize size) const;
|
[[nodiscard]] Image *image(PhotoSize size) const;
|
||||||
[[nodiscard]] QSize size(PhotoSize size) const;
|
[[nodiscard]] QSize size(PhotoSize size) const;
|
||||||
void wanted(PhotoSize size, Data::FileOrigin origin);
|
void wanted(PhotoSize size, Data::FileOrigin origin);
|
||||||
void set(PhotoSize size, QImage image);
|
void set(PhotoSize size, PhotoSize goodFor, QImage image);
|
||||||
|
|
||||||
[[nodiscard]] QByteArray videoContent() const;
|
[[nodiscard]] QByteArray videoContent() const;
|
||||||
[[nodiscard]] QSize videoSize() const;
|
[[nodiscard]] QSize videoSize() const;
|
||||||
|
@ -41,12 +41,17 @@ public:
|
||||||
void collectLocalData(not_null<PhotoMedia*> local);
|
void collectLocalData(not_null<PhotoMedia*> local);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
struct PhotoImage {
|
||||||
|
std::unique_ptr<Image> data;
|
||||||
|
PhotoSize goodFor = PhotoSize();
|
||||||
|
};
|
||||||
|
|
||||||
// NB! Right now DocumentMedia can outlive Main::Session!
|
// NB! Right now DocumentMedia can outlive Main::Session!
|
||||||
// In DocumentData::collectLocalData a shared_ptr is sent on_main.
|
// In DocumentData::collectLocalData a shared_ptr is sent on_main.
|
||||||
// In case this is a problem the ~Gif code should be rewritten.
|
// In case this is a problem the ~Gif code should be rewritten.
|
||||||
const not_null<PhotoData*> _owner;
|
const not_null<PhotoData*> _owner;
|
||||||
mutable std::unique_ptr<Image> _inlineThumbnail;
|
mutable std::unique_ptr<Image> _inlineThumbnail;
|
||||||
std::array<std::unique_ptr<Image>, kPhotoSizeCount> _images;
|
std::array<PhotoImage, kPhotoSizeCount> _images;
|
||||||
QByteArray _videoBytes;
|
QByteArray _videoBytes;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -2262,6 +2262,21 @@ void Session::photoApplyFields(
|
||||||
not_null<PhotoData*> photo,
|
not_null<PhotoData*> photo,
|
||||||
const MTPDphoto &data) {
|
const MTPDphoto &data) {
|
||||||
const auto &sizes = data.vsizes().v;
|
const auto &sizes = data.vsizes().v;
|
||||||
|
const auto progressive = [&] {
|
||||||
|
const auto kInvalidIndex = sizes.size();
|
||||||
|
const auto area = [&](const MTPPhotoSize &size) {
|
||||||
|
return size.match([](const MTPDphotoSizeProgressive &data) {
|
||||||
|
return data.vw().v * data.vh().v;
|
||||||
|
}, [](const auto &) {
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
const auto found = ranges::max_element(sizes, std::greater<>(), area);
|
||||||
|
return (found == sizes.end()
|
||||||
|
|| found->type() != mtpc_photoSizeProgressive)
|
||||||
|
? sizes.end()
|
||||||
|
: found;
|
||||||
|
}();
|
||||||
const auto find = [&](const QByteArray &levels) {
|
const auto find = [&](const QByteArray &levels) {
|
||||||
const auto kInvalidIndex = int(levels.size());
|
const auto kInvalidIndex = int(levels.size());
|
||||||
const auto level = [&](const MTPPhotoSize &size) {
|
const auto level = [&](const MTPPhotoSize &size) {
|
||||||
|
@ -2300,7 +2315,10 @@ void Session::photoApplyFields(
|
||||||
std::greater<>(),
|
std::greater<>(),
|
||||||
area);
|
area);
|
||||||
};
|
};
|
||||||
const auto large = image(LargeLevels);
|
const auto useProgressive = (progressive != sizes.end());
|
||||||
|
const auto large = useProgressive
|
||||||
|
? Images::FromPhotoSize(_session, data, *progressive)
|
||||||
|
: image(LargeLevels);
|
||||||
if (large.location.valid()) {
|
if (large.location.valid()) {
|
||||||
const auto video = findVideoSize();
|
const auto video = findVideoSize();
|
||||||
photoApplyFields(
|
photoApplyFields(
|
||||||
|
@ -2311,8 +2329,12 @@ void Session::photoApplyFields(
|
||||||
data.vdc_id().v,
|
data.vdc_id().v,
|
||||||
data.is_has_stickers(),
|
data.is_has_stickers(),
|
||||||
FindPhotoInlineThumbnail(data),
|
FindPhotoInlineThumbnail(data),
|
||||||
image(SmallLevels),
|
(useProgressive
|
||||||
image(ThumbnailLevels),
|
? ImageWithLocation()
|
||||||
|
: image(SmallLevels)),
|
||||||
|
(useProgressive
|
||||||
|
? Images::FromProgressiveSize(_session, *progressive, 1)
|
||||||
|
: image(ThumbnailLevels)),
|
||||||
large,
|
large,
|
||||||
(video
|
(video
|
||||||
? Images::FromVideoSize(_session, data, *video)
|
? Images::FromVideoSize(_session, data, *video)
|
||||||
|
|
|
@ -265,8 +265,11 @@ Image ParseMaxImage(
|
||||||
result.file.content = data.vbytes().v;
|
result.file.content = data.vbytes().v;
|
||||||
result.file.size = result.file.content.size();
|
result.file.size = result.file.content.size();
|
||||||
} else if constexpr (MTPDphotoSizeProgressive::Is<decltype(data)>()) {
|
} else if constexpr (MTPDphotoSizeProgressive::Is<decltype(data)>()) {
|
||||||
|
if (data.vsizes().v.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
result.file.content = QByteArray();
|
result.file.content = QByteArray();
|
||||||
result.file.size = data.vsizes().v.size();
|
result.file.size = data.vsizes().v.back().v;
|
||||||
} else {
|
} else {
|
||||||
result.file.content = QByteArray();
|
result.file.content = QByteArray();
|
||||||
result.file.size = data.vsize().v;
|
result.file.size = data.vsize().v;
|
||||||
|
@ -426,8 +429,11 @@ Image ParseDocumentThumb(
|
||||||
result.file.content = data.vbytes().v;
|
result.file.content = data.vbytes().v;
|
||||||
result.file.size = result.file.content.size();
|
result.file.size = result.file.content.size();
|
||||||
} else if constexpr (MTPDphotoSizeProgressive::Is<decltype(data)>()) {
|
} else if constexpr (MTPDphotoSizeProgressive::Is<decltype(data)>()) {
|
||||||
|
if (data.vsizes().v.isEmpty()) {
|
||||||
|
return Image();
|
||||||
|
}
|
||||||
result.file.content = QByteArray();
|
result.file.content = QByteArray();
|
||||||
result.file.size = data.vsizes().v.size();
|
result.file.size = data.vsizes().v.back().v;
|
||||||
} else {
|
} else {
|
||||||
result.file.content = QByteArray();
|
result.file.content = QByteArray();
|
||||||
result.file.size = data.vsize().v;
|
result.file.size = data.vsize().v;
|
||||||
|
|
|
@ -145,29 +145,21 @@ void FileLoader::finishWithBytes(const QByteArray &data) {
|
||||||
session->notifyDownloaderTaskFinished();
|
session->notifyDownloaderTaskFinished();
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray FileLoader::imageFormat(const QSize &shrinkBox) const {
|
QImage FileLoader::imageData(int progressiveSizeLimit) const {
|
||||||
if (_imageFormat.isEmpty() && _locationType == UnknownFileLocation) {
|
|
||||||
readImage(shrinkBox);
|
|
||||||
}
|
|
||||||
return _imageFormat;
|
|
||||||
}
|
|
||||||
|
|
||||||
QImage FileLoader::imageData(const QSize &shrinkBox) const {
|
|
||||||
if (_imageData.isNull() && _locationType == UnknownFileLocation) {
|
if (_imageData.isNull() && _locationType == UnknownFileLocation) {
|
||||||
readImage(shrinkBox);
|
readImage(progressiveSizeLimit);
|
||||||
}
|
}
|
||||||
return _imageData;
|
return _imageData;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileLoader::readImage(const QSize &shrinkBox) const {
|
void FileLoader::readImage(int progressiveSizeLimit) const {
|
||||||
|
const auto buffer = progressiveSizeLimit
|
||||||
|
? QByteArray::fromRawData(_data.data(), progressiveSizeLimit)
|
||||||
|
: _data;
|
||||||
auto format = QByteArray();
|
auto format = QByteArray();
|
||||||
auto image = App::readImage(_data, &format, false);
|
auto image = App::readImage(buffer, &format, false);
|
||||||
if (!image.isNull()) {
|
if (!image.isNull()) {
|
||||||
if (!shrinkBox.isEmpty() && (image.width() > shrinkBox.width() || image.height() > shrinkBox.height())) {
|
_imageData = std::move(image);
|
||||||
_imageData = image.scaled(shrinkBox, Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
|
||||||
} else {
|
|
||||||
_imageData = std::move(image);
|
|
||||||
}
|
|
||||||
_imageFormat = format;
|
_imageFormat = format;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -199,6 +191,12 @@ void FileLoader::permitLoadFromCloud() {
|
||||||
_fromCloud = LoadFromCloudOrLocal;
|
_fromCloud = LoadFromCloudOrLocal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FileLoader::increaseLoadSize(int size) {
|
||||||
|
Expects(size > _size);
|
||||||
|
|
||||||
|
_size = size;
|
||||||
|
}
|
||||||
|
|
||||||
void FileLoader::notifyAboutProgress() {
|
void FileLoader::notifyAboutProgress() {
|
||||||
_updates.fire({});
|
_updates.fire({});
|
||||||
}
|
}
|
||||||
|
@ -213,6 +211,13 @@ void FileLoader::localLoaded(
|
||||||
start();
|
start();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (result.data.size() < _size) {
|
||||||
|
_localStatus = LocalStatus::NotFound;
|
||||||
|
if (checkForOpen()) {
|
||||||
|
startLoadingWithData(result.data);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (!imageData.isNull()) {
|
if (!imageData.isNull()) {
|
||||||
_imageFormat = imageFormat;
|
_imageFormat = imageFormat;
|
||||||
_imageData = imageData;
|
_imageData = imageData;
|
||||||
|
@ -228,13 +233,23 @@ void FileLoader::start() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_filename.isEmpty() && _toCache == LoadToFileOnly && !_fileIsOpen) {
|
if (checkForOpen()) {
|
||||||
_fileIsOpen = _file.open(QIODevice::WriteOnly);
|
startLoading();
|
||||||
if (!_fileIsOpen) {
|
|
||||||
return cancel(true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
startLoading();
|
}
|
||||||
|
|
||||||
|
bool FileLoader::checkForOpen() {
|
||||||
|
if (_filename.isEmpty()
|
||||||
|
|| (_toCache != LoadToFileOnly)
|
||||||
|
|| _fileIsOpen) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
_fileIsOpen = _file.open(QIODevice::WriteOnly);
|
||||||
|
if (_fileIsOpen) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
cancel(true);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileLoader::loadLocal(const Storage::Cache::Key &key) {
|
void FileLoader::loadLocal(const Storage::Cache::Key &key) {
|
||||||
|
|
|
@ -80,9 +80,7 @@ public:
|
||||||
[[nodiscard]] virtual uint64 objId() const {
|
[[nodiscard]] virtual uint64 objId() const {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
[[nodiscard]] QByteArray imageFormat(
|
[[nodiscard]] QImage imageData(int progressiveSizeLimit = 0) const;
|
||||||
const QSize &shrinkBox = QSize()) const;
|
|
||||||
[[nodiscard]] QImage imageData(const QSize &shrinkBox = QSize()) const;
|
|
||||||
[[nodiscard]] QString fileName() const {
|
[[nodiscard]] QString fileName() const {
|
||||||
return _filename;
|
return _filename;
|
||||||
}
|
}
|
||||||
|
@ -94,6 +92,7 @@ public:
|
||||||
|
|
||||||
bool setFileName(const QString &filename); // set filename for loaders to cache
|
bool setFileName(const QString &filename); // set filename for loaders to cache
|
||||||
void permitLoadFromCloud();
|
void permitLoadFromCloud();
|
||||||
|
void increaseLoadSize(int size);
|
||||||
|
|
||||||
void start();
|
void start();
|
||||||
void cancel();
|
void cancel();
|
||||||
|
@ -126,14 +125,18 @@ protected:
|
||||||
Loaded,
|
Loaded,
|
||||||
};
|
};
|
||||||
|
|
||||||
void readImage(const QSize &shrinkBox) const;
|
void readImage(int progressiveSizeLimit) const;
|
||||||
|
|
||||||
|
bool checkForOpen();
|
||||||
bool tryLoadLocal();
|
bool tryLoadLocal();
|
||||||
void loadLocal(const Storage::Cache::Key &key);
|
void loadLocal(const Storage::Cache::Key &key);
|
||||||
virtual Storage::Cache::Key cacheKey() const = 0;
|
virtual Storage::Cache::Key cacheKey() const = 0;
|
||||||
virtual std::optional<MediaKey> fileLocationKey() const = 0;
|
virtual std::optional<MediaKey> fileLocationKey() const = 0;
|
||||||
virtual void cancelHook() = 0;
|
virtual void cancelHook() = 0;
|
||||||
virtual void startLoading() = 0;
|
virtual void startLoading() = 0;
|
||||||
|
virtual void startLoadingWithData(const QByteArray &data) {
|
||||||
|
startLoading();
|
||||||
|
}
|
||||||
|
|
||||||
void cancel(bool failed);
|
void cancel(bool failed);
|
||||||
|
|
||||||
|
|
|
@ -114,7 +114,9 @@ int mtpFileLoader::takeNextRequestOffset() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool mtpFileLoader::feedPart(int offset, const QByteArray &bytes) {
|
bool mtpFileLoader::feedPart(int offset, const QByteArray &bytes) {
|
||||||
const auto buffer = bytes::make_span(bytes);
|
const auto buffer = (_size > 0 && offset + bytes.size() > _size)
|
||||||
|
? bytes::make_span(bytes).subspan(0, _size - offset)
|
||||||
|
: bytes::make_span(bytes);
|
||||||
if (!writeResultPart(offset, buffer)) {
|
if (!writeResultPart(offset, buffer)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -155,6 +157,16 @@ void mtpFileLoader::startLoading() {
|
||||||
addToQueue();
|
addToQueue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void mtpFileLoader::startLoadingWithData(const QByteArray &data) {
|
||||||
|
const auto parts = data.size() / Storage::kDownloadPartSize;
|
||||||
|
const auto use = parts * Storage::kDownloadPartSize;
|
||||||
|
if (use > 0) {
|
||||||
|
_nextRequestOffset = use;
|
||||||
|
feedPart(0, QByteArray::fromRawData(data.data(), use));
|
||||||
|
}
|
||||||
|
startLoading();
|
||||||
|
}
|
||||||
|
|
||||||
void mtpFileLoader::cancelHook() {
|
void mtpFileLoader::cancelHook() {
|
||||||
cancelAllRequests();
|
cancelAllRequests();
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,6 +48,7 @@ private:
|
||||||
Storage::Cache::Key cacheKey() const override;
|
Storage::Cache::Key cacheKey() const override;
|
||||||
std::optional<MediaKey> fileLocationKey() const override;
|
std::optional<MediaKey> fileLocationKey() const override;
|
||||||
void startLoading() override;
|
void startLoading() override;
|
||||||
|
void startLoadingWithData(const QByteArray &data) override;
|
||||||
void cancelHook() override;
|
void cancelHook() override;
|
||||||
|
|
||||||
bool readyToRequest() const override;
|
bool readyToRequest() const override;
|
||||||
|
|
|
@ -614,6 +614,7 @@ struct ImageWithLocation {
|
||||||
QByteArray bytes;
|
QByteArray bytes;
|
||||||
QImage preloaded;
|
QImage preloaded;
|
||||||
int bytesCount = 0;
|
int bytesCount = 0;
|
||||||
|
int progressivePartSize = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
InMemoryKey inMemoryKey(const StorageFileLocation &location);
|
InMemoryKey inMemoryKey(const StorageFileLocation &location);
|
||||||
|
|
|
@ -96,6 +96,21 @@ ImageWithLocation FromPhotoSize(
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ImageWithLocation FromProgressiveSize(
|
||||||
|
not_null<Main::Session*> session,
|
||||||
|
const MTPPhotoSize &size,
|
||||||
|
int index) {
|
||||||
|
Expects(size.type() == mtpc_photoSizeProgressive);
|
||||||
|
|
||||||
|
const auto &data = size.c_photoSizeProgressive();
|
||||||
|
if (data.vsizes().v.size() <= index) {
|
||||||
|
return ImageWithLocation();
|
||||||
|
}
|
||||||
|
return ImageWithLocation{
|
||||||
|
.progressivePartSize = data.vsizes().v[index].v,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
ImageWithLocation FromPhotoSize(
|
ImageWithLocation FromPhotoSize(
|
||||||
not_null<Main::Session*> session,
|
not_null<Main::Session*> session,
|
||||||
const MTPDdocument &document,
|
const MTPDdocument &document,
|
||||||
|
@ -133,7 +148,6 @@ ImageWithLocation FromPhotoSize(
|
||||||
.bytesCount = bytes.size(),
|
.bytesCount = bytes.size(),
|
||||||
};
|
};
|
||||||
}, [&](const MTPDphotoSizeProgressive &data) {
|
}, [&](const MTPDphotoSizeProgressive &data) {
|
||||||
// #TODO layer118
|
|
||||||
if (data.vsizes().v.isEmpty()) {
|
if (data.vsizes().v.isEmpty()) {
|
||||||
return ImageWithLocation();
|
return ImageWithLocation();
|
||||||
}
|
}
|
||||||
|
@ -214,7 +228,6 @@ ImageWithLocation FromPhotoSize(
|
||||||
.bytesCount = bytes.size(),
|
.bytesCount = bytes.size(),
|
||||||
};
|
};
|
||||||
}, [&](const MTPDphotoSizeProgressive &data) {
|
}, [&](const MTPDphotoSizeProgressive &data) {
|
||||||
// #TODO layer118
|
|
||||||
if (data.vsizes().v.isEmpty()) {
|
if (data.vsizes().v.isEmpty()) {
|
||||||
return ImageWithLocation();
|
return ImageWithLocation();
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,10 @@ namespace Images {
|
||||||
not_null<Main::Session*> session,
|
not_null<Main::Session*> session,
|
||||||
const MTPDphoto &photo,
|
const MTPDphoto &photo,
|
||||||
const MTPPhotoSize &size);
|
const MTPPhotoSize &size);
|
||||||
|
[[nodiscard]] ImageWithLocation FromProgressiveSize(
|
||||||
|
not_null<Main::Session*> session,
|
||||||
|
const MTPPhotoSize &size,
|
||||||
|
int index);
|
||||||
[[nodiscard]] ImageWithLocation FromPhotoSize(
|
[[nodiscard]] ImageWithLocation FromPhotoSize(
|
||||||
not_null<Main::Session*> session,
|
not_null<Main::Session*> session,
|
||||||
const MTPDdocument &document,
|
const MTPDdocument &document,
|
||||||
|
|
2
Telegram/ThirdParty/tgcalls
vendored
2
Telegram/ThirdParty/tgcalls
vendored
|
@ -1 +1 @@
|
||||||
Subproject commit b221a088a701ab8af60feb8deed87313500af435
|
Subproject commit db23f73e451e3ae11551e7a444ec1a4087348e5c
|
Loading…
Add table
Reference in a new issue