Added util functions to process photo and document as dynamic images.

This commit is contained in:
23rd 2024-10-18 12:10:13 +03:00
parent bbdcb047d0
commit c857c24a64
2 changed files with 67 additions and 27 deletions

View file

@ -61,7 +61,7 @@ private:
class StoryThumbnail : public DynamicImage { class StoryThumbnail : public DynamicImage {
public: public:
explicit StoryThumbnail(FullStoryId id); explicit StoryThumbnail(Data::FileOrigin origin, bool forceRound);
QImage image(int size) override; QImage image(int size) override;
void subscribeToUpdates(Fn<void()> callback) override; void subscribeToUpdates(Fn<void()> callback) override;
@ -72,14 +72,16 @@ protected:
bool blurred = false; bool blurred = false;
}; };
[[nodiscard]] FullStoryId id() const; [[nodiscard]] Data::FileOrigin origin() const;
[[nodiscard]] bool forceRound() const;
[[nodiscard]] virtual Main::Session &session() = 0; [[nodiscard]] virtual Main::Session &session() = 0;
[[nodiscard]] virtual Thumb loaded(FullStoryId id) = 0; [[nodiscard]] virtual Thumb loaded(Data::FileOrigin origin) = 0;
virtual void clear() = 0; virtual void clear() = 0;
private: private:
const FullStoryId _id; const Data::FileOrigin _origin;
const bool _forceRound;
QImage _full; QImage _full;
rpl::lifetime _subscription; rpl::lifetime _subscription;
QImage _prepared; QImage _prepared;
@ -89,13 +91,16 @@ private:
class PhotoThumbnail final : public StoryThumbnail { class PhotoThumbnail final : public StoryThumbnail {
public: public:
PhotoThumbnail(not_null<PhotoData*> photo, FullStoryId id); PhotoThumbnail(
not_null<PhotoData*> photo,
Data::FileOrigin origin,
bool forceRound);
std::shared_ptr<DynamicImage> clone() override; std::shared_ptr<DynamicImage> clone() override;
private: private:
Main::Session &session() override; Main::Session &session() override;
Thumb loaded(FullStoryId id) override; Thumb loaded(Data::FileOrigin origin) override;
void clear() override; void clear() override;
const not_null<PhotoData*> _photo; const not_null<PhotoData*> _photo;
@ -105,13 +110,16 @@ private:
class VideoThumbnail final : public StoryThumbnail { class VideoThumbnail final : public StoryThumbnail {
public: public:
VideoThumbnail(not_null<DocumentData*> video, FullStoryId id); VideoThumbnail(
not_null<DocumentData*> video,
Data::FileOrigin origin,
bool forceRound);
std::shared_ptr<DynamicImage> clone() override; std::shared_ptr<DynamicImage> clone() override;
private: private:
Main::Session &session() override; Main::Session &session() override;
Thumb loaded(FullStoryId id) override; Thumb loaded(Data::FileOrigin origin) override;
void clear() override; void clear() override;
const not_null<DocumentData*> _video; const not_null<DocumentData*> _video;
@ -296,8 +304,9 @@ void PeerUserpic::processNewPhoto() {
}, _subscribed->downloadLifetime); }, _subscribed->downloadLifetime);
} }
StoryThumbnail::StoryThumbnail(FullStoryId id) StoryThumbnail::StoryThumbnail(Data::FileOrigin origin, bool forceRound)
: _id(id) { : _origin(origin)
, _forceRound(forceRound) {
} }
QImage StoryThumbnail::image(int size) { QImage StoryThumbnail::image(int size) {
@ -316,7 +325,9 @@ QImage StoryThumbnail::image(int size) {
Qt::IgnoreAspectRatio, Qt::IgnoreAspectRatio,
Qt::SmoothTransformation); Qt::SmoothTransformation);
} }
_prepared = Images::Circle(std::move(_prepared)); if (_forceRound) {
_prepared = Images::Circle(std::move(_prepared));
}
_prepared.setDevicePixelRatio(ratio); _prepared.setDevicePixelRatio(ratio);
} }
return _prepared; return _prepared;
@ -330,7 +341,7 @@ void StoryThumbnail::subscribeToUpdates(Fn<void()> callback) {
} else if (!_full.isNull() && !_blurred) { } else if (!_full.isNull() && !_blurred) {
return; return;
} }
const auto thumbnail = loaded(_id); const auto thumbnail = loaded(_origin);
if (const auto image = thumbnail.image) { if (const auto image = thumbnail.image) {
_full = image->original(); _full = image->original();
} }
@ -340,7 +351,7 @@ void StoryThumbnail::subscribeToUpdates(Fn<void()> callback) {
} else { } else {
_subscription = session().downloaderTaskFinished( _subscription = session().downloaderTaskFinished(
) | rpl::filter([=] { ) | rpl::filter([=] {
const auto thumbnail = loaded(_id); const auto thumbnail = loaded(_origin);
if (!thumbnail.blurred) { if (!thumbnail.blurred) {
_full = thumbnail.image->original(); _full = thumbnail.image->original();
_prepared = QImage(); _prepared = QImage();
@ -352,27 +363,34 @@ void StoryThumbnail::subscribeToUpdates(Fn<void()> callback) {
} }
} }
FullStoryId StoryThumbnail::id() const { Data::FileOrigin StoryThumbnail::origin() const {
return _id; return _origin;
} }
PhotoThumbnail::PhotoThumbnail(not_null<PhotoData*> photo, FullStoryId id) bool StoryThumbnail::forceRound() const {
: StoryThumbnail(id) return _forceRound;
}
PhotoThumbnail::PhotoThumbnail(
not_null<PhotoData*> photo,
Data::FileOrigin origin,
bool forceRound)
: StoryThumbnail(origin, forceRound)
, _photo(photo) { , _photo(photo) {
} }
std::shared_ptr<DynamicImage> PhotoThumbnail::clone() { std::shared_ptr<DynamicImage> PhotoThumbnail::clone() {
return std::make_shared<PhotoThumbnail>(_photo, id()); return std::make_shared<PhotoThumbnail>(_photo, origin(), forceRound());
} }
Main::Session &PhotoThumbnail::session() { Main::Session &PhotoThumbnail::session() {
return _photo->session(); return _photo->session();
} }
StoryThumbnail::Thumb PhotoThumbnail::loaded(FullStoryId id) { StoryThumbnail::Thumb PhotoThumbnail::loaded(Data::FileOrigin origin) {
if (!_media) { if (!_media) {
_media = _photo->createMediaView(); _media = _photo->createMediaView();
_media->wanted(Data::PhotoSize::Small, id); _media->wanted(Data::PhotoSize::Small, origin);
} }
if (const auto small = _media->image(Data::PhotoSize::Small)) { if (const auto small = _media->image(Data::PhotoSize::Small)) {
return { .image = small }; return { .image = small };
@ -386,23 +404,24 @@ void PhotoThumbnail::clear() {
VideoThumbnail::VideoThumbnail( VideoThumbnail::VideoThumbnail(
not_null<DocumentData*> video, not_null<DocumentData*> video,
FullStoryId id) Data::FileOrigin origin,
: StoryThumbnail(id) bool forceRound)
: StoryThumbnail(origin, forceRound)
, _video(video) { , _video(video) {
} }
std::shared_ptr<DynamicImage> VideoThumbnail::clone() { std::shared_ptr<DynamicImage> VideoThumbnail::clone() {
return std::make_shared<VideoThumbnail>(_video, id()); return std::make_shared<VideoThumbnail>(_video, origin(), forceRound());
} }
Main::Session &VideoThumbnail::session() { Main::Session &VideoThumbnail::session() {
return _video->session(); return _video->session();
} }
StoryThumbnail::Thumb VideoThumbnail::loaded(FullStoryId id) { StoryThumbnail::Thumb VideoThumbnail::loaded(Data::FileOrigin origin) {
if (!_media) { if (!_media) {
_media = _video->createMediaView(); _media = _video->createMediaView();
_media->thumbnailWanted(id); _media->thumbnailWanted(origin);
} }
if (const auto small = _media->thumbnail()) { if (const auto small = _media->thumbnail()) {
return { .image = small }; return { .image = small };
@ -634,9 +653,9 @@ std::shared_ptr<DynamicImage> MakeStoryThumbnail(
return v::match(story->media().data, [](v::null_t) -> Result { return v::match(story->media().data, [](v::null_t) -> Result {
return std::make_shared<EmptyThumbnail>(); return std::make_shared<EmptyThumbnail>();
}, [&](not_null<PhotoData*> photo) -> Result { }, [&](not_null<PhotoData*> photo) -> Result {
return std::make_shared<PhotoThumbnail>(photo, id); return std::make_shared<PhotoThumbnail>(photo, id, true);
}, [&](not_null<DocumentData*> video) -> Result { }, [&](not_null<DocumentData*> video) -> Result {
return std::make_shared<VideoThumbnail>(video, id); return std::make_shared<VideoThumbnail>(video, id, true);
}); });
} }
@ -650,4 +669,16 @@ std::shared_ptr<DynamicImage> MakeEmojiThumbnail(
return std::make_shared<EmojiThumbnail>(owner, data); return std::make_shared<EmojiThumbnail>(owner, data);
} }
std::shared_ptr<DynamicImage> MakePhotoThumbnail(
not_null<PhotoData*> photo,
FullMsgId fullId) {
return std::make_shared<PhotoThumbnail>(photo, fullId, false);
}
std::shared_ptr<DynamicImage> MakeDocumentThumbnail(
not_null<DocumentData*> document,
FullMsgId fullId) {
return std::make_shared<VideoThumbnail>(document, fullId, false);
}
} // namespace Ui } // namespace Ui

View file

@ -7,7 +7,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#pragma once #pragma once
class DocumentData;
class PeerData; class PeerData;
class PhotoData;
namespace Data { namespace Data {
class Story; class Story;
@ -32,4 +34,11 @@ class DynamicImage;
not_null<Data::Session*> owner, not_null<Data::Session*> owner,
const QString &data); const QString &data);
[[nodiscard]] std::shared_ptr<DynamicImage> MakePhotoThumbnail(
not_null<PhotoData*> photo,
FullMsgId fullId);
[[nodiscard]] std::shared_ptr<DynamicImage> MakeDocumentThumbnail(
not_null<DocumentData*> document,
FullMsgId fullId);
} // namespace Ui } // namespace Ui