Skip to content

Commit

Permalink
implement image_span::blit()
Browse files Browse the repository at this point in the history
  • Loading branch information
igagis committed Nov 7, 2024
1 parent cf6be68 commit 57e23f2
Show file tree
Hide file tree
Showing 2 changed files with 122 additions and 1 deletion.
45 changes: 44 additions & 1 deletion src/rasterimage/image_span.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -392,7 +392,50 @@ class image_span : public dimensioned
{
static_assert(!is_const_span, "image_span is const, cannot blit to it");

// TODO:
auto this_rect = r4::rectangle<int>(
0, //
this->dims().to<int>()
);

auto span_rect_relative_to_this_rect = r4::rectangle<int>(
position, //
span.dims().template to<int>()
);

auto dst_rect = this_rect.intersect(span_rect_relative_to_this_rect);

if (dst_rect.d.is_any_zero()) {
// image to blit is out of destination span
return;
}

ASSERT(dst_rect.p.is_positive_or_zero())
ASSERT(dst_rect.d.is_positive())

// rectangle on the source span which will actually be blitted
auto src_rect = r4::rectangle<int>(max(-position, 0), dst_rect.d);

ASSERT(src_rect.p.is_positive_or_zero())
ASSERT(src_rect.d.is_positive())
ASSERT(r4::rectangle<int>(0, span.dims().template to<int>()).contains(src_rect))

auto dst_span = this->subspan(dst_rect.to<unsigned>());
auto src_span = span.subspan(src_rect.to<unsigned>());

ASSERT(!dst_span.empty())
ASSERT(!src_span.empty())
ASSERT(src_span.dims() == dst_span.dims())

// TODO: use zip_view
auto src_line = src_span.begin();
auto dst_line = dst_span.begin();
for (; src_line != src_span.end(); ++src_line, ++dst_line) {
std::copy(
src_line->begin(), //
src_line->end(),
dst_line->begin()
);
}
}

void swap_red_blue() noexcept
Expand Down
78 changes: 78 additions & 0 deletions tests/unit/src/image_span.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -464,5 +464,83 @@ const tst::set set("image_span", [](tst::suite& suite) {
tst::check_eq(span.stride_pixels(), unsigned(0), SL);
tst::check_eq(span.stride_bytes(), size_t(0), SL);
});

suite.add("blit__fully_within", []() {
rasterimage::image<uint8_t, 4> dst_img(rasterimage::dimensioned::dimensions_type{20, 10});
dst_img.span().clear(0);
tst::check_eq(dst_img[0][0], decltype(dst_img)::pixel_type(0), SL);

rasterimage::image<uint8_t, 4> src_img(rasterimage::dimensioned::dimensions_type{3, 2});
src_img.span().clear(13);
tst::check_eq(src_img[0][0], decltype(src_img)::pixel_type(13), SL);

dst_img.span().blit(src_img.span(), {2, 1});

tst::check_eq(dst_img[0][0], decltype(dst_img)::pixel_type(0), SL);
tst::check_eq(dst_img[0][1], decltype(dst_img)::pixel_type(0), SL);
tst::check_eq(dst_img[0][2], decltype(dst_img)::pixel_type(0), SL);
tst::check_eq(dst_img[0][3], decltype(dst_img)::pixel_type(0), SL);
tst::check_eq(dst_img[0][4], decltype(dst_img)::pixel_type(0), SL);
tst::check_eq(dst_img[0][5], decltype(dst_img)::pixel_type(0), SL);

tst::check_eq(dst_img[1][0], decltype(dst_img)::pixel_type(0), SL);
tst::check_eq(dst_img[1][1], decltype(dst_img)::pixel_type(0), SL);
tst::check_eq(dst_img[1][2], decltype(dst_img)::pixel_type(13), SL);
tst::check_eq(dst_img[1][3], decltype(dst_img)::pixel_type(13), SL);
tst::check_eq(dst_img[1][4], decltype(dst_img)::pixel_type(13), SL);
tst::check_eq(dst_img[1][5], decltype(dst_img)::pixel_type(0), SL);

tst::check_eq(dst_img[2][0], decltype(dst_img)::pixel_type(0), SL);
tst::check_eq(dst_img[2][1], decltype(dst_img)::pixel_type(0), SL);
tst::check_eq(dst_img[2][2], decltype(dst_img)::pixel_type(13), SL);
tst::check_eq(dst_img[2][3], decltype(dst_img)::pixel_type(13), SL);
tst::check_eq(dst_img[2][4], decltype(dst_img)::pixel_type(13), SL);
tst::check_eq(dst_img[2][5], decltype(dst_img)::pixel_type(0), SL);

tst::check_eq(dst_img[3][0], decltype(dst_img)::pixel_type(0), SL);
tst::check_eq(dst_img[3][1], decltype(dst_img)::pixel_type(0), SL);
tst::check_eq(dst_img[3][2], decltype(dst_img)::pixel_type(0), SL);
tst::check_eq(dst_img[3][3], decltype(dst_img)::pixel_type(0), SL);
tst::check_eq(dst_img[3][4], decltype(dst_img)::pixel_type(0), SL);
tst::check_eq(dst_img[3][5], decltype(dst_img)::pixel_type(0), SL);
});

suite.add("blit__partly_negative", []() {
rasterimage::image<uint8_t, 4> dst_img(rasterimage::dimensioned::dimensions_type{20, 10});
dst_img.span().clear(0);
tst::check_eq(dst_img[0][0], decltype(dst_img)::pixel_type(0), SL);

rasterimage::image<uint8_t, 4> src_img(rasterimage::dimensioned::dimensions_type{3, 2});
src_img.span().clear(13);
tst::check_eq(src_img[0][0], decltype(src_img)::pixel_type(13), SL);

dst_img.span().blit(src_img.span(), {-2, -1});

tst::check_eq(dst_img[0][0], decltype(dst_img)::pixel_type(13), SL);
tst::check_eq(dst_img[0][1], decltype(dst_img)::pixel_type(0), SL);

tst::check_eq(dst_img[1][0], decltype(dst_img)::pixel_type(0), SL);
tst::check_eq(dst_img[1][1], decltype(dst_img)::pixel_type(0), SL);
});

suite.add("blit__partly_over", []() {
rasterimage::image<uint8_t, 4> dst_img(rasterimage::dimensioned::dimensions_type{20, 10});
dst_img.span().clear(0);
tst::check_eq(dst_img[0][0], decltype(dst_img)::pixel_type(0), SL);

rasterimage::image<uint8_t, 4> src_img(rasterimage::dimensioned::dimensions_type{3, 2});
src_img.span().clear(13);
tst::check_eq(src_img[0][0], decltype(src_img)::pixel_type(13), SL);

dst_img.span().blit(src_img.span(), {18, 9});

tst::check_eq(dst_img[8][17], decltype(dst_img)::pixel_type(0), SL);
tst::check_eq(dst_img[8][18], decltype(dst_img)::pixel_type(0), SL);
tst::check_eq(dst_img[8][19], decltype(dst_img)::pixel_type(0), SL);

tst::check_eq(dst_img[9][17], decltype(dst_img)::pixel_type(0), SL);
tst::check_eq(dst_img[9][18], decltype(dst_img)::pixel_type(13), SL);
tst::check_eq(dst_img[9][19], decltype(dst_img)::pixel_type(13), SL);
});
});
} // namespace

0 comments on commit 57e23f2

Please sign in to comment.