Skip to content

Commit 73c8493

Browse files
committed
Merge branch 'master' of github.com:Libvisual/libvisual into bin-rewrite
2 parents b4bd090 + 53b86b6 commit 73c8493

File tree

12 files changed

+488
-116
lines changed

12 files changed

+488
-116
lines changed

libvisual/CMakeLists.txt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,11 @@ IF(NOT HAVE_STDC_MATH)
8282
MESSAGE(FATAL_ERROR "Libvisual requires libm to build")
8383
ENDIF()
8484

85+
# Check for Zlib
86+
FIND_PACKAGE(ZLIB 1.2 REQUIRED)
87+
8588
# Check for libpng
86-
FIND_PACKAGE(PNG REQUIRED)
89+
FIND_PACKAGE(PNG 1.4 REQUIRED)
8790

8891
# Internationalization
8992
SET(GETTEXT_PACKAGE "libvisual-${LV_VERSION_SUFFIX}")

libvisual/libvisual/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ TARGET_LINK_LIBRARIES(libvisual
176176
PkgConfig::ORC
177177
PNG::PNG
178178
Threads::Threads
179+
ZLIB::ZLIB
179180
)
180181

181182
IF(WIN32)

libvisual/libvisual/lv_video.cpp

Lines changed: 106 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,26 +29,87 @@
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"
3536
#include "private/lv_video_fill.hpp"
3637
#include "private/lv_video_transform.hpp"
3738
#include "private/lv_video_bmp.hpp"
3839
#include "private/lv_video_png.hpp"
40+
#include <algorithm>
41+
#include <cctype>
3942
#include <cstring>
43+
#include <filesystem>
4044
#include <fstream>
45+
#include <functional>
46+
#include <optional>
47+
#include <string>
48+
#include <unordered_map>
49+
#include <vector>
4150

4251
namespace LV {
4352

53+
namespace fs = std::filesystem;
54+
4455
namespace {
4556

57+
using BitmapReader = std::function<VideoPtr (std::istream&)>;
58+
using BitmapWriter = std::function<bool (Video const&, std::ostream&)>;
59+
60+
struct ImageFormatInfo
61+
{
62+
std::string name;
63+
BitmapReader reader;
64+
BitmapWriter writer;
65+
std::vector<std::string> extensions;
66+
};
67+
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
72+
{
73+
{ImageFormat::BMP, {"BMP", bitmap_load_bmp, nullptr, {".bmp"}}},
74+
{ImageFormat::PNG, {"PNG", bitmap_load_png, bitmap_save_png, {".png"}}}
75+
};
76+
77+
ImageFormatExtensionLookup build_image_format_extension_lookup ()
78+
{
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+
}
97+
4698
bool is_valid_scale_method (VisVideoScaleMethod scale_method)
4799
{
48100
return scale_method == VISUAL_VIDEO_SCALE_NEAREST
49101
|| scale_method == VISUAL_VIDEO_SCALE_BILINEAR;
50102
}
51103

104+
// TODO: Factor this out into a string utility library
105+
std::string to_lower_ascii (std::string const& s)
106+
{
107+
auto result {s};
108+
for (auto& c : result)
109+
c = std::tolower (c);
110+
return result;
111+
}
112+
52113
} // anonymous namespace
53114

54115

@@ -191,17 +252,16 @@ namespace LV {
191252

192253
VideoPtr Video::create_from_stream (std::istream& input)
193254
{
194-
auto image = bitmap_load_bmp (input);
195-
if (image) {
196-
return image;
197-
}
198-
199-
image = bitmap_load_png (input);
200-
if (image) {
201-
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+
}
261+
}
202262
}
203263

204-
return {};
264+
return nullptr;
205265
}
206266

207267
VideoPtr Video::create_scale_depth (VideoConstPtr const& src,
@@ -260,6 +320,43 @@ namespace LV {
260320
return m_impl->buffer->is_allocated ();
261321
}
262322

323+
bool Video::save_to_file (std::string const& path) const
324+
{
325+
auto extension {fs::path {path}.extension ()};
326+
auto extension_lower (to_lower_ascii (extension.string ()));
327+
328+
auto format {find_image_format_by_extension (extension_lower)};
329+
if (!format.has_value ()) {
330+
visual_log (VISUAL_LOG_ERROR, "Could not deduce format from filename (%s)", path.c_str ());
331+
return false;
332+
}
333+
334+
std::ofstream output {path};
335+
if (!output) {
336+
visual_log (VISUAL_LOG_ERROR, "Could not create file '%s'", path.c_str ());
337+
return false;
338+
}
339+
340+
return save_to_stream (output, format.value ());
341+
}
342+
343+
bool Video::save_to_stream (std::ostream& output, ImageFormat format) const
344+
{
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 ());
354+
return false;
355+
}
356+
357+
return entry->second.writer (*this, output);
358+
}
359+
263360
void Video::copy_attrs (VideoConstPtr const& src)
264361
{
265362
set_depth (src->m_impl->depth);

libvisual/libvisual/lv_video.h

Lines changed: 38 additions & 0 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;
@@ -259,6 +276,25 @@ namespace LV {
259276
*/
260277
BufferPtr get_buffer () const;
261278

279+
/**
280+
* Saves contents to a file.
281+
*
282+
* @param path Path name of file to save to. Specify the file format by using the appropriate extension.
283+
*
284+
* @return true if file was successfully saved, false otherwise.
285+
*/
286+
bool save_to_file (std::string const& path) const;
287+
288+
/**
289+
* Saves contents to a stream.
290+
*
291+
* @param output stream to write contents to.
292+
* @param format image file format to encode contents in.
293+
*
294+
* @return true if file was successfully saved, false otherwise.
295+
*/
296+
bool save_to_stream (std::ostream& output, ImageFormat format) const;
297+
262298
/**
263299
* Sets all attributes.
264300
*
@@ -513,6 +549,8 @@ LV_NODISCARD LV_API VisVideo *visual_video_new_with_buffer (int width, int heigh
513549
LV_NODISCARD LV_API VisVideo *visual_video_new_wrap_buffer (void *buffer, int owner, int width, int height, VisVideoDepth depth, int pitch);
514550
LV_NODISCARD LV_API VisVideo *visual_video_load_from_file (const char *path);
515551

552+
LV_API int visual_video_save_to_file (VisVideo *video);
553+
516554
LV_API void visual_video_ref (VisVideo *video);
517555
LV_API void visual_video_unref (VisVideo *video);
518556

libvisual/libvisual/lv_video_c.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,14 @@ VisVideo *visual_video_load_from_file (const char *path)
6868
return self.get ();
6969
}
7070

71+
int visual_video_save_to_file (VisVideo *self, const char *path)
72+
{
73+
visual_return_val_if_fail (self != nullptr, FALSE);
74+
visual_return_val_if_fail (path != nullptr, FALSE);
75+
76+
return self->save_to_file (path);
77+
}
78+
7179
int visual_video_has_allocated_buffer (VisVideo *self)
7280
{
7381
visual_return_val_if_fail (self != nullptr, FALSE);

0 commit comments

Comments
 (0)