Use final Image with different Images::Source-s.

This commit is contained in:
John Preston 2018-10-12 19:41:51 +03:00
parent 5a50248055
commit 4b5b79e415
16 changed files with 1376 additions and 993 deletions

View file

@ -660,8 +660,8 @@ bool DocumentData::loaded(FilePathResolveType type) const {
auto that = const_cast<DocumentData*>(this);
that->_location = FileLocation(_loader->fileName());
that->_data = _loader->bytes();
if (that->sticker() && !_loader->imagePixmap().isNull()) {
that->sticker()->img = ImagePtr(_data, _loader->imageFormat(), _loader->imagePixmap());
if (that->sticker() && !_loader->imageData().isNull()) {
that->sticker()->img = ImagePtr(_data, _loader->imageFormat(), _loader->imageData());
}
destroyLoaderDelayed();
}
@ -954,7 +954,7 @@ ImagePtr DocumentData::makeReplyPreview(Data::FileOrigin origin) {
auto options = Images::Option::Smooth | (isVideoMessage() ? Images::Option::Circled : Images::Option::None) | Images::Option::TransparentBackground;
auto outerSize = st::msgReplyBarSize.height();
auto image = thumb->pixNoCache(origin, thumbSize.width(), thumbSize.height(), options, outerSize, outerSize);
replyPreview = ImagePtr(image, "PNG");
replyPreview = ImagePtr(image.toImage(), "PNG");
} else {
thumb->load(origin);
}

View file

@ -354,15 +354,14 @@ bool MediaPhoto::updateSentMedia(const MTPMessageMedia &media) {
if (key.isNull() || image->isNull() || !image->loaded()) {
return;
}
if (image->savedData().isEmpty()) {
image->forget();
} else if (image->savedData().size() > Storage::kMaxFileInMemory) {
auto bytes = image->bytesForCache();
if (bytes.isEmpty() || bytes.size() > Storage::kMaxFileInMemory) {
return;
}
Auth().data().cache().putIfEmpty(
Data::StorageCacheKey(key),
Storage::Cache::Database::TaggedValue(
image->savedData(),
std::move(bytes),
Data::kImageCacheTag));
};
auto &sizes = photo.c_photo().vsizes.v;

View file

@ -195,6 +195,9 @@ ImagePtr PeerData::currentUserpic() const {
return _userpic;
}
}
if (!_userpicEmpty) {
refreshEmptyUserpic();
}
return ImagePtr();
}
@ -296,10 +299,9 @@ void PeerData::clearUserpic() {
auto image = Messenger::Instance().logoNoMargin().scaledToWidth(
kUserpicSize,
Qt::SmoothTransformation);
auto pixmap = App::pixmapFromImageInPlace(std::move(image));
return _userpic
? _userpic
: ImagePtr(std::move(pixmap), "PNG");
: ImagePtr(std::move(image), "PNG");
}
return ImagePtr();
}();

View file

@ -126,7 +126,8 @@ ImagePtr PhotoData::makeReplyPreview(Data::FileOrigin origin) {
origin,
w * st::msgReplyBarSize.height() / h,
st::msgReplyBarSize.height())
: image->pix(origin, st::msgReplyBarSize.height())),
: image->pix(origin, st::msgReplyBarSize.height())
).toImage(),
"PNG");
};
if (thumb->isDelayedStorageImage()

View file

@ -777,9 +777,9 @@ not_null<PhotoData*> Session::photo(const MTPDphoto &data) {
not_null<PhotoData*> Session::photo(
const MTPPhoto &data,
const PreparedPhotoThumbs &thumbs) {
auto thumb = (const QPixmap*)nullptr;
auto medium = (const QPixmap*)nullptr;
auto full = (const QPixmap*)nullptr;
auto thumb = (const QImage*)nullptr;
auto medium = (const QImage*)nullptr;
auto full = (const QImage*)nullptr;
auto thumbLevel = -1;
auto mediumLevel = -1;
auto fullLevel = -1;
@ -813,9 +813,9 @@ not_null<PhotoData*> Session::photo(
data.c_photo().vaccess_hash.v,
data.c_photo().vfile_reference.v,
data.c_photo().vdate.v,
ImagePtr(*thumb, "JPG"),
ImagePtr(*medium, "JPG"),
ImagePtr(*full, "JPG"));
ImagePtr(base::duplicate(*thumb), "JPG"),
ImagePtr(base::duplicate(*medium), "JPG"),
ImagePtr(base::duplicate(*full), "JPG"));
case mtpc_photoEmpty:
return photo(data.c_photoEmpty().vid.v);
@ -1013,7 +1013,7 @@ not_null<DocumentData*> Session::document(const MTPDdocument &data) {
not_null<DocumentData*> Session::document(
const MTPdocument &data,
const QPixmap &thumb) {
QImage &&thumb) {
switch (data.type()) {
case mtpc_documentEmpty:
return document(data.c_documentEmpty().vid.v);
@ -1027,7 +1027,7 @@ not_null<DocumentData*> Session::document(
fields.vdate.v,
fields.vattributes.v,
qs(fields.vmime_type),
ImagePtr(thumb, "JPG"),
ImagePtr(std::move(thumb), "JPG"),
fields.vdc_id.v,
fields.vsize.v,
StorageImageLocation());

View file

@ -269,7 +269,7 @@ public:
not_null<DocumentData*> document(const MTPDdocument &data);
not_null<DocumentData*> document(
const MTPdocument &data,
const QPixmap &thumb);
QImage &&thumb);
not_null<DocumentData*> document(
DocumentId id,
const uint64 &access,

View file

@ -294,7 +294,7 @@ using WebPageId = uint64;
using GameId = uint64;
constexpr auto CancelledWebPageId = WebPageId(0xFFFFFFFFFFFFFFFFULL);
using PreparedPhotoThumbs = QMap<char, QPixmap>;
using PreparedPhotoThumbs = QMap<char, QImage>;
// [0] == -1 -- counting, [0] == -2 -- could not count
using VoiceWaveform = QVector<signed char>;

View file

@ -127,6 +127,31 @@ FileLoader::FileLoader(
Expects(!_filename.isEmpty() || (_size <= Storage::kMaxFileInMemory));
}
void FileLoader::finishWithBytes(const QByteArray &data) {
_data = data;
_localStatus = LocalStatus::Loaded;
if (!_filename.isEmpty() && _toCache == LoadToCacheAsWell) {
if (!_fileIsOpen) _fileIsOpen = _file.open(QIODevice::WriteOnly);
if (!_fileIsOpen) {
cancel(true);
return;
}
if (_file.write(_data) != qint64(_data.size())) {
cancel(true);
return;
}
}
_finished = true;
if (_fileIsOpen) {
_file.close();
_fileIsOpen = false;
Platform::File::PostprocessDownloaded(
QFileInfo(_file).absoluteFilePath());
}
_downloader->taskFinished().notify();
}
QByteArray FileLoader::imageFormat(const QSize &shrinkBox) const {
if (_imageFormat.isEmpty() && _locationType == UnknownFileLocation) {
readImage(shrinkBox);
@ -134,11 +159,11 @@ QByteArray FileLoader::imageFormat(const QSize &shrinkBox) const {
return _imageFormat;
}
QPixmap FileLoader::imagePixmap(const QSize &shrinkBox) const {
if (_imagePixmap.isNull() && _locationType == UnknownFileLocation) {
QImage FileLoader::imageData(const QSize &shrinkBox) const {
if (_imageData.isNull() && _locationType == UnknownFileLocation) {
readImage(shrinkBox);
}
return _imagePixmap;
return _imageData;
}
void FileLoader::readImage(const QSize &shrinkBox) const {
@ -146,9 +171,9 @@ void FileLoader::readImage(const QSize &shrinkBox) const {
auto image = App::readImage(_data, &format, false);
if (!image.isNull()) {
if (!shrinkBox.isEmpty() && (image.width() > shrinkBox.width() || image.height() > shrinkBox.height())) {
_imagePixmap = App::pixmapFromImageInPlace(image.scaled(shrinkBox, Qt::KeepAspectRatio, Qt::SmoothTransformation));
_imageData = image.scaled(shrinkBox, Qt::KeepAspectRatio, Qt::SmoothTransformation);
} else {
_imagePixmap = App::pixmapFromImageInPlace(std::move(image));
_imageData = std::move(image);
}
_imageFormat = format;
}
@ -222,39 +247,18 @@ FileLoader::~FileLoader() {
void FileLoader::localLoaded(
const StorageImageSaved &result,
const QByteArray &imageFormat,
const QPixmap &imagePixmap) {
const QImage &imageData) {
_localLoading.kill();
if (result.data.isEmpty()) {
_localStatus = LocalStatus::NotFound;
start(true);
return;
}
_data = result.data;
if (!imagePixmap.isNull()) {
if (!imageData.isNull()) {
_imageFormat = imageFormat;
_imagePixmap = imagePixmap;
_imageData = imageData;
}
_localStatus = LocalStatus::Loaded;
if (!_filename.isEmpty() && _toCache == LoadToCacheAsWell) {
if (!_fileIsOpen) _fileIsOpen = _file.open(QIODevice::WriteOnly);
if (!_fileIsOpen) {
cancel(true);
return;
}
if (_file.write(_data) != qint64(_data.size())) {
cancel(true);
return;
}
}
_finished = true;
if (_fileIsOpen) {
_file.close();
_fileIsOpen = false;
Platform::File::PostprocessDownloaded(
QFileInfo(_file).absoluteFilePath());
}
_downloader->taskFinished().notify();
finishWithBytes(result.data);
emit progress(this);
@ -389,7 +393,7 @@ void FileLoader::loadLocal(const Storage::Cache::Key &key) {
localLoaded(
StorageImageSaved(std::move(value)),
format,
App::pixmapFromImageInPlace(std::move(image)));
std::move(image));
});
};
Auth().data().cache().get(key, [=, callback = std::move(done)](

View file

@ -84,6 +84,7 @@ public:
bool finished() const {
return _finished;
}
void finishWithBytes(const QByteArray &data);
bool cancelled() const {
return _cancelled;
}
@ -94,7 +95,7 @@ public:
return 0;
}
QByteArray imageFormat(const QSize &shrinkBox = QSize()) const;
QPixmap imagePixmap(const QSize &shrinkBox = QSize()) const;
QImage imageData(const QSize &shrinkBox = QSize()) const;
QString fileName() const {
return _filename;
}
@ -134,8 +135,8 @@ public:
void localLoaded(
const StorageImageSaved &result,
const QByteArray &imageFormat = QByteArray(),
const QPixmap &imagePixmap = QPixmap());
const QByteArray &imageFormat,
const QImage &imageData);
signals:
void progress(FileLoader *loader);
@ -191,7 +192,7 @@ protected:
base::binary_guard _localLoading;
mutable QByteArray _imageFormat;
mutable QPixmap _imagePixmap;
mutable QImage _imageData;
};

View file

@ -124,7 +124,9 @@ void Uploader::uploadMedia(const FullMsgId &msgId, const SendMediaReady &media)
} else if (media.type == SendMediaType::File || media.type == SendMediaType::Audio) {
const auto document = media.photoThumbs.isEmpty()
? Auth().data().document(media.document)
: Auth().data().document(media.document, media.photoThumbs.begin().value());
: Auth().data().document(
media.document,
base::duplicate(media.photoThumbs.begin().value()));
if (!media.data.isEmpty()) {
document->setData(media.data);
if (document->saveToCache()
@ -153,7 +155,9 @@ void Uploader::upload(
} else if (file->type == SendMediaType::File || file->type == SendMediaType::Audio) {
auto document = file->thumb.isNull()
? Auth().data().document(file->document)
: Auth().data().document(file->document, file->thumb);
: Auth().data().document(
file->document,
base::duplicate(file->thumb));
document->uploadingData = std::make_unique<Data::UploadState>(document->size);
if (!file->content.isEmpty()) {
document->setData(file->content);

View file

@ -31,26 +31,26 @@ SendMediaReady PreparePeerPhoto(PeerId peerId, QImage &&image) {
image.save(&jpegBuffer, "JPG", 87);
const auto scaled = [&](int size) {
return App::pixmapFromImageInPlace(image.scaled(
return image.scaled(
size,
size,
Qt::KeepAspectRatio,
Qt::SmoothTransformation));
Qt::SmoothTransformation);
};
const auto push = [&](const char *type, QPixmap &&pixmap) {
const auto push = [&](const char *type, QImage &&image) {
photoSizes.push_back(MTP_photoSize(
MTP_string(type),
MTP_fileLocationUnavailable(
MTP_long(0),
MTP_int(0),
MTP_long(0)),
MTP_int(pixmap.width()),
MTP_int(pixmap.height()), MTP_int(0)));
photoThumbs.insert(type[0], std::move(pixmap));
MTP_int(image.width()),
MTP_int(image.height()), MTP_int(0)));
photoThumbs.insert(type[0], std::move(image));
};
push("a", scaled(160));
push("b", scaled(320));
push("c", App::pixmapFromImageInPlace(std::move(image)));
push("c", std::move(image));
const auto id = rand_value<PhotoId>();
const auto photo = MTP_photo(
@ -531,7 +531,7 @@ void FileLoadTask::process() {
PreparedPhotoThumbs photoThumbs;
QVector<MTPPhotoSize> photoSizes;
QPixmap thumb;
QImage thumb;
QVector<MTPDocumentAttribute> attributes(1, MTP_documentAttributeFilename(MTP_string(filename)));
@ -552,7 +552,7 @@ void FileLoadTask::process() {
if (!song->cover.isNull()) { // cover to thumb
auto coverWidth = song->cover.width();
auto coverHeight = song->cover.height();
auto full = (coverWidth > 90 || coverHeight > 90) ? App::pixmapFromImageInPlace(song->cover.scaled(90, 90, Qt::KeepAspectRatio, Qt::SmoothTransformation)) : App::pixmapFromImageInPlace(std::move(song->cover));
auto full = (coverWidth > 90 || coverHeight > 90) ? song->cover.scaled(90, 90, Qt::KeepAspectRatio, Qt::SmoothTransformation) : std::move(song->cover);
{
auto thumbFormat = QByteArray("JPG");
auto thumbQuality = 87;
@ -588,10 +588,9 @@ void FileLoadTask::process() {
cover.save(&buffer, thumbFormat, thumbQuality);
}
thumb = App::pixmapFromImageInPlace(std::move(cover));
thumbSize = MTP_photoSize(MTP_string(""), MTP_fileLocationUnavailable(MTP_long(0), MTP_int(0), MTP_long(0)), MTP_int(thumb.width()), MTP_int(thumb.height()), MTP_int(0));
thumbId = rand_value<uint64>();
thumb = std::move(cover);
thumbSize = MTP_photoSize(MTP_string(""), MTP_fileLocationUnavailable(MTP_long(0), MTP_int(0), MTP_long(0)), MTP_int(thumb.width()), MTP_int(thumb.height()), MTP_int(0));
}
}
@ -603,15 +602,15 @@ void FileLoadTask::process() {
if (isAnimation) {
attributes.push_back(MTP_documentAttributeAnimated());
} else if (_type != SendMediaType::File) {
auto thumb = (w > 100 || h > 100) ? App::pixmapFromImageInPlace(fullimage.scaled(100, 100, Qt::KeepAspectRatio, Qt::SmoothTransformation)) : QPixmap::fromImage(fullimage);
auto thumb = (w > 100 || h > 100) ? fullimage.scaled(100, 100, Qt::KeepAspectRatio, Qt::SmoothTransformation) : fullimage;
photoThumbs.insert('s', thumb);
photoSizes.push_back(MTP_photoSize(MTP_string("s"), MTP_fileLocationUnavailable(MTP_long(0), MTP_int(0), MTP_long(0)), MTP_int(thumb.width()), MTP_int(thumb.height()), MTP_int(0)));
auto medium = (w > 320 || h > 320) ? App::pixmapFromImageInPlace(fullimage.scaled(320, 320, Qt::KeepAspectRatio, Qt::SmoothTransformation)) : QPixmap::fromImage(fullimage);
auto medium = (w > 320 || h > 320) ? fullimage.scaled(320, 320, Qt::KeepAspectRatio, Qt::SmoothTransformation) : fullimage;
photoThumbs.insert('m', medium);
photoSizes.push_back(MTP_photoSize(MTP_string("m"), MTP_fileLocationUnavailable(MTP_long(0), MTP_int(0), MTP_long(0)), MTP_int(medium.width()), MTP_int(medium.height()), MTP_int(0)));
auto full = (w > 1280 || h > 1280) ? App::pixmapFromImageInPlace(fullimage.scaled(1280, 1280, Qt::KeepAspectRatio, Qt::SmoothTransformation)) : QPixmap::fromImage(fullimage);
auto full = (w > 1280 || h > 1280) ? fullimage.scaled(1280, 1280, Qt::KeepAspectRatio, Qt::SmoothTransformation) : fullimage;
photoThumbs.insert('y', full);
photoSizes.push_back(MTP_photoSize(MTP_string("y"), MTP_fileLocationUnavailable(MTP_long(0), MTP_int(0), MTP_long(0)), MTP_int(full.width()), MTP_int(full.height()), MTP_int(0)));
@ -647,17 +646,13 @@ void FileLoadTask::process() {
thumbname = qsl("thumb.webp");
}
QPixmap full = (w > 90 || h > 90) ? App::pixmapFromImageInPlace(fullimage.scaled(90, 90, Qt::KeepAspectRatio, Qt::SmoothTransformation)) : QPixmap::fromImage(fullimage, Qt::ColorOnly);
thumbId = rand_value<uint64>();
thumb = (w > 90 || h > 90) ? fullimage.scaled(90, 90, Qt::KeepAspectRatio, Qt::SmoothTransformation) : fullimage;
thumbSize = MTP_photoSize(MTP_string(""), MTP_fileLocationUnavailable(MTP_long(0), MTP_int(0), MTP_long(0)), MTP_int(thumb.width()), MTP_int(thumb.height()), MTP_int(0));
{
QBuffer buffer(&thumbdata);
full.save(&buffer, thumbFormat, thumbQuality);
thumb.save(&buffer, thumbFormat, thumbQuality);
}
thumb = full;
thumbSize = MTP_photoSize(MTP_string(""), MTP_fileLocationUnavailable(MTP_long(0), MTP_int(0), MTP_long(0)), MTP_int(full.width()), MTP_int(full.height()), MTP_int(0));
thumbId = rand_value<uint64>();
}
}
@ -704,7 +699,7 @@ void FileLoadTask::process() {
_result->thumbId = thumbId;
_result->thumbname = thumbname;
_result->setThumbData(thumbdata);
_result->thumb = thumb;
_result->thumb = std::move(thumb);
_result->photo = photo;
_result->document = document;

View file

@ -214,7 +214,7 @@ struct FileLoadResult {
QString thumbname;
UploadFileParts thumbparts;
QByteArray thumbmd5;
QPixmap thumb;
QImage thumb;
MTPPhoto photo;
MTPDocument document;

File diff suppressed because it is too large Load diff

View file

@ -13,44 +13,363 @@ void ClearRemote();
void ClearAll();
void CheckCacheSize();
class Source {
public:
virtual ~Source();
virtual void load(
Data::FileOrigin origin,
bool loadFirst,
bool prior) = 0;
virtual void loadEvenCancelled(
Data::FileOrigin origin,
bool loadFirst,
bool prior) = 0;
virtual QImage takeLoaded() = 0;
virtual void forget() = 0;
virtual void automaticLoad(
Data::FileOrigin origin,
const HistoryItem *item) = 0;
virtual void automaticLoadSettingsChanged() = 0;
virtual bool loading() = 0;
virtual bool displayLoading() = 0;
virtual void cancel() = 0;
virtual float64 progress() = 0;
virtual int loadOffset() = 0;
virtual const StorageImageLocation &location() = 0;
virtual void refreshFileReference(const QByteArray &data) = 0;
virtual std::optional<Storage::Cache::Key> cacheKey() = 0;
virtual void setDelayedStorageLocation(
const StorageImageLocation &location) = 0;
virtual void performDelayedLoad(Data::FileOrigin origin) = 0;
virtual bool isDelayedStorageImage() const = 0;
virtual void setImageBytes(const QByteArray &bytes) = 0;
virtual int width() = 0;
virtual int height() = 0;
virtual void setInformation(int size, int width, int height) = 0;
virtual QByteArray bytesForCache() = 0;
};
class ImageSource : public Source {
public:
ImageSource(QImage &&data, const QByteArray &format);
void load(
Data::FileOrigin origin,
bool loadFirst,
bool prior) override;
void loadEvenCancelled(
Data::FileOrigin origin,
bool loadFirst,
bool prior) override;
QImage takeLoaded() override;
void forget() override;
void automaticLoad(
Data::FileOrigin origin,
const HistoryItem *item) override;
void automaticLoadSettingsChanged() override;
bool loading() override;
bool displayLoading() override;
void cancel() override;
float64 progress() override;
int loadOffset() override;
const StorageImageLocation &location() override;
void refreshFileReference(const QByteArray &data) override;
std::optional<Storage::Cache::Key> cacheKey() override;
void setDelayedStorageLocation(
const StorageImageLocation &location) override;
void performDelayedLoad(Data::FileOrigin origin) override;
bool isDelayedStorageImage() const override;
void setImageBytes(const QByteArray &bytes) override;
int width() override;
int height() override;
void setInformation(int size, int width, int height) override;
QByteArray bytesForCache() override;
private:
QImage _data;
QByteArray _format;
};
class LocalFileSource : public Source {
public:
LocalFileSource(
const QString &path,
const QByteArray &content,
const QByteArray &format,
QImage &&data = QImage());
void load(
Data::FileOrigin origin,
bool loadFirst,
bool prior) override;
void loadEvenCancelled(
Data::FileOrigin origin,
bool loadFirst,
bool prior) override;
QImage takeLoaded() override;
void forget() override;
void automaticLoad(
Data::FileOrigin origin,
const HistoryItem *item) override;
void automaticLoadSettingsChanged() override;
bool loading() override;
bool displayLoading() override;
void cancel() override;
float64 progress() override;
int loadOffset() override;
const StorageImageLocation &location() override;
void refreshFileReference(const QByteArray &data) override;
std::optional<Storage::Cache::Key> cacheKey() override;
void setDelayedStorageLocation(
const StorageImageLocation &location) override;
void performDelayedLoad(Data::FileOrigin origin) override;
bool isDelayedStorageImage() const override;
void setImageBytes(const QByteArray &bytes) override;
int width() override;
int height() override;
void setInformation(int size, int width, int height) override;
QByteArray bytesForCache() override;
private:
void ensureDimensionsKnown();
QString _path;
QByteArray _bytes;
QByteArray _format;
QImage _data;
int _width = 0;
int _height = 0;
};
class RemoteSource : public Source {
public:
void load(
Data::FileOrigin origin,
bool loadFirst,
bool prior) override;
void loadEvenCancelled(
Data::FileOrigin origin,
bool loadFirst,
bool prior) override;
QImage takeLoaded() override;
void forget() override;
void automaticLoad(
Data::FileOrigin origin,
const HistoryItem *item) override;
void automaticLoadSettingsChanged() override;
bool loading() override;
bool displayLoading() override;
void cancel() override;
float64 progress() override;
int loadOffset() override;
const StorageImageLocation &location() override;
void refreshFileReference(const QByteArray &data) override;
void setDelayedStorageLocation(
const StorageImageLocation &location) override;
void performDelayedLoad(Data::FileOrigin origin) override;
bool isDelayedStorageImage() const override;
void setImageBytes(const QByteArray &bytes) override;
QByteArray bytesForCache() override;
~RemoteSource();
protected:
// If after loading the image we need to shrink it to fit into a
// specific size, you can return this size here.
virtual QSize shrinkBox() const = 0;
virtual FileLoader *createLoader(
Data::FileOrigin origin,
LoadFromCloudSetting fromCloud,
bool autoLoading) = 0;
void loadLocal();
private:
bool loaderValid() const;
void destroyLoaderDelayed(FileLoader *newValue = nullptr);
FileLoader *_loader = nullptr;
};
class StorageSource : public RemoteSource {
public:
StorageSource(
const StorageImageLocation &location,
int size);
const StorageImageLocation &location() override;
std::optional<Storage::Cache::Key> cacheKey() override;
void refreshFileReference(const QByteArray &data) override;
int width() override;
int height() override;
void setInformation(int size, int width, int height) override;
protected:
QSize shrinkBox() const override;
FileLoader *createLoader(
Data::FileOrigin origin,
LoadFromCloudSetting fromCloud,
bool autoLoading) override;
StorageImageLocation _location;
int _size = 0;
};
class WebCachedSource : public RemoteSource {
public:
WebCachedSource(const WebFileLocation &location, QSize box, int size = 0);
WebCachedSource(
const WebFileLocation &location,
int width,
int height,
int size = 0);
std::optional<Storage::Cache::Key> cacheKey() override;
int width() override;
int height() override;
void setInformation(int size, int width, int height) override;
protected:
QSize shrinkBox() const override;
FileLoader *createLoader(
Data::FileOrigin origin,
LoadFromCloudSetting fromCloud,
bool autoLoading) override;
WebFileLocation _location;
QSize _box;
int _width = 0;
int _height = 0;
int _size = 0;
};
class GeoPointSource : public RemoteSource {
public:
GeoPointSource(const GeoPointLocation &location);
std::optional<Storage::Cache::Key> cacheKey() override;
int width() override;
int height() override;
void setInformation(int size, int width, int height) override;
protected:
QSize shrinkBox() const override;
FileLoader *createLoader(
Data::FileOrigin origin,
LoadFromCloudSetting fromCloud,
bool autoLoading) override;
GeoPointLocation _location;
int _size = 0;
};
class DelayedStorageSource : public StorageSource {
public:
DelayedStorageSource();
DelayedStorageSource(int width, int height);
void load(
Data::FileOrigin origin,
bool loadFirst,
bool prior) override;
void loadEvenCancelled(
Data::FileOrigin origin,
bool loadFirst,
bool prior) override;
void setDelayedStorageLocation(
const StorageImageLocation &location) override;
bool isDelayedStorageImage() const override;
void performDelayedLoad(Data::FileOrigin origin) override;
void automaticLoad(
Data::FileOrigin origin,
const HistoryItem *item) override; // auto load photo
void automaticLoadSettingsChanged() override;
bool loading() override {
return _location.isNull() ? _loadRequested : StorageSource::loading();
}
bool displayLoading() override;
void cancel() override;
private:
bool _loadRequested = false;
bool _loadCancelled = false;
bool _loadFromCloud = false;
};
class WebUrlSource : public RemoteSource {
public:
// If !box.isEmpty() then resize the image to fit in this box.
explicit WebUrlSource(const QString &url, QSize box = QSize());
WebUrlSource(const QString &url, int width, int height);
std::optional<Storage::Cache::Key> cacheKey() override;
int width() override;
int height() override;
void setInformation(int size, int width, int height) override;
protected:
QSize shrinkBox() const override;
FileLoader *createLoader(
Data::FileOrigin origin,
LoadFromCloudSetting fromCloud,
bool autoLoading) override;
private:
QString _url;
QSize _box;
int _size = 0;
int _width = 0;
int _height = 0;
};
} // namespace Images
class HistoryItem;
class Image {
class Image final {
public:
Image(const QString &file, QByteArray format = QByteArray());
Image(const QByteArray &filecontent, QByteArray format = QByteArray());
Image(const QPixmap &pixmap, QByteArray format = QByteArray());
Image(const QByteArray &filecontent, QByteArray format, const QPixmap &pixmap);
explicit Image(std::unique_ptr<Images::Source> &&source);
static Image *Blank();
virtual void automaticLoad(
Data::FileOrigin origin,
const HistoryItem *item) {
}
virtual void automaticLoadSettingsChanged() {
}
virtual bool loaded() const {
return true;
}
virtual bool loading() const {
return false;
}
virtual bool displayLoading() const {
return false;
}
virtual void cancel() {
}
virtual float64 progress() const {
return 1;
}
virtual int32 loadOffset() const {
return 0;
}
const QPixmap &pix(
Data::FileOrigin origin,
int32 w = 0,
@ -120,285 +439,85 @@ public:
int32 w,
int32 h = 0) const;
int32 width() const {
return qMax(countWidth(), 1);
void automaticLoad(Data::FileOrigin origin, const HistoryItem *item) {
if (!loaded()) {
_source->automaticLoad(origin, item);
}
int32 height() const {
return qMax(countHeight(), 1);
}
virtual void load(
Data::FileOrigin origin,
bool loadFirst = false,
bool prior = true) {
void automaticLoadSettingsChanged() {
_source->automaticLoadSettingsChanged();
}
virtual void loadEvenCancelled(
Data::FileOrigin origin,
bool loadFirst = false,
bool prior = true) {
bool loading() const {
return _source->loading();
}
virtual const StorageImageLocation &location() const {
return StorageImageLocation::Null;
bool displayLoading() const {
return _source->displayLoading();
}
virtual std::optional<Storage::Cache::Key> cacheKey() const;
bool isNull() const;
void forget() const;
QByteArray savedFormat() const {
return _format;
void cancel() {
_source->cancel();
}
QByteArray savedData() const {
return _saved;
float64 progress() const {
return loaded() ? 1. : _source->progress();
}
virtual void setDelayedStorageLocation(
Data::FileOrigin origin,
const StorageImageLocation location) {
};
virtual bool isDelayedStorageImage() const {
return false;
int loadOffset() const {
return _source->loadOffset();
}
virtual ~Image();
protected:
Image(QByteArray format = "PNG") : _format(format) {
int width() const {
return _source->width();
}
void restore() const;
virtual void checkload() const {
int height() const {
return _source->height();
}
void invalidateSizeCache() const;
virtual int32 countWidth() const {
restore();
return _data.width();
void setInformation(int size, int width, int height) {
_source->setInformation(size, width, height);
}
virtual int32 countHeight() const {
restore();
return _data.height();
}
mutable QByteArray _saved, _format;
mutable bool _forgot = false;
mutable QPixmap _data;
private:
using Sizes = QMap<uint64, QPixmap>;
mutable Sizes _sizesCache;
};
class RemoteImage : public Image {
public:
void automaticLoad(
Data::FileOrigin origin,
const HistoryItem *item) override; // auto load photo
void automaticLoadSettingsChanged() override;
bool loaded() const override;
bool loading() const override {
return amLoading();
}
bool displayLoading() const override;
void cancel() override;
float64 progress() const override;
int32 loadOffset() const override;
void setImageBytes(
const QByteArray &bytes,
const QByteArray &format = QByteArray());
void load(
Data::FileOrigin origin,
bool loadFirst = false,
bool prior = true) override;
bool prior = true) {
if (!loaded()) {
_source->load(origin, loadFirst, prior);
}
}
void loadEvenCancelled(
Data::FileOrigin origin,
bool loadFirst = false,
bool prior = true) override;
~RemoteImage();
protected:
// If after loading the image we need to shrink it to fit into a
// specific size, you can return this size here.
virtual QSize shrinkBox() const {
return QSize();
bool prior = true) {
if (!loaded()) {
_source->loadEvenCancelled(origin, loadFirst, prior);
}
virtual void setInformation(int32 size, int32 width, int32 height) = 0;
virtual FileLoader *createLoader(
Data::FileOrigin origin,
LoadFromCloudSetting fromCloud,
bool autoLoading) = 0;
void checkload() const override {
doCheckload();
}
void loadLocal();
private:
mutable FileLoader *_loader = nullptr;
bool amLoading() const;
void doCheckload() const;
void destroyLoaderDelayed(FileLoader *newValue = nullptr) const;
};
class StorageImage : public RemoteImage {
public:
explicit StorageImage(const StorageImageLocation &location, int32 size = 0);
StorageImage(const StorageImageLocation &location, const QByteArray &bytes);
const StorageImageLocation &location() const override {
return _location;
const StorageImageLocation &location() const {
return _source->location();
}
std::optional<Storage::Cache::Key> cacheKey() const override;
void refreshFileReference(const QByteArray &data) {
_location.refreshFileReference(data);
_source->refreshFileReference(data);
}
std::optional<Storage::Cache::Key> cacheKey() const;
QByteArray bytesForCache() const {
return _source->bytesForCache();
}
bool isDelayedStorageImage() const {
return _source->isDelayedStorageImage();
}
protected:
void setInformation(int32 size, int32 width, int32 height) override;
FileLoader *createLoader(
Data::FileOrigin origin,
LoadFromCloudSetting fromCloud,
bool autoLoading) override;
int32 countWidth() const override;
int32 countHeight() const override;
StorageImageLocation _location;
int32 _size;
};
class WebFileImage : public RemoteImage {
public:
WebFileImage(const WebFileLocation &location, QSize box, int size = 0);
WebFileImage(
const WebFileLocation &location,
int width,
int height,
int size = 0);
std::optional<Storage::Cache::Key> cacheKey() const override;
protected:
void setInformation(int size, int width, int height) override;
FileLoader *createLoader(
Data::FileOrigin origin,
LoadFromCloudSetting fromCloud,
bool autoLoading) override;
QSize shrinkBox() const override {
return _box;
}
int countWidth() const override;
int countHeight() const override;
WebFileLocation _location;
QSize _box;
int _width = 0;
int _height = 0;
int _size = 0;
};
class GeoPointImage : public RemoteImage {
public:
GeoPointImage(const GeoPointLocation &location);
std::optional<Storage::Cache::Key> cacheKey() const override;
protected:
void setInformation(int size, int width, int height) override;
FileLoader *createLoader(
Data::FileOrigin origin,
LoadFromCloudSetting fromCloud,
bool autoLoading) override;
int countWidth() const override;
int countHeight() const override;
GeoPointLocation _location;
int _size = 0;
};
class DelayedStorageImage : public StorageImage {
public:
DelayedStorageImage();
DelayedStorageImage(int32 w, int32 h);
//DelayedStorageImage(QByteArray &bytes);
bool loaded() const;
bool isNull() const;
void forget() const;
void setDelayedStorageLocation(
Data::FileOrigin origin,
const StorageImageLocation location) override;
bool isDelayedStorageImage() const override {
return true;
}
const StorageImageLocation &location);
void setImageBytes(const QByteArray &bytes);
void automaticLoad(
Data::FileOrigin origin,
const HistoryItem *item) override; // auto load photo
void automaticLoadSettingsChanged() override;
bool loading() const override {
return _location.isNull() ? _loadRequested : StorageImage::loading();
}
bool displayLoading() const override;
void cancel() override;
void load(
Data::FileOrigin origin,
bool loadFirst = false,
bool prior = true) override;
void loadEvenCancelled(
Data::FileOrigin origin,
bool loadFirst = false,
bool prior = true) override;
~Image();
private:
bool _loadRequested, _loadCancelled, _loadFromCloud;
void checkSource() const;
void invalidateSizeCache() const;
};
class WebImage : public RemoteImage {
public:
// If !box.isEmpty() then resize the image to fit in this box.
WebImage(const QString &url, QSize box = QSize());
WebImage(const QString &url, int width, int height);
void setSize(int width, int height);
std::optional<Storage::Cache::Key> cacheKey() const override;
protected:
QSize shrinkBox() const override {
return _box;
}
void setInformation(int32 size, int32 width, int32 height) override;
FileLoader *createLoader(
Data::FileOrigin origin,
LoadFromCloudSetting fromCloud,
bool autoLoading) override;
int32 countWidth() const override;
int32 countHeight() const override;
private:
QString _url;
QSize _box;
int32 _size, _width, _height;
std::unique_ptr<Images::Source> _source;
mutable QMap<uint64, QPixmap> _sizesCache;
mutable QImage _data;
};
@ -409,28 +528,28 @@ Image *Create(const QString &file, QByteArray format);
Image *Create(const QString &url, QSize box);
Image *Create(const QString &url, int width, int height);
Image *Create(const QByteArray &filecontent, QByteArray format);
Image *Create(const QPixmap &pixmap, QByteArray format);
Image *Create(QImage &&data, QByteArray format);
Image *Create(
const QByteArray &filecontent,
QByteArray format,
const QPixmap &pixmap);
Image *Create(int32 width, int32 height);
StorageImage *Create(const StorageImageLocation &location, int size = 0);
StorageImage *Create( // photoCachedSize
QImage &&data);
Image *Create(int width, int height);
Image *Create(const StorageImageLocation &location, int size = 0);
Image *Create( // photoCachedSize
const StorageImageLocation &location,
const QByteArray &bytes);
Image *Create(const MTPWebDocument &location);
Image *Create(const MTPWebDocument &location, QSize box);
WebFileImage *Create(
Image *Create(
const WebFileLocation &location,
int width,
int height,
int size = 0);
WebFileImage *Create(
Image *Create(
const WebFileLocation &location,
QSize box,
int size = 0);
GeoPointImage *Create(
Image *Create(
const GeoPointLocation &location);
} // namespace details

View file

@ -389,12 +389,12 @@ ImagePtr::ImagePtr(const QByteArray &filecontent, QByteArray format)
ImagePtr::ImagePtr(
const QByteArray &filecontent,
QByteArray format,
const QPixmap &pixmap)
: _data(Images::details::Create(filecontent, format, pixmap)) {
QImage &&data)
: _data(Images::details::Create(filecontent, format, std::move(data))) {
}
ImagePtr::ImagePtr(const QPixmap &pixmap, QByteArray format)
: _data(Images::details::Create(pixmap, format)) {
ImagePtr::ImagePtr(QImage &&data, QByteArray format)
: _data(Images::details::Create(std::move(data), format)) {
}
ImagePtr::ImagePtr(const StorageImageLocation &location, int32 size)

View file

@ -287,8 +287,8 @@ public:
ImagePtr(const QString &url, QSize box);
ImagePtr(const QString &url, int width, int height);
ImagePtr(const QByteArray &filecontent, QByteArray format = QByteArray());
ImagePtr(const QByteArray &filecontent, QByteArray format, const QPixmap &pixmap);
ImagePtr(const QPixmap &pixmap, QByteArray format);
ImagePtr(const QByteArray &filecontent, QByteArray format, QImage &&data);
ImagePtr(QImage &&data, QByteArray format);
ImagePtr(const StorageImageLocation &location, int32 size = 0);
ImagePtr(const StorageImageLocation &location, const QByteArray &bytes);
ImagePtr(const MTPWebDocument &location);