From 61abe608ee0189c98d9f8e76f4c8085910132774 Mon Sep 17 00:00:00 2001 From: Blake Thompson Date: Fri, 6 Mar 2015 17:24:23 -0600 Subject: [PATCH] Added the ability to get_type from an image, fixed possible bugs associated with image copy. --- bindings/python/mapnik_image.cpp | 6 +++++ include/mapnik/image.hpp | 23 +++++------------ include/mapnik/image_any.hpp | 16 ++++++++++++ include/mapnik/image_view.hpp | 6 +++++ include/mapnik/image_view_any.hpp | 14 +++++++++++ include/mapnik/pixel_types.hpp | 42 +++++++++++++++++++++++-------- src/image_copy.cpp | 12 ++++++++- tests/python_tests/image_test.py | 6 +++++ 8 files changed, 96 insertions(+), 29 deletions(-) diff --git a/bindings/python/mapnik_image.cpp b/bindings/python/mapnik_image.cpp index 87c9f2d7b..8c54b6cb3 100644 --- a/bindings/python/mapnik_image.cpp +++ b/bindings/python/mapnik_image.cpp @@ -222,6 +222,11 @@ void set_pixel_int(mapnik::image_any & im, unsigned x, unsigned y, int val) mapnik::set_pixel(im, x, y, val); } +unsigned get_type(mapnik::image_any & im) +{ + return im.get_dtype(); +} + std::shared_ptr open_from_file(std::string const& filename) { boost::optional type = type_from_filename(filename); @@ -441,6 +446,7 @@ void export_image() arg("y"), arg("get_color")=false )) + .def("get_type",&get_type) .def("clear",&clear) //TODO(haoyu) The method name 'tostring' might be confusing since they actually return bytes in Python 3 diff --git a/include/mapnik/image.hpp b/include/mapnik/image.hpp index b7eed4da1..abf856e8c 100644 --- a/include/mapnik/image.hpp +++ b/include/mapnik/image.hpp @@ -124,6 +124,7 @@ class image public: using pixel = T; using pixel_type = typename T::type; + static const image_dtype dtype = T::id; static constexpr std::size_t pixel_size = sizeof(pixel_type); private: detail::image_dimensions dimensions_; @@ -313,6 +314,11 @@ public: { return painted_; } + + inline image_dtype get_dtype() const + { + return dtype; + } }; using image_rgba8 = image; @@ -327,23 +333,6 @@ using image_gray64 = image; using image_gray64s = image; using image_gray64f = image; -enum image_dtype : std::uint8_t -{ - image_dtype_rgba8 = 0, - image_dtype_gray8, - image_dtype_gray8s, - image_dtype_gray16, - image_dtype_gray16s, - image_dtype_gray32, - image_dtype_gray32s, - image_dtype_gray32f, - image_dtype_gray64, - image_dtype_gray64s, - image_dtype_gray64f, - image_dtype_null, - IMAGE_DTYPE_MAX -}; - } // end ns #endif // MAPNIK_IMAGE_DATA_HPP diff --git a/include/mapnik/image_any.hpp b/include/mapnik/image_any.hpp index b432227fd..8b2ce6627 100644 --- a/include/mapnik/image_any.hpp +++ b/include/mapnik/image_any.hpp @@ -31,6 +31,7 @@ namespace mapnik { struct image_null { using pixel_type = uint8_t; + static const image_dtype dtype = image_dtype_null; unsigned char const* getBytes() const { return nullptr; } unsigned char* getBytes() { return nullptr;} unsigned getSize() const { return 0; } @@ -40,6 +41,7 @@ struct image_null bool painted() const { return false; } double get_offset() const { return 0.0; } void set_offset(double) {} + image_dtype get_dtype() const { return dtype; } double get_scaling() const { return 1.0; } void set_scaling(double) {} bool get_premultiplied() const { return false; } @@ -88,6 +90,15 @@ struct get_bytes_visitor } }; +struct get_dtype_visitor +{ + template + image_dtype operator()(T & data) + { + return data.get_dtype(); + } +}; + struct get_bytes_visitor_const { template @@ -263,6 +274,11 @@ struct image_any : image_base return util::apply_visitor(detail::get_scaling_visitor(),*this); } + image_dtype get_dtype() const + { + return util::apply_visitor(detail::get_dtype_visitor(),*this); + } + void set_offset(double val) { util::apply_visitor(detail::set_offset_visitor(val),*this); diff --git a/include/mapnik/image_view.hpp b/include/mapnik/image_view.hpp index 640235ac5..2d2d63650 100644 --- a/include/mapnik/image_view.hpp +++ b/include/mapnik/image_view.hpp @@ -33,6 +33,7 @@ class image_view public: using pixel = typename T::pixel; using pixel_type = typename T::pixel_type; + static const image_dtype dtype = T::dtype; static constexpr std::size_t pixel_size = sizeof(pixel_type); image_view(unsigned x, unsigned y, unsigned width, unsigned height, T const& data) @@ -131,6 +132,11 @@ public: { return data_.get_scaling(); } + + inline image_dtype get_dtype() const + { + return dtype; + } private: unsigned x_; diff --git a/include/mapnik/image_view_any.hpp b/include/mapnik/image_view_any.hpp index 9f47f0ae4..90bb0dbe4 100644 --- a/include/mapnik/image_view_any.hpp +++ b/include/mapnik/image_view_any.hpp @@ -69,6 +69,15 @@ struct get_view_size_visitor } }; +struct get_view_dtype_visitor +{ + template + image_dtype operator()(T const& data) const + { + return data.get_dtype(); + } +}; + struct get_view_row_size_visitor { template @@ -148,6 +157,11 @@ struct image_view_any : image_view_base { return util::apply_visitor(detail::get_view_scaling_visitor(),*this); } + + image_dtype get_dtype() const + { + return util::apply_visitor(detail::get_view_dtype_visitor(),*this); + } }; } diff --git a/include/mapnik/pixel_types.hpp b/include/mapnik/pixel_types.hpp index aef5dca8c..2a36cd443 100644 --- a/include/mapnik/pixel_types.hpp +++ b/include/mapnik/pixel_types.hpp @@ -25,16 +25,36 @@ #include -struct rgba8_t { using type = std::uint32_t; }; -struct gray8_t { using type = std::uint8_t; }; -struct gray8s_t { using type = std::int8_t; }; -struct gray16_t { using type = std::uint16_t; }; -struct gray16s_t { using type = std::int16_t; }; -struct gray32_t { using type = std::uint32_t; }; -struct gray32s_t { using type = std::int32_t; }; -struct gray32f_t { using type = float; }; -struct gray64_t { using type = std::uint64_t; }; -struct gray64s_t { using type = std::int64_t; }; -struct gray64f_t { using type = double; }; +namespace mapnik { +enum image_dtype : std::uint8_t +{ + image_dtype_rgba8 = 0, + image_dtype_gray8, + image_dtype_gray8s, + image_dtype_gray16, + image_dtype_gray16s, + image_dtype_gray32, + image_dtype_gray32s, + image_dtype_gray32f, + image_dtype_gray64, + image_dtype_gray64s, + image_dtype_gray64f, + image_dtype_null, + IMAGE_DTYPE_MAX +}; + +struct rgba8_t { using type = std::uint32_t; static const image_dtype id = image_dtype_rgba8; }; +struct gray8_t { using type = std::uint8_t; static const image_dtype id = image_dtype_gray8; }; +struct gray8s_t { using type = std::int8_t; static const image_dtype id = image_dtype_gray8s; }; +struct gray16_t { using type = std::uint16_t; static const image_dtype id = image_dtype_gray16; }; +struct gray16s_t { using type = std::int16_t; static const image_dtype id = image_dtype_gray16s; }; +struct gray32_t { using type = std::uint32_t; static const image_dtype id = image_dtype_gray32; }; +struct gray32s_t { using type = std::int32_t; static const image_dtype id = image_dtype_gray32s; }; +struct gray32f_t { using type = float; static const image_dtype id = image_dtype_gray32f; }; +struct gray64_t { using type = std::uint64_t; static const image_dtype id = image_dtype_gray64; }; +struct gray64s_t { using type = std::int64_t; static const image_dtype id = image_dtype_gray64s; }; +struct gray64f_t { using type = double; static const image_dtype id = image_dtype_gray64f; }; + +} // end ns #endif // MAPNIK_PIXEL_TYPES_HPP diff --git a/src/image_copy.cpp b/src/image_copy.cpp index 312b51dda..f676cee3d 100644 --- a/src/image_copy.cpp +++ b/src/image_copy.cpp @@ -94,7 +94,17 @@ struct visitor_image_copy_so T0 operator() (T0 const& src) { - return T0(src); + if (offset_ == src.get_offset() && scaling_ == src.get_scaling()) + { + return T0(src); + } + else + { + T0 dst(src); + dst.set_scaling(scaling_); + dst.set_offset(offset_); + return T0(std::move(dst)); + } } template diff --git a/tests/python_tests/image_test.py b/tests/python_tests/image_test.py index d4a473d03..3a1dd9a81 100644 --- a/tests/python_tests/image_test.py +++ b/tests/python_tests/image_test.py @@ -10,6 +10,12 @@ def setup(): # from another directory we need to chdir() os.chdir(execution_path('.')) +def test_type(): + im = mapnik.Image(256, 256) + eq_(im.get_type(), mapnik.ImageType.rgba8) + im = mapnik.Image(256, 256, mapnik.ImageType.gray8) + eq_(im.get_type(), mapnik.ImageType.gray8) + def test_image_premultiply(): im = mapnik.Image(256,256) eq_(im.premultiplied(),False)