#include "catch.hpp" // mapnik #include <mapnik/image.hpp> #include <mapnik/image_view.hpp> #include <mapnik/image_any.hpp> #include <mapnik/color.hpp> #include <mapnik/image_util.hpp> TEST_CASE("image class") { SECTION("test gray16") { const mapnik::image_gray16 im(4,4); mapnik::image_gray16 im2(im); mapnik::image_gray16 im3(5,5); CHECK(im == im); CHECK_FALSE(im == im2); CHECK_FALSE(im2 == im3); CHECK(im < im3); CHECK_FALSE(im < im2); // Check that width is correct CHECK(im.width() == 4); CHECK(im2.width() == 4); // Check that height is correct CHECK(im.height() == 4); CHECK(im2.height() == 4); CHECK(im(0,0) == 0); CHECK(im2(0,0) == 0); im2(0,0) = 1; CHECK(im2(0,0) == 1); im2.set(514); CHECK(im2(0,0) == 514); CHECK(im2(1,1) == 514); // Check that size is correct CHECK(im.size() == 32); CHECK(im2.size() == 32); // Check that row_size is correct CHECK(im.row_size() == 8); CHECK(im2.row_size() == 8); // Check that get_premultiplied is correct CHECK_FALSE(im.get_premultiplied()); CHECK_FALSE(im2.get_premultiplied()); // Check that set premultiplied works im2.set_premultiplied(true); CHECK(im2.get_premultiplied()); // Check that painted is correct CHECK_FALSE(im.painted()); CHECK_FALSE(im2.painted()); // Check that set premultiplied works im2.painted(true); CHECK(im2.painted()); // Check that offset is correct CHECK(im.get_offset() == 0.0); CHECK(im2.get_offset() == 0.0); // Check that set offset works im2.set_offset(2.3); CHECK(im2.get_offset() == 2.3); // Check that scaling is correct CHECK(im.get_scaling() == 1.0); CHECK(im2.get_scaling() == 1.0); // Check that set scaling works im2.set_scaling(1.1); CHECK(im2.get_scaling() == 1.1); // CHECK that image dtype is correct CHECK(im.get_dtype() == mapnik::image_dtype_gray16); CHECK(im2.get_dtype() == mapnik::image_dtype_gray16); using pixel_type = mapnik::image_view_gray16::pixel_type; pixel_type expected_val; // Check that all data in the view is correct // IM expected_val = 0; pixel_type const* data_im = im.data(); CHECK(*data_im == expected_val); unsigned char const* data_b = im.bytes(); CHECK(*data_b == 0); for (std::size_t y = 0; y < im.height(); ++y) { std::size_t width = im.width(); pixel_type const* data_1 = im.get_row(y); pixel_type const* data_2 = im.get_row(y, 1); for (std::size_t x = 0; x < width; ++x) { CHECK(*data_1 == expected_val); ++data_1; } for (std::size_t x = 1; x < width; ++x) { CHECK(*data_2 == expected_val); ++data_2; } } // IM2 expected_val = 514; pixel_type * data_im2 = im2.data(); CHECK(*data_im2 == expected_val); unsigned char * data_b2 = im2.bytes(); CHECK(*data_b2 == 2); ++data_b; CHECK(*data_b2 == 2); for (std::size_t y = 0; y < im2.height(); ++y) { std::size_t width = im2.width(); pixel_type const* data_1 = im2.get_row(y); pixel_type const* data_2 = im2.get_row(y, 1); for (std::size_t x = 0; x < width; ++x) { CHECK(*data_1 == expected_val); ++data_1; } for (std::size_t x = 1; x < width; ++x) { CHECK(*data_2 == expected_val); ++data_2; } } // Test set row std::vector<pixel_type> v1(im2.width(), 30); std::vector<pixel_type> v2(im2.width()-1, 50); im2.set_row(0, v1.data(), v1.size()); im2.set_row(1, 1, v2.size(), v2.data()); CHECK(im2(0,0) == 30); CHECK(im2(0,1) == 514); CHECK(im2(1,1) == 50); } // END SECTION SECTION("image_null") { mapnik::image_null im_null; const mapnik::image_null im_null2(2,2); // Actually doesn't really set any size mapnik::image_null im_null3(im_null2); mapnik::image_null im_null4(std::move(im_null3)); // All nulls are equal CHECK(im_null == im_null4); CHECK(im_null == im_null2); // No null is greater CHECK_FALSE(im_null < im_null4); CHECK_FALSE(im_null < im_null2); // Check defaults CHECK(im_null.width() == 0); CHECK(im_null.height() == 0); CHECK(im_null.size() == 0); CHECK(im_null.row_size() == 0); // Setting offset does nothing im_null.set_offset(10000000.0); CHECK(im_null.get_offset() == 0.0); // Setting scaling does nothing im_null.set_scaling(123123123.0); CHECK(im_null.get_scaling() == 1.0); CHECK(im_null.get_dtype() == mapnik::image_dtype_null); // Setting premultiplied does nothing im_null.set_premultiplied(true); CHECK_FALSE(im_null.get_premultiplied()); // Setting painted does nothing im_null.painted(true); CHECK_FALSE(im_null.painted()); // Should throw if we try to access or setdata. REQUIRE_THROWS(im_null(0,0)); REQUIRE_THROWS(im_null2(0,0)); REQUIRE_THROWS(im_null(0,0) = 1); unsigned char const* e1 = im_null.bytes(); unsigned char * e2 = im_null.bytes(); CHECK(e1 == nullptr); CHECK(e2 == nullptr); } // END SECTION SECTION("image any") { mapnik::image_null null_im; const mapnik::image_any im_any_null(null_im); CHECK(im_any_null.get_dtype() == mapnik::image_dtype_null); CHECK(im_any_null.bytes() == nullptr); mapnik::image_gray16 im(4,4); mapnik::fill(im, 514); mapnik::image_any im_any(im); CHECK(im_any.get_dtype() == mapnik::image_dtype_gray16); unsigned char * foo = im_any.bytes(); CHECK(*foo == 2); ++foo; CHECK(*foo == 2); CHECK(im_any.width() == 4); CHECK(im_any.height() == 4); CHECK(im_any.size() == 32); CHECK(im_any.row_size() == 8); CHECK_FALSE(im_any.get_premultiplied()); im_any.set_offset(10.0); CHECK(im_any.get_offset() == 10.0); im_any.set_scaling(2.1); CHECK(im_any.get_scaling() == 2.1); CHECK_FALSE(im_any.painted()); } // END SECTION SECTION("test image_any initialization") { { mapnik::image_any im(4,4); CHECK(im.get_dtype() == mapnik::image_dtype_rgba8); } { mapnik::image_any im(4, 4, mapnik::image_dtype_null); CHECK(im.get_dtype() == mapnik::image_dtype_null); } { mapnik::image_any im(4, 4, mapnik::image_dtype_gray8); CHECK(im.get_dtype() == mapnik::image_dtype_gray8); } { mapnik::image_any im(4, 4, mapnik::image_dtype_gray8s); CHECK(im.get_dtype() == mapnik::image_dtype_gray8s); } { mapnik::image_any im(4, 4, mapnik::image_dtype_gray16); CHECK(im.get_dtype() == mapnik::image_dtype_gray16); } { mapnik::image_any im(4, 4, mapnik::image_dtype_gray16s); CHECK(im.get_dtype() == mapnik::image_dtype_gray16s); } { mapnik::image_any im(4, 4, mapnik::image_dtype_gray32); CHECK(im.get_dtype() == mapnik::image_dtype_gray32); } { mapnik::image_any im(4, 4, mapnik::image_dtype_gray32s); CHECK(im.get_dtype() == mapnik::image_dtype_gray32s); } { mapnik::image_any im(4, 4, mapnik::image_dtype_gray32f); CHECK(im.get_dtype() == mapnik::image_dtype_gray32f); } { mapnik::image_any im(4, 4, mapnik::image_dtype_gray64); CHECK(im.get_dtype() == mapnik::image_dtype_gray64); } { mapnik::image_any im(4, 4, mapnik::image_dtype_gray64s); CHECK(im.get_dtype() == mapnik::image_dtype_gray64s); } { mapnik::image_any im(4, 4, mapnik::image_dtype_gray64f); CHECK(im.get_dtype() == mapnik::image_dtype_gray64f); } } // END SECTION SECTION("Image Buffer") { mapnik::detail::buffer buf_zero(0); CHECK(buf_zero.size() == 0); CHECK(!buf_zero); mapnik::detail::buffer buf(10); CHECK(buf.size() == 10); CHECK_FALSE(!buf); unsigned char * d = buf.data(); *d = 9; const mapnik::detail::buffer buf2 = buf; CHECK(buf2.size() == 10); unsigned char const* d2 = buf2.data(); CHECK(*d2 == 9); } // END SECTION SECTION("Image copy/move") { mapnik::detail::buffer buf(16 * 16 * 4); // large enough to hold 16*16 RGBA image CHECK(buf.size() == 16 * 16 * 4); // fill buffer with 0xff std::fill(buf.data(), buf.data() + buf.size(), 0xff); // move buffer mapnik::detail::buffer buf2(std::move(buf)); CHECK (buf.size() == 0); CHECK (buf.data() == nullptr); mapnik::image_rgba8 im(16, 16, buf2.data()); // shallow copy std::size_t count = 0; for (auto const& pixel : im) { // expect rgba(255,255,255,1.0) CHECK( sizeof(pixel) == sizeof(mapnik::image_rgba8::pixel_type)); CHECK( pixel == 0xffffffff); ++count; } CHECK( count == im.width() * im.height()); CHECK( buf2.size() == im.width() * im.height() * sizeof( mapnik::image_rgba8::pixel_type)); // mutate buffer // fill buffer with 0x7f - semi-transparent grey std::fill(buf2.data(), buf2.data() + buf2.size(), 0x7f); for (auto const& pixel : im) { // expect rgba(127,127,127,0.5) CHECK( pixel == 0x7f7f7f7f); } // mutate image directly (buf) for (auto & pixel : im) { pixel = mapnik::color(0,255,0).rgba(); // green } // move mapnik::image_rgba8 im2(std::move(im)); CHECK (im.data() == nullptr); CHECK (im.bytes() == nullptr); CHECK (im.width() == 0); CHECK (im.height() == 0); for (auto const& pixel : im2) { // expect `green` CHECK( pixel == mapnik::color(0,255,0).rgba()); } mapnik::image_rgba8 im3(im2); // shallow copy for (auto & pixel : im3) { // expect `green` CHECK( pixel == mapnik::color(0,255,0).rgba()); // mutate pixel = mapnik::color(255,0,0).rgba(); //red } for (auto const& pixel : im3) { // expect `red` CHECK( pixel == mapnik::color(255,0,0).rgba()); } for (auto const& pixel : im2) { // expect `red` CHECK( pixel == mapnik::color(255,0,0).rgba()); } } SECTION("image::swap") { auto blue = mapnik::color(50, 50, 250).rgba(); auto orange = mapnik::color(250, 150, 0).rgba(); mapnik::image_rgba8 im; mapnik::image_rgba8 im2(16, 16); mapnik::image_rgba8 im3(16, 16); im2.set(blue); im3.set(orange); // swap two non-empty images CHECK_NOTHROW(im2.swap(im3)); CHECK(im2(0, 0) == orange); CHECK(im3(0, 0) == blue); // swap empty <-> non-empty CHECK_NOTHROW(im.swap(im3)); CHECK(im3.data() == nullptr); CHECKED_IF(im.data() != nullptr) { CHECK(im(0, 0) == blue); } } } // END TEST CASE