// 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 "carla/FileSystem.h" #include "carla/Logging.h" #include "carla/StringUtil.h" #include "carla/image/BoostGil.h" #ifndef LIBCARLA_IMAGE_WITH_PNG_SUPPORT # if defined(__has_include) && __has_include("png.h") # define LIBCARLA_IMAGE_WITH_PNG_SUPPORT true # else # define LIBCARLA_IMAGE_WITH_PNG_SUPPORT false # endif #endif #ifndef LIBCARLA_IMAGE_WITH_JPEG_SUPPORT # if defined(__has_include) && __has_include("jpeglib.h") # define LIBCARLA_IMAGE_WITH_JPEG_SUPPORT true # else # define LIBCARLA_IMAGE_WITH_JPEG_SUPPORT false # endif #endif #ifndef LIBCARLA_IMAGE_WITH_TIFF_SUPPORT # if defined(__has_include) && __has_include("tiffio.h") # define LIBCARLA_IMAGE_WITH_TIFF_SUPPORT true # else # define LIBCARLA_IMAGE_WITH_TIFF_SUPPORT false # endif #endif #if defined(__clang__) # pragma clang diagnostic push # pragma clang diagnostic ignored "-Wunused-parameter" #endif #if LIBCARLA_IMAGE_WITH_PNG_SUPPORT == true # ifndef png_infopp_NULL # define png_infopp_NULL (png_infopp)NULL # endif // png_infopp_NULL # ifndef int_p_NULL # define int_p_NULL (int*)NULL # endif // int_p_NULL # if defined(__clang__) # pragma clang diagnostic push # pragma clang diagnostic ignored "-Wignored-qualifiers" # pragma clang diagnostic ignored "-Wparentheses" # endif # include # if defined(__clang__) # pragma clang diagnostic pop # endif #endif #if LIBCARLA_IMAGE_WITH_JPEG_SUPPORT == true # include #endif #if LIBCARLA_IMAGE_WITH_TIFF_SUPPORT == true # include #endif #if defined(__clang__) # pragma clang diagnostic pop #endif namespace carla { namespace image { namespace io { constexpr bool has_png_support() { return LIBCARLA_IMAGE_WITH_PNG_SUPPORT; } constexpr bool has_jpeg_support() { return LIBCARLA_IMAGE_WITH_JPEG_SUPPORT; } constexpr bool has_tiff_support() { return LIBCARLA_IMAGE_WITH_TIFF_SUPPORT; } static_assert(has_png_support() || has_jpeg_support() || has_tiff_support(), "No image format supported, please compile with at least one of " "LIBCARLA_IMAGE_WITH_PNG_SUPPORT, LIBCARLA_IMAGE_WITH_JPEG_SUPPORT, " "or LIBCARLA_IMAGE_WITH_TIFF_SUPPORT"); namespace detail { template struct is_write_supported { static constexpr bool value = boost::gil::is_write_supported::type, IOTag>::value; }; struct io_png { static constexpr bool is_supported = has_png_support(); #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, ImageT &image) { boost::gil::read_and_convert_image(std::forward(in_filename), image, boost::gil::png_tag()); } template static void write_view(Str &&out_filename, const ViewT &view) { boost::gil::write_view(std::forward(out_filename), view, boost::gil::png_tag()); } #endif // LIBCARLA_IMAGE_WITH_PNG_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, ImageT &image) { boost::gil::read_image(std::forward(in_filename), image, boost::gil::jpeg_tag()); } template static typename std::enable_if::value>::type write_view(Str &&out_filename, const ViewT &view) { boost::gil::write_view(std::forward(out_filename), view, boost::gil::jpeg_tag()); } template static typename std::enable_if::value>::type write_view(Str &&out_filename, const ViewT &view) { boost::gil::write_view( std::forward(out_filename), boost::gil::color_converted_view(view), boost::gil::jpeg_tag()); } #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, ImageT &image) { boost::gil::read_and_convert_image(std::forward(in_filename), image, boost::gil::tiff_tag()); } template static typename std::enable_if::value>::type write_view(Str &&out_filename, const ViewT &view) { boost::gil::write_view(std::forward(out_filename), view, boost::gil::tiff_tag()); } template static typename std::enable_if::value>::type write_view(Str &&out_filename, const ViewT &view) { boost::gil::write_view( std::forward(out_filename), boost::gil::color_converted_view(view), boost::gil::tiff_tag()); } #endif // LIBCARLA_IMAGE_WITH_TIFF_SUPPORT }; 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 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(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 png : detail::io_impl {}; struct jpeg : detail::io_impl {}; struct tiff : detail::io_impl {}; #if LIBCARLA_IMAGE_WITH_PNG_SUPPORT struct any : detail::io_any {}; #elif LIBCARLA_IMAGE_WITH_TIFF_SUPPORT struct any : detail::io_any {}; #else // Then for sure this one is available. struct any : detail::io_any {}; #endif } // namespace io } // namespace image } // namespace carla