aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2021-04-30 16:33:07 +0200
committerdec05eba <dec05eba@protonmail.com>2021-04-30 16:33:07 +0200
commit47bb22a4aee886deb54ca432bdb14747bf2e9160 (patch)
tree57f4cff63872f70b6d60bf098cb46879bccc3251 /src
parentc89ffb842054de24e2ad8020d9df81da55e3e574 (diff)
Support webp thumbnails
Diffstat (limited to 'src')
-rw-r--r--src/AsyncImageLoader.cpp25
-rw-r--r--src/FileAnalyzer.cpp10
-rw-r--r--src/plugins/Matrix.cpp2
-rw-r--r--src/plugins/Youtube.cpp15
4 files changed, 41 insertions, 11 deletions
diff --git a/src/AsyncImageLoader.cpp b/src/AsyncImageLoader.cpp
index 34df062..6504992 100644
--- a/src/AsyncImageLoader.cpp
+++ b/src/AsyncImageLoader.cpp
@@ -1,5 +1,4 @@
#include "../include/AsyncImageLoader.hpp"
-#include "../include/FileAnalyzer.hpp"
#include "../include/DownloadUtils.hpp"
#include "../include/Program.hpp"
#include "../include/ImageUtils.hpp"
@@ -11,18 +10,34 @@
#include <assert.h>
namespace QuickMedia {
- bool create_thumbnail(const Path &thumbnail_path, const Path &thumbnail_path_resized, sf::Vector2i resize_target_size) {
+ bool create_thumbnail(const Path &thumbnail_path, const Path &thumbnail_path_resized, sf::Vector2i resize_target_size, ContentType content_type) {
+ Path input_path = thumbnail_path;
+
+ // TODO: Remove this when imagemagick supports webp
+ // Convert webp to png
+ if(content_type == ContentType::IMAGE_WEBP) {
+ Path result_path_tmp = input_path;
+ result_path_tmp.append(".tmp.png");
+
+ const char *args[] = { "ffmpeg", "-y", "-v", "quiet", "-i", input_path.data.c_str(), "--", result_path_tmp.data.c_str(), nullptr};
+ int res = exec_program(args, nullptr, nullptr);
+ if(res != 0)
+ return false;
+
+ input_path = std::move(result_path_tmp);
+ }
+
// > is to only shrink image if smaller than the target size
std::string new_size = std::to_string(resize_target_size.x) + "x" + std::to_string(resize_target_size.y) + ">";
// We only want the first frame if its a gif
- Path thumbnail_path_first_frame = thumbnail_path;
+ Path thumbnail_path_first_frame = std::move(input_path);
thumbnail_path_first_frame.append("[0]");
Path result_path_tmp = thumbnail_path_resized;
result_path_tmp.append(".tmp");
- const char *args[] = { "convert", thumbnail_path_first_frame.data.c_str(), "-thumbnail", new_size.c_str(), result_path_tmp.data.c_str(), nullptr};
+ const char *args[] = { "convert", thumbnail_path_first_frame.data.c_str(), "-thumbnail", new_size.c_str(), result_path_tmp.data.c_str(), nullptr};
int convert_res = exec_program(args, nullptr, nullptr);
if(convert_res == 0 && rename_atomic(result_path_tmp.data.c_str(), thumbnail_path_resized.data.c_str()) == 0)
return true;
@@ -46,7 +61,7 @@ namespace QuickMedia {
return;
}
- if(create_thumbnail(thumbnail_path, thumbnail_path_resized, resize_target_size)) {
+ if(create_thumbnail(thumbnail_path, thumbnail_path_resized, resize_target_size, file_analyzer.get_content_type())) {
load_image_from_file(*thumbnail_data->image, thumbnail_path_resized.data);
} else {
load_image_from_file(*thumbnail_data->image, thumbnail_path.data);
diff --git a/src/FileAnalyzer.cpp b/src/FileAnalyzer.cpp
index 9f05919..bd13a01 100644
--- a/src/FileAnalyzer.cpp
+++ b/src/FileAnalyzer.cpp
@@ -21,7 +21,7 @@ namespace QuickMedia {
// What about audio ogg files that are not opus?
// TODO: Test all of these
- static const std::array<MagicNumber, 25> magic_numbers = {
+ static const std::array<MagicNumber, 26> magic_numbers = {
MagicNumber{ {'R', 'I', 'F', 'F', -1, -1, -1, -1, 'A', 'V', 'I', ' '}, 12, ContentType::VIDEO_AVI },
MagicNumber{ {0x00, 0x00, 0x00, -1, 'f', 't', 'y', 'p', 'i', 's', 'o', 'm'}, 12, ContentType::VIDEO_MP4 },
MagicNumber{ {0x00, 0x00, 0x00, -1, 'f', 't', 'y', 'p', 'm', 'p', '4', '2'}, 12, ContentType::VIDEO_MP4 },
@@ -47,7 +47,8 @@ namespace QuickMedia {
MagicNumber{ {'G', 'I', 'F', '8', '7', 'a'}, 6, ContentType::IMAGE_GIF },
MagicNumber{ {'G', 'I', 'F', '8', '9', 'a'}, 6, ContentType::IMAGE_GIF },
MagicNumber{ {'B', 'M'}, 2, ContentType::IMAGE_BMP },
- MagicNumber{ {'R', 'I', 'F', 'F', -1, -1, -1, -1, 'W', 'E', 'B', 'V', 'P'}, 6, ContentType::IMAGE_WEBP }
+ MagicNumber{ {'R', 'I', 'F', 'F', -1, -1, -1, -1, 'W', 'E', 'B', 'P'}, 12, ContentType::IMAGE_WEBP },
+ MagicNumber{ {'R', 'I', 'F', 'F', -1, -1, -1, -1, 'W', 'E', 'B', 'V', 'P'}, 13, ContentType::IMAGE_WEBP }
};
bool is_content_type_video(ContentType content_type) {
@@ -121,7 +122,7 @@ namespace QuickMedia {
Path destination_path_tmp = destination_path;
destination_path_tmp.append(".ftmp");
- const char *program_args[] = { "ffmpeg", "-y", "-v", "quiet", "-i", filepath, "-vframes", "1", "-f", "singlejpeg", destination_path_tmp.data.c_str(), nullptr };
+ const char *program_args[] = { "ffmpeg", "-y", "-v", "quiet", "-i", filepath, "-vframes", "1", "-f", "singlejpeg", "--", destination_path_tmp.data.c_str(), nullptr };
std::string ffmpeg_result;
if(exec_program(program_args, nullptr, nullptr) != 0) {
fprintf(stderr, "Failed to execute ffmpeg, maybe its not installed?\n");
@@ -129,7 +130,8 @@ namespace QuickMedia {
}
if(width > 0 && height > 0) {
- if(create_thumbnail(destination_path_tmp, destination_path, sf::Vector2i(width, height))) {
+ FileAnalyzer file_analyzer;
+ if(file_analyzer.load_file(destination_path_tmp.data.c_str(), false) && create_thumbnail(destination_path_tmp, destination_path, sf::Vector2i(width, height), file_analyzer.get_content_type())) {
remove(destination_path_tmp.data.c_str());
return true;
}
diff --git a/src/plugins/Matrix.cpp b/src/plugins/Matrix.cpp
index 77d8f32..6f8b30b 100644
--- a/src/plugins/Matrix.cpp
+++ b/src/plugins/Matrix.cpp
@@ -3278,7 +3278,7 @@ namespace QuickMedia {
int tmp_file = mkstemp(tmp_filename);
if(tmp_file != -1) {
std::string thumbnail_path;
- if(create_thumbnail(filepath, tmp_filename, thumbnail_max_size))
+ if(create_thumbnail(filepath, tmp_filename, thumbnail_max_size, file_analyzer.get_content_type()))
thumbnail_path = tmp_filename;
else
thumbnail_path = filepath;
diff --git a/src/plugins/Youtube.cpp b/src/plugins/Youtube.cpp
index 993c861..cf3bbe4 100644
--- a/src/plugins/Youtube.cpp
+++ b/src/plugins/Youtube.cpp
@@ -53,10 +53,10 @@ namespace QuickMedia {
enum class ThumbnailSize {
SMALLEST,
+ MEDIUM,
LARGEST
};
- // TODO: Use this in |parse_common_video_item| when QuickMedia supports webp
static std::optional<Thumbnail> yt_json_get_thumbnail(const Json::Value &thumbnail_json, ThumbnailSize thumbnail_size) {
if(!thumbnail_json.isObject())
return std::nullopt;
@@ -85,6 +85,9 @@ namespace QuickMedia {
thumbnails.push_back({ url_json.asCString(), width_json.asInt(), height_json.asInt() });
}
+ if(thumbnails.empty())
+ return std::nullopt;
+
switch(thumbnail_size) {
case ThumbnailSize::SMALLEST:
return *std::min_element(thumbnails.begin(), thumbnails.end(), [](const Thumbnail &thumbnail1, const Thumbnail &thumbnail2) {
@@ -92,6 +95,14 @@ namespace QuickMedia {
int size2 = thumbnail2.width * thumbnail2.height;
return size1 < size2;
});
+ case ThumbnailSize::MEDIUM: {
+ std::sort(thumbnails.begin(), thumbnails.end(), [](const Thumbnail &thumbnail1, const Thumbnail &thumbnail2) {
+ int size1 = thumbnail1.width * thumbnail1.height;
+ int size2 = thumbnail2.width * thumbnail2.height;
+ return size1 < size2;
+ });
+ return thumbnails[thumbnails.size() / 2];
+ }
case ThumbnailSize::LARGEST:
return *std::max_element(thumbnails.begin(), thumbnails.end(), [](const Thumbnail &thumbnail1, const Thumbnail &thumbnail2) {
int size1 = thumbnail1.width * thumbnail1.height;
@@ -184,8 +195,10 @@ namespace QuickMedia {
body_item->set_description_color(sf::Color(179, 179, 179));
if(scheduled_text.empty())
body_item->url = "https://www.youtube.com/watch?v=" + video_id_str;
+
body_item->thumbnail_url = "https://img.youtube.com/vi/" + video_id_str + "/hqdefault.jpg";
body_item->thumbnail_size = sf::Vector2i(175, 131);
+
added_videos.insert(video_id_str);
return body_item;
}