From 06b04343c64919312e81225a8a3ef4dabc43182c Mon Sep 17 00:00:00 2001 From: Chong Kai Xiong Date: Wed, 29 Jan 2025 19:38:32 +0800 Subject: [PATCH] Core (LV::Video): Introduce LV::ImageFormat enum for identifying image formats. --- libvisual/libvisual/lv_video.cpp | 79 +++++++++++++------ libvisual/libvisual/lv_video.h | 22 +++++- .../tests/video_test/video_save_test.cpp | 6 +- 3 files changed, 78 insertions(+), 29 deletions(-) diff --git a/libvisual/libvisual/lv_video.cpp b/libvisual/libvisual/lv_video.cpp index cbb8fac6..a073d5b4 100644 --- a/libvisual/libvisual/lv_video.cpp +++ b/libvisual/libvisual/lv_video.cpp @@ -29,6 +29,7 @@ #include "lv_color.h" #include "lv_common.h" #include "lv_cpu.h" +#include "private/lv_string_hash.hpp" #include "private/lv_video_private.hpp" #include "private/lv_video_blit.hpp" #include "private/lv_video_convert.hpp" @@ -42,7 +43,10 @@ #include #include #include +#include +#include #include +#include namespace LV { @@ -50,25 +54,45 @@ namespace LV { namespace { - using BitmapLoad = std::function; - using BitmapSave = std::function; + using BitmapReader = std::function; + using BitmapWriter = std::function; - std::unordered_map const bitmap_load_map = + struct ImageFormatInfo { - { "bmp", bitmap_load_bmp }, - { "png", bitmap_load_png } + std::string name; + BitmapReader reader; + BitmapWriter writer; + std::vector extensions; }; - std::unordered_map const bitmap_save_map = + using FormatExtensionLookup = std::unordered_map>; + + std::unordered_map const supported_image_formats { - { "png", bitmap_save_png } + {ImageFormat::BMP, {"BMP", bitmap_load_bmp, nullptr, {".bmp"}}}, + {ImageFormat::PNG, {"PNG", bitmap_load_png, bitmap_save_png, {".png"}}} }; - std::unordered_map const bitmap_format_extension_map = + FormatExtensionLookup build_image_format_extension_lookup () { - { ".png", "png" }, - { ".bmp", "bmp" } - }; + FormatExtensionLookup map; + + for (auto const& entry : supported_image_formats) + for (auto const& extension : entry.second.extensions) + map.emplace (extension, entry.first); + + return map; + } + + std::optional find_image_format_by_extension (std::string_view extension) + { + static auto const lookup {build_image_format_extension_lookup ()}; + + auto match {lookup.find (extension)}; + if (match == lookup.end ()) + return std::nullopt; + return match->second; + } bool is_valid_scale_method (VisVideoScaleMethod scale_method) { @@ -227,10 +251,12 @@ namespace LV { VideoPtr Video::create_from_stream (std::istream& input) { - for (auto entry : bitmap_load_map) { - auto image {entry.second (input)}; - if (image) { - return image; + for (auto entry : supported_image_formats) { + if (entry.second.reader) { + auto image {entry.second.reader (input)}; + if (image) { + return image; + } } } @@ -298,8 +324,8 @@ namespace LV { auto extension {fs::path {path}.extension ()}; auto extension_lower (to_lower_ascii (extension.string ())); - auto entry {bitmap_format_extension_map.find (extension_lower)}; - if (entry == bitmap_format_extension_map.end ()) { + auto format {find_image_format_by_extension (extension_lower)}; + if (!format.has_value ()) { visual_log (VISUAL_LOG_ERROR, "Could not deduce format from filename (%s)", path.c_str ()); return false; } @@ -310,19 +336,24 @@ namespace LV { return false; } - return save_to_stream (output, entry->second); + return save_to_stream (output, format.value ()); } - bool Video::save_to_stream (std::ostream& output, std::string const& format) const + bool Video::save_to_stream (std::ostream& output, ImageFormat format) const { - auto entry {bitmap_save_map.find (format)}; - if (entry == bitmap_save_map.end ()) { - std::string format_str {format}; - visual_log (VISUAL_LOG_ERROR, "Saving to %s format is not supported", format_str.c_str ()); + auto entry {supported_image_formats.find (format)}; + + if (entry == supported_image_formats.end ()) { + visual_log (VISUAL_LOG_ERROR, "Saving to unknown format (%d).", static_cast (format)); + return false; + } + + if (!entry->second.writer) { + visual_log (VISUAL_LOG_ERROR, "Saving to %s is unsupported.", entry->second.name.c_str ()); return false; } - return entry->second (*this, output); + return entry->second.writer (*this, output); } void Video::copy_attrs (VideoConstPtr const& src) diff --git a/libvisual/libvisual/lv_video.h b/libvisual/libvisual/lv_video.h index 1c4589ff..3c1f3fec 100644 --- a/libvisual/libvisual/lv_video.h +++ b/libvisual/libvisual/lv_video.h @@ -96,6 +96,14 @@ typedef enum { VISUAL_VIDEO_COMPOSE_TYPE_CUSTOM /**< Custom compose function (looks up on the source VisVideo. */ } VisVideoComposeType; +/** + * The set of known and supported image formats. + */ +typedef enum { + VISUAL_IMAGE_FORMAT_BMP = 0, + VISUAL_IMAGE_FORMAT_PNG +} VisImageFormat; + typedef struct _VisVideoAttrOptions VisVideoAttrOptions; #ifdef __cplusplus @@ -125,6 +133,15 @@ struct _VisVideoAttrOptions { namespace LV { + /** + * The set of known and supported image formats. + */ + enum class ImageFormat + { + BMP = VISUAL_IMAGE_FORMAT_BMP, + PNG = VISUAL_IMAGE_FORMAT_PNG + }; + class Video; typedef IntrusivePtr