Try using progressive jpeg photo size.

This commit is contained in:
John Preston 2020-08-25 22:03:41 +04:00
parent 55edb3bdfe
commit 0888901d79
17 changed files with 198 additions and 63 deletions

View file

@ -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();

View file

@ -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(

View file

@ -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,

View file

@ -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);
} }
}); });
}; };

View file

@ -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;

View file

@ -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
};
} }
} }
} }

View file

@ -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;
}; };

View file

@ -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)

View file

@ -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;

View file

@ -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) {

View file

@ -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);

View file

@ -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();
} }

View file

@ -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;

View file

@ -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);

View file

@ -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();
} }

View file

@ -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,

@ -1 +1 @@
Subproject commit b221a088a701ab8af60feb8deed87313500af435 Subproject commit db23f73e451e3ae11551e7a444ec1a4087348e5c