diff --git a/common/ROIFilter.h b/common/ROIFilter.h index eab8fefe..339755c3 100644 --- a/common/ROIFilter.h +++ b/common/ROIFilter.h @@ -10,35 +10,49 @@ #include "JFJochException.h" class ROIFilter { - size_t width, height; + int32_t width, height; std::vector mask; public: - ROIFilter(size_t in_width, size_t in_height, uint8_t fill_value = 0) - : width(in_width), height(in_height), mask (in_width * in_height, fill_value) {} + ROIFilter(int32_t in_width, int32_t in_height, uint8_t fill_value = 0) + : width(in_width), height(in_height) { + if ((width < 0) || (height < 0)) + throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, "Negative dimensions are wrong"); + mask = std::vector(in_width * in_height, fill_value); + } - void SetRectangle(size_t x0, size_t y0, size_t in_width, size_t in_height, uint8_t fill_value = 1) { - if (y0 + in_height > height) - throw JFJochException(JFJochExceptionCategory::ArrayOutOfBounds, "Mismatch in array size"); - if (x0 + in_width > width) - throw JFJochException(JFJochExceptionCategory::ArrayOutOfBounds, "Mismatch in array size"); + void SetRectangle(int32_t x0, int32_t y0, int32_t in_width, int32_t in_height, uint8_t mask_value = 1) { + if (x0 < 0) { in_width += x0; x0 = 0; } + if (in_width <= 0) return; - for (size_t y = y0; y < y0 + in_height; y++) { + if (x0 >= width) return; + if (x0 + in_width >= width) in_width = width - 1 - x0; + + if (y0 < 0) { in_height += y0; y0 = 0; } + if (in_height <= 0) return; + + if (y0 >= height) return; + if (y0 + in_height >= height) in_height = height - 1 - y0; + + for (size_t y = y0; y < y0 + in_height; y++) { for (size_t x = x0; x < x0 + in_width; x++) { - mask[y * width + x] |= fill_value; + mask[y * width + x] |= mask_value; } } } + void ClearRectangle(int32_t x0, int32_t y0, int32_t in_width, int32_t in_height, uint8_t mask_value = 1) { + if (x0 < 0) { in_width += x0; x0 = 0; } + if (in_width <= 0) return; - void ClearRectangle(size_t x0, size_t y0, size_t in_width, size_t in_height, uint8_t fill_value = 1) { - if (y0 + in_height > height) - throw JFJochException(JFJochExceptionCategory::ArrayOutOfBounds, "Mismatch in array size"); - if (x0 + in_width > width) - throw JFJochException(JFJochExceptionCategory::ArrayOutOfBounds, "Mismatch in array size"); + if (x0 >= width) return; + if (x0 + in_width >= width) in_width = width - 1 - x0; + + if (y0 < 0) { in_height += y0; y0 = 0; } + if (in_height <= 0) return; for (size_t y = y0; y < y0 + in_height; y++) { for (size_t x = x0; x < x0 + in_width; x++) { - mask[y * width + x] &= ~fill_value; + mask[y * width + x] &= ~mask_value; } } } diff --git a/tests/ROIFilterTest.cpp b/tests/ROIFilterTest.cpp index 4d9738ed..bf96de9b 100644 --- a/tests/ROIFilterTest.cpp +++ b/tests/ROIFilterTest.cpp @@ -6,8 +6,8 @@ #include "../common/ROIFilter.h" TEST_CASE("ROIFilter") { - size_t width = 4; - size_t height = 5; + int32_t width = 4; + int32_t height = 5; std::vector v(width * height, 1); ROIFilter filter(width, height); @@ -27,3 +27,112 @@ TEST_CASE("ROIFilter") { REQUIRE(v[width * 3 + 2] == 1); REQUIRE(v[width * 4 + 2] == 55); } + +TEST_CASE("ROIFilter_out_of_bounds") { + int32_t width = 4; + int32_t height = 5; + std::vector v(width * height, 1); + + ROIFilter filter(width, height); + + filter.SetRectangle(1, 5, 2, 3); + + filter.SetRectangle(4, 1, 2, 3); + + filter.Apply(v, (uint32_t) 55); + size_t diff = 0; + for (auto &i: v) { + if (i != 55) + diff++; + } + REQUIRE(diff == 0); +} + +TEST_CASE("ROIFilter_negative_out_of_bounds") { + int32_t width = 4; + int32_t height = 5; + std::vector v(width * height, 1); + + ROIFilter filter(width, height); + + filter.SetRectangle(1, -9, 2, 3); + + filter.SetRectangle(-3, 1, 2, 3); + + filter.Apply(v, (uint32_t) 55); + size_t diff = 0; + for (auto &i: v) { + if (i != 55) + diff++; + } + REQUIRE(diff == 0); +} + +TEST_CASE("ROIFilter_on_bounds") { + int32_t width = 4; + int32_t height = 5; + std::vector v(width * height, 1); + + ROIFilter filter(width, height); + + filter.SetRectangle(2, 3, 10, 10); + + filter.Apply(v, (uint32_t) 55); + + REQUIRE(v[1 * width + 0] == 55); + REQUIRE(v[1 * width + 1] == 55); + REQUIRE(v[1 * width + 2] == 55); + REQUIRE(v[1 * width + 3] == 55); + + REQUIRE(v[2 * width + 0] == 55); + REQUIRE(v[2 * width + 1] == 55); + REQUIRE(v[2 * width + 2] == 55); + REQUIRE(v[2 * width + 3] == 55); + + REQUIRE(v[3 * width + 0] == 55); + REQUIRE(v[3 * width + 1] == 55); + REQUIRE(v[3 * width + 2] == 1); + REQUIRE(v[3 * width + 3] == 1); + + REQUIRE(v[4 * width + 0] == 55); + REQUIRE(v[4 * width + 1] == 55); + REQUIRE(v[4 * width + 2] == 1); + REQUIRE(v[4 * width + 3] == 1); +} + +TEST_CASE("ROIFilter_negative_start") { + int32_t width = 4; + int32_t height = 5; + std::vector v(width * height, 1); + + ROIFilter filter(width, height); + + filter.SetRectangle(-1, -1, 3, 4); + + filter.Apply(v, (uint32_t) 55); + + CHECK(v[0 * width + 0] == 1); + CHECK(v[0 * width + 1] == 1); + CHECK(v[0 * width + 2] == 55); + CHECK(v[0 * width + 3] == 55); + + CHECK(v[1 * width + 0] == 1); + CHECK(v[1 * width + 1] == 1); + CHECK(v[1 * width + 2] == 55); + CHECK(v[1 * width + 3] == 55); + + CHECK(v[2 * width + 0] == 1); + CHECK(v[2 * width + 1] == 1); + CHECK(v[2 * width + 2] == 55); + CHECK(v[2 * width + 3] == 55); + + CHECK(v[3 * width + 0] == 55); + CHECK(v[3 * width + 1] == 55); + CHECK(v[3 * width + 2] == 55); + CHECK(v[3 * width + 3] == 55); + + CHECK(v[4 * width + 0] == 55); + CHECK(v[4 * width + 1] == 55); + CHECK(v[4 * width + 2] == 55); + CHECK(v[4 * width + 3] == 55); +} \ No newline at end of file