diff --git a/bindings/python/mapnik_image.cpp b/bindings/python/mapnik_image.cpp index 92e023970..5d674be72 100644 --- a/bindings/python/mapnik_image.cpp +++ b/bindings/python/mapnik_image.cpp @@ -83,7 +83,7 @@ PyObject* tostring2(image_32 const & im, std::string const& format) (s.data(),s.size()); } -PyObject* tostring3(image_32 const & im, std::string const& format, mapnik::rgba_palette_ptr const& pal) +PyObject* tostring3(image_32 const & im, std::string const& format, mapnik::rgba_palette const& pal) { std::string s = save_to_string(im, format, pal); return @@ -106,7 +106,7 @@ void save_to_file2(mapnik::image_32 const& im, std::string const& filename, std: save_to_file(im,filename,type); } -void save_to_file3(mapnik::image_32 const& im, std::string const& filename, std::string const& type, mapnik::rgba_palette_ptr const& pal) +void save_to_file3(mapnik::image_32 const& im, std::string const& filename, std::string const& type, mapnik::rgba_palette const& pal) { save_to_file(im,filename,type,pal); } diff --git a/bindings/python/mapnik_image_view.cpp b/bindings/python/mapnik_image_view.cpp index bcd890385..e08129f7f 100644 --- a/bindings/python/mapnik_image_view.cpp +++ b/bindings/python/mapnik_image_view.cpp @@ -77,7 +77,7 @@ PyObject* view_tostring2(image_view const & view, std::string (s.data(),s.size()); } -PyObject* view_tostring3(image_view const & view, std::string const& format, mapnik::rgba_palette_ptr const& pal) +PyObject* view_tostring3(image_view const & view, std::string const& format, mapnik::rgba_palette const& pal) { std::string s = save_to_string(view, format, pal); return @@ -126,7 +126,7 @@ void save_view2(image_view const& view, void save_view3(image_view const& view, std::string const& filename, std::string const& type, - mapnik::rgba_palette_ptr const& pal) + mapnik::rgba_palette const& pal) { save_to_file(view,filename,type,pal); } diff --git a/bindings/python/mapnik_palette.cpp b/bindings/python/mapnik_palette.cpp index 08ab80e92..12cf2fdec 100644 --- a/bindings/python/mapnik_palette.cpp +++ b/bindings/python/mapnik_palette.cpp @@ -55,7 +55,7 @@ void export_palette () { using namespace boost::python; - class_, + class_, boost::noncopyable >("Palette",no_init) //, init( diff --git a/include/mapnik/image_data_any.hpp b/include/mapnik/image_data_any.hpp index e1501cd16..336b4220c 100644 --- a/include/mapnik/image_data_any.hpp +++ b/include/mapnik/image_data_any.hpp @@ -24,8 +24,6 @@ #define MAPNIK_IMAGE_DATA_ANY_HPP #include -#include -#include #include namespace mapnik { @@ -42,12 +40,7 @@ using image_data_base = util::variant, - image_view, - image_view, - image_view>; + image_data_gray32f>; namespace detail { diff --git a/include/mapnik/image_scaling_traits.hpp b/include/mapnik/image_scaling_traits.hpp index fbc805bb5..fe2ce61ed 100644 --- a/include/mapnik/image_scaling_traits.hpp +++ b/include/mapnik/image_scaling_traits.hpp @@ -23,9 +23,6 @@ #ifndef MAPNIK_IMAGE_SCALING_TRAITS_HPP #define MAPNIK_IMAGE_SCALING_TRAITS_HPP -// mapnik -#include - // agg #include "agg_image_accessors.h" #include "agg_pixfmt_rgba.h" @@ -52,18 +49,6 @@ struct agg_scaling_traits }; -template <> -struct agg_scaling_traits -{ - using pixfmt_pre = agg::pixfmt_rgba32_pre; - using color_type = agg::rgba8; - using interpolator_type = agg::span_interpolator_linear<>; - using img_src_type = agg::image_accessor_clone; - using span_image_filter = agg::span_image_filter_rgba_nn; - using span_image_resample_affine = agg::span_image_resample_rgba_affine; - -}; - template <> struct agg_scaling_traits { diff --git a/include/mapnik/image_util.hpp b/include/mapnik/image_util.hpp index b00c44c8b..f6bb1ca21 100644 --- a/include/mapnik/image_util.hpp +++ b/include/mapnik/image_util.hpp @@ -46,7 +46,6 @@ namespace mapnik { class Map; class rgba_palette; class image_32; -typedef std::shared_ptr rgba_palette_ptr; class ImageWriterException : public std::exception { @@ -85,7 +84,7 @@ template MAPNIK_DECL void save_to_file(T const& image, std::string const& filename, std::string const& type, - rgba_palette_ptr const& palette); + rgba_palette const& palette); // guess type from file extension template @@ -95,7 +94,7 @@ MAPNIK_DECL void save_to_file(T const& image, template MAPNIK_DECL void save_to_file(T const& image, std::string const& filename, - rgba_palette_ptr const& palette); + rgba_palette const& palette); template MAPNIK_DECL std::string save_to_string(T const& image, @@ -104,7 +103,7 @@ MAPNIK_DECL std::string save_to_string(T const& image, template MAPNIK_DECL std::string save_to_string(T const& image, std::string const& type, - rgba_palette_ptr const& palette); + rgba_palette const& palette); template MAPNIK_DECL void save_to_stream @@ -112,7 +111,7 @@ MAPNIK_DECL void save_to_stream T const& image, std::ostream & stream, std::string const& type, - rgba_palette_ptr const& palette + rgba_palette const& palette ); template @@ -126,7 +125,7 @@ MAPNIK_DECL void save_to_stream template void save_as_png(T const& image, std::string const& filename, - rgba_palette_ptr const& palette); + rgba_palette const& palette); #if defined(HAVE_JPEG) template @@ -225,7 +224,7 @@ MAPNIK_DECL void save_to_file (image_32 const& image, MAPNIK_DECL void save_to_file (image_32 const& image, std::string const& file, std::string const& type, - rgba_palette_ptr const& palette); + rgba_palette const& palette); /////////////////////////////////////////////////////////////////////////// @@ -235,14 +234,14 @@ MAPNIK_DECL std::string save_to_string(image_32 const& image, MAPNIK_DECL std::string save_to_string(image_32 const& image, std::string const& type, - rgba_palette_ptr const& palette); + rgba_palette const& palette); /////////////////////////////////////////////////////////////////////////// MAPNIK_DECL void save_to_stream(image_32 const& image, std::ostream & stream, std::string const& type, - rgba_palette_ptr const& palette); + rgba_palette const& palette); MAPNIK_DECL void save_to_stream(image_32 const& image, std::ostream & stream, @@ -253,7 +252,7 @@ MAPNIK_DECL void save_to_stream(image_32 const& image, extern template MAPNIK_DECL void save_to_file(image_data_rgba8 const&, std::string const&, std::string const&, - rgba_palette_ptr const&); + rgba_palette const&); extern template MAPNIK_DECL void save_to_file(image_data_rgba8 const&, std::string const&, @@ -261,7 +260,7 @@ extern template MAPNIK_DECL void save_to_file(image_data_rgba8 extern template MAPNIK_DECL void save_to_file(image_data_rgba8 const&, std::string const&, - rgba_palette_ptr const&); + rgba_palette const&); extern template MAPNIK_DECL void save_to_file(image_data_rgba8 const&, std::string const&); @@ -270,7 +269,7 @@ extern template MAPNIK_DECL void save_to_file(image_data_rgba8 extern template MAPNIK_DECL void save_to_file > (image_view const&, std::string const&, std::string const&, - rgba_palette_ptr const&); + rgba_palette const&); extern template MAPNIK_DECL void save_to_file > (image_view const&, std::string const&, @@ -278,7 +277,7 @@ extern template MAPNIK_DECL void save_to_file > (im extern template MAPNIK_DECL void save_to_file > (image_view const&, std::string const&, - rgba_palette_ptr const&); + rgba_palette const&); extern template MAPNIK_DECL void save_to_file > (image_view const&, std::string const&); @@ -288,21 +287,21 @@ extern template MAPNIK_DECL std::string save_to_string(image_d extern template MAPNIK_DECL std::string save_to_string(image_data_rgba8 const&, std::string const&, - rgba_palette_ptr const&); + rgba_palette const&); extern template MAPNIK_DECL std::string save_to_string > (image_view const&, std::string const&); extern template MAPNIK_DECL std::string save_to_string > (image_view const&, std::string const&, - rgba_palette_ptr const&); + rgba_palette const&); #ifdef _MSC_VER template MAPNIK_DECL void save_to_stream( image_data_rgba8 const& image, std::ostream & stream, std::string const& type, - rgba_palette_ptr const& palette + rgba_palette const& palette ); template MAPNIK_DECL void save_to_stream( @@ -315,7 +314,7 @@ template MAPNIK_DECL void save_to_stream > ( image_view const& image, std::ostream & stream, std::string const& type, - rgba_palette_ptr const& palette + rgba_palette const& palette ); template MAPNIK_DECL void save_to_stream > ( diff --git a/include/mapnik/image_util_jpeg.hpp b/include/mapnik/image_util_jpeg.hpp new file mode 100644 index 000000000..091ce2566 --- /dev/null +++ b/include/mapnik/image_util_jpeg.hpp @@ -0,0 +1,47 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2014 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +#ifndef MAPNIK_IMAGE_UTIL_JPEG_HPP +#define MAPNIK_IMAGE_UTIL_JPEG_HPP + +// mapnik +#include + +// stl +#include +#include + +namespace mapnik { + +struct jpeg_saver : public mapnik::util::static_visitor<> +{ + jpeg_saver(std::ostream &, std::string &); + template + void operator() (T const&) const; + private: + std::ostream & stream_; + std::string const& t_; +}; + +} // end ns + +#endif // MAPNIK_IMAGE_UTIL_JPEG_HPP diff --git a/include/mapnik/image_util_png.hpp b/include/mapnik/image_util_png.hpp index b3097b24a..a48c02bef 100644 --- a/include/mapnik/image_util_png.hpp +++ b/include/mapnik/image_util_png.hpp @@ -32,15 +32,25 @@ namespace mapnik { -struct png_saver : public mapnik::util::static_visitor<> +struct png_saver_pal : public mapnik::util::static_visitor<> { - png_saver(std::ostream &, std::string &, rgba_palette_ptr const& = nullptr); + png_saver_pal(std::ostream &, std::string &, rgba_palette const&); + template + void operator() (T const&) const; + private: + std::ostream & stream_; + std::string const& t_; + rgba_palette const& pal_; +}; + +struct png_saver : public mapnik::util::static_visitor<> +{ + png_saver(std::ostream &, std::string &); template void operator() (T const&) const; private: std::ostream & stream_; std::string const& t_; - rgba_palette_ptr const& pal_; }; } // end ns diff --git a/include/mapnik/image_util_tiff.hpp b/include/mapnik/image_util_tiff.hpp new file mode 100644 index 000000000..6a2861b2a --- /dev/null +++ b/include/mapnik/image_util_tiff.hpp @@ -0,0 +1,47 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2014 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +#ifndef MAPNIK_IMAGE_UTIL_TIFF_HPP +#define MAPNIK_IMAGE_UTIL_TIFF_HPP + +// mapnik +#include + +// stl +#include +#include + +namespace mapnik { + +struct tiff_saver : public mapnik::util::static_visitor<> +{ + tiff_saver(std::ostream &, std::string &); + template + void operator() (T const&) const; + private: + std::ostream & stream_; + std::string const& t_; +}; + +} // end ns + +#endif // MAPNIK_IMAGE_UTIL_TIFF_HPP diff --git a/include/mapnik/image_util_webp.hpp b/include/mapnik/image_util_webp.hpp new file mode 100644 index 000000000..8ba687082 --- /dev/null +++ b/include/mapnik/image_util_webp.hpp @@ -0,0 +1,47 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2014 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +#ifndef MAPNIK_IMAGE_UTIL_WEBP_HPP +#define MAPNIK_IMAGE_UTIL_WEBP_HPP + +// mapnik +#include + +// stl +#include +#include + +namespace mapnik { + +struct webp_saver : public mapnik::util::static_visitor<> +{ + webp_saver(std::ostream &, std::string &); + template + void operator() (T const&) const; + private: + std::ostream & stream_; + std::string const& t_; +}; + +} // end ns + +#endif // MAPNIK_IMAGE_UTIL_WEBP_HPP diff --git a/include/mapnik/image_view.hpp b/include/mapnik/image_view.hpp index 0b748d552..74fe7cab8 100644 --- a/include/mapnik/image_view.hpp +++ b/include/mapnik/image_view.hpp @@ -133,6 +133,12 @@ private: unsigned height_; T const& data_; }; -} + +using image_view_rgba8 = image_view; +using image_view_gray8 = image_view; +using image_view_gray16 = image_view; +using image_view_gray32f = image_view; + +} // end ns #endif // MAPNIK_IMAGE_VIEW_HPP diff --git a/include/mapnik/image_view_any.hpp b/include/mapnik/image_view_any.hpp new file mode 100644 index 000000000..822986d13 --- /dev/null +++ b/include/mapnik/image_view_any.hpp @@ -0,0 +1,79 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2014 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +#ifndef MAPNIK_IMAGE_VIEW_ANY_HPP +#define MAPNIK_IMAGE_VIEW_ANY_HPP + +#include +#include + +namespace mapnik { + +using image_view_base = util::variant; + +namespace detail { + +struct get_view_width_visitor +{ + template + std::size_t operator()(T const& data) const + { + return data.width(); + } +}; + +struct get_view_height_visitor +{ + template + std::size_t operator()(T const& data) const + { + return data.height(); + } +}; + +} // namespace detail + +struct image_view_any : image_view_base +{ + image_view_any() = default; + + template + image_view_any(T && data) noexcept + : image_view_base(std::move(data)) {} + + std::size_t width() const + { + return util::apply_visitor(detail::get_view_width_visitor(),*this); + } + + std::size_t height() const + { + return util::apply_visitor(detail::get_view_height_visitor(),*this); + } +}; + +} + +#endif // MAPNIK_IMAGE_VIEW_ANY_HPP diff --git a/include/mapnik/palette.hpp b/include/mapnik/palette.hpp index 950a76984..5dc3a4cdf 100644 --- a/include/mapnik/palette.hpp +++ b/include/mapnik/palette.hpp @@ -130,8 +130,6 @@ private: std::vector alpha_pal_; }; -typedef std::shared_ptr rgba_palette_ptr; - } // namespace mapnik #endif // MAPNIK_PALETTE_HPP diff --git a/include/mapnik/png_io.hpp b/include/mapnik/png_io.hpp index 4efd781ff..14b9edc44 100644 --- a/include/mapnik/png_io.hpp +++ b/include/mapnik/png_io.hpp @@ -657,14 +657,14 @@ void save_as_png8_hex(T1 & file, if (width + height > 3) // at least 3 pixels (hextree implementation requirement) { // structure for color quantization - std::shared_ptr> tree = std::make_shared>(opts.colors); + hextree tree(opts.colors); if (opts.trans_mode >= 0) { - tree->setTransMode(opts.trans_mode); + tree.setTransMode(opts.trans_mode); } if (opts.gamma > 0) { - tree->setGamma(opts.gamma); + tree.setGamma(opts.gamma); } for (unsigned y = 0; y < height; ++y) @@ -673,13 +673,13 @@ void save_as_png8_hex(T1 & file, for (unsigned x = 0; x < width; ++x) { unsigned val = row[x]; - tree->insert(mapnik::rgba(U2RED(val), U2GREEN(val), U2BLUE(val), U2ALPHA(val))); + tree.insert(mapnik::rgba(U2RED(val), U2GREEN(val), U2BLUE(val), U2ALPHA(val))); } } //transparency values per palette index std::vector pal; - tree->create_palette(pal); + tree.create_palette(pal); std::vector palette; std::vector alphaTable; for (unsigned i=0; i> >(file, image, tree, palette, alphaTable, opts); + save_as_png8 >(file, image, tree, palette, alphaTable, opts); } else { @@ -698,10 +698,10 @@ void save_as_png8_hex(T1 & file, template void save_as_png8_pal(T1 & file, T2 const& image, - rgba_palette_ptr const& pal, + rgba_palette const& pal, png_options const& opts) { - save_as_png8(file, image, pal, pal->palette(), pal->alphaTable(), opts); + save_as_png8(file, image, pal, pal.palette(), pal.alphaTable(), opts); } } diff --git a/src/image_util.cpp b/src/image_util.cpp index 2d0e68747..b54e75a8a 100644 --- a/src/image_util.cpp +++ b/src/image_util.cpp @@ -21,21 +21,13 @@ *****************************************************************************/ // mapnik -#if defined(HAVE_TIFF) -#include -#endif - -#if defined(HAVE_JPEG) -#include -#endif - -#if defined(HAVE_WEBP) -#include -#endif - #include +#include #include +#include +#include #include +#include #include #include #include @@ -75,7 +67,7 @@ namespace mapnik template std::string save_to_string(T const& image, std::string const& type, - rgba_palette_ptr const& palette) + rgba_palette const& palette) { std::ostringstream ss(std::ios::out|std::ios::binary); save_to_stream(image, ss, type, palette); @@ -95,7 +87,7 @@ template void save_to_file(T const& image, std::string const& filename, std::string const& type, - rgba_palette_ptr const& palette) + rgba_palette const& palette) { std::ofstream file (filename.c_str(), std::ios::out| std::ios::trunc|std::ios::binary); if (file) @@ -118,420 +110,11 @@ void save_to_file(T const& image, else throw ImageWriterException("Could not write file to " + filename ); } -#if defined(HAVE_TIFF) -void handle_tiff_options(std::string const& type, - tiff_config & config) -{ - if (type == "tiff") - { - return; - } - if (type.length() > 4) - { - boost::char_separator sep(":"); - boost::tokenizer< boost::char_separator > tokens(type, sep); - for (auto const& t : tokens) - { - if (t == "tiff") - { - continue; - } - else if (boost::algorithm::starts_with(t, "compression=")) - { - std::string val = t.substr(12); - if (!val.empty()) - { - if (val == "deflate") - { - config.compression = COMPRESSION_DEFLATE; - } - else if (val == "adobedeflate") - { - config.compression = COMPRESSION_ADOBE_DEFLATE; - } - else if (val == "lzw") - { - config.compression = COMPRESSION_LZW; - } - else if (val == "none") - { - config.compression = COMPRESSION_NONE; - } - else - { - throw ImageWriterException("invalid tiff compression: '" + val + "'"); - } - } - } - else if (boost::algorithm::starts_with(t, "method=")) - { - std::string val = t.substr(7); - if (!val.empty()) - { - if (val == "scanline") - { - config.method = TIFF_WRITE_SCANLINE; - } - else if (val == "strip" || val == "stripped") - { - config.method = TIFF_WRITE_STRIPPED; - } - else if (val == "tiled") - { - config.method = TIFF_WRITE_TILED; - } - else - { - throw ImageWriterException("invalid tiff method: '" + val + "'"); - } - } - } - else if (boost::algorithm::starts_with(t, "zlevel=")) - { - std::string val = t.substr(7); - if (!val.empty()) - { - if (!mapnik::util::string2int(val,config.zlevel) || config.zlevel < 0 || config.zlevel > 9) - { - throw ImageWriterException("invalid tiff zlevel: '" + val + "'"); - } - } - } - else if (boost::algorithm::starts_with(t, "tile_height=")) - { - std::string val = t.substr(12); - if (!val.empty()) - { - if (!mapnik::util::string2int(val,config.tile_height) || config.tile_height < 0 ) - { - throw ImageWriterException("invalid tiff tile_height: '" + val + "'"); - } - } - } - else if (boost::algorithm::starts_with(t, "tile_width=")) - { - std::string val = t.substr(11); - if (!val.empty()) - { - if (!mapnik::util::string2int(val,config.tile_width) || config.tile_width < 0 ) - { - throw ImageWriterException("invalid tiff tile_width: '" + val + "'"); - } - } - } - else if (boost::algorithm::starts_with(t, "rows_per_strip=")) - { - std::string val = t.substr(15); - if (!val.empty()) - { - if (!mapnik::util::string2int(val,config.rows_per_strip) || config.rows_per_strip < 0 ) - { - throw ImageWriterException("invalid tiff rows_per_strip: '" + val + "'"); - } - } - } - else - { - throw ImageWriterException("unhandled tiff option: " + t); - } - } - } -} -#endif - -#if defined(HAVE_WEBP) -void handle_webp_options(std::string const& type, - WebPConfig & config, - bool & alpha) -{ - if (type == "webp") - { - return; - } - if (type.length() > 4){ - boost::char_separator sep(":"); - boost::tokenizer< boost::char_separator > tokens(type, sep); - for (auto const& t : tokens) - { - if (t == "webp") - { - continue; - } - else if (boost::algorithm::starts_with(t, "quality=")) - { - std::string val = t.substr(8); - if (!val.empty()) - { - double quality = 90; - if (!mapnik::util::string2double(val,quality) || quality < 0.0 || quality > 100.0) - { - throw ImageWriterException("invalid webp quality: '" + val + "'"); - } - config.quality = static_cast(quality); - } - } - else if (boost::algorithm::starts_with(t, "method=")) - { - std::string val = t.substr(7); - if (!val.empty()) - { - if (!mapnik::util::string2int(val,config.method) || config.method < 0 || config.method > 6) - { - throw ImageWriterException("invalid webp method: '" + val + "'"); - } - } - } - else if (boost::algorithm::starts_with(t, "lossless=")) - { - std::string val = t.substr(9); - if (!val.empty()) - { - #if (WEBP_ENCODER_ABI_VERSION >> 8) >= 1 // >= v0.1.99 / 0x0100 - if (!mapnik::util::string2int(val,config.lossless) || config.lossless < 0 || config.lossless > 1) - { - throw ImageWriterException("invalid webp lossless: '" + val + "'"); - } - #else - #ifdef _MSC_VER - #pragma NOTE(compiling against webp that does not support the lossless flag) - #else - #warning "compiling against webp that does not support the lossless flag" - #endif - throw ImageWriterException("your webp version does not support the lossless option"); - #endif - } - } - else if (boost::algorithm::starts_with(t, "image_hint=")) - { - std::string val = t.substr(11); - if (!val.empty()) - { - #if (WEBP_ENCODER_ABI_VERSION >> 8) >= 1 // >= v0.1.99 / 0x0100 - int image_hint = 0; - if (!mapnik::util::string2int(val,image_hint) || image_hint < 0 || image_hint > 3) - { - throw ImageWriterException("invalid webp image_hint: '" + val + "'"); - } - config.image_hint = static_cast(image_hint); - #else - #ifdef _MSC_VER - #pragma NOTE(compiling against webp that does not support the image_hint flag) - #else - #warning "compiling against webp that does not support the image_hint flag" - #endif - throw ImageWriterException("your webp version does not support the image_hint option"); - #endif - } - } - else if (boost::algorithm::starts_with(t, "alpha=")) - { - std::string val = t.substr(6); - if (!val.empty()) - { - if (!mapnik::util::string2bool(val,alpha)) - { - throw ImageWriterException("invalid webp alpha: '" + val + "'"); - } - } - } - else if (boost::algorithm::starts_with(t, "target_size=")) - { - std::string val = t.substr(12); - if (!val.empty()) - { - if (!mapnik::util::string2int(val,config.target_size)) - { - throw ImageWriterException("invalid webp target_size: '" + val + "'"); - } - } - } - else if (boost::algorithm::starts_with(t, "target_psnr=")) - { - std::string val = t.substr(12); - if (!val.empty()) - { - double psnr = 0; - if (!mapnik::util::string2double(val,psnr)) - { - throw ImageWriterException("invalid webp target_psnr: '" + val + "'"); - } - config.target_PSNR = psnr; - } - } - else if (boost::algorithm::starts_with(t, "segments=")) - { - std::string val = t.substr(9); - if (!val.empty()) - { - if (!mapnik::util::string2int(val,config.segments)) - { - throw ImageWriterException("invalid webp segments: '" + val + "'"); - } - } - } - else if (boost::algorithm::starts_with(t, "sns_strength=")) - { - std::string val = t.substr(13); - if (!val.empty()) - { - if (!mapnik::util::string2int(val,config.sns_strength)) - { - throw ImageWriterException("invalid webp sns_strength: '" + val + "'"); - } - } - } - else if (boost::algorithm::starts_with(t, "filter_strength=")) - { - std::string val = t.substr(16); - if (!val.empty()) - { - if (!mapnik::util::string2int(val,config.filter_strength)) - { - throw ImageWriterException("invalid webp filter_strength: '" + val + "'"); - } - } - } - else if (boost::algorithm::starts_with(t, "filter_sharpness=")) - { - std::string val = t.substr(17); - if (!val.empty()) - { - if (!mapnik::util::string2int(val,config.filter_sharpness)) - { - throw ImageWriterException("invalid webp filter_sharpness: '" + val + "'"); - } - } - } - else if (boost::algorithm::starts_with(t, "filter_type=")) - { - std::string val = t.substr(12); - if (!val.empty()) - { - if (!mapnik::util::string2int(val,config.filter_type)) - { - throw ImageWriterException("invalid webp filter_type: '" + val + "'"); - } - } - } - else if (boost::algorithm::starts_with(t, "autofilter=")) - { - std::string val = t.substr(11); - if (!val.empty()) - { - if (!mapnik::util::string2int(val,config.autofilter)) - { - throw ImageWriterException("invalid webp autofilter: '" + val + "'"); - } - } - } - else if (boost::algorithm::starts_with(t, "alpha_compression=")) - { - std::string val = t.substr(18); - if (!val.empty()) - { - if (!mapnik::util::string2int(val,config.alpha_compression)) - { - throw ImageWriterException("invalid webp alpha_compression: '" + val + "'"); - } - } - } - else if (boost::algorithm::starts_with(t, "alpha_filtering=")) - { - std::string val = t.substr(16); - if (!val.empty()) - { - #if (WEBP_ENCODER_ABI_VERSION >> 8) >= 1 // >= v0.1.99 / 0x0100 - if (!mapnik::util::string2int(val,config.alpha_filtering)) - { - throw ImageWriterException("invalid webp alpha_filtering: '" + val + "'"); - } - #else - #ifdef _MSC_VER - #pragma NOTE(compiling against webp that does not support the alpha_filtering flag) - #else - #warning "compiling against webp that does not support the alpha_filtering flag" - #endif - throw ImageWriterException("your webp version does not support the alpha_filtering option"); - #endif - } - } - else if (boost::algorithm::starts_with(t, "alpha_quality=")) - { - std::string val = t.substr(14); - if (!val.empty()) - { - #if (WEBP_ENCODER_ABI_VERSION >> 8) >= 1 // >= v0.1.99 / 0x0100 - if (!mapnik::util::string2int(val,config.alpha_quality)) - { - throw ImageWriterException("invalid webp alpha_quality: '" + val + "'"); - } - #else - #ifdef _MSC_VER - #pragma NOTE(compiling against webp that does not support the alpha_quality flag) - #else - #warning "compiling against webp that does not support the alpha_quality flag" - #endif - throw ImageWriterException("your webp version does not support the alpha_quality option"); - #endif - } - } - else if (boost::algorithm::starts_with(t, "pass=")) - { - std::string val = t.substr(5); - if (!val.empty()) - { - if (!mapnik::util::string2int(val,config.pass)) - { - throw ImageWriterException("invalid webp pass: '" + val + "'"); - } - } - } - else if (boost::algorithm::starts_with(t, "preprocessing=")) - { - std::string val = t.substr(14); - if (!val.empty()) - { - if (!mapnik::util::string2int(val,config.preprocessing)) - { - throw ImageWriterException("invalid webp preprocessing: '" + val + "'"); - } - } - } - else if (boost::algorithm::starts_with(t, "partitions=")) - { - std::string val = t.substr(11); - if (!val.empty()) - { - if (!mapnik::util::string2int(val,config.partitions)) - { - throw ImageWriterException("invalid webp partitions: '" + val + "'"); - } - } - } - else if (boost::algorithm::starts_with(t, "partition_limit=")) - { - std::string val = t.substr(16); - if (!val.empty()) - { - if (!mapnik::util::string2int(val,config.partition_limit)) - { - throw ImageWriterException("invalid webp partition_limit: '" + val + "'"); - } - } - } - else - { - throw ImageWriterException("unhandled webp option: " + t); - } - } - } -} -#endif - -void save_to_stream(image_data_any const& image, +template <> +void save_to_stream(image_data_any const& image, std::ostream & stream, std::string const& type, - rgba_palette_ptr const& palette) + rgba_palette const& palette) { if (stream && image.width() > 0 && image.height() > 0) { @@ -539,7 +122,7 @@ void save_to_stream(image_data_any const& image, std::transform(t.begin(), t.end(), t.begin(), ::tolower); if (t == "png" || boost::algorithm::starts_with(t, "png")) { - mapnik::util::apply_visitor(png_saver(stream, t, palette), image); + mapnik::util::apply_visitor(png_saver_pal(stream, t, palette), image); } else if (boost::algorithm::starts_with(t, "tif")) { @@ -564,51 +147,19 @@ void save_to_stream(image_data_any const& image, std::transform(t.begin(), t.end(), t.begin(), ::tolower); if (t == "png" || boost::algorithm::starts_with(t, "png")) { - mapnik::util::apply_visitor(png_saver(stream, t), image); + util::apply_visitor(png_saver(stream, t), image); } else if (boost::algorithm::starts_with(t, "tif")) { -#if defined(HAVE_TIFF) - tiff_config config; - handle_tiff_options(t, config); - save_as_tiff(stream, image, config); -#else - throw ImageWriterException("tiff output is not enabled in your build of Mapnik"); -#endif + util::apply_visitor(tiff_saver(stream, t), image); } else if (boost::algorithm::starts_with(t, "jpeg")) { -#if defined(HAVE_JPEG) - int quality = 85; - std::string val = t.substr(4); - if (!val.empty()) - { - if (!mapnik::util::string2int(val,quality) || quality < 0 || quality > 100) - { - throw ImageWriterException("invalid jpeg quality: '" + val + "'"); - } - } - save_as_jpeg(stream, quality, image); -#else - throw ImageWriterException("jpeg output is not enabled in your build of Mapnik"); -#endif + util::apply_visitor(jpeg_saver(stream, t), image); } else if (boost::algorithm::starts_with(t, "webp")) { -#if defined(HAVE_WEBP) - WebPConfig config; - // Default values set here will be lossless=0 and quality=75 (as least as of webp v0.3.1) - if (!WebPConfigInit(&config)) - { - throw std::runtime_error("version mismatch"); - } - // see for more details: https://github.com/mapnik/mapnik/wiki/Image-IO#webp-output-options - bool alpha = true; - handle_webp_options(t,config,alpha); - save_as_webp(stream,image,config,alpha); -#else - throw ImageWriterException("webp output is not enabled in your build of Mapnik"); -#endif + util::apply_visitor(webp_saver(stream, t), image); } else throw ImageWriterException("unknown file type: " + type); } @@ -627,7 +178,7 @@ void save_to_file(T const& image, std::string const& filename) } template -void save_to_file(T const& image, std::string const& filename, rgba_palette_ptr const& palette) +void save_to_file(T const& image, std::string const& filename, rgba_palette const& palette) { boost::optional type = type_from_filename(filename); if (type) @@ -726,21 +277,21 @@ template void save_to_file(image_data_rgba8 const&, template void save_to_file(image_data_rgba8 const&, std::string const&, std::string const&, - rgba_palette_ptr const& palette); + rgba_palette const& palette); template void save_to_file(image_data_rgba8 const&, std::string const&); template void save_to_file(image_data_rgba8 const&, std::string const&, - rgba_palette_ptr const& palette); + rgba_palette const& palette); template std::string save_to_string(image_data_rgba8 const&, std::string const&); template std::string save_to_string(image_data_rgba8 const&, std::string const&, - rgba_palette_ptr const& palette); + rgba_palette const& palette); template void save_to_file > (image_view const&, std::string const&, @@ -749,21 +300,21 @@ template void save_to_file > (image_view > (image_view const&, std::string const&, std::string const&, - rgba_palette_ptr const& palette); + rgba_palette const& palette); template void save_to_file > (image_view const&, std::string const&); template void save_to_file > (image_view const&, std::string const&, - rgba_palette_ptr const& palette); + rgba_palette const& palette); template std::string save_to_string > (image_view const&, std::string const&); template std::string save_to_string > (image_view const&, std::string const&, - rgba_palette_ptr const& palette); + rgba_palette const& palette); void save_to_file(image_32 const& image,std::string const& file) { @@ -780,7 +331,7 @@ void save_to_file (image_32 const& image, void save_to_file (image_32 const& image, std::string const& file, std::string const& type, - rgba_palette_ptr const& palette) + rgba_palette const& palette) { save_to_file(image.data(), file, type, palette); } @@ -793,7 +344,7 @@ std::string save_to_string(image_32 const& image, std::string save_to_string(image_32 const& image, std::string const& type, - rgba_palette_ptr const& palette) + rgba_palette const& palette) { return save_to_string(image.data(), type, palette); } diff --git a/src/image_util_jpeg.cpp b/src/image_util_jpeg.cpp new file mode 100644 index 000000000..74a3c5aa5 --- /dev/null +++ b/src/image_util_jpeg.cpp @@ -0,0 +1,77 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2014 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +// mapnik +#if defined(HAVE_JPEG) +#include +#endif + +#include +#include + +// boost +#include + +// stl +#include +#include + +namespace mapnik +{ + +jpeg_saver::jpeg_saver(std::ostream & stream, std::string const& t): + stream_(stream), t_(t) {} + +void jpeg_saver::operator() (image_data_null const& image) const +{ + throw ImageWriterException("null images not supported"); +} + +template +void jpeg_saver::operator() (T const& image) const +{ +#if defined(HAVE_JPEG) + int quality = 85; + std::string val = t.substr(4); + if (!val.empty()) + { + if (!mapnik::util::string2int(val,quality) || quality < 0 || quality > 100) + { + throw ImageWriterException("invalid jpeg quality: '" + val + "'"); + } + } + save_as_jpeg(stream, quality, image); +#else + throw ImageWriterException("jpeg output is not enabled in your build of Mapnik"); +#endif +} + +template void jpeg_saver::operator() (image_data_rgba8 const& image) const; +template void jpeg_saver::operator() (image_data_gray8 const& image) const; +template void jpeg_saver::operator() (image_data_gray16 const& image) const; +template void jpeg_saver::operator() (image_data_gray32f const& image) const; +template void jpeg_saver::operator()> (image_view const& image) const; +template void jpeg_saver::operator()> (image_view const& image) const; +template void jpeg_saver::operator()> (image_view const& image) const; +template void jpeg_saver::operator()> (image_view const& image) const; + +} // end ns diff --git a/src/image_util_png.cpp b/src/image_util_png.cpp index b639b98d2..cd3527e8a 100644 --- a/src/image_util_png.cpp +++ b/src/image_util_png.cpp @@ -173,7 +173,10 @@ void handle_png_options(std::string const& type, } #endif -png_saver::png_saver(std::ostream & stream, std::string const& t, rgba_palette_ptr const& pal): +png_saver::png_saver(std::ostream & stream, std::string const& t): + stream_(stream), t_(t) {} + +png_saver_pal::png_saver_pal(std::ostream & stream, std::string const& t, rgba_palette const& pal): stream_(stream), t_(t), pal_(pal) {} void png_saver::operator() (image_data_null const& image) const @@ -181,7 +184,8 @@ void png_saver::operator() (image_data_null const& image) const throw ImageWriterException("null images not supported"); } -void png_saver::operator() (image_data_rgba8 const& image) const +template +void process_rgb8_png_pal(T const& image) { #if defined(HAVE_PNG) png_options opts; @@ -212,38 +216,54 @@ void png_saver::operator() (image_data_rgba8 const& image) const #endif } +template +void process_rgb8_png(T const& image) +{ +#if defined(HAVE_PNG) + png_options opts; + handle_png_options(t_, opts); + if (opts.paletted) + { + if (opts.use_hextree) + { + save_as_png8_hex(stream_, image, opts); + } + else + { + save_as_png8_oct(stream_, image, opts); + } + } + else + { + save_as_png(stream_, image, opts); + } +#else + throw ImageWriterException("png output is not enabled in your build of Mapnik"); +#endif +} + +void png_saver_pal::operator() (image_data_rgba8 const& image) const +{ + process_rgb8_png(image); +} + +void png_saver_pal::operator() (image_view const& image) const +{ + process_rgb8_png(image); +} + +void png_saver::operator() (image_data_rgba8 const& image) const +{ + process_rgb8_png(image); +} + void png_saver::operator() (image_view const& image) const { -#if defined(HAVE_PNG) - png_options opts; - handle_png_options(t_, opts); - if (pal_ && pal_->valid()) - { - png_options opts; - handle_png_options(t,opts); - save_as_png8_pal(stream, image, pal_, opts); - } - else if (opts.paletted) - { - if (opts.use_hextree) - { - save_as_png8_hex(stream_, image, opts); - } - else - { - save_as_png8_oct(stream_, image, opts); - } - } - else - { - save_as_png(stream_, image, opts); - } -#else - throw ImageWriterException("png output is not enabled in your build of Mapnik"); -#endif + process_rgb8_png(image); } -void png_saver::operator() (image_data_gray8 const& image) const +template +void png_saver::operator() (T const& image) const { #if defined(HAVE_PNG) png_options opts; @@ -254,7 +274,15 @@ void png_saver::operator() (image_data_gray8 const& image) const #endif } -void png_saver::operator() (image_view const& image) const +template void png_saver::operator() (image_data_gray8 const& image) const; +template void png_saver::operator() (image_data_gray16 const& image) const; +template void png_saver::operator() (image_data_gray32f const& image) const; +template void png_saver::operator()> (image_view const& image) const; +template void png_saver::operator()> (image_view const& image) const; +template void png_saver::operator()> (image_view const& image) const; + +template +void png_saver_pal::operator() (T const& image) const { #if defined(HAVE_PNG) png_options opts; @@ -265,47 +293,11 @@ void png_saver::operator() (image_view const& image) const #endif } -void png_saver::operator() (image_data_gray16 const& image) const -{ -#if defined(HAVE_PNG) - png_options opts; - handle_png_options(t_, opts); - save_as_png(stream_, image, opts); -#else - throw ImageWriterException("png output is not enabled in your build of Mapnik"); -#endif -} - -void png_saver::operator() (image_view const& image) const -{ -#if defined(HAVE_PNG) - png_options opts; - handle_png_options(t_, opts); - save_as_png(stream_, image, opts); -#else - throw ImageWriterException("png output is not enabled in your build of Mapnik"); -#endif -} - -void png_saver::operator() (mapnik::image_data_gray32f const& image) const -{ -#if defined(HAVE_PNG) - png_options opts; - handle_png_options(t_, opts); - save_as_png(stream_, image, opts); -#else - throw ImageWriterException("png output is not enabled in your build of Mapnik"); -#endif -} -void png_saver::operator() (mapnik::image_data_gray32f const& image) const -{ -#if defined(HAVE_PNG) - png_options opts; - handle_png_options(t_, opts); - save_as_png(stream_, image, opts); -#else - throw ImageWriterException("png output is not enabled in your build of Mapnik"); -#endif -} +template void png_saver_pal::operator() (image_data_gray8 const& image) const; +template void png_saver_pal::operator() (image_data_gray16 const& image) const; +template void png_saver_pal::operator() (image_data_gray32f const& image) const; +template void png_saver_pal::operator()> (image_view const& image) const; +template void png_saver_pal::operator()> (image_view const& image) const; +template void png_saver_pal::operator()> (image_view const& image) const; } // end ns diff --git a/src/image_util_tiff.cpp b/src/image_util_tiff.cpp new file mode 100644 index 000000000..92bd01a2b --- /dev/null +++ b/src/image_util_tiff.cpp @@ -0,0 +1,191 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2014 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +// mapnik +#if defined(HAVE_TIFF) +#include +#endif + +#include +#include + +// boost +#include + +// stl +#include +#include + +namespace mapnik +{ + +#if defined(HAVE_TIFF) +void handle_tiff_options(std::string const& type, + tiff_config & config) +{ + if (type == "tiff") + { + return; + } + if (type.length() > 4) + { + boost::char_separator sep(":"); + boost::tokenizer< boost::char_separator > tokens(type, sep); + for (auto const& t : tokens) + { + if (t == "tiff") + { + continue; + } + else if (boost::algorithm::starts_with(t, "compression=")) + { + std::string val = t.substr(12); + if (!val.empty()) + { + if (val == "deflate") + { + config.compression = COMPRESSION_DEFLATE; + } + else if (val == "adobedeflate") + { + config.compression = COMPRESSION_ADOBE_DEFLATE; + } + else if (val == "lzw") + { + config.compression = COMPRESSION_LZW; + } + else if (val == "none") + { + config.compression = COMPRESSION_NONE; + } + else + { + throw ImageWriterException("invalid tiff compression: '" + val + "'"); + } + } + } + else if (boost::algorithm::starts_with(t, "method=")) + { + std::string val = t.substr(7); + if (!val.empty()) + { + if (val == "scanline") + { + config.method = TIFF_WRITE_SCANLINE; + } + else if (val == "strip" || val == "stripped") + { + config.method = TIFF_WRITE_STRIPPED; + } + else if (val == "tiled") + { + config.method = TIFF_WRITE_TILED; + } + else + { + throw ImageWriterException("invalid tiff method: '" + val + "'"); + } + } + } + else if (boost::algorithm::starts_with(t, "zlevel=")) + { + std::string val = t.substr(7); + if (!val.empty()) + { + if (!mapnik::util::string2int(val,config.zlevel) || config.zlevel < 0 || config.zlevel > 9) + { + throw ImageWriterException("invalid tiff zlevel: '" + val + "'"); + } + } + } + else if (boost::algorithm::starts_with(t, "tile_height=")) + { + std::string val = t.substr(12); + if (!val.empty()) + { + if (!mapnik::util::string2int(val,config.tile_height) || config.tile_height < 0 ) + { + throw ImageWriterException("invalid tiff tile_height: '" + val + "'"); + } + } + } + else if (boost::algorithm::starts_with(t, "tile_width=")) + { + std::string val = t.substr(11); + if (!val.empty()) + { + if (!mapnik::util::string2int(val,config.tile_width) || config.tile_width < 0 ) + { + throw ImageWriterException("invalid tiff tile_width: '" + val + "'"); + } + } + } + else if (boost::algorithm::starts_with(t, "rows_per_strip=")) + { + std::string val = t.substr(15); + if (!val.empty()) + { + if (!mapnik::util::string2int(val,config.rows_per_strip) || config.rows_per_strip < 0 ) + { + throw ImageWriterException("invalid tiff rows_per_strip: '" + val + "'"); + } + } + } + else + { + throw ImageWriterException("unhandled tiff option: " + t); + } + } + } +} +#endif + +tiff_saver::tiff_saver(std::ostream & stream, std::string const& t): + stream_(stream), t_(t) {} + +void tiff_saver::operator() (image_data_null const& image) const +{ + throw ImageWriterException("null images not supported"); +} + +template +void tiff_saver::operator() (T const& image) const +{ +#if defined(HAVE_TIFF) + tiff_config opts; + handle_tiff_options(t_, opts); + save_as_tiff(stream_, image, opts); +#else + throw ImageWriterException("tiff output is not enabled in your build of Mapnik"); +#endif +} + +template void tiff_saver::operator() (image_data_rgba8 const& image) const; +template void tiff_saver::operator() (image_data_gray8 const& image) const; +template void tiff_saver::operator() (image_data_gray16 const& image) const; +template void tiff_saver::operator() (image_data_gray32f const& image) const; +template void tiff_saver::operator()> (image_view const& image) const; +template void tiff_saver::operator()> (image_view const& image) const; +template void tiff_saver::operator()> (image_view const& image) const; +template void tiff_saver::operator()> (image_view const& image) const; + +} // end ns diff --git a/src/image_util_webp.cpp b/src/image_util_webp.cpp new file mode 100644 index 000000000..a98168cbf --- /dev/null +++ b/src/image_util_webp.cpp @@ -0,0 +1,366 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2014 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +// mapnik +#if defined(HAVE_WEBP) +#include +#endif + +#include +#include + +// boost +#include + +// stl +#include +#include + +namespace mapnik +{ + +#if defined(HAVE_WEBP) +void handle_webp_options(std::string const& type, + WebPConfig & config, + bool & alpha) +{ + if (type == "webp") + { + return; + } + if (type.length() > 4){ + boost::char_separator sep(":"); + boost::tokenizer< boost::char_separator > tokens(type, sep); + for (auto const& t : tokens) + { + if (t == "webp") + { + continue; + } + else if (boost::algorithm::starts_with(t, "quality=")) + { + std::string val = t.substr(8); + if (!val.empty()) + { + double quality = 90; + if (!mapnik::util::string2double(val,quality) || quality < 0.0 || quality > 100.0) + { + throw ImageWriterException("invalid webp quality: '" + val + "'"); + } + config.quality = static_cast(quality); + } + } + else if (boost::algorithm::starts_with(t, "method=")) + { + std::string val = t.substr(7); + if (!val.empty()) + { + if (!mapnik::util::string2int(val,config.method) || config.method < 0 || config.method > 6) + { + throw ImageWriterException("invalid webp method: '" + val + "'"); + } + } + } + else if (boost::algorithm::starts_with(t, "lossless=")) + { + std::string val = t.substr(9); + if (!val.empty()) + { + #if (WEBP_ENCODER_ABI_VERSION >> 8) >= 1 // >= v0.1.99 / 0x0100 + if (!mapnik::util::string2int(val,config.lossless) || config.lossless < 0 || config.lossless > 1) + { + throw ImageWriterException("invalid webp lossless: '" + val + "'"); + } + #else + #ifdef _MSC_VER + #pragma NOTE(compiling against webp that does not support the lossless flag) + #else + #warning "compiling against webp that does not support the lossless flag" + #endif + throw ImageWriterException("your webp version does not support the lossless option"); + #endif + } + } + else if (boost::algorithm::starts_with(t, "image_hint=")) + { + std::string val = t.substr(11); + if (!val.empty()) + { + #if (WEBP_ENCODER_ABI_VERSION >> 8) >= 1 // >= v0.1.99 / 0x0100 + int image_hint = 0; + if (!mapnik::util::string2int(val,image_hint) || image_hint < 0 || image_hint > 3) + { + throw ImageWriterException("invalid webp image_hint: '" + val + "'"); + } + config.image_hint = static_cast(image_hint); + #else + #ifdef _MSC_VER + #pragma NOTE(compiling against webp that does not support the image_hint flag) + #else + #warning "compiling against webp that does not support the image_hint flag" + #endif + throw ImageWriterException("your webp version does not support the image_hint option"); + #endif + } + } + else if (boost::algorithm::starts_with(t, "alpha=")) + { + std::string val = t.substr(6); + if (!val.empty()) + { + if (!mapnik::util::string2bool(val,alpha)) + { + throw ImageWriterException("invalid webp alpha: '" + val + "'"); + } + } + } + else if (boost::algorithm::starts_with(t, "target_size=")) + { + std::string val = t.substr(12); + if (!val.empty()) + { + if (!mapnik::util::string2int(val,config.target_size)) + { + throw ImageWriterException("invalid webp target_size: '" + val + "'"); + } + } + } + else if (boost::algorithm::starts_with(t, "target_psnr=")) + { + std::string val = t.substr(12); + if (!val.empty()) + { + double psnr = 0; + if (!mapnik::util::string2double(val,psnr)) + { + throw ImageWriterException("invalid webp target_psnr: '" + val + "'"); + } + config.target_PSNR = psnr; + } + } + else if (boost::algorithm::starts_with(t, "segments=")) + { + std::string val = t.substr(9); + if (!val.empty()) + { + if (!mapnik::util::string2int(val,config.segments)) + { + throw ImageWriterException("invalid webp segments: '" + val + "'"); + } + } + } + else if (boost::algorithm::starts_with(t, "sns_strength=")) + { + std::string val = t.substr(13); + if (!val.empty()) + { + if (!mapnik::util::string2int(val,config.sns_strength)) + { + throw ImageWriterException("invalid webp sns_strength: '" + val + "'"); + } + } + } + else if (boost::algorithm::starts_with(t, "filter_strength=")) + { + std::string val = t.substr(16); + if (!val.empty()) + { + if (!mapnik::util::string2int(val,config.filter_strength)) + { + throw ImageWriterException("invalid webp filter_strength: '" + val + "'"); + } + } + } + else if (boost::algorithm::starts_with(t, "filter_sharpness=")) + { + std::string val = t.substr(17); + if (!val.empty()) + { + if (!mapnik::util::string2int(val,config.filter_sharpness)) + { + throw ImageWriterException("invalid webp filter_sharpness: '" + val + "'"); + } + } + } + else if (boost::algorithm::starts_with(t, "filter_type=")) + { + std::string val = t.substr(12); + if (!val.empty()) + { + if (!mapnik::util::string2int(val,config.filter_type)) + { + throw ImageWriterException("invalid webp filter_type: '" + val + "'"); + } + } + } + else if (boost::algorithm::starts_with(t, "autofilter=")) + { + std::string val = t.substr(11); + if (!val.empty()) + { + if (!mapnik::util::string2int(val,config.autofilter)) + { + throw ImageWriterException("invalid webp autofilter: '" + val + "'"); + } + } + } + else if (boost::algorithm::starts_with(t, "alpha_compression=")) + { + std::string val = t.substr(18); + if (!val.empty()) + { + if (!mapnik::util::string2int(val,config.alpha_compression)) + { + throw ImageWriterException("invalid webp alpha_compression: '" + val + "'"); + } + } + } + else if (boost::algorithm::starts_with(t, "alpha_filtering=")) + { + std::string val = t.substr(16); + if (!val.empty()) + { + #if (WEBP_ENCODER_ABI_VERSION >> 8) >= 1 // >= v0.1.99 / 0x0100 + if (!mapnik::util::string2int(val,config.alpha_filtering)) + { + throw ImageWriterException("invalid webp alpha_filtering: '" + val + "'"); + } + #else + #ifdef _MSC_VER + #pragma NOTE(compiling against webp that does not support the alpha_filtering flag) + #else + #warning "compiling against webp that does not support the alpha_filtering flag" + #endif + throw ImageWriterException("your webp version does not support the alpha_filtering option"); + #endif + } + } + else if (boost::algorithm::starts_with(t, "alpha_quality=")) + { + std::string val = t.substr(14); + if (!val.empty()) + { + #if (WEBP_ENCODER_ABI_VERSION >> 8) >= 1 // >= v0.1.99 / 0x0100 + if (!mapnik::util::string2int(val,config.alpha_quality)) + { + throw ImageWriterException("invalid webp alpha_quality: '" + val + "'"); + } + #else + #ifdef _MSC_VER + #pragma NOTE(compiling against webp that does not support the alpha_quality flag) + #else + #warning "compiling against webp that does not support the alpha_quality flag" + #endif + throw ImageWriterException("your webp version does not support the alpha_quality option"); + #endif + } + } + else if (boost::algorithm::starts_with(t, "pass=")) + { + std::string val = t.substr(5); + if (!val.empty()) + { + if (!mapnik::util::string2int(val,config.pass)) + { + throw ImageWriterException("invalid webp pass: '" + val + "'"); + } + } + } + else if (boost::algorithm::starts_with(t, "preprocessing=")) + { + std::string val = t.substr(14); + if (!val.empty()) + { + if (!mapnik::util::string2int(val,config.preprocessing)) + { + throw ImageWriterException("invalid webp preprocessing: '" + val + "'"); + } + } + } + else if (boost::algorithm::starts_with(t, "partitions=")) + { + std::string val = t.substr(11); + if (!val.empty()) + { + if (!mapnik::util::string2int(val,config.partitions)) + { + throw ImageWriterException("invalid webp partitions: '" + val + "'"); + } + } + } + else if (boost::algorithm::starts_with(t, "partition_limit=")) + { + std::string val = t.substr(16); + if (!val.empty()) + { + if (!mapnik::util::string2int(val,config.partition_limit)) + { + throw ImageWriterException("invalid webp partition_limit: '" + val + "'"); + } + } + } + else + { + throw ImageWriterException("unhandled webp option: " + t); + } + } + } +} +#endif + +webp_saver::webp_saver(std::ostream & stream, std::string const& t): + stream_(stream), t_(t) {} + +void webp_saver::operator() (image_data_null const& image) const +{ + throw ImageWriterException("null images not supported"); +} + +template +void webp_saver::operator() (T const& image) const +{ +#if defined(HAVE_WEBP) + WebPConfig config; + // Default values set here will be lossless=0 and quality=75 (as least as of webp v0.3.1) + if (!WebPConfigInit(&config)) + { + throw std::runtime_error("version mismatch"); + } + // see for more details: https://github.com/mapnik/mapnik/wiki/Image-IO#webp-output-options + bool alpha = true; + handle_webp_options(t,config,alpha); + save_as_webp(stream,image,config,alpha); +#else + throw ImageWriterException("webp output is not enabled in your build of Mapnik"); +#endif +} + +template void webp_saver::operator() (image_data_rgba8 const& image) const; +template void webp_saver::operator() (image_data_gray8 const& image) const; +template void webp_saver::operator() (image_data_gray16 const& image) const; +template void webp_saver::operator() (image_data_gray32f const& image) const; +template void webp_saver::operator()> (image_view const& image) const; +template void webp_saver::operator()> (image_view const& image) const; +template void webp_saver::operator()> (image_view const& image) const; +template void webp_saver::operator()> (image_view const& image) const; + +} // end ns