diff --git a/include/mapnik/pixel_cast.hpp b/include/mapnik/pixel_cast.hpp index efa76d9bc..23d465975 100644 --- a/include/mapnik/pixel_cast.hpp +++ b/include/mapnik/pixel_cast.hpp @@ -23,23 +23,147 @@ #ifndef MAPNIK_PIXEL_CAST_HPP #define MAPNIK_PIXEL_CAST_HPP -#include +#include namespace mapnik { +namespace detail { + +template +struct numeric_compare; + +template +struct numeric_compare_same_sign +{ + using sizeup = typename std::conditional= sizeof(S), T, S>::type; + + static inline bool less(T t, S s) { + return static_cast(t) < static_cast(s); + } + + static inline bool greater(T t, S s) { + return static_cast(t) > static_cast(s); + } +}; + +template +struct numeric_compare::value && !std::is_floating_point::value && + ((std::is_unsigned::value && std::is_unsigned::value) + || (std::is_signed::value && std::is_signed::value))> + ::type> : numeric_compare_same_sign +{}; + + +template +struct numeric_compare::value && !std::is_floating_point::value && + std::is_integral::value && std::is_signed::value && std::is_unsigned::value>::type> +{ + static inline bool less(T t, S s) { + return (t < static_cast(0)) ? true : static_cast(t) < static_cast(s); + } + + static inline bool greater(T t, S s) { + return (t < static_cast(0)) ? false : static_cast(t) > static_cast(s); + } +}; + +template +struct numeric_compare::value && !std::is_floating_point::value && + std::is_integral::value && std::is_unsigned::value && std::is_signed::value>::type> +{ + static inline bool less(T t, S s) { + return (s < static_cast(0)) ? false : static_cast(t) < static_cast(s); + } + + static inline bool greater(T t, S s) { + return (s < static_cast(0)) ? true : static_cast(t) > static_cast(s); + } +}; + +template +struct numeric_compare::value && std::is_floating_point::value>::type> +{ + static inline bool less(T t, S s) { + return t < s; + } + + static inline bool greater(T t, S s) { + return t > s; + } +}; + +template +struct numeric_compare::value && std::is_integral::value>::type> +{ + static inline bool less(T t, S s) { + return less(static_cast(t),static_cast(s)); + } + + static inline bool greater(T t, S s) { + return greater(static_cast(t),static_cast(s)); + } +}; + + +template +struct numeric_compare::value && std::is_floating_point::value>::type> +{ + static inline bool less(T t, S s) { + return less(static_cast(t),static_cast(s)); + } + + static inline bool greater(T t, S s) { + return greater(static_cast(t),static_cast(s)); + } +}; + +template +inline bool less(T t, S s) { + return numeric_compare::less(t,s); +} + +template +inline bool greater(T t, S s) { + return numeric_compare::greater(t,s); +} + +// floats +template +struct bounds +{ + static constexpr T lowest() { return static_cast(-std::numeric_limits::max());} + static constexpr T highest() { return std::numeric_limits::max();} +}; + +// integers +template +struct bounds::is_integer>::type > +{ + static constexpr T lowest() { return std::numeric_limits::min();} + static constexpr T highest() { return std::numeric_limits::max();} +}; + +} // ns detail + + template inline T pixel_cast(S s) { - using namespace boost::numeric; - if (s > bounds::highest() ) + static constexpr auto max_val = detail::bounds::highest(); + static constexpr auto min_val = detail::bounds::lowest(); + + if (detail::greater(s,max_val)) { - return bounds::highest(); + return max_val; } - else if (s < bounds::lowest()) + else if (detail::less(s,min_val)) { - return bounds::lowest(); + return min_val; + } + else + { + return static_cast(s); } - else return static_cast(s); } } // ns mapnik diff --git a/test/unit/imaging/image_set_pixel.cpp b/test/unit/imaging/image_set_pixel.cpp new file mode 100644 index 000000000..ed7ceaffc --- /dev/null +++ b/test/unit/imaging/image_set_pixel.cpp @@ -0,0 +1,28 @@ +#include "catch.hpp" + +// mapnik +#include +#include +#include +#include + + +TEST_CASE("image set_pixel") { + +SECTION("test gray32") { + mapnik::image_gray32 im(256,256); + mapnik::set_pixel(im, 0, 0, -1); + auto pixel = mapnik::get_pixel(im, 0, 0); + INFO( pixel ); + CHECK( pixel == 0 ); +} + +SECTION("test gray8s") { + mapnik::image_gray8s im(256,256); + mapnik::set_pixel(im, 0, 0, std::numeric_limits::max()+1); + auto pixel = mapnik::get_pixel(im, 0, 0); + INFO( pixel ); + CHECK( (int)pixel == (int)std::numeric_limits::max() ); +} + +} \ No newline at end of file