3636#include " private/lv_video_transform.hpp"
3737#include " private/lv_video_bmp.hpp"
3838#include " private/lv_video_png.hpp"
39+ #include < algorithm>
40+ #include < cctype>
3941#include < cstring>
4042#include < filesystem>
4143#include < fstream>
@@ -49,18 +51,40 @@ namespace LV {
4951 namespace {
5052
5153 using BitmapLoad = std::function<VideoPtr (std::istream&)>;
54+ using BitmapSave = std::function<bool (Video const &, std::ostream&)>;
55+
5256 std::unordered_map<std::string, BitmapLoad> const bitmap_load_map =
5357 {
5458 { " bmp" , bitmap_load_bmp },
5559 { " png" , bitmap_load_png }
5660 };
5761
62+ std::unordered_map<std::string, BitmapSave> const bitmap_save_map =
63+ {
64+ { " png" , bitmap_save_png }
65+ };
66+
67+ std::unordered_map<std::string, std::string> const bitmap_format_extension_map =
68+ {
69+ { " .png" , " png" },
70+ { " .bmp" , " bmp" }
71+ };
72+
5873 bool is_valid_scale_method (VisVideoScaleMethod scale_method)
5974 {
6075 return scale_method == VISUAL_VIDEO_SCALE_NEAREST
6176 || scale_method == VISUAL_VIDEO_SCALE_BILINEAR;
6277 }
6378
79+ // TODO: Factor this out into a string utility library
80+ std::string to_lower_ascii (std::string const & s)
81+ {
82+ std::string result {s};
83+ std::transform (result.begin (), result.end (), result.begin (),
84+ [=] (unsigned char c) { return std::tolower (c); });
85+ return result;
86+ }
87+
6488 } // anonymous namespace
6589
6690
@@ -271,17 +295,33 @@ namespace LV {
271295
272296 bool Video::save_to_file (std::string const & path) const
273297 {
274- auto extension = fs::path {path}.extension ();
298+ std::string extension { to_lower_ascii ( fs::path {path}.extension ())} ;
275299
276- std::ofstream file {path};
300+ auto entry {bitmap_format_extension_map.find (extension)};
301+ if (entry == bitmap_format_extension_map.end ()) {
302+ visual_log (VISUAL_LOG_ERROR, " Could not deduce format from filename (%s)" , path.c_str ());
303+ return false ;
304+ }
277305
278- if (extension == " .png" ) {
279- return bitmap_save_png (*this , file);
306+ std::ofstream output {path};
307+ if (!output) {
308+ visual_log (VISUAL_LOG_ERROR, " Could not create file '%s'" , path.c_str ());
309+ return false ;
280310 }
281311
282- visual_log (VISUAL_LOG_ERROR, " Unsupported format with extension '%s'." , extension.c_str ());
312+ return save_to_stream (output, entry->second );
313+ }
314+
315+ bool Video::save_to_stream (std::ostream& output, std::string const & format) const
316+ {
317+ auto entry {bitmap_save_map.find (format)};
318+ if (entry == bitmap_save_map.end ()) {
319+ std::string format_str {format};
320+ visual_log (VISUAL_LOG_ERROR, " Saving to %s format is not supported" , format_str.c_str ());
321+ return false ;
322+ }
283323
284- return false ;
324+ return entry-> second (* this , output) ;
285325 }
286326
287327 void Video::copy_attrs (VideoConstPtr const & src)
0 commit comments