2929#include " lv_color.h"
3030#include " lv_common.h"
3131#include " lv_cpu.h"
32+ #include " private/lv_string_hash.hpp"
3233#include " private/lv_video_private.hpp"
3334#include " private/lv_video_blit.hpp"
3435#include " private/lv_video_convert.hpp"
4243#include < filesystem>
4344#include < fstream>
4445#include < functional>
46+ #include < optional>
47+ #include < string>
4548#include < unordered_map>
49+ #include < vector>
4650
4751namespace LV {
4852
4953 namespace fs = std::filesystem;
5054
5155 namespace {
5256
53- using BitmapLoad = std::function<VideoPtr (std::istream&)>;
54- using BitmapSave = std::function<bool (Video const &, std::ostream&)>;
57+ using BitmapReader = std::function<VideoPtr (std::istream&)>;
58+ using BitmapWriter = std::function<bool (Video const &, std::ostream&)>;
5559
56- std::unordered_map<std::string, BitmapLoad> const bitmap_load_map =
60+ struct ImageFormatInfo
5761 {
58- { " bmp" , bitmap_load_bmp },
59- { " png" , bitmap_load_png }
62+ std::string name;
63+ BitmapReader reader;
64+ BitmapWriter writer;
65+ std::vector<std::string> extensions;
6066 };
6167
62- std::unordered_map<std::string, BitmapSave> const bitmap_save_map =
68+ using FormatExtensionLookup = std::unordered_map<std::string, ImageFormat, StringHash, std::equal_to<>>;
69+
70+ std::unordered_map<ImageFormat, ImageFormatInfo> const supported_image_formats
6371 {
64- { " png" , bitmap_save_png }
72+ {ImageFormat::BMP, {" BMP" , bitmap_load_bmp, nullptr , {" .bmp" }}},
73+ {ImageFormat::PNG, {" PNG" , bitmap_load_png, bitmap_save_png, {" .png" }}}
6574 };
6675
67- std::unordered_map<std::string, std::string> const bitmap_format_extension_map =
76+ FormatExtensionLookup build_image_format_extension_lookup ()
6877 {
69- { " .png" , " png" },
70- { " .bmp" , " bmp" }
71- };
78+ FormatExtensionLookup map;
79+
80+ for (auto const & entry : supported_image_formats)
81+ for (auto const & extension : entry.second .extensions )
82+ map.emplace (extension, entry.first );
83+
84+ return map;
85+ }
86+
87+ std::optional<ImageFormat> find_image_format_by_extension (std::string_view extension)
88+ {
89+ static auto const lookup {build_image_format_extension_lookup ()};
90+
91+ auto match {lookup.find (extension)};
92+ if (match == lookup.end ())
93+ return std::nullopt ;
94+ return match->second ;
95+ }
7296
7397 bool is_valid_scale_method (VisVideoScaleMethod scale_method)
7498 {
@@ -227,10 +251,12 @@ namespace LV {
227251
228252 VideoPtr Video::create_from_stream (std::istream& input)
229253 {
230- for (auto entry : bitmap_load_map) {
231- auto image {entry.second (input)};
232- if (image) {
233- return image;
254+ for (auto entry : supported_image_formats) {
255+ if (entry.second .reader ) {
256+ auto image {entry.second .reader (input)};
257+ if (image) {
258+ return image;
259+ }
234260 }
235261 }
236262
@@ -298,8 +324,8 @@ namespace LV {
298324 auto extension {fs::path {path}.extension ()};
299325 auto extension_lower (to_lower_ascii (extension.string ()));
300326
301- auto entry {bitmap_format_extension_map. find (extension_lower)};
302- if (entry == bitmap_format_extension_map. end ()) {
327+ auto format { find_image_format_by_extension (extension_lower)};
328+ if (!format. has_value ()) {
303329 visual_log (VISUAL_LOG_ERROR, " Could not deduce format from filename (%s)" , path.c_str ());
304330 return false ;
305331 }
@@ -310,19 +336,24 @@ namespace LV {
310336 return false ;
311337 }
312338
313- return save_to_stream (output, entry-> second );
339+ return save_to_stream (output, format. value () );
314340 }
315341
316- bool Video::save_to_stream (std::ostream& output, std::string const & format) const
342+ bool Video::save_to_stream (std::ostream& output, ImageFormat format) const
317343 {
318- auto entry {bitmap_save_map.find (format)};
319- if (entry == bitmap_save_map.end ()) {
320- std::string format_str {format};
321- visual_log (VISUAL_LOG_ERROR, " Saving to %s format is not supported" , format_str.c_str ());
344+ auto entry {supported_image_formats.find (format)};
345+
346+ if (entry == supported_image_formats.end ()) {
347+ visual_log (VISUAL_LOG_ERROR, " Saving to unknown format (%d)." , static_cast <int > (format));
348+ return false ;
349+ }
350+
351+ if (!entry->second .writer ) {
352+ visual_log (VISUAL_LOG_ERROR, " Saving to %s is unsupported." , entry->second .name .c_str ());
322353 return false ;
323354 }
324355
325- return entry->second (*this , output);
356+ return entry->second . writer (*this , output);
326357 }
327358
328359 void Video::copy_attrs (VideoConstPtr const & src)
0 commit comments