diff options
Diffstat (limited to 'src/AsyncImageLoader.cpp')
-rw-r--r-- | src/AsyncImageLoader.cpp | 65 |
1 files changed, 37 insertions, 28 deletions
diff --git a/src/AsyncImageLoader.cpp b/src/AsyncImageLoader.cpp index 4661960..c1d4aab 100644 --- a/src/AsyncImageLoader.cpp +++ b/src/AsyncImageLoader.cpp @@ -3,7 +3,6 @@ #include "../include/Program.hpp" #include "../include/ImageUtils.hpp" #include "../include/Scale.hpp" -#include "../include/SfmlFixes.hpp" #include "../include/Utils.hpp" #include "../external/hash-library/sha256.h" @@ -22,13 +21,16 @@ #define STB_IMAGE_RESIZE_IMPLEMENTATION #include "../external/stb/stb_image_resize.h" +#define STB_IMAGE_WRITE_IMPLEMENTATION +#include "../external/stb/stb_image_write.h" + namespace QuickMedia { static bool webp_to_png(const Path &thumbnail_path, const Path &destination_path) { const char *args[] = { "ffmpeg", "-y", "-v", "quiet", "-i", thumbnail_path.data.c_str(), "--", destination_path.data.c_str(), nullptr}; 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 symlink_if_no_resize) { + bool create_thumbnail(const Path &thumbnail_path, const Path &thumbnail_path_resized, mgl::vec2i resize_target_size, ContentType content_type, bool symlink_if_no_resize) { Path input_path = thumbnail_path; if(content_type == ContentType::IMAGE_WEBP) { @@ -56,8 +58,8 @@ namespace QuickMedia { if(getppid() != parent_pid) _exit(127); - sf::Image image; - if(!image.loadFromFile(input_path.data) || image.getSize().x == 0 || image.getSize().y == 0) { + mgl::Image image; + if(!image.load_from_file(input_path.data.c_str()) || image.get_size().x == 0 || image.get_size().y == 0) { fprintf(stderr, "Failed to load %s\n", input_path.data.c_str()); _exit(1); } @@ -65,7 +67,7 @@ namespace QuickMedia { Path result_path_tmp = thumbnail_path_resized; 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) { + if(image.get_size().x <= resize_target_size.x && image.get_size().y <= resize_target_size.y) { if(content_type == ContentType::IMAGE_WEBP) { if(rename_atomic(input_path.data.c_str(), thumbnail_path_resized.data.c_str()) == 0) _exit(0); @@ -109,17 +111,24 @@ namespace QuickMedia { close(output_file); } } else { - sf::Vector2u clamped_size = clamp_to_size(image.getSize(), sf::Vector2u(resize_target_size.x, resize_target_size.y)); - unsigned char *output_pixels = new unsigned char[clamped_size.x * clamped_size.y * 4]; - stbir_resize_uint8(image.getPixelsPtr(), image.getSize().x, image.getSize().y, 0, output_pixels, clamped_size.x, clamped_size.y, 0, 4); - - // TODO: Remove this and use stb write to remove this unecessary extra copy of the data and write the data directly to file after converting it to png - sf::Image destination_image; - destination_image.create(clamped_size.x, clamped_size.y, output_pixels); - if(!destination_image.saveToFile(result_path_tmp.data)) { - fprintf(stderr, "Failed to save %s\n", thumbnail_path_resized.data.c_str()); - _exit(1); + mgl::vec2i clamped_size = clamp_to_size(image.get_size(), mgl::vec2i(resize_target_size.x, resize_target_size.y)); + unsigned char *output_pixels = new unsigned char[clamped_size.x * clamped_size.y * image.get_num_channels()]; + stbir_resize_uint8(image.data(), image.get_size().x, image.get_size().y, 0, output_pixels, clamped_size.x, clamped_size.y, 0, image.get_num_channels()); + + if(image.get_num_channels() == 4) { + if(!stbi_write_png(result_path_tmp.data.c_str(), clamped_size.x, clamped_size.y, 4, output_pixels, 0)) { + fprintf(stderr, "Failed to save %s\n", thumbnail_path_resized.data.c_str()); + _exit(1); + } + } else { + if(!stbi_write_jpg(result_path_tmp.data.c_str(), clamped_size.x, clamped_size.y, image.get_num_channels(), output_pixels, 0)) { + fprintf(stderr, "Failed to save %s\n", thumbnail_path_resized.data.c_str()); + _exit(1); + } } + + // TODO: Resize and save to dxt format which can be loaded faster, uses less memory during loading (since no conversion is needed to upload to gpu), + // it uses less memory while in gpu (because its in dxt compressed format) and it gives better rendering performance because of compressed image = smaller = better cache utilization. } if(rename_atomic(result_path_tmp.data.c_str(), thumbnail_path_resized.data.c_str()) == 0) @@ -147,11 +156,11 @@ namespace QuickMedia { return true; } - void AsyncImageLoader::load_create_thumbnail(const Path &thumbnail_path, const Path &thumbnail_path_resized, ThumbnailData *thumbnail_data, sf::Vector2i resize_target_size) { + void AsyncImageLoader::load_create_thumbnail(const Path &thumbnail_path, const Path &thumbnail_path_resized, ThumbnailData *thumbnail_data, mgl::vec2i resize_target_size) { FileAnalyzer file_analyzer; if(!file_analyzer.load_file(thumbnail_path.data.c_str(), false)) { fprintf(stderr, "Failed to convert %s to a thumbnail\n", thumbnail_path.data.c_str()); - thumbnail_data->image = std::make_unique<sf::Image>(); + thumbnail_data->image = std::make_unique<mgl::Image>(); thumbnail_data->loading_state = LoadingState::FINISHED_LOADING; return; } @@ -161,7 +170,7 @@ namespace QuickMedia { thumbnail_data->loading_state = LoadingState::READY_TO_LOAD; } else { fprintf(stderr, "Failed to get first frame of %s\n", thumbnail_path.data.c_str()); - thumbnail_data->image = std::make_unique<sf::Image>(); + thumbnail_data->image = std::make_unique<mgl::Image>(); thumbnail_data->loading_state = LoadingState::FINISHED_LOADING; } return; @@ -171,7 +180,7 @@ namespace QuickMedia { thumbnail_data->loading_state = LoadingState::READY_TO_LOAD; } else { fprintf(stderr, "Failed to convert %s to a thumbnail\n", thumbnail_path.data.c_str()); - thumbnail_data->image = std::make_unique<sf::Image>(); + thumbnail_data->image = std::make_unique<mgl::Image>(); thumbnail_data->loading_state = LoadingState::FINISHED_LOADING; } } @@ -190,7 +199,7 @@ namespace QuickMedia { if(get_file_type(thumbnail_path_resized) == FileType::REGULAR) { fprintf(stderr, "Loaded %s from thumbnail cache\n", thumbnail_path_resized.data.c_str()); - thumbnail_load_data.thumbnail_data->image = std::make_unique<sf::Image>(); + thumbnail_load_data.thumbnail_data->image = std::make_unique<mgl::Image>(); thumbnail_load_data.thumbnail_data->loading_state = LoadingState::READY_TO_LOAD; return; } @@ -208,14 +217,14 @@ namespace QuickMedia { } static void load_processed_thumbnail(ThumbnailLoadData &thumbnail_load_data) { - thumbnail_load_data.thumbnail_data->image = std::make_unique<sf::Image>(); + thumbnail_load_data.thumbnail_data->image = std::make_unique<mgl::Image>(); Path thumbnail_path_resized = thumbnail_load_data.thumbnail_path; if(thumbnail_load_data.resize_target_size.x != 0 && thumbnail_load_data.resize_target_size.y != 0) thumbnail_path_resized.append("_" + std::to_string(thumbnail_load_data.resize_target_size.x) + "x" + std::to_string(thumbnail_load_data.resize_target_size.y)); if(get_file_type(thumbnail_path_resized) == FileType::REGULAR) { - load_image_from_file(*thumbnail_load_data.thumbnail_data->image, thumbnail_path_resized.data); + thumbnail_load_data.thumbnail_data->image->load_from_file(thumbnail_path_resized.data.c_str()); thumbnail_load_data.thumbnail_data->loading_state = LoadingState::FINISHED_LOADING; return; } @@ -227,10 +236,10 @@ namespace QuickMedia { thumbnail_original_path = thumbnail_load_data.thumbnail_path; if(thumbnail_load_data.resize_target_size.x != 0 && thumbnail_load_data.resize_target_size.y != 0) { - load_image_from_file(*thumbnail_load_data.thumbnail_data->image, thumbnail_path_resized.data); + thumbnail_load_data.thumbnail_data->image->load_from_file(thumbnail_path_resized.data.c_str()); thumbnail_load_data.thumbnail_data->loading_state = LoadingState::FINISHED_LOADING; } else { - load_image_from_file(*thumbnail_load_data.thumbnail_data->image, thumbnail_original_path.data); + thumbnail_load_data.thumbnail_data->image->load_from_file(thumbnail_original_path.data.c_str()); thumbnail_load_data.thumbnail_data->loading_state = LoadingState::FINISHED_LOADING; } } @@ -304,12 +313,12 @@ namespace QuickMedia { return exec_program_pipe(args, read_program) == 0; } - bool AsyncImageLoader::load_thumbnail(const std::string &url, bool local, sf::Vector2i resize_target_size, std::shared_ptr<ThumbnailData> thumbnail_data, Path &thumbnail_path) { + bool AsyncImageLoader::load_thumbnail(const std::string &url, bool local, mgl::vec2i resize_target_size, std::shared_ptr<ThumbnailData> thumbnail_data, Path &thumbnail_path) { if(thumbnail_data->loading_state != LoadingState::NOT_LOADED) return true; if(url.empty()) { - thumbnail_data->image = std::make_unique<sf::Image>(); + thumbnail_data->image = std::make_unique<mgl::Image>(); thumbnail_data->loading_state = LoadingState::FINISHED_LOADING; return false; } @@ -319,7 +328,7 @@ namespace QuickMedia { memset(&file_stat, 0, sizeof(file_stat)); if(stat(url.c_str(), &file_stat) != 0 || !S_ISREG(file_stat.st_mode)) { fprintf(stderr, "Failed to load thumbnail %s: no such file\n", url.c_str()); - thumbnail_data->image = std::make_unique<sf::Image>(); + thumbnail_data->image = std::make_unique<mgl::Image>(); thumbnail_data->loading_state = LoadingState::FINISHED_LOADING; return false; } @@ -357,7 +366,7 @@ namespace QuickMedia { return true; } - std::shared_ptr<ThumbnailData> AsyncImageLoader::get_thumbnail(const std::string &url, bool local, sf::Vector2i resize_target_size) { + std::shared_ptr<ThumbnailData> AsyncImageLoader::get_thumbnail(const std::string &url, bool local, mgl::vec2i resize_target_size) { // TODO: Instead of generating a new hash everytime to access thumbnail, cache the hash of the thumbnail url auto &thumbnail_data = thumbnails[url]; if(!thumbnail_data) |