aboutsummaryrefslogtreecommitdiff
path: root/src/AsyncImageLoader.cpp
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2021-08-08 10:48:55 +0200
committerdec05eba <dec05eba@protonmail.com>2021-08-08 10:48:55 +0200
commit23ab8cc08d2d6281ef56c184f1e1e905e70a2a22 (patch)
treedf1c2d59db08da7ea12e9359b7583e622a8ff0f2 /src/AsyncImageLoader.cpp
parent244ee01df48d702ff126a73ee36911b43adfdba8 (diff)
Matrix: fix thumbnail upload of small thumbnails, fix small thumbnail creation if webp
Diffstat (limited to 'src/AsyncImageLoader.cpp')
-rw-r--r--src/AsyncImageLoader.cpp52
1 files changed, 46 insertions, 6 deletions
diff --git a/src/AsyncImageLoader.cpp b/src/AsyncImageLoader.cpp
index ccf9f42..a871078 100644
--- a/src/AsyncImageLoader.cpp
+++ b/src/AsyncImageLoader.cpp
@@ -10,6 +10,8 @@
#include <sys/prctl.h>
#include <sys/stat.h>
#include <sys/wait.h>
+#include <sys/sendfile.h>
+#include <fcntl.h>
#include <signal.h>
#include <malloc.h>
#include <assert.h>
@@ -24,7 +26,7 @@ namespace QuickMedia {
return exec_program(args, nullptr, nullptr) == 0;
}
- bool create_thumbnail(const Path &thumbnail_path, const Path &thumbnail_path_resized, sf::Vector2i resize_target_size, ContentType content_type) {
+ bool create_thumbnail(const Path &thumbnail_path, const Path &thumbnail_path_resized, sf::Vector2i resize_target_size, ContentType content_type, bool symlink_if_no_resize) {
Path input_path = thumbnail_path;
if(content_type == ContentType::IMAGE_WEBP) {
@@ -62,10 +64,47 @@ namespace QuickMedia {
result_path_tmp.append(".tmp.png");
if(image.getSize().x <= (unsigned int)resize_target_size.x && image.getSize().y <= (unsigned int)resize_target_size.y) {
- int res = symlink(input_path.data.c_str(), result_path_tmp.data.c_str());
- if(res == -1 && errno != EEXIST) {
- fprintf(stderr, "Failed to save %s\n", thumbnail_path_resized.data.c_str());
- _exit(1);
+ if(content_type == ContentType::IMAGE_WEBP) {
+ if(rename_atomic(input_path.data.c_str(), thumbnail_path_resized.data.c_str()) == 0)
+ _exit(0);
+ else
+ _exit(1);
+ } else if(symlink_if_no_resize) {
+ int res = symlink(thumbnail_path.data.c_str(), result_path_tmp.data.c_str());
+ if(res == -1 && errno != EEXIST) {
+ fprintf(stderr, "Failed to symlink %s to %s\n", thumbnail_path_resized.data.c_str(), thumbnail_path.data.c_str());
+ _exit(1);
+ }
+ } else {
+ // TODO: When mac is supported (or other OS than linux), then fix this for them. Mac for example needs fcopyfile instead of sendfile
+ int input_file = open(thumbnail_path.data.c_str(), O_RDONLY);
+ if(input_file == -1) {
+ fprintf(stderr, "Failed to save %s\n", thumbnail_path_resized.data.c_str());
+ _exit(1);
+ }
+
+ int output_file = creat(result_path_tmp.data.c_str(), 0660);
+ if(output_file == -1) {
+ fprintf(stderr, "Failed to save %s\n", thumbnail_path_resized.data.c_str());
+ _exit(1);
+ }
+
+ off_t bytes_copied = 0;
+ struct stat file_stat;
+ memset(&file_stat, 0, sizeof(file_stat));
+ if(fstat(input_file, &file_stat) == -1) {
+ fprintf(stderr, "Failed to save %s\n", thumbnail_path_resized.data.c_str());
+ _exit(1);
+ }
+
+ // No need to retry, small files
+ if(sendfile(output_file, input_file, &bytes_copied, file_stat.st_size) == -1) {
+ fprintf(stderr, "Failed to save %s\n", thumbnail_path_resized.data.c_str());
+ _exit(1);
+ }
+
+ close(input_file);
+ close(output_file);
}
} else {
sf::Vector2u clamped_size = clamp_to_size(image.getSize(), sf::Vector2u(resize_target_size.x, resize_target_size.y));
@@ -121,7 +160,7 @@ namespace QuickMedia {
return;
}
- if(create_thumbnail(thumbnail_path, thumbnail_path_resized, resize_target_size, file_analyzer.get_content_type())) {
+ if(create_thumbnail(thumbnail_path, thumbnail_path_resized, resize_target_size, file_analyzer.get_content_type(), true)) {
load_image_from_file(*thumbnail_data->image, thumbnail_path_resized.data);
} else {
load_image_from_file(*thumbnail_data->image, thumbnail_path.data);
@@ -198,6 +237,7 @@ namespace QuickMedia {
Path thumbnail_path = get_cache_dir().join("thumbnails").join(sha256.getHash());
if(local) {
struct stat file_stat;
+ memset(&file_stat, 0, sizeof(file_stat));
if(stat(url.c_str(), &file_stat) != 0 || !S_ISREG(file_stat.st_mode)) {
thumbnail_data->image = std::make_unique<sf::Image>();
thumbnail_data->loading_state = LoadingState::FINISHED_LOADING;