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 ImageFormatExtensionLookup = std::unordered_map<
69+ std::string, ImageFormat, StringHash, std::equal_to<>>;
70+
71+ std::unordered_map<ImageFormat, ImageFormatInfo> const supported_image_formats
6372 {
64- { " png" , bitmap_save_png }
73+ {ImageFormat::BMP, {" BMP" , bitmap_load_bmp, nullptr , {" .bmp" }}},
74+ {ImageFormat::PNG, {" PNG" , bitmap_load_png, bitmap_save_png, {" .png" }}}
6575 };
6676
67- std::unordered_map<std::string, std::string> const bitmap_format_extension_map =
77+ ImageFormatExtensionLookup build_image_format_extension_lookup ()
6878 {
69- { " .png" , " png" },
70- { " .bmp" , " bmp" }
71- };
79+ ImageFormatExtensionLookup map;
80+
81+ for (auto const & entry : supported_image_formats)
82+ for (auto const & extension : entry.second .extensions )
83+ map.emplace (extension, entry.first );
84+
85+ return map;
86+ }
87+
88+ std::optional<ImageFormat> find_image_format_by_extension (std::string_view extension)
89+ {
90+ static auto const lookup {build_image_format_extension_lookup ()};
91+
92+ auto match {lookup.find (extension)};
93+ if (match == lookup.end ())
94+ return std::nullopt ;
95+ return match->second ;
96+ }
7297
7398 bool is_valid_scale_method (VisVideoScaleMethod scale_method)
7499 {
@@ -227,10 +252,12 @@ namespace LV {
227252
228253 VideoPtr Video::create_from_stream (std::istream& input)
229254 {
230- for (auto entry : bitmap_load_map) {
231- auto image {entry.second (input)};
232- if (image) {
233- return image;
255+ for (auto entry : supported_image_formats) {
256+ if (entry.second .reader ) {
257+ auto image {entry.second .reader (input)};
258+ if (image) {
259+ return image;
260+ }
234261 }
235262 }
236263
@@ -298,8 +325,8 @@ namespace LV {
298325 auto extension {fs::path {path}.extension ()};
299326 auto extension_lower (to_lower_ascii (extension.string ()));
300327
301- auto entry {bitmap_format_extension_map. find (extension_lower)};
302- if (entry == bitmap_format_extension_map. end ()) {
328+ auto format { find_image_format_by_extension (extension_lower)};
329+ if (!format. has_value ()) {
303330 visual_log (VISUAL_LOG_ERROR, " Could not deduce format from filename (%s)" , path.c_str ());
304331 return false ;
305332 }
@@ -310,19 +337,24 @@ namespace LV {
310337 return false ;
311338 }
312339
313- return save_to_stream (output, entry-> second );
340+ return save_to_stream (output, format. value () );
314341 }
315342
316- bool Video::save_to_stream (std::ostream& output, std::string const & format) const
343+ bool Video::save_to_stream (std::ostream& output, ImageFormat format) const
317344 {
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 ());
345+ auto entry {supported_image_formats.find (format)};
346+
347+ if (entry == supported_image_formats.end ()) {
348+ visual_log (VISUAL_LOG_ERROR, " Saving to unknown format (%d)." , static_cast <int > (format));
349+ return false ;
350+ }
351+
352+ if (!entry->second .writer ) {
353+ visual_log (VISUAL_LOG_ERROR, " Saving to %s is unsupported." , entry->second .name .c_str ());
322354 return false ;
323355 }
324356
325- return entry->second (*this , output);
357+ return entry->second . writer (*this , output);
326358 }
327359
328360 void Video::copy_attrs (VideoConstPtr const & src)
0 commit comments