diff --git a/Src/libCZI/SingleChannelAccessorBase.cpp b/Src/libCZI/SingleChannelAccessorBase.cpp index e2fac974..a4a3a8dc 100644 --- a/Src/libCZI/SingleChannelAccessorBase.cpp +++ b/Src/libCZI/SingleChannelAccessorBase.cpp @@ -88,10 +88,10 @@ std::vector CSingleChannelAccessorBase::CheckForVisibility(const libCZI::In roi, count, get_subblock_index, - [this](int index) -> IntRect + [this](int subblock_index) -> IntRect { SubBlockInfo subblock_info; - bool b = this->sbBlkRepository->TryGetSubBlockInfo(index, &subblock_info); + bool b = this->sbBlkRepository->TryGetSubBlockInfo(subblock_index, &subblock_info); return subblock_info.logicalRect; }); /* @@ -168,14 +168,14 @@ std::vector CSingleChannelAccessorBase::CheckForVisibility(const libCZI::In //for (int i = 0; i < count; ++i) for (int i = count -1; i >= 0; --i) // we start at the end, because that is the subblock which is rendered last (and thus is on top) { - coverage_calculator.AddRectangle(get_rect_of_subblock(i)); + int subblock_index = get_subblock_index(i); + coverage_calculator.AddRectangle(get_rect_of_subblock(subblock_index)); const int64_t new_covered_pixel_count = coverage_calculator.CalcAreaOfIntersectionWithRectangle(roi); if (new_covered_pixel_count > covered_pixel_count) // if the covered pixel count has increased, it means that this subblock covers some new pixels, - // some pixels which were not overdrawn by all the previous ones - { + { // some pixels which were not overdrawn by all the previous ones // this means - when drawing this subblock, some new pixels will be covered which were not covered before, // so we need to draw this subblock, therefore we add it to our result vector - result.push_back(i); + result.push_back(subblock_index); covered_pixel_count = new_covered_pixel_count; if (new_covered_pixel_count == total_pixel_count) diff --git a/Src/libCZI/SingleChannelAccessorBase.h b/Src/libCZI/SingleChannelAccessorBase.h index 505ab4be..e8598820 100644 --- a/Src/libCZI/SingleChannelAccessorBase.h +++ b/Src/libCZI/SingleChannelAccessorBase.h @@ -24,15 +24,15 @@ class CSingleChannelAccessorBase /// This method is used to do a visibility test of a list of subblocks. The mode of operation is as follows: /// - The method is given a ROI, and the number of subblocks to check. - /// - The functor 'get_subblock_index' is called with the argument being a counter, starting with 0 and counting up to count-1. - /// If called with value 0, the subblock is the **last** one to be rendered, if called with value 1, the subblock is the - /// second-to-the-last one to be rendered, and so on. + /// - The functor 'get_subblock_index' is called with the argument being a counter, starting with count-1 and counting down to zero. + /// If called with value count-1, the subblock is the **last** one to be rendered; if called with value count-2, the subblock is the + /// second-to-the-last one to be rendered, and so on. If called with 0, the subblock is the **first** one to be rendered. /// The value it returns is the subblock index (in the subblock repository) to check. /// - The subblocks are assumed to be rendered in the order given, so the one we get by calling 'get_subblock_index' with /// argument 0 is the first one to be rendered, the one with argument 1 is the second one, and so on. The rendering /// is assumed to be done with the 'painter's algorithm", so what is rendered last is on top. /// - We return a list of indices which are to be rendered, potentially leaving out some which have been determined - /// as not being visible. The indices returned are "indices as used by the 'get_subblock_index' functor, i.e. + /// as not being visible. The indices returned are "indices as used by the 'get_subblock_index' functor", i.e. /// it is **not** the subblock-number, but the argument that was passed to the functor. /// - The caller can then use this list to render the subblocks (in the order as given in this vector). /// diff --git a/Src/libCZI_UnitTests/test_TileAccessorCoverageOptimization.cpp b/Src/libCZI_UnitTests/test_TileAccessorCoverageOptimization.cpp index 3587c35a..4be9f6b0 100644 --- a/Src/libCZI_UnitTests/test_TileAccessorCoverageOptimization.cpp +++ b/Src/libCZI_UnitTests/test_TileAccessorCoverageOptimization.cpp @@ -494,3 +494,70 @@ TEST(TileAccessorCoverageOptimization, CheckForVisibility_SubblocksNotIntersecti ASSERT_TRUE(indices_of_visible_tiles.empty()); } + +TEST(TileAccessorCoverageOptimization, CheckForVisibility_TestCase1) +{ + static constexpr array kSubBlocks{ IntRect{0,0,2,1}, IntRect{0,0,3,3} }; + + // We report {0,0,3,3} as the subblock being rendered *last* (the one with index 1), and {0,0,2,1} as the one + // being rendered before. {0,0,2,1} is completely overdrawn by {0,0,3,3}, so we expect that only the last + // index (i.e. "1") is returned as visible. + const auto indices_of_visible_tiles = CSingleChannelAccessorBaseToTestStub::CheckForVisibilityCore( + { 0, 0, 3, 3 }, + kSubBlocks.size(), + [&](int index)->int + { + return index; + }, + [&](int subblock_index)->IntRect + { + return kSubBlocks[subblock_index]; + }); + + ASSERT_EQ(indices_of_visible_tiles.size(), 1); + EXPECT_EQ(indices_of_visible_tiles[0], 1); +} + +TEST(TileAccessorCoverageOptimization, CheckForVisibility_TestCase2) +{ + static constexpr array kSubBlocks{ IntRect{0,0,1,3}, IntRect{0,1,1,1}, IntRect{0,2,1,1}, IntRect{0,0,1,1}, IntRect{1,0,2,3} }; + + const auto indices_of_visible_tiles = CSingleChannelAccessorBaseToTestStub::CheckForVisibilityCore( + { 0, 0, 3, 3 }, + kSubBlocks.size(), + [&](int index)->int + { + return index; + }, + [&](int subblock_index)->IntRect + { + return kSubBlocks[subblock_index]; + }); + + ASSERT_EQ(indices_of_visible_tiles.size(), 4); + EXPECT_EQ(indices_of_visible_tiles[0], 1); + EXPECT_EQ(indices_of_visible_tiles[1], 2); + EXPECT_EQ(indices_of_visible_tiles[2], 3); + EXPECT_EQ(indices_of_visible_tiles[3], 4); +} + +TEST(TileAccessorCoverageOptimization, CheckForVisibility_TestCase3) +{ + static constexpr array kSubBlocks{ IntRect{0,0,1,1}, IntRect{0,0,1,1}, IntRect{1,0,1,2}, IntRect{2,0,1,1}, IntRect{1,0,2,3} }; + + const auto indices_of_visible_tiles = CSingleChannelAccessorBaseToTestStub::CheckForVisibilityCore( + { 0, 0, 3, 3 }, + kSubBlocks.size(), + [&](int index)->int + { + return index; + }, + [&](int subblock_index)->IntRect + { + return kSubBlocks[subblock_index]; + }); + + ASSERT_EQ(indices_of_visible_tiles.size(), 2); + EXPECT_EQ(indices_of_visible_tiles[0], 1); + EXPECT_EQ(indices_of_visible_tiles[1], 4); +}