From a002139e186c4a85ad7ab3ef1b7130f6ec5df347 Mon Sep 17 00:00:00 2001 From: Blake Thompson Date: Fri, 16 Jan 2015 18:26:56 -0600 Subject: [PATCH] Added set_pixel to visitor pattern and moved it to image_util. Added exception throwing in composite only if debug flags are on. Ref #2633 --- bindings/python/mapnik_image.cpp | 2 +- include/mapnik/graphics.hpp | 15 ----- include/mapnik/image_data_any.hpp | 1 + include/mapnik/image_util.hpp | 7 ++- src/agg/agg_renderer.cpp | 8 +-- src/agg/process_debug_symbolizer.cpp | 19 +++--- src/image_compositing.cpp | 3 +- src/image_util.cpp | 92 ++++++++++++++++++++++++++++ 8 files changed, 115 insertions(+), 32 deletions(-) diff --git a/bindings/python/mapnik_image.cpp b/bindings/python/mapnik_image.cpp index 3b6156c7f..684ebeeea 100644 --- a/bindings/python/mapnik_image.cpp +++ b/bindings/python/mapnik_image.cpp @@ -144,7 +144,7 @@ unsigned get_pixel(mapnik::image_32 const& im, int x, int y) void set_pixel(mapnik::image_32 & im, unsigned x, unsigned y, mapnik::color const& c) { - im.setPixel(x, y, c.rgba()); + mapnik::set_pixel(im.data(), x, y, c); } std::shared_ptr open_from_file(std::string const& filename) diff --git a/include/mapnik/graphics.hpp b/include/mapnik/graphics.hpp index 2fa5e5770..1ea190283 100644 --- a/include/mapnik/graphics.hpp +++ b/include/mapnik/graphics.hpp @@ -89,22 +89,7 @@ public: return image_view_rgba8(x,y,w,h,data_); } -private: - - inline bool checkBounds(int x, int y) const - { - return (x >= 0 && x < static_cast(data_.width()) && y >= 0 && y < static_cast(data_.height())); - } - public: - inline void setPixel(int x,int y,unsigned int rgba) - { - if (checkBounds(x,y)) - { - data_(x,y)=rgba; - } - } - inline unsigned width() const { return data_.width(); diff --git a/include/mapnik/image_data_any.hpp b/include/mapnik/image_data_any.hpp index 072688c46..32133813c 100644 --- a/include/mapnik/image_data_any.hpp +++ b/include/mapnik/image_data_any.hpp @@ -38,6 +38,7 @@ struct image_data_null bool get_premultiplied() const { return false; } void set_premultiplied(bool) const {} void set(pixel_type const&) { throw std::runtime_error("Can not set values for null image_data"); } + pixel_type& operator() (std::size_t, std::size_t) { throw std::runtime_error("Can not set or get values for null image_data"); } }; using image_data_base = util::variant MAPNIK_DECL void set_rectangle (T & dst, T const& src, int x = 0, int y = 0); template -MAPNIK_DECL bool check_bounds (T const& data, int x, int y) +MAPNIK_DECL bool check_bounds (T const& data, std::size_t x, std::size_t y) { - return (x >= 0 && x < static_cast(data.width()) && y >= 0 && y < static_cast(data.height())); + return (x < static_cast(data.width()) && y < static_cast(data.height())); } template MAPNIK_DECL void composite_pixel(T & data, unsigned op, int x, int y, unsigned c, unsigned cover, double opacity ); +template +MAPNIK_DECL void set_pixel(T1 & data, std::size_t x, std::size_t y, T2 const& val); + inline bool is_png(std::string const& filename) { return boost::algorithm::iends_with(filename,std::string(".png")); diff --git a/src/agg/agg_renderer.cpp b/src/agg/agg_renderer.cpp index f34c6aee4..9274a6f01 100644 --- a/src/agg/agg_renderer.cpp +++ b/src/agg/agg_renderer.cpp @@ -507,13 +507,13 @@ void agg_renderer::draw_geo_extent(box2d const& extent, mapnik::c unsigned rgba = color.rgba(); for (double x=x0; x #include #include +#include namespace mapnik { @@ -38,13 +39,13 @@ void draw_rect(image_32 &pixmap, box2d const& box) unsigned color1 = 0xff0000ff; for (int x=x0; x::process(debug_symbolizer const& sym, if (cmd == SEG_CLOSE) continue; prj_trans.backward(x,y,z); common_.t_.forward(&x,&y); - pixmap_.setPixel(x,y,0xff0000ff); - pixmap_.setPixel(x-1,y-1,0xff0000ff); - pixmap_.setPixel(x+1,y+1,0xff0000ff); - pixmap_.setPixel(x-1,y+1,0xff0000ff); - pixmap_.setPixel(x+1,y-1,0xff0000ff); + mapnik::set_pixel(pixmap_.data(),x,y,0xff0000ff); + mapnik::set_pixel(pixmap_.data(),x-1,y-1,0xff0000ff); + mapnik::set_pixel(pixmap_.data(),x+1,y+1,0xff0000ff); + mapnik::set_pixel(pixmap_.data(),x-1,y+1,0xff0000ff); + mapnik::set_pixel(pixmap_.data(),x+1,y-1,0xff0000ff); } } } diff --git a/src/image_compositing.cpp b/src/image_compositing.cpp index ac1823f6e..181702c12 100644 --- a/src/image_compositing.cpp +++ b/src/image_compositing.cpp @@ -166,7 +166,7 @@ MAPNIK_DECL void composite(image_data_rgba8 & dst, image_data_rgba8 const& src, pixfmt_type pixf(dst_buffer); pixf.comp_op(static_cast(mode)); agg::pixfmt_alpha_blend_rgba pixf_mask(src_buffer); - // DEBUGGING ONLY REMOVE +#ifdef MAPNIK_DEBUG if (!src.get_premultiplied()) { throw std::runtime_error("SOURCE MUST BE PREMULTIPLIED FOR COMPOSITING!"); @@ -175,6 +175,7 @@ MAPNIK_DECL void composite(image_data_rgba8 & dst, image_data_rgba8 const& src, { throw std::runtime_error("DESTINATION MUST BE PREMULTIPLIED FOR COMPOSITING!"); } +#endif renderer_type ren(pixf); ren.blend_from(pixf_mask,0,dx,dy,unsigned(255*opacity)); } diff --git a/src/image_util.cpp b/src/image_util.cpp index b8978d936..83681e5ec 100644 --- a/src/image_util.cpp +++ b/src/image_util.cpp @@ -1014,4 +1014,96 @@ MAPNIK_DECL void composite_pixel(image_data_rgba8 & data, unsi visitor(data); } +namespace detail { + +template +struct visitor_set_pixel +{ + visitor_set_pixel(std::size_t x, std::size_t y, T1 const& val) + : val_(val), x_(x), y_(y) {} + + template + void operator() (T2 & data) + { + using pixel_type = typename T2::pixel_type; + pixel_type val = static_cast(val_); + if (check_bounds(data, x_, y_)) + { + data(x_, y_) = val; + } + } + + private: + T1 const& val_; + std::size_t x_; + std::size_t y_; +}; + +template<> +struct visitor_set_pixel +{ + visitor_set_pixel(std::size_t x, std::size_t y, color const& val) + : val_(val), x_(x), y_(y) {} + + template + void operator() (T2 & data) + { + using pixel_type = typename T2::pixel_type; + pixel_type val = static_cast(val_.rgba()); + if (check_bounds(data, x_, y_)) + { + data(x_, y_) = val; + } + } + + private: + color const& val_; + std::size_t x_; + std::size_t y_; +}; + +} // end detail ns + +// For all the generic data types. +template +MAPNIK_DECL void set_pixel (T1 & data, std::size_t x, std::size_t y, T2 const& val) +{ + util::apply_visitor(detail::visitor_set_pixel(x, y, val), data); +} + +template void set_pixel(image_data_any &, std::size_t, std::size_t, color const&); +template void set_pixel(image_data_any &, std::size_t, std::size_t, uint32_t const&); +template void set_pixel(image_data_any &, std::size_t, std::size_t, int32_t const&); +template void set_pixel(image_data_any &, std::size_t, std::size_t, uint16_t const&); +template void set_pixel(image_data_any &, std::size_t, std::size_t, int16_t const&); +template void set_pixel(image_data_any &, std::size_t, std::size_t, uint8_t const&); +template void set_pixel(image_data_any &, std::size_t, std::size_t, int8_t const&); +template void set_pixel(image_data_any &, std::size_t, std::size_t, float const&); +template void set_pixel(image_data_any &, std::size_t, std::size_t, double const&); + + +// Temporary remove these later! +template <> +MAPNIK_DECL void set_pixel (image_data_rgba8 & data, std::size_t x, std::size_t y, color const& val) +{ + detail::visitor_set_pixel visitor(x, y, val); + visitor(data); +} + +// Temporary remove these later! +template <> +MAPNIK_DECL void set_pixel (image_data_rgba8 & data, std::size_t x, std::size_t y, uint32_t const& val) +{ + detail::visitor_set_pixel visitor(x, y, val); + visitor(data); +} + +// Temporary remove these later! +template <> +MAPNIK_DECL void set_pixel (image_data_rgba8 & data, std::size_t x, std::size_t y, int32_t const& val) +{ + detail::visitor_set_pixel visitor(x, y, val); + visitor(data); +} + } // end ns