Skip to content

Commit 1a2a908

Browse files
committed
Resolve merge conflicts
1 parent 843ea37 commit 1a2a908

File tree

6 files changed

+248
-5
lines changed

6 files changed

+248
-5
lines changed

include/boost/gil/algorithm.hpp

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1416,11 +1416,12 @@ void view_multiplies_scalar(SrcView const& src_view, Scalar const& scalar, DstVi
14161416
/// \brief Boundary options for image boundary extension
14171417
enum class boundary_option
14181418
{
1419-
output_ignore, /// do nothing to the output
1420-
output_zero, /// set the output to zero
1421-
extend_padded, /// assume the source boundaries to be padded already
1422-
extend_zero, /// assume the source boundaries to be zero
1423-
extend_constant /// assume the source boundaries to be the boundary value
1419+
output_ignore, /// do nothing to the output
1420+
output_zero, /// set the output to zero
1421+
extend_padded, /// assume the source boundaries to be padded already
1422+
extend_zero, /// assume the source boundaries to be zero
1423+
extend_constant, /// assume the source boundaries to be the boundary value
1424+
extend_reflection /// assumes boundary values as reflection of source row pixels
14241425
};
14251426

14261427
namespace detail

include/boost/gil/image_processing/convolve.hpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Copyright 2005-2007 Adobe Systems Incorporated
33
// Copyright 2019 Miral Shah <[email protected]>
44
// Copyright 2019-2021 Pranam Lashkari <[email protected]>
5+
// Copyright 2021 Prathamesh Tagore <[email protected]>
56
//
67
// Distributed under the Boost Software License, Version 1.0
78
// See accompanying file LICENSE_1_0.txt or copy at
@@ -143,6 +144,18 @@ void correlate_rows_impl(
143144
pixel_assigns_t<src_pixel_ref_t, PixelAccum>()(src_view.row_end(y)[-1], filler);
144145
std::fill_n(it_buffer, kernel.right_size(), filler);
145146
}
147+
else if (option == boundary_option::extend_reflection)
148+
{
149+
assign_pixels(src_view.row_begin(y), src_view.row_begin(y) + kernel.left_size(),
150+
it_buffer);
151+
std::reverse(buffer.begin(), buffer.begin() + kernel.left_size());
152+
it_buffer += kernel.left_size();
153+
assign_pixels(src_view.row_begin(y), src_view.row_end(y), it_buffer);
154+
it_buffer += width;
155+
assign_pixels(src_view.row_end(y) - kernel.right_size(), src_view.row_end(y),
156+
it_buffer);
157+
std::reverse(buffer.end() - kernel.right_size(), buffer.end());
158+
}
146159

147160
correlator(
148161
&buffer.front(), &buffer.front() + width,

test/core/image_processing/convolve.cpp

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
//
22
// Copyright 2019-2020 Mateusz Loskot <mateusz at loskot dot net>
33
// Copyright 2021 Pranam Lashkari <[email protected]>
4+
// Copyright 2021 Prathamesh Tagore <[email protected]>
45
//
56
// Distributed under the Boost Software License, Version 1.0
67
// See accompanying file LICENSE_1_0.txt or copy at
@@ -111,12 +112,81 @@ struct test_image_5x5_kernel_3x3_identity
111112
}
112113
};
113114

115+
struct test_image_5x5_kernel_1x9_boundary_extend_reflection
116+
{
117+
template <typename Image>
118+
void operator()(Image const&)
119+
{
120+
using image_t = Image;
121+
using pixel_t = typename image_t::value_type;
122+
using channel_t = typename gil::channel_type<pixel_t>::type;
123+
auto img = fixture::generate_image<image_t>(5, 5, fixture::random_value<channel_t>{});
124+
auto img_view = gil::view(img);
125+
image_t img_out_up_left_offset(img), img_expected_row_up_offset(img);
126+
image_t img_expected_col_left_offset(img), img_out_down_right_offset(img);
127+
image_t img_expected_row_down_offset(img), img_expected_col_right_offset(img);
128+
int kernel_shift_up_left_offset = 2, kernel_shift_down_right_offset = -2;
129+
130+
fixture::row_conv1D_offset_img_generator(img_view, gil::view(img_expected_row_up_offset),
131+
kernel_shift_up_left_offset);
132+
fixture::row_conv1D_offset_img_generator(img_view, gil::view(img_expected_row_up_offset),
133+
-1, 0, 1, img_view.height(), 1);
134+
fixture::row_conv1D_offset_img_generator(img_view, gil::view(img_expected_row_up_offset),
135+
1, 0, 0, img_view.height(), 2);
136+
137+
fixture::col_conv1D_offset_img_generator(gil::view(img_expected_row_up_offset),
138+
gil::view(img_expected_col_left_offset), kernel_shift_up_left_offset);
139+
fixture::col_conv1D_offset_img_generator(gil::view(img_expected_row_up_offset),
140+
gil::view(img_expected_col_left_offset), -1, 1, 0, 1, img_view.width());
141+
fixture::col_conv1D_offset_img_generator(gil::view(img_expected_row_up_offset),
142+
gil::view(img_expected_col_left_offset), 1, 0, 0, 2, img_view.width());
143+
144+
fixture::row_conv1D_offset_img_generator(img_view, gil::view(img_expected_row_down_offset),
145+
kernel_shift_down_right_offset, 0, 2, img_view.height(), img_view.width());
146+
fixture::row_conv1D_offset_img_generator(img_view, gil::view(img_expected_row_down_offset),
147+
-1, 0, img_view.width() - 1, img_view.height(), img_view.width());
148+
fixture::row_conv1D_offset_img_generator(img_view, gil::view(img_expected_row_down_offset),
149+
1, 0, img_view.width() - 2, img_view.height(), img_view.width());
150+
151+
fixture::col_conv1D_offset_img_generator(gil::view(img_expected_row_down_offset),
152+
gil::view(img_expected_col_right_offset), kernel_shift_down_right_offset, 2, 0,
153+
img_view.height(), img_view.width());
154+
fixture::col_conv1D_offset_img_generator(gil::view(img_expected_row_down_offset),
155+
gil::view(img_expected_col_right_offset), -1, img_view.height() - 1, 0,
156+
img_view.height(), img_view.width());
157+
fixture::col_conv1D_offset_img_generator(gil::view(img_expected_row_down_offset),
158+
gil::view(img_expected_col_right_offset), 1, img_view.height() - 2, 0,
159+
img_view.height(), img_view.width());
160+
161+
auto const kernel_up_left_offset = fixture::create_kernel<channel_t>(
162+
{0, 0, 0, 0, 0, 0, 1, 0, 0});
163+
gil::detail::convolve_1d<pixel_t>(gil::const_view(img), kernel_up_left_offset,
164+
gil::view(img_out_up_left_offset), gil::boundary_option::extend_reflection);
165+
166+
auto const kernel_down_right_offset = fixture::create_kernel<channel_t>(
167+
{0, 0, 1, 0, 0, 0, 0, 0, 0});
168+
gil::detail::convolve_1d<pixel_t>(gil::const_view(img), kernel_down_right_offset,
169+
gil::view(img_out_down_right_offset), gil::boundary_option::extend_reflection);
170+
171+
BOOST_TEST(gil::equal_pixels(gil::const_view(img_out_up_left_offset),
172+
gil::const_view(img_expected_col_left_offset)));
173+
BOOST_TEST(gil::equal_pixels(gil::const_view(img_out_down_right_offset),
174+
gil::const_view(img_expected_col_right_offset)));
175+
}
176+
static void run()
177+
{
178+
boost::mp11::mp_for_each<fixture::image_types>(
179+
test_image_5x5_kernel_1x9_boundary_extend_reflection{});
180+
}
181+
};
182+
114183
int main()
115184
{
116185
test_image_1x1_kernel_1x1_identity::run();
117186
test_image_1x1_kernel_3x3_identity::run();
118187
test_image_3x3_kernel_3x3_identity::run();
119188
test_image_5x5_kernel_3x3_identity::run();
120189

190+
test_image_5x5_kernel_1x9_boundary_extend_reflection::run();
121191
return ::boost::report_errors();
122192
}

test/core/image_processing/convolve_cols.cpp

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
//
22
// Copyright 2019-2020 Mateusz Loskot <mateusz at loskot dot net>
33
// Copyright 2021 Pranam Lashkari <[email protected]>
4+
// Copyright 2021 Prathamesh Tagore <[email protected]>
45
//
56
// Distributed under the Boost Software License, Version 1.0
67
// See accompanying file LICENSE_1_0.txt or copy at
@@ -65,10 +66,61 @@ struct test_image_1x1_kernel_3x3_identity
6566
}
6667
};
6768

69+
struct test_image_5x5_kernel_1x9_boundary_extend_reflection
70+
{
71+
template <typename Image>
72+
void operator()(Image const&)
73+
{
74+
using image_t = Image;
75+
using pixel_t = typename image_t::value_type;
76+
using channel_t = typename gil::channel_type<pixel_t>::type;
77+
auto img = fixture::generate_image<image_t>(5, 5, fixture::random_value<channel_t>{});
78+
auto img_view = gil::view(img);
79+
image_t img_out_left_offset(img), img_expected_left_offset(img);
80+
image_t img_out_right_offset(img), img_expected_right_offset(img);
81+
int kernel_shift_left_offset = 2, kernel_shift_right_offset = -2;
82+
83+
fixture::col_conv1D_offset_img_generator(img_view, gil::view(img_expected_left_offset),
84+
kernel_shift_left_offset);
85+
fixture::col_conv1D_offset_img_generator(img_view, gil::view(img_expected_left_offset),
86+
-1, 1, 0, 1, img_view.width());
87+
fixture::col_conv1D_offset_img_generator(img_view, gil::view(img_expected_left_offset),
88+
1, 0, 0, 2, img_view.width());
89+
90+
fixture::col_conv1D_offset_img_generator(img_view, gil::view(img_expected_right_offset),
91+
kernel_shift_right_offset, 2, 0, img_view.height(), img_view.width());
92+
fixture::col_conv1D_offset_img_generator(img_view, gil::view(img_expected_right_offset),
93+
-1, img_view.height() - 1, 0, img_view.height(), img_view.width());
94+
fixture::col_conv1D_offset_img_generator(img_view, gil::view(img_expected_right_offset),
95+
1, img_view.height() - 2, 0, img_view.height(), img_view.width());
96+
97+
auto const kernel_left_offset = fixture::create_kernel<channel_t>(
98+
{0, 0, 0, 0, 0, 0, 1, 0, 0});
99+
gil::convolve_cols<pixel_t>(gil::const_view(img), kernel_left_offset,
100+
gil::view(img_out_left_offset), gil::boundary_option::extend_reflection);
101+
102+
auto const kernel_right_offset = fixture::create_kernel<channel_t>(
103+
{0, 0, 1, 0, 0, 0, 0, 0, 0});
104+
gil::convolve_cols<pixel_t>(gil::const_view(img), kernel_right_offset,
105+
gil::view(img_out_right_offset), gil::boundary_option::extend_reflection);
106+
107+
BOOST_TEST(gil::equal_pixels(gil::const_view(img_out_left_offset),
108+
gil::const_view(img_expected_left_offset)));
109+
BOOST_TEST(gil::equal_pixels(gil::const_view(img_out_right_offset),
110+
gil::const_view(img_expected_right_offset)));
111+
}
112+
static void run()
113+
{
114+
boost::mp11::mp_for_each<fixture::image_types>(
115+
test_image_5x5_kernel_1x9_boundary_extend_reflection{});
116+
}
117+
};
118+
68119
int main()
69120
{
70121
test_image_1x1_kernel_1x1_identity::run();
71122
test_image_1x1_kernel_3x3_identity::run();
72123

124+
test_image_5x5_kernel_1x9_boundary_extend_reflection::run();
73125
return ::boost::report_errors();
74126
}

test/core/image_processing/convolve_rows.cpp

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
//
22
// Copyright 2019-2020 Mateusz Loskot <mateusz at loskot dot net>
33
// Copyright 2021 Pranam Lashkari <[email protected]>
4+
// Copyright 2021 Prathamesh Tagore <[email protected]>
45
//
56
// Distributed under the Boost Software License, Version 1.0
67
// See accompanying file LICENSE_1_0.txt or copy at
@@ -65,10 +66,61 @@ struct test_image_1x1_kernel_3x3_identity
6566
}
6667
};
6768

69+
struct test_image_5x5_kernel_1x9_boundary_extend_reflection
70+
{
71+
template <typename Image>
72+
void operator()(Image const&)
73+
{
74+
using image_t = Image;
75+
using pixel_t = typename image_t::value_type;
76+
using channel_t = typename gil::channel_type<pixel_t>::type;
77+
auto img = fixture::generate_image<image_t>(5, 5, fixture::random_value<channel_t>{});
78+
auto img_view = gil::view(img);
79+
image_t img_out_up_offset(img), img_expected_up_offset(img);
80+
image_t img_out_down_offset(img), img_expected_down_offset(img);
81+
int kernel_shift_up_offset = 2, kernel_shift_down_offset = -2;
82+
83+
fixture::row_conv1D_offset_img_generator(img_view, gil::view(img_expected_up_offset),
84+
kernel_shift_up_offset);
85+
fixture::row_conv1D_offset_img_generator(img_view, gil::view(img_expected_up_offset),
86+
-1, 0, 1, img_view.height(), 1);
87+
fixture::row_conv1D_offset_img_generator(img_view, gil::view(img_expected_up_offset),
88+
1, 0, 0, img_view.height(), 2);
89+
90+
fixture::row_conv1D_offset_img_generator(img_view, gil::view(img_expected_down_offset),
91+
kernel_shift_down_offset, 0, 2, img_view.height(), img_view.width());
92+
fixture::row_conv1D_offset_img_generator(img_view, gil::view(img_expected_down_offset),
93+
-1, 0, img_view.width() - 1, img_view.height(), img_view.width());
94+
fixture::row_conv1D_offset_img_generator(img_view, gil::view(img_expected_down_offset),
95+
1, 0, img_view.width() - 2, img_view.height(), img_view.width());
96+
97+
auto const kernel_up_offset = fixture::create_kernel<channel_t>(
98+
{0, 0, 0, 0, 0, 0, 1, 0, 0});
99+
gil::convolve_rows<pixel_t>(gil::const_view(img), kernel_up_offset,
100+
gil::view(img_out_up_offset), gil::boundary_option::extend_reflection);
101+
102+
auto const kernel_down_offset = fixture::create_kernel<channel_t>(
103+
{0, 0, 1, 0, 0, 0, 0, 0, 0});
104+
gil::convolve_rows<pixel_t>(gil::const_view(img), kernel_down_offset,
105+
gil::view(img_out_down_offset), gil::boundary_option::extend_reflection);
106+
107+
BOOST_TEST(gil::equal_pixels(gil::const_view(img_out_up_offset),
108+
gil::const_view(img_expected_up_offset)));
109+
BOOST_TEST(gil::equal_pixels(gil::const_view(img_out_down_offset),
110+
gil::const_view(img_expected_down_offset)));
111+
}
112+
static void run()
113+
{
114+
boost::mp11::mp_for_each<fixture::image_types>(
115+
test_image_5x5_kernel_1x9_boundary_extend_reflection{});
116+
}
117+
};
118+
68119
int main()
69120
{
70121
test_image_1x1_kernel_1x1_identity::run();
71122
test_image_1x1_kernel_3x3_identity::run();
72123

124+
test_image_5x5_kernel_1x9_boundary_extend_reflection::run();
73125
return ::boost::report_errors();
74126
}

test/core/image_processing/test_fixture.hpp

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
//
22
// Copyright 2019 Mateusz Loskot <mateusz at loskot dot net>
33
// Copyright 2021 Pranam Lashkari <[email protected]>
4+
// Copyright 2021 Prathamesh Tagore <[email protected]>
45
//
56
// Distributed under the Boost Software License, Version 1.0
67
// See accompanying file LICENSE_1_0.txt or copy at
@@ -28,4 +29,58 @@ auto create_kernel(std::initializer_list<T> const& values)
2829
return kernel;
2930
}
3031

32+
// Adds an offset similar to 1D row convolution with kernel {0, 0, 0, 0, 0, 0, 1, 0, 0}
33+
// (for offset = 2) having its anchor point at 5th element and boundary option as "extend_zero".
34+
template <typename SrcView, typename DstView>
35+
void row_conv1D_offset_img_generator(SrcView src_view, DstView dst_view, int const offset,
36+
std::ptrdiff_t start_row = 0, std::ptrdiff_t start_col = 0, std::ptrdiff_t end_row = -1,
37+
std::ptrdiff_t end_col = -1)
38+
{
39+
BOOST_ASSERT(src_view.dimensions() == dst_view.dimensions());
40+
static_assert(color_spaces_are_compatible
41+
<
42+
typename color_space_type<SrcView>::type,
43+
typename color_space_type<DstView>::type
44+
>::value, "Source and destination views must have pixels with the same color space");
45+
46+
if (end_row == -1)
47+
end_row = src_view.height();
48+
if (end_col == -1)
49+
end_col = src_view.width();
50+
for (std::ptrdiff_t y = start_row; y < end_row; ++y)
51+
{
52+
auto src_it = src_view.row_begin(y);
53+
auto dst_it = dst_view.row_begin(y);
54+
for (std::ptrdiff_t x = offset + start_col; x < end_col; ++x)
55+
dst_it[x] = src_it[x - offset];
56+
}
57+
}
58+
59+
// Adds an offset similar to 1D column convolution with kernel {0, 0, 0, 0, 0, 0, 1, 0, 0}
60+
// (for offset = 2) having its anchor point at 5th element and boundary option as "extend_zero".
61+
template <typename SrcView, typename DstView>
62+
void col_conv1D_offset_img_generator(SrcView src_view, DstView dst_view, int const offset,
63+
std::ptrdiff_t start_row = 0, std::ptrdiff_t start_col = 0, std::ptrdiff_t end_row = -1,
64+
std::ptrdiff_t end_col = -1)
65+
{
66+
BOOST_ASSERT(src_view.dimensions() == dst_view.dimensions());
67+
static_assert(color_spaces_are_compatible
68+
<
69+
typename color_space_type<SrcView>::type,
70+
typename color_space_type<DstView>::type
71+
>::value, "Source and destination views must have pixels with the same color space");
72+
73+
if (end_row == -1)
74+
end_row = src_view.height();
75+
if (end_col == -1)
76+
end_col = src_view.width();
77+
for (std::ptrdiff_t x = start_col; x < end_col; ++x)
78+
{
79+
auto src_it = src_view.col_begin(x);
80+
auto dst_it = dst_view.col_begin(x);
81+
for (std::ptrdiff_t y = offset + start_row; y < end_row; ++y)
82+
dst_it[y] = src_it[y - offset];
83+
}
84+
}
85+
3186
}}}} // namespace boost::gil::test::fixture

0 commit comments

Comments
 (0)