diff --git a/Telegram/CMakeLists.txt b/Telegram/CMakeLists.txt index dde955df3..c28db4566 100644 --- a/Telegram/CMakeLists.txt +++ b/Telegram/CMakeLists.txt @@ -510,6 +510,7 @@ PRIVATE dialogs/dialogs_widget.h editor/photo_editor.cpp editor/photo_editor.h + editor/photo_editor_common.cpp editor/photo_editor_common.h editor/photo_editor_content.cpp editor/photo_editor_content.h diff --git a/Telegram/SourceFiles/boxes/send_files_box.cpp b/Telegram/SourceFiles/boxes/send_files_box.cpp index f5fc45e5e..b5467f542 100644 --- a/Telegram/SourceFiles/boxes/send_files_box.cpp +++ b/Telegram/SourceFiles/boxes/send_files_box.cpp @@ -976,6 +976,9 @@ void SendFilesBox::send( for (auto &block : _blocks) { block.applyAlbumOrder(); } + + Storage::ApplyModifications(_list); + _confirmed = true; if (_confirmedCallback) { auto caption = (_caption && !_caption->isHidden()) diff --git a/Telegram/SourceFiles/editor/photo_editor.cpp b/Telegram/SourceFiles/editor/photo_editor.cpp index 270176eec..4191c7cdb 100644 --- a/Telegram/SourceFiles/editor/photo_editor.cpp +++ b/Telegram/SourceFiles/editor/photo_editor.cpp @@ -46,4 +46,12 @@ PhotoEditor::PhotoEditor( }, lifetime()); } +void PhotoEditor::save() { + _done.fire_copy(_modifications); +} + +rpl::producer PhotoEditor::done() const { + return _done.events(); +} + } // namespace Editor diff --git a/Telegram/SourceFiles/editor/photo_editor.h b/Telegram/SourceFiles/editor/photo_editor.h index ad07bf390..30efacca7 100644 --- a/Telegram/SourceFiles/editor/photo_editor.h +++ b/Telegram/SourceFiles/editor/photo_editor.h @@ -24,6 +24,9 @@ public: not_null parent, std::shared_ptr photo); + void save(); + rpl::producer done() const; + private: PhotoModifications _modifications; @@ -31,6 +34,8 @@ private: base::unique_qptr _content; base::unique_qptr _controls; + rpl::event_stream _done; + }; } // namespace Editor diff --git a/Telegram/SourceFiles/editor/photo_editor_common.cpp b/Telegram/SourceFiles/editor/photo_editor_common.cpp new file mode 100644 index 000000000..67813ecd2 --- /dev/null +++ b/Telegram/SourceFiles/editor/photo_editor_common.cpp @@ -0,0 +1,26 @@ +/* +This file is part of Telegram Desktop, +the official desktop application for the Telegram messaging service. + +For license and copyright information please follow this link: +https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL +*/ +#include "editor/photo_editor_common.h" + +namespace Editor { + +QImage ImageModified(QImage image, const PhotoModifications &mods) { + if (!mods) { + return image; + } + QTransform transform; + if (mods.flipped) { + transform.scale(-1, 1); + } + if (mods.angle) { + transform.rotate(mods.angle); + } + return image.transformed(transform); +} + +} // namespace Editor diff --git a/Telegram/SourceFiles/editor/photo_editor_common.h b/Telegram/SourceFiles/editor/photo_editor_common.h index 3a83db0c9..245f3259a 100644 --- a/Telegram/SourceFiles/editor/photo_editor_common.h +++ b/Telegram/SourceFiles/editor/photo_editor_common.h @@ -12,6 +12,18 @@ namespace Editor { struct PhotoModifications { int angle = 0; bool flipped = false; + + [[nodiscard]] bool empty() const { + return !angle && !flipped; + } + [[nodiscard]] explicit operator bool() const { + return !empty(); + } + }; +[[nodiscard]] QImage ImageModified( + QImage image, + const PhotoModifications &mods); + } // namespace Editor diff --git a/Telegram/SourceFiles/storage/storage_media_prepare.cpp b/Telegram/SourceFiles/storage/storage_media_prepare.cpp index 3a8f6f61c..e2dad21e8 100644 --- a/Telegram/SourceFiles/storage/storage_media_prepare.cpp +++ b/Telegram/SourceFiles/storage/storage_media_prepare.cpp @@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "storage/storage_media_prepare.h" +#include "editor/photo_editor_common.h" #include "platform/platform_file_utilities.h" #include "storage/localimageloader.h" #include "core/mime_type.h" @@ -25,6 +26,8 @@ using Ui::PreparedFileInformation; using Ui::PreparedFile; using Ui::PreparedList; +using Image = PreparedFileInformation::Image; + bool HasExtensionFrom(const QString &file, const QStringList &extensions) { for (const auto &extension : extensions) { const auto ext = file.right(extension.size()); @@ -36,7 +39,7 @@ bool HasExtensionFrom(const QString &file, const QStringList &extensions) { } bool ValidPhotoForAlbum( - const PreparedFileInformation::Image &image, + const Image &image, const QString &mime) { if (image.animated || Core::IsMimeSticker(mime) @@ -262,19 +265,12 @@ void PrepareDetails(PreparedFile &file, int previewWidth) { Assert(file.information != nullptr); } - using Image = PreparedFileInformation::Image; using Video = PreparedFileInformation::Video; using Song = PreparedFileInformation::Song; if (const auto image = std::get_if( &file.information->media)) { if (ValidPhotoForAlbum(*image, file.information->filemime)) { - file.shownDimensions = PrepareShownDimensions(image->data); - file.preview = Images::prepareOpaque(image->data.scaledToWidth( - std::min(previewWidth, style::ConvertScale(image->data.width())) - * cIntRetinaFactor(), - Qt::SmoothTransformation)); - Assert(!file.preview.isNull()); - file.preview.setDevicePixelRatio(cRetinaFactor()); + UpdateImageDetails(file, previewWidth); file.type = PreparedFile::Type::Photo; } else if (Core::IsMimeSticker(file.information->filemime)) { file.type = PreparedFile::Type::None; @@ -296,5 +292,34 @@ void PrepareDetails(PreparedFile &file, int previewWidth) { } } +void UpdateImageDetails(PreparedFile &file, int previewWidth) { + const auto image = std::get_if(&file.information->media); + if (!image) { + return; + } + const auto &preview = image->modifications + ? Editor::ImageModified(image->data, image->modifications) + : image->data; + file.shownDimensions = PrepareShownDimensions(preview); + file.preview = Images::prepareOpaque(preview.scaledToWidth( + std::min(previewWidth, style::ConvertScale(preview.width())) + * cIntRetinaFactor(), + Qt::SmoothTransformation)); + Assert(!file.preview.isNull()); + file.preview.setDevicePixelRatio(cRetinaFactor()); +} + +void ApplyModifications(const PreparedList &list) { + for (auto &file : list.files) { + const auto image = std::get_if(&file.information->media); + if (!image || !image->modifications) { + continue; + } + image->data = Editor::ImageModified( + std::move(image->data), + image->modifications); + } +} + } // namespace Storage diff --git a/Telegram/SourceFiles/storage/storage_media_prepare.h b/Telegram/SourceFiles/storage/storage_media_prepare.h index e2c02553f..f4e158922 100644 --- a/Telegram/SourceFiles/storage/storage_media_prepare.h +++ b/Telegram/SourceFiles/storage/storage_media_prepare.h @@ -42,5 +42,8 @@ Ui::PreparedList PrepareMediaFromImage( QByteArray &&content, int previewWidth); void PrepareDetails(Ui::PreparedFile &file, int previewWidth); +void UpdateImageDetails(Ui::PreparedFile &file, int previewWidth); + +void ApplyModifications(const Ui::PreparedList &list); } // namespace Storage diff --git a/Telegram/SourceFiles/ui/chat/attach/attach_prepare.h b/Telegram/SourceFiles/ui/chat/attach/attach_prepare.h index fe7d5251d..55891753a 100644 --- a/Telegram/SourceFiles/ui/chat/attach/attach_prepare.h +++ b/Telegram/SourceFiles/ui/chat/attach/attach_prepare.h @@ -7,6 +7,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once +#include "editor/photo_editor_common.h" + #include #include @@ -18,6 +20,7 @@ struct PreparedFileInformation { struct Image { QImage data; bool animated = false; + Editor::PhotoModifications modifications; }; struct Song { int duration = -1; diff --git a/Telegram/SourceFiles/ui/chat/attach/attach_single_media_preview.cpp b/Telegram/SourceFiles/ui/chat/attach/attach_single_media_preview.cpp index ca4a3cffe..36ab993d5 100644 --- a/Telegram/SourceFiles/ui/chat/attach/attach_single_media_preview.cpp +++ b/Telegram/SourceFiles/ui/chat/attach/attach_single_media_preview.cpp @@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "ui/chat/attach/attach_single_media_preview.h" +#include "editor/photo_editor_common.h" #include "ui/chat/attach/attach_prepare.h" #include "ui/widgets/buttons.h" #include "core/mime_type.h" @@ -32,7 +33,7 @@ SingleMediaPreview *SingleMediaPreview::Create( bool animationPreview = false; if (const auto image = std::get_if( &file.information->media)) { - preview = image->data; + preview = Editor::ImageModified(image->data, image->modifications); animated = animationPreview = image->animated; } else if (const auto video = std::get_if( &file.information->media)) {