diff --git a/LibCarla/source/carla/FileSystem.cpp b/LibCarla/source/carla/FileSystem.cpp new file mode 100644 index 000000000..cb4a652b0 --- /dev/null +++ b/LibCarla/source/carla/FileSystem.cpp @@ -0,0 +1,26 @@ +// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma +// de Barcelona (UAB). +// +// This work is licensed under the terms of the MIT license. +// For a copy, see . + +#include "carla/FileSystem.h" + +#include + +namespace carla { + + void FileSystem::ValidateFilePath(std::string &filepath, const std::string &ext) { + namespace fs = boost::filesystem; + fs::path path(filepath); + if (path.extension().empty() && !ext.empty()) { + if (ext[0] != '.') { + path += '.'; + } + path += ext; + } + fs::create_directories(path.parent_path()); + filepath = path.string(); + } + +} // namespace carla diff --git a/LibCarla/source/carla/FileSystem.h b/LibCarla/source/carla/FileSystem.h new file mode 100644 index 000000000..7c9bcbfda --- /dev/null +++ b/LibCarla/source/carla/FileSystem.h @@ -0,0 +1,29 @@ +// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma +// de Barcelona (UAB). +// +// This work is licensed under the terms of the MIT license. +// For a copy, see . + +#pragma once + +#include + +namespace carla { + + /// Static functions for accessing the file system. + /// + /// @warning Using this file requires linking against boost_filesystem. + class FileSystem { + public: + + /// Convenient function to validate a path before creating a file. + /// + /// 1) Ensures all the parent directories are created if missing. + /// 2) If @a filepath is missing the extension, @a default_extension is + /// appended to the path. + static void ValidateFilePath( + std::string &filepath, + const std::string &default_extension = ""); + }; + +} // namespace carla diff --git a/LibCarla/source/carla/image/ImageIO.h b/LibCarla/source/carla/image/ImageIO.h index 2b6c11503..642295760 100644 --- a/LibCarla/source/carla/image/ImageIO.h +++ b/LibCarla/source/carla/image/ImageIO.h @@ -14,16 +14,12 @@ namespace image { class ImageIO { public: - using io_default = io::png; - - static_assert(io_default::is_supported, "Default format not supported!"); - - template + template static void ReadImage(Str &&in_filename, ImageT &image, IO = IO()) { IO::read_image(std::forward(in_filename), image); } - template + template static void WriteView(Str &&out_filename, const ViewT &image_view, IO = IO()) { IO::write_view(std::forward(out_filename), image_view); } diff --git a/LibCarla/source/carla/image/ImageIOConfig.h b/LibCarla/source/carla/image/ImageIOConfig.h index b23b6d909..54f19d17f 100644 --- a/LibCarla/source/carla/image/ImageIOConfig.h +++ b/LibCarla/source/carla/image/ImageIOConfig.h @@ -6,6 +6,9 @@ #pragma once +#include "carla/FileSystem.h" +#include "carla/Logging.h" +#include "carla/StringUtil.h" #include "carla/image/BoostGil.h" #ifndef LIBCARLA_IMAGE_WITH_PNG_SUPPORT @@ -82,88 +85,213 @@ namespace io { namespace detail { - struct jpeg_reader { -#if LIBCARLA_IMAGE_WITH_JPEG_SUPPORT - template - static void read_image(Str &&in_filename, IMAGE &image) { - static_assert(has_jpeg_support(), "JPEG not supported"); - boost::gil::jpeg_read_image(std::forward(in_filename), image); - } -#endif // LIBCARLA_IMAGE_WITH_JPEG_SUPPORT - }; + struct io_png { - struct jpeg_writer { -#if LIBCARLA_IMAGE_WITH_JPEG_SUPPORT - template - static void write_view(Str &&out_filename, const VIEW &view) { - static_assert(has_jpeg_support(), "JPEG not supported"); - boost::gil::jpeg_write_view(std::forward(out_filename), view); - } -#endif // LIBCARLA_IMAGE_WITH_JPEG_SUPPORT - }; + static constexpr bool is_supported = has_png_support(); - struct png_reader { #if LIBCARLA_IMAGE_WITH_PNG_SUPPORT + + static constexpr const char *get_default_extension() { + return "png"; + } + + template + static bool match_extension(const Str &str) { + return StringUtil::EndsWith(str, get_default_extension()); + } + template static void read_image(Str &&in_filename, IMAGE &image) { - static_assert(has_png_support(), "PNG not supported"); boost::gil::png_read_and_convert_image(std::forward(in_filename), image); } -#endif // LIBCARLA_IMAGE_WITH_PNG_SUPPORT - }; - struct png_writer { -#if LIBCARLA_IMAGE_WITH_PNG_SUPPORT template static void write_view(Str &&out_filename, const VIEW &view) { - static_assert(has_png_support(), "PNG not supported"); boost::gil::png_write_view(std::forward(out_filename), view); } + #endif // LIBCARLA_IMAGE_WITH_PNG_SUPPORT }; - struct tiff_reader { -#if LIBCARLA_IMAGE_WITH_TIFF_SUPPORT + struct io_jpeg { + + static constexpr bool is_supported = has_jpeg_support(); + +#if LIBCARLA_IMAGE_WITH_JPEG_SUPPORT + + static constexpr const char *get_default_extension() { + return "jpeg"; + } + + template + static bool match_extension(const Str &str) { + return StringUtil::EndsWith(str, get_default_extension()) || + StringUtil::EndsWith(str, "jpg"); + } + template static void read_image(Str &&in_filename, IMAGE &image) { - static_assert(has_tiff_support(), "TIFF not supported"); - boost::gil::tiff_read_and_convert_image(std::forward(in_filename), image); + boost::gil::jpeg_read_image(std::forward(in_filename), image); + } + + template + static void write_view(Str &&out_filename, const VIEW &view) { + boost::gil::jpeg_write_view(std::forward(out_filename), view); + } + +#endif // LIBCARLA_IMAGE_WITH_JPEG_SUPPORT + }; + + struct io_tiff { + + static constexpr bool is_supported = has_tiff_support(); + +#if LIBCARLA_IMAGE_WITH_TIFF_SUPPORT + + static constexpr const char *get_default_extension() { + return "tiff"; + } + + template + static bool match_extension(const Str &str) { + return StringUtil::EndsWith(str, get_default_extension()); + } + + template + static void read_image(Str &&in_filename, IMAGE &image) { + boost::gil::tiff_read_and_convert_image(std::forward(in_filename), image); } -#endif // LIBCARLA_IMAGE_WITH_TIFF_SUPPORT - }; - struct tiff_writer { -#if LIBCARLA_IMAGE_WITH_TIFF_SUPPORT template static void write_view(Str &&out_filename, const VIEW &view) { - static_assert(has_tiff_support(), "TIFF not supported"); boost::gil::tiff_write_view(std::forward(out_filename), view); } + #endif // LIBCARLA_IMAGE_WITH_TIFF_SUPPORT }; - template - struct image_io; + struct io_resolver { + + template + static typename std::enable_if::type match_extension(const Str &str) { + return IO::match_extension(str); + } + + template + static typename std::enable_if::type match_extension(const Str &) { + return false; + } + + template + static typename std::enable_if::type read_image(const Str &path, Args &&... args) { + log_debug("reading", path, "as", IO::get_default_extension()); + IO::read_image(path, std::forward(args)...); + } + + template + static typename std::enable_if::type read_image(Args &&...) { + DEBUG_ASSERT(false); + } + + template + static typename std::enable_if::type write_view(std::string path, Args &&... args) { + FileSystem::ValidateFilePath(path, IO::get_default_extension()); + log_debug("writing", path, "as", IO::get_default_extension()); + IO::write_view(path, std::forward(args)...); + } + + template + static typename std::enable_if::type write_view(Args &&...) { + DEBUG_ASSERT(false); + } - template - struct image_io { - constexpr static bool is_supported = false; }; - template - struct image_io { - constexpr static bool is_supported = true; - using reader_type = READER; - using writer_type = WRITER; + template + struct io_impl; + + template + struct io_impl { + constexpr static bool is_supported = IO::is_supported; + + template + static void read_image(Args &&... args) { + io_resolver::read_image(std::forward(args)...); + } + + template + static void write_view(Args &&... args) { + io_resolver::write_view(std::forward(args)...); + } + + template + static bool try_read_image(const Str &filename, Args &&... args) { + if (io_resolver::match_extension(filename)) { + io_resolver::read_image(filename, std::forward(args)...); + return true; + } + return false; + } + + template + static bool try_write_view(const Str &filename, Args &&... args) { + if (io_resolver::match_extension(filename)) { + io_resolver::write_view(filename, std::forward(args)...); + return true; + } + return false; + } + + }; + + template + struct io_impl { + private: + using self = io_impl; + using recursive = io_impl; + public: + + constexpr static bool is_supported = self::is_supported || recursive::is_supported; + + template + static void read_image(Args &... args) { + if (!recursive::try_read_image(args...)) { + self::read_image(args...); + } + } + + template + static bool try_read_image(Args &... args) { + return recursive::try_read_image(args...) || self::try_read_image(args...); + } + + template + static void write_view(Args &... args) { + if (!recursive::try_write_view(args...)) { + self::write_view(args...); + } + } + + template + static bool try_write_view(Args &... args) { + return recursive::try_write_view(args...) || self::try_write_view(args...); + } + }; + + template + struct io_any : detail::io_impl { + static_assert(DefaultIO::is_supported, "Default IO needs to be supported."); }; } // namespace detail - struct jpeg : public detail::image_io {}; + struct png : detail::io_impl {}; - struct png : public detail::image_io {}; + struct jpeg : detail::io_impl {}; - struct tiff : public detail::image_io {}; + struct tiff : detail::io_impl {}; + + struct any : detail::io_any {}; } // namespace io } // namespace image