Merge branch 'image_filters'

This commit is contained in:
artemp 2015-08-12 11:28:32 +02:00
commit 241b900673
7 changed files with 448 additions and 46 deletions

View file

@ -18,6 +18,7 @@ Released: YYYY XX, 2015
- Added 3 new image-filters to simulate types of colorblindness (`color-blind-protanope`,`color-blind-deuteranope`,`color-blind-tritanope`)
- Fix so that null text boxes have no bounding boxes when attempting placement ( 162f82cba5b0fb984c425586c6a4b354917abc47 )
- Patch to add legacy method for setting JPEG quality in images ( #3024 )
- Added `filter_image` method which can modify an image in place or return a new image that is filtered.
## 3.0.2

View file

@ -26,6 +26,7 @@
//mapnik
#include <mapnik/image_filter_types.hpp>
#include <mapnik/image_util.hpp>
#include <mapnik/util/hsl.hpp>
// boost GIL
@ -394,17 +395,15 @@ void apply_convolution_3x3(Src const& src_view, Dst & dst_view, Filter const& fi
template <typename Src, typename Filter>
void apply_filter(Src & src, Filter const& filter)
{
{
demultiply_alpha(src);
double_buffer<Src> tb(src);
apply_convolution_3x3(tb.src_view, tb.dst_view, filter);
} // ensure ~double_buffer() is called before premultiplying
premultiply_alpha(src);
demultiply_alpha(src);
double_buffer<Src> tb(src);
apply_convolution_3x3(tb.src_view, tb.dst_view, filter);
}
template <typename Src>
void apply_filter(Src & src, agg_stack_blur const& op)
{
premultiply_alpha(src);
agg::rendering_buffer buf(src.bytes(),src.width(),src.height(), src.row_size());
agg::pixfmt_rgba32_pre pixf(buf);
agg::stack_blur_rgba32(pixf,op.rx,op.ry);
@ -427,6 +426,7 @@ template <typename Src>
void apply_filter(Src & src, color_to_alpha const& op)
{
using namespace boost::gil;
bool premultiplied = src.get_premultiplied();
rgba8_view_t src_view = rgba8_view(src);
double cr = static_cast<double>(op.color.red())/255.0;
double cg = static_cast<double>(op.color.green())/255.0;
@ -450,7 +450,7 @@ void apply_filter(Src & src, color_to_alpha const& op)
r = g = b = 0;
continue;
}
else
else if (premultiplied)
{
sr /= sa;
sg /= sa;
@ -479,6 +479,8 @@ void apply_filter(Src & src, color_to_alpha const& op)
}
}
}
// set as premultiplied
set_premultiplied_alpha(src, true);
}
template <typename Src>
@ -509,6 +511,8 @@ void apply_filter(Src & src, colorize_alpha const& op)
}
}
}
// set as premultiplied
set_premultiplied_alpha(src, true);
}
else if (size > 1)
{
@ -584,6 +588,8 @@ void apply_filter(Src & src, colorize_alpha const& op)
}
}
}
// set as premultiplied
set_premultiplied_alpha(src, true);
}
}
@ -597,6 +603,7 @@ void apply_filter(Src & src, scale_hsla const& transform)
// should be run to avoid overhead of temp buffer
if (tinting || set_alpha)
{
bool premultiplied = src.get_premultiplied();
rgba8_view_t src_view = rgba8_view(src);
for (std::ptrdiff_t y = 0; y < src_view.height(); ++y)
{
@ -617,12 +624,13 @@ void apply_filter(Src & src, scale_hsla const& transform)
r = g = b = 0;
continue;
}
else
else if (premultiplied)
{
r2 /= a2;
g2 /= a2;
b2 /= a2;
}
if (set_alpha)
{
a2 = transform.a0 + (a2 * (transform.a1 - transform.a0));
@ -671,6 +679,8 @@ void apply_filter(Src & src, scale_hsla const& transform)
if (b>a) b=a;
}
}
// set as premultiplied
set_premultiplied_alpha(src, true);
}
}
@ -679,6 +689,7 @@ void color_blind_filter(Src & src, ColorBlindFilter const& op)
{
using namespace boost::gil;
rgba8_view_t src_view = rgba8_view(src);
bool premultiplied = src.get_premultiplied();
for (std::ptrdiff_t y = 0; y < src_view.height(); ++y)
{
@ -700,7 +711,7 @@ void color_blind_filter(Src & src, ColorBlindFilter const& op)
r = g = b = 0;
continue;
}
else
else if (premultiplied)
{
dr /= da;
dg /= da;
@ -790,7 +801,8 @@ void color_blind_filter(Src & src, ColorBlindFilter const& op)
b = static_cast<uint8_t>(db * 255.0);
}
}
// set as premultiplied
set_premultiplied_alpha(src, true);
}
template <typename Src>
@ -814,6 +826,7 @@ void apply_filter(Src & src, color_blind_tritanope const& op)
template <typename Src>
void apply_filter(Src & src, gray const& /*op*/)
{
premultiply_alpha(src);
using namespace boost::gil;
rgba8_view_t src_view = rgba8_view(src);
@ -864,6 +877,7 @@ void x_gradient_impl(Src const& src_view, Dst const& dst_view)
template <typename Src>
void apply_filter(Src & src, x_gradient const& /*op*/)
{
premultiply_alpha(src);
double_buffer<Src> tb(src);
x_gradient_impl(tb.src_view, tb.dst_view);
}
@ -871,6 +885,7 @@ void apply_filter(Src & src, x_gradient const& /*op*/)
template <typename Src>
void apply_filter(Src & src, y_gradient const& /*op*/)
{
premultiply_alpha(src);
double_buffer<Src> tb(src);
x_gradient_impl(rotated90ccw_view(tb.src_view),
rotated90ccw_view(tb.dst_view));
@ -879,6 +894,7 @@ void apply_filter(Src & src, y_gradient const& /*op*/)
template <typename Src>
void apply_filter(Src & src, invert const& /*op*/)
{
premultiply_alpha(src);
using namespace boost::gil;
rgba8_view_t src_view = rgba8_view(src);
@ -931,6 +947,40 @@ struct filter_radius_visitor
}
};
}}
template<typename Src>
void filter_image(Src & src, std::string const& filter)
{
std::vector<filter_type> filter_vector;
if(!parse_image_filters(filter, filter_vector))
{
throw std::runtime_error("Failed to parse filter argument in filter_image: '" + filter + "'");
}
filter_visitor<Src> visitor(src);
for (filter_type const& filter_tag : filter_vector)
{
util::apply_visitor(visitor, filter_tag);
}
}
template<typename Src>
Src filter_image(Src const& src, std::string const& filter)
{
std::vector<filter_type> filter_vector;
if(!parse_image_filters(filter, filter_vector))
{
throw std::runtime_error("Failed to parse filter argument in filter_image: '" + filter + "'");
}
Src new_src(src);
filter_visitor<Src> visitor(new_src);
for (filter_type const& filter_tag : filter_vector)
{
util::apply_visitor(visitor, filter_tag);
}
return new_src;
}
} // End Namespace Filter
} // End Namespace Mapnik
#endif // MAPNIK_IMAGE_FILTER_HPP

View file

@ -33,7 +33,6 @@
#include <mapnik/well_known_srs.hpp>
#include <mapnik/image_compositing.hpp>
#include <mapnik/font_engine_freetype.hpp>
#include <mapnik/image_filter_types.hpp>
// boost
#include <boost/optional.hpp>
@ -102,7 +101,6 @@ private:
boost::optional<std::string> font_directory_;
freetype_engine::font_file_mapping_type font_file_mapping_;
freetype_engine::font_memory_cache_type font_memory_cache_;
std::vector<filter::filter_type> filters_;
public:
@ -502,16 +500,6 @@ public:
return font_memory_cache_;
}
std::vector<filter::filter_type> & image_filters()
{
return filters_;
}
std::vector<filter::filter_type> const& image_filters() const
{
return filters_;
}
private:
friend void swap(Map & rhs, Map & lhs);
void fixAspectRatio();

View file

@ -199,15 +199,6 @@ void agg_renderer<T0,T1>::start_map_processing(Map const& map)
template <typename T0, typename T1>
void agg_renderer<T0,T1>::end_map_processing(Map const& map)
{
if (map.image_filters().size() > 0)
{
mapnik::filter::filter_visitor<buffer_type> visitor(pixmap_);
for (mapnik::filter::filter_type const& filter_tag : map.image_filters())
{
util::apply_visitor(visitor, filter_tag);
}
}
mapnik::demultiply_alpha(pixmap_);
MAPNIK_LOG_DEBUG(agg_renderer) << "agg_renderer: End map processing";
}
@ -318,6 +309,7 @@ void agg_renderer<T0,T1>::end_style_processing(feature_type_style const& st)
{
util::apply_visitor(visitor, filter_tag);
}
mapnik::premultiply_alpha(*current_buffer_);
}
if (st.comp_op())
{
@ -334,11 +326,15 @@ void agg_renderer<T0,T1>::end_style_processing(feature_type_style const& st)
-common_.t_.offset());
}
}
// apply any 'direct' image filters
mapnik::filter::filter_visitor<buffer_type> visitor(pixmap_);
for (mapnik::filter::filter_type const& filter_tag : st.direct_image_filters())
if (st.direct_image_filters().size() > 0)
{
util::apply_visitor(visitor, filter_tag);
// apply any 'direct' image filters
mapnik::filter::filter_visitor<buffer_type> visitor(pixmap_);
for (mapnik::filter::filter_type const& filter_tag : st.direct_image_filters())
{
util::apply_visitor(visitor, filter_tag);
}
mapnik::premultiply_alpha(pixmap_);
}
MAPNIK_LOG_DEBUG(agg_renderer) << "agg_renderer: End processing style";
}

View file

@ -197,15 +197,6 @@ void map_parser::parse_map(Map & map, xml_node const& node, std::string const& b
map.set_background(*bgcolor);
}
optional<std::string> filters = map_node.get_opt_attr<std::string>("image-filters");
if (filters)
{
if (!parse_image_filters(*filters, map.image_filters()))
{
throw config_error("failed to parse image-filters: '" + *filters + "'");
}
}
optional<std::string> image_filename = map_node.get_opt_attr<std::string>("background-image");
if (image_filename)
{

View file

@ -624,7 +624,6 @@ void serialize_map(ptree & pt, Map const& map, bool explicit_defaults)
set_attr(map_node, "background-image-opacity", opacity);
}
int buffer_size = map.buffer_size();
if ( buffer_size || explicit_defaults)
{

View file

@ -0,0 +1,377 @@
#include "catch.hpp"
// mapnik
#include <mapnik/value.hpp>
#include <mapnik/image_any.hpp>
#include <mapnik/color.hpp>
#include <mapnik/image_filter.hpp>
#include <mapnik/image_util.hpp>
TEST_CASE("image filter") {
SECTION("test bad filter input") {
mapnik::image_rgba8 im(3,3);
mapnik::fill(im,mapnik::color("blue"));
mapnik::set_pixel(im, 1, 1, mapnik::color("red"));
REQUIRE_THROWS( mapnik::filter::filter_image(im, "foo,asdfasdf()"); );
REQUIRE_THROWS( mapnik::filter::filter_image(im, "colorize-alpha("); );
REQUIRE_THROWS( mapnik::filter::filter_image(im, "color-to-alpha(blue"); );
REQUIRE_THROWS( mapnik::filter::filter_image(im, "color-to-alpha(,blue)"); );
REQUIRE_THROWS( mapnik::filter::filter_image(im, "colorize-alpha()"); );
REQUIRE_THROWS(
mapnik::image_rgba8 const& im2 = im;
mapnik::image_rgba8 new_im = mapnik::filter::filter_image(im2, "foo");
);
CHECK(im(0,0) == 0xffff0000);
CHECK(im(0,1) == 0xffff0000);
CHECK(im(0,2) == 0xffff0000);
CHECK(im(1,0) == 0xffff0000);
CHECK(im(1,1) == 0xff0000ff);
CHECK(im(1,2) == 0xffff0000);
CHECK(im(2,0) == 0xffff0000);
CHECK(im(2,1) == 0xffff0000);
CHECK(im(2,2) == 0xffff0000);
} // END SECTION
SECTION("test blur") {
mapnik::image_rgba8 im(3,3);
mapnik::fill(im,mapnik::color("blue"));
mapnik::set_pixel(im, 1, 1, mapnik::color("red"));
mapnik::filter::filter_image(im, "blur");
CHECK(im(0,0) == 0xffc60038);
CHECK(im(0,1) == 0xffe2001c);
CHECK(im(0,2) == 0xffc60038);
CHECK(im(1,0) == 0xffc60038);
CHECK(im(1,1) == 0xffe2001c);
CHECK(im(1,2) == 0xffc60038);
CHECK(im(2,0) == 0xffc60038);
CHECK(im(2,1) == 0xffe2001c);
CHECK(im(2,2) == 0xffc60038);
} // END SECTION
SECTION("test blur constant") {
mapnik::image_rgba8 im_orig(3,3);
mapnik::fill(im_orig,mapnik::color("blue"));
mapnik::set_pixel(im_orig, 1, 1, mapnik::color("red"));
mapnik::image_rgba8 const& im_new = im_orig;
mapnik::image_rgba8 im = mapnik::filter::filter_image(im_new, "blur");
CHECK(im(0,0) == 0xffc60038);
CHECK(im(0,1) == 0xffe2001c);
CHECK(im(0,2) == 0xffc60038);
CHECK(im(1,0) == 0xffc60038);
CHECK(im(1,1) == 0xffe2001c);
CHECK(im(1,2) == 0xffc60038);
CHECK(im(2,0) == 0xffc60038);
CHECK(im(2,1) == 0xffe2001c);
CHECK(im(2,2) == 0xffc60038);
} // END SECTION
SECTION("test gray") {
mapnik::image_rgba8 im(3,3);
mapnik::fill(im,mapnik::color("blue"));
mapnik::set_pixel(im, 1, 1, mapnik::color("red"));
mapnik::filter::filter_image(im, "gray");
CHECK(im(0,0) == 0xff1c1c1c);
CHECK(im(0,1) == 0xff1c1c1c);
CHECK(im(0,2) == 0xff1c1c1c);
CHECK(im(1,0) == 0xff1c1c1c);
CHECK(im(1,1) == 0xff4c4c4c);
CHECK(im(1,2) == 0xff1c1c1c);
CHECK(im(2,0) == 0xff1c1c1c);
CHECK(im(2,1) == 0xff1c1c1c);
CHECK(im(2,2) == 0xff1c1c1c);
} // END SECTION
SECTION("test agg stack blur") {
mapnik::image_rgba8 im(3,3);
mapnik::fill(im,mapnik::color("blue"));
mapnik::set_pixel(im, 1, 1, mapnik::color("red"));
mapnik::filter::filter_image(im, "agg-stack-blur(1,1)");
CHECK(im(0,0) == 0xffef000f);
CHECK(im(0,1) == 0xffdf001f);
CHECK(im(0,2) == 0xffef000f);
CHECK(im(1,0) == 0xffdf001f);
CHECK(im(1,1) == 0xffbf003f);
CHECK(im(1,2) == 0xffdf001f);
CHECK(im(2,0) == 0xffef000f);
CHECK(im(2,1) == 0xffdf001f);
CHECK(im(2,2) == 0xffef000f);
} // END SECTION
SECTION("test scale-hsla") {
mapnik::image_rgba8 im(3,3);
mapnik::fill(im,mapnik::color("blue"));
mapnik::set_pixel(im, 1, 1, mapnik::color("red"));
// Should throw because a value is greater then 1.0
REQUIRE_THROWS(mapnik::filter::filter_image(im, "scale-hsla(0.0,1.5,0.0,1.0,0.0,0.5,0.0,0.5)"););
mapnik::filter::filter_image(im, "scale-hsla(0.0,0.5,0.0,1.0,0.0,0.5,0.0,0.5)");
CHECK(im(0,0) == 0x80004000);
CHECK(im(0,1) == 0x80004000);
CHECK(im(0,2) == 0x80004000);
CHECK(im(1,0) == 0x80004000);
CHECK(im(1,1) == 0x80000040);
CHECK(im(1,2) == 0x80004000);
CHECK(im(2,0) == 0x80004000);
CHECK(im(2,1) == 0x80004000);
CHECK(im(2,2) == 0x80004000);
} // END SECTION
SECTION("test emboss") {
mapnik::image_rgba8 im(3,3);
mapnik::fill(im,mapnik::color("white"));
mapnik::set_pixel(im, 1, 1, mapnik::color("orange"));
mapnik::filter::filter_image(im, "emboss");
CHECK(im(0,0) == 0xff004bff);
CHECK(im(0,1) == 0xff00a5ff);
CHECK(im(0,2) == 0xff004bff);
CHECK(im(1,0) == 0xffffffff);
CHECK(im(1,1) == 0xff00a5ff);
CHECK(im(1,2) == 0xffffffff);
CHECK(im(2,0) == 0xffffffff);
CHECK(im(2,1) == 0xffffffff);
CHECK(im(2,2) == 0xffffffff);
} // END SECTION
SECTION("test sharpen") {
mapnik::image_rgba8 im(3,3);
mapnik::fill(im,mapnik::color("blue"));
mapnik::set_pixel(im, 1, 1, mapnik::color("gray"));
mapnik::filter::filter_image(im, "sharpen");
CHECK(im(0,0) == 0xffff0000);
CHECK(im(0,1) == 0xffff0000);
CHECK(im(0,2) == 0xffff0000);
CHECK(im(1,0) == 0xffff0000);
CHECK(im(1,1) == 0xff00ffff);
CHECK(im(1,2) == 0xffff0000);
CHECK(im(2,0) == 0xffff0000);
CHECK(im(2,1) == 0xffff0000);
CHECK(im(2,2) == 0xffff0000);
} // END SECTION
SECTION("test edge detect") {
mapnik::image_rgba8 im(3,3);
mapnik::fill(im,mapnik::color("blue"));
mapnik::set_pixel(im, 1, 1, mapnik::color("gray"));
mapnik::filter::filter_image(im, "edge-detect");
CHECK(im(0,0) == 0xff000000);
CHECK(im(0,1) == 0xff008080);
CHECK(im(0,2) == 0xff000000);
CHECK(im(1,0) == 0xff00ffff);
CHECK(im(1,1) == 0xffff0000);
CHECK(im(1,2) == 0xff00ffff);
CHECK(im(2,0) == 0xff000000);
CHECK(im(2,1) == 0xff008080);
CHECK(im(2,2) == 0xff000000);
} // END SECTION
SECTION("test sobel") {
mapnik::image_rgba8 im(3,3);
mapnik::fill(im,mapnik::color("blue"));
mapnik::set_pixel(im, 1, 1, mapnik::color("gray"));
mapnik::filter::filter_image(im, "sobel");
CHECK(im(0,0) == 0xfffeffff);
CHECK(im(0,1) == 0xfffeffff);
CHECK(im(0,2) == 0xfffeffff);
CHECK(im(1,0) == 0xff000000);
CHECK(im(1,1) == 0xff000000);
CHECK(im(1,2) == 0xff000000);
CHECK(im(2,0) == 0xfffeffff);
CHECK(im(2,1) == 0xfffeffff);
CHECK(im(2,2) == 0xfffeffff);
} // END SECTION
SECTION("test x-gradient") {
mapnik::image_rgba8 im(3,3);
mapnik::fill(im,mapnik::color("blue"));
mapnik::set_pixel(im, 1, 1, mapnik::color("gray"));
mapnik::filter::filter_image(im, "x-gradient");
CHECK(im(0,0) == 0xff808080);
CHECK(im(0,1) == 0xffbf4040);
CHECK(im(0,2) == 0xff808080);
CHECK(im(1,0) == 0xff808080);
CHECK(im(1,1) == 0xff808080);
CHECK(im(1,2) == 0xff808080);
CHECK(im(2,0) == 0xff808080);
CHECK(im(2,1) == 0xff41c0c0);
CHECK(im(2,2) == 0xff808080);
} // END SECTION
SECTION("test y-gradient") {
mapnik::image_rgba8 im(3,3);
mapnik::fill(im,mapnik::color("blue"));
mapnik::set_pixel(im, 1, 1, mapnik::color("gray"));
mapnik::filter::filter_image(im, "y-gradient");
CHECK(im(0,0) == 0xff808080);
CHECK(im(0,1) == 0xff808080);
CHECK(im(0,2) == 0xff808080);
CHECK(im(1,0) == 0xffbf4040);
CHECK(im(1,1) == 0xff808080);
CHECK(im(1,2) == 0xff41c0c0);
CHECK(im(2,0) == 0xff808080);
CHECK(im(2,1) == 0xff808080);
CHECK(im(2,2) == 0xff808080);
} // END SECTION
SECTION("test invert") {
mapnik::image_rgba8 im(3,3);
mapnik::fill(im,mapnik::color("blue"));
mapnik::set_pixel(im, 1, 1, mapnik::color("gray"));
mapnik::filter::filter_image(im, "invert");
CHECK(im(0,0) == 0xff00ffff);
CHECK(im(0,1) == 0xff00ffff);
CHECK(im(0,2) == 0xff00ffff);
CHECK(im(1,0) == 0xff00ffff);
CHECK(im(1,1) == 0xff7f7f7f);
CHECK(im(1,2) == 0xff00ffff);
CHECK(im(2,0) == 0xff00ffff);
CHECK(im(2,1) == 0xff00ffff);
CHECK(im(2,2) == 0xff00ffff);
} // END SECTION
SECTION("test colorize-alpha - one color") {
mapnik::image_rgba8 im(3,3);
mapnik::fill(im,mapnik::color("blue"));
mapnik::set_pixel(im, 1, 1, mapnik::color("gray"));
mapnik::filter::filter_image(im, "colorize-alpha(blue)");
CHECK(im(0,0) == 0xffff0000);
CHECK(im(0,1) == 0xffff0000);
CHECK(im(0,2) == 0xffff0000);
CHECK(im(1,0) == 0xffff0000);
CHECK(im(1,1) == 0xffff0000);
CHECK(im(1,2) == 0xffff0000);
CHECK(im(2,0) == 0xffff0000);
CHECK(im(2,1) == 0xffff0000);
CHECK(im(2,2) == 0xffff0000);
} // END SECTION
SECTION("test colorize-alpha - two color") {
mapnik::image_rgba8 im(3,3);
mapnik::fill(im,mapnik::color("blue"));
mapnik::set_pixel(im, 1, 1, mapnik::color("gray"));
mapnik::filter::filter_image(im, "colorize-alpha(green,blue)");
CHECK(im(0,0) == 0xfffc0000);
CHECK(im(0,1) == 0xfffc0000);
CHECK(im(0,2) == 0xfffc0000);
CHECK(im(1,0) == 0xfffc0000);
CHECK(im(1,1) == 0xfffc0000);
CHECK(im(1,2) == 0xfffc0000);
CHECK(im(2,0) == 0xfffc0000);
CHECK(im(2,1) == 0xfffc0000);
CHECK(im(2,2) == 0xfffc0000);
} // END SECTION
SECTION("test color-blind-protanope") {
mapnik::image_rgba8 im(2,2);
mapnik::fill(im,mapnik::color("blue"));
mapnik::set_pixel(im, 0, 1, mapnik::color("green"));
mapnik::set_pixel(im, 1, 0, mapnik::color("yellow"));
mapnik::set_pixel(im, 1, 1, mapnik::color("red"));
mapnik::filter::filter_image(im, "color-blind-protanope");
CHECK(im(0,0) == 0xff9a4a00);
CHECK(im(0,1) == 0xff006e7c);
CHECK(im(1,0) == 0xffd9f6ff);
CHECK(im(1,1) == 0xff1d7e8e);
} // END SECTION
SECTION("test color-blind-deuteranope") {
mapnik::image_rgba8 im(2,2);
mapnik::fill(im,mapnik::color("blue"));
mapnik::set_pixel(im, 0, 1, mapnik::color("green"));
mapnik::set_pixel(im, 1, 0, mapnik::color("yellow"));
mapnik::set_pixel(im, 1, 1, mapnik::color("red"));
mapnik::filter::filter_image(im, "color-blind-deuteranope");
CHECK(im(0,0) == 0xff824f00);
CHECK(im(0,1) == 0xff1c688b);
CHECK(im(1,0) == 0xffe9f5ff);
CHECK(im(1,1) == 0xff0077a0);
} // END SECTION
SECTION("test color-blind-tritanope") {
mapnik::image_rgba8 im(2,2);
mapnik::fill(im,mapnik::color("blue"));
mapnik::set_pixel(im, 0, 1, mapnik::color("green"));
mapnik::set_pixel(im, 1, 0, mapnik::color("yellow"));
mapnik::set_pixel(im, 1, 1, mapnik::color("red"));
mapnik::filter::filter_image(im, "color-blind-tritanope");
CHECK(im(0,0) == 0xff595500);
CHECK(im(0,1) == 0xff80763a);
CHECK(im(1,0) == 0xfff8f3ff);
CHECK(im(1,1) == 0xff0017fd);
} // END SECTION
} // END TEST CASE