Skip to content

Commit d723ede

Browse files
committed
Core (LV::Video): Introduce LV::ImageFormat enum for identifying image formats.
1 parent dfbbc07 commit d723ede

File tree

3 files changed

+81
-28
lines changed

3 files changed

+81
-28
lines changed

libvisual/libvisual/lv_video.cpp

Lines changed: 58 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -42,34 +42,62 @@
4242
#include <filesystem>
4343
#include <fstream>
4444
#include <functional>
45+
#include <optional>
46+
#include <string>
4547
#include <unordered_map>
48+
#include <vector>
4649

4750
namespace LV {
4851

4952
namespace fs = std::filesystem;
5053

5154
namespace {
5255

53-
using BitmapLoad = std::function<VideoPtr (std::istream&)>;
54-
using BitmapSave = std::function<bool (Video const&, std::ostream&)>;
56+
using BitmapReader = std::function<VideoPtr (std::istream&)>;
57+
using BitmapWriter = std::function<bool (Video const&, std::ostream&)>;
5558

56-
std::unordered_map<std::string, BitmapLoad> const bitmap_load_map =
59+
struct ImageFormatInfo
5760
{
58-
{ "bmp", bitmap_load_bmp },
59-
{ "png", bitmap_load_png }
61+
std::string name;
62+
BitmapReader reader;
63+
BitmapWriter writer;
64+
std::vector<std::string> extensions;
6065
};
6166

62-
std::unordered_map<std::string, BitmapSave> const bitmap_save_map =
67+
std::unordered_map<ImageFormat, ImageFormatInfo> const supported_image_formats
6368
{
64-
{ "png", bitmap_save_png }
69+
{ImageFormat::BMP, {"BMP", bitmap_load_bmp, nullptr, {".bmp"}}},
70+
{ImageFormat::PNG, {"PNG", bitmap_load_png, bitmap_save_png, {".png"}}}
6571
};
6672

67-
std::unordered_map<std::string, std::string> const bitmap_format_extension_map =
73+
std::unordered_map<std::string, ImageFormat> const image_format_by_extension
6874
{
69-
{ ".png", "png" },
70-
{ ".bmp", "bmp" }
75+
{".bmp", ImageFormat::BMP},
76+
{".png", ImageFormat::PNG}
7177
};
7278

79+
std::unordered_map<std::string, ImageFormat> build_image_format_extension_lookup ()
80+
{
81+
std::unordered_map<std::string, ImageFormat> map;
82+
83+
for (auto const& entry : supported_image_formats)
84+
for (auto const& extension : entry.second.extensions)
85+
map.emplace (extension, entry.first);
86+
87+
return map;
88+
}
89+
90+
// TODO: Use heterogeneous/transparent lookups to avoid having to accept only std::string.
91+
std::optional<ImageFormat> find_image_format_by_extension (std::string const& extension)
92+
{
93+
static auto const lookup {build_image_format_extension_lookup ()};
94+
95+
auto match {lookup.find (extension)};
96+
if (match == lookup.end ())
97+
return std::nullopt;
98+
return match->second;
99+
}
100+
73101
bool is_valid_scale_method (VisVideoScaleMethod scale_method)
74102
{
75103
return scale_method == VISUAL_VIDEO_SCALE_NEAREST
@@ -227,10 +255,12 @@ namespace LV {
227255

228256
VideoPtr Video::create_from_stream (std::istream& input)
229257
{
230-
for (auto entry : bitmap_load_map) {
231-
auto image {entry.second (input)};
232-
if (image) {
233-
return image;
258+
for (auto entry : supported_image_formats) {
259+
if (entry.second.reader) {
260+
auto image {entry.second.reader (input)};
261+
if (image) {
262+
return image;
263+
}
234264
}
235265
}
236266

@@ -298,8 +328,8 @@ namespace LV {
298328
auto extension {fs::path {path}.extension ()};
299329
auto extension_lower (to_lower_ascii (extension.string ()));
300330

301-
auto entry {bitmap_format_extension_map.find (extension_lower)};
302-
if (entry == bitmap_format_extension_map.end ()) {
331+
auto format {find_image_format_by_extension (extension_lower)};
332+
if (!format.has_value ()) {
303333
visual_log (VISUAL_LOG_ERROR, "Could not deduce format from filename (%s)", path.c_str ());
304334
return false;
305335
}
@@ -310,19 +340,24 @@ namespace LV {
310340
return false;
311341
}
312342

313-
return save_to_stream (output, entry->second);
343+
return save_to_stream (output, format.value ());
314344
}
315345

316-
bool Video::save_to_stream (std::ostream& output, std::string const& format) const
346+
bool Video::save_to_stream (std::ostream& output, ImageFormat format) const
317347
{
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 ());
348+
auto entry {supported_image_formats.find (format)};
349+
350+
if (entry == supported_image_formats.end ()) {
351+
visual_log (VISUAL_LOG_ERROR, "Saving to unknown format (%d).", static_cast<int> (format));
352+
return false;
353+
}
354+
355+
if (!entry->second.writer) {
356+
visual_log (VISUAL_LOG_ERROR, "Saving to %s is unsupported.", entry->second.name.c_str ());
322357
return false;
323358
}
324359

325-
return entry->second (*this, output);
360+
return entry->second.writer (*this, output);
326361
}
327362

328363
void Video::copy_attrs (VideoConstPtr const& src)

libvisual/libvisual/lv_video.h

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,14 @@ typedef enum {
9696
VISUAL_VIDEO_COMPOSE_TYPE_CUSTOM /**< Custom compose function (looks up on the source VisVideo. */
9797
} VisVideoComposeType;
9898

99+
/**
100+
* The set of known and supported image formats.
101+
*/
102+
typedef enum {
103+
VISUAL_IMAGE_FORMAT_BMP = 0,
104+
VISUAL_IMAGE_FORMAT_PNG
105+
} VisImageFormat;
106+
99107
typedef struct _VisVideoAttrOptions VisVideoAttrOptions;
100108

101109
#ifdef __cplusplus
@@ -125,6 +133,15 @@ struct _VisVideoAttrOptions {
125133

126134
namespace LV {
127135

136+
/**
137+
* The set of known and supported image formats.
138+
*/
139+
enum class ImageFormat
140+
{
141+
BMP = VISUAL_IMAGE_FORMAT_BMP,
142+
PNG = VISUAL_IMAGE_FORMAT_PNG
143+
};
144+
128145
class Video;
129146

130147
typedef IntrusivePtr<Video> VideoPtr;
@@ -271,11 +288,12 @@ namespace LV {
271288
/**
272289
* Saves contents to a stream.
273290
*
274-
* @param output stream
291+
* @param output stream to write contents to.
292+
* @param format image file format to encode contents in.
275293
*
276294
* @return true if file was successfully saved, false otherwise.
277295
*/
278-
bool save_to_stream (std::ostream& output, std::string const& format) const;
296+
bool save_to_stream (std::ostream& output, ImageFormat format) const;
279297

280298
/**
281299
* Sets all attributes.

libvisual/tests/video_test/video_save_test.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ void test_save_indexed8 ()
88
LV_TEST_ASSERT (png_image);
99

1010
std::stringstream buffer;
11-
LV_TEST_ASSERT (png_image->save_to_stream (buffer, "png"));
11+
LV_TEST_ASSERT (png_image->save_to_stream (buffer, LV::ImageFormat::PNG));
1212

1313
auto png_saved_image {LV::Video::create_from_stream (buffer)};
1414
LV_TEST_ASSERT (png_saved_image);
@@ -21,7 +21,7 @@ void test_save_rgb24 ()
2121
LV_TEST_ASSERT (png_image);
2222

2323
std::stringstream buffer;
24-
LV_TEST_ASSERT (png_image->save_to_stream (buffer, "png"));
24+
LV_TEST_ASSERT (png_image->save_to_stream (buffer, LV::ImageFormat::PNG));
2525

2626
auto png_saved_image {LV::Video::create_from_stream (buffer)};
2727
LV_TEST_ASSERT (png_saved_image);
@@ -34,7 +34,7 @@ void test_save_argb32 ()
3434
LV_TEST_ASSERT (png_image);
3535

3636
std::stringstream buffer;
37-
LV_TEST_ASSERT (png_image->save_to_stream (buffer, "png"));
37+
LV_TEST_ASSERT (png_image->save_to_stream (buffer, LV::ImageFormat::PNG));
3838

3939
auto png_saved_image {LV::Video::create_from_stream (buffer)};
4040
LV_TEST_ASSERT (png_saved_image);

0 commit comments

Comments
 (0)