1 //
2 // Copyright 2019-2020 Mateusz Loskot <mateusz at loskot dot net>
3 //
4 // Distributed under the Boost Software License, Version 1.0
5 // See accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt
7 //
8 #include <boost/gil.hpp>
9 #include <boost/gil/extension/numeric/pixel_numeric_operations.hpp>
10
11 #include <boost/core/lightweight_test.hpp>
12
13 #include <tuple>
14 #include <type_traits>
15
16 #include "test_utility_output_stream.hpp"
17 #include "core/test_fixture.hpp" // random_value
18 #include "core/pixel/test_fixture.hpp"
19
20 namespace gil = boost::gil;
21 namespace fixture = boost::gil::test::fixture;
22
23 struct test_plus_integer_same_types
24 {
25 template <typename Pixel>
operator ()test_plus_integer_same_types26 void operator()(Pixel const&)
27 {
28 using pixel_t = Pixel;
29 using channel_t = typename gil::channel_type<pixel_t>::type;
30 gil::pixel_plus_t<pixel_t, pixel_t, pixel_t> f;
31 {
32 pixel_t p0;
33 gil::static_fill(p0, static_cast<channel_t>(0));
34 BOOST_TEST_EQ(f(p0, p0), p0);
35 }
36 {
37 pixel_t p1;
38 gil::static_fill(p1, static_cast<channel_t>(1));
39 pixel_t r2;
40 gil::static_fill(r2, static_cast<channel_t>(2));
41 BOOST_TEST_EQ(f(p1, p1), r2);
42 }
43 {
44 // Generates pixels with consecutive channel values: {1} or {1,2,3} or {1,2,3,4} etc.
45 fixture::consecutive_value<channel_t> g(1);
46 pixel_t p;
47 gil::static_generate(p, [&g]() { return g(); });
48 auto const r = f(p, p);
49 BOOST_TEST_NE(r, p);
50 BOOST_TEST_EQ(gil::at_c<0>(r), (gil::at_c<0>(p) + gil::at_c<0>(p)));
51 }
52 }
runtest_plus_integer_same_types53 static void run()
54 {
55 boost::mp11::mp_for_each<fixture::pixel_integer_types>(test_plus_integer_same_types{});
56 }
57 };
58
59 struct test_minus_integer_same_types
60 {
61 template <typename Pixel>
operator ()test_minus_integer_same_types62 void operator()(Pixel const&)
63 {
64 using pixel_t = Pixel;
65 using channel_t = typename gil::channel_type<pixel_t>::type;
66 gil::pixel_minus_t<pixel_t, pixel_t, pixel_t> f;
67
68 pixel_t p0;
69 gil::static_fill(p0, static_cast<channel_t>(0));
70 BOOST_TEST_EQ(f(p0, p0), p0);
71 {
72 pixel_t p1, p2;
73 gil::static_fill(p1, static_cast<channel_t>(1));
74 gil::static_fill(p2, static_cast<channel_t>(2));
75 pixel_t r1;
76 gil::static_fill(r1, static_cast<channel_t>(1));
77 BOOST_TEST_EQ(f(p2, p1), r1);
78 }
79 {
80 // Generates pixels with consecutive channel values: {1} or {1,2,3} or {1,2,3,4} etc.
81 fixture::consecutive_value<channel_t> g(1);
82 pixel_t p;
83 gil::static_generate(p, [&g]() { return g(); });
84 BOOST_TEST_EQ(f(p, p), p0);
85 }
86 }
runtest_minus_integer_same_types87 static void run()
88 {
89 boost::mp11::mp_for_each<fixture::pixel_integer_types>(test_minus_integer_same_types{});
90 }
91 };
92
93 struct test_pixel_multiplies_scalar_integer_same_types
94 {
95 template <typename Pixel>
operator ()test_pixel_multiplies_scalar_integer_same_types96 void operator()(Pixel const&)
97 {
98 using pixel_t = Pixel;
99 using channel_t = typename gil::channel_type<pixel_t>::type;
100 gil::pixel_multiplies_scalar_t<pixel_t, channel_t, pixel_t> f;
101
102 pixel_t p0;
103 gil::static_fill(p0, static_cast<channel_t>(0));
104 BOOST_TEST_EQ(f(p0, 0), p0);
105
106 {
107 pixel_t p1;
108 gil::static_fill(p1, static_cast<channel_t>(1));
109 BOOST_TEST_EQ(f(p1, 0), p0);
110 BOOST_TEST_EQ(f(p1, 1), p1);
111 }
112 {
113 // Generates pixels with consecutive channel values: {1} or {1,2,3} or {1,2,3,4} etc.
114 fixture::consecutive_value<channel_t> g(1);
115 pixel_t p;
116 gil::static_generate(p, [&g]() { return g(); });
117
118 // check first channel value is doubled
119 auto const r = f(p, 2);
120 BOOST_TEST_NE(r, p);
121 BOOST_TEST_EQ(gil::at_c<0>(r), (gil::at_c<0>(p) * 2));
122 }
123 }
runtest_pixel_multiplies_scalar_integer_same_types124 static void run()
125 {
126 boost::mp11::mp_for_each<fixture::pixel_integer_types>(test_pixel_multiplies_scalar_integer_same_types{});
127 }
128 };
129
130 struct test_pixel_multiply_integer_same_types
131 {
132 template <typename Pixel>
operator ()test_pixel_multiply_integer_same_types133 void operator()(Pixel const&)
134 {
135 using pixel_t = Pixel;
136 using channel_t = typename gil::channel_type<pixel_t>::type;
137 gil::pixel_multiply_t<pixel_t, pixel_t, pixel_t> f;
138
139 pixel_t p0;
140 gil::static_fill(p0, static_cast<channel_t>(0));
141 BOOST_TEST_EQ(f(p0, p0), p0);
142
143 pixel_t p1;
144 gil::static_fill(p1, static_cast<channel_t>(1));
145 BOOST_TEST_EQ(f(p1, p1), p1);
146
147 pixel_t p2;
148 gil::static_fill(p2, static_cast<channel_t>(2));
149 BOOST_TEST_EQ(f(p1, p2), p2);
150 }
runtest_pixel_multiply_integer_same_types151 static void run()
152 {
153 boost::mp11::mp_for_each<fixture::pixel_integer_types>(test_pixel_multiply_integer_same_types{});
154 }
155 };
156
157 struct test_pixel_divides_scalar_integer_same_types
158 {
159 template <typename Pixel>
operator ()test_pixel_divides_scalar_integer_same_types160 void operator()(Pixel const&)
161 {
162 using pixel_t = Pixel;
163 using channel_t = typename gil::channel_type<pixel_t>::type;
164 gil::pixel_divides_scalar_t<pixel_t, channel_t, pixel_t> f;
165
166 pixel_t p0;
167 gil::static_fill(p0, static_cast<channel_t>(0));
168 BOOST_TEST_EQ(f(p0, 1), p0);
169
170 pixel_t p1;
171 gil::static_fill(p1, static_cast<channel_t>(1));
172 BOOST_TEST_EQ(f(p1, 1), p1);
173
174 pixel_t p2;
175 gil::static_fill(p2, static_cast<channel_t>(2));
176 BOOST_TEST_EQ(f(p2, 2), p1);
177 }
runtest_pixel_divides_scalar_integer_same_types178 static void run()
179 {
180 boost::mp11::mp_for_each<fixture::pixel_integer_types>(test_pixel_divides_scalar_integer_same_types{});
181 }
182 };
183
184 struct test_pixel_divide_integer_same_types
185 {
186 template <typename Pixel>
operator ()test_pixel_divide_integer_same_types187 void operator()(Pixel const&)
188 {
189 using pixel_t = Pixel;
190 using channel_t = typename gil::channel_type<pixel_t>::type;
191 gil::pixel_divide_t<pixel_t, pixel_t, pixel_t> f;
192
193 pixel_t p0;
194 gil::static_fill(p0, static_cast<channel_t>(0));
195 pixel_t p1;
196 gil::static_fill(p1, static_cast<channel_t>(1));
197 BOOST_TEST_EQ(f(p0, p1), p0);
198 BOOST_TEST_EQ(f(p1, p1), p1);
199
200 pixel_t p2;
201 gil::static_fill(p2, static_cast<channel_t>(2));
202 BOOST_TEST_EQ(f(p2, p1), p2);
203 }
runtest_pixel_divide_integer_same_types204 static void run()
205 {
206 boost::mp11::mp_for_each<fixture::pixel_integer_types>(test_pixel_divide_integer_same_types{});
207 }
208 };
209
210 struct test_pixel_halves_integer_same_types
211 {
212 template <typename Pixel>
operator ()test_pixel_halves_integer_same_types213 void operator()(Pixel const&)
214 {
215 using pixel_t = Pixel;
216 using channel_t = typename gil::channel_type<pixel_t>::type;
217 gil::pixel_halves_t<pixel_t> f;
218
219 pixel_t p0;
220 gil::static_fill(p0, static_cast<channel_t>(0));
221 pixel_t p1;
222 gil::static_fill(p1, static_cast<channel_t>(1));
223
224 {
225 auto p = p0;
226 BOOST_TEST_EQ(f(p), p0);
227 }
228 {
229 auto p = p1;
230 BOOST_TEST_EQ(f(p), p0); // truncates toward Zero
231 }
232 {
233 pixel_t p2;
234 gil::static_fill(p2, static_cast<channel_t>(2));
235 BOOST_TEST_EQ(f(p2), p1);
236 }
237 }
runtest_pixel_halves_integer_same_types238 static void run()
239 {
240 boost::mp11::mp_for_each<fixture::pixel_integer_types>(test_pixel_halves_integer_same_types{});
241 }
242 };
243
244 struct test_pixel_zeros_integer_same_types
245 {
246 template <typename Pixel>
operator ()test_pixel_zeros_integer_same_types247 void operator()(Pixel const&)
248 {
249 using pixel_t = Pixel;
250 using channel_t = typename gil::channel_type<pixel_t>::type;
251 gil::pixel_zeros_t<pixel_t> f;
252
253 pixel_t p0;
254 gil::static_fill(p0, static_cast<channel_t>(0));
255 {
256 auto p = p0;
257 BOOST_TEST_EQ(f(p), p0);
258 }
259 {
260 fixture::consecutive_value<channel_t> g(1);
261 pixel_t p;
262 gil::static_generate(p, [&g]() { return g(); });
263 BOOST_TEST_EQ(f(p), p0);
264 }
265 }
runtest_pixel_zeros_integer_same_types266 static void run()
267 {
268 boost::mp11::mp_for_each<fixture::pixel_integer_types>(test_pixel_zeros_integer_same_types{});
269 }
270 };
271
272 struct test_zero_channels_integer_same_types
273 {
274 template <typename Pixel>
operator ()test_zero_channels_integer_same_types275 void operator()(Pixel const&)
276 {
277 using pixel_t = Pixel;
278 using channel_t = typename gil::channel_type<pixel_t>::type;
279
280 pixel_t p0;
281 gil::static_fill(p0, static_cast<channel_t>(0));
282 {
283 auto p = p0;
284 gil::zero_channels(p);
285 BOOST_TEST_EQ(p, p0);
286 }
287 {
288 fixture::consecutive_value<channel_t> g(1);
289 pixel_t p;
290 gil::static_generate(p, [&g]() { return g(); });
291 gil::zero_channels(p);
292 BOOST_TEST_EQ(p, p0);
293 }
294 }
runtest_zero_channels_integer_same_types295 static void run()
296 {
297 boost::mp11::mp_for_each<fixture::pixel_integer_types>(test_zero_channels_integer_same_types{});
298 }
299 };
300
301 struct test_pixel_assigns_integer_same_types
302 {
303 template <typename Pixel>
operator ()test_pixel_assigns_integer_same_types304 void operator()(Pixel const&)
305 {
306 using pixel_t = Pixel;
307 using channel_t = typename gil::channel_type<pixel_t>::type;
308 gil::pixel_assigns_t<pixel_t, pixel_t> f;
309
310 {
311 pixel_t p0, r;
312 gil::static_fill(p0, static_cast<channel_t>(0));
313 f(p0, r);
314 BOOST_TEST_EQ(p0, r);
315 }
316 {
317 fixture::consecutive_value<channel_t> g(1);
318 pixel_t p, r;
319 gil::static_generate(p, [&g]() { return g(); });
320 f(p, r);
321 BOOST_TEST_EQ(p, r);
322 }
323 }
runtest_pixel_assigns_integer_same_types324 static void run()
325 {
326 boost::mp11::mp_for_each<fixture::pixel_integer_types>(test_pixel_assigns_integer_same_types{});
327 }
328 };
main()329 int main()
330 {
331 test_plus_integer_same_types::run();
332 test_minus_integer_same_types::run();
333 test_pixel_multiplies_scalar_integer_same_types::run();
334 test_pixel_multiply_integer_same_types::run();
335 test_pixel_divides_scalar_integer_same_types::run();
336 test_pixel_divide_integer_same_types::run();
337 test_pixel_halves_integer_same_types::run();
338 test_pixel_zeros_integer_same_types::run();
339 test_zero_channels_integer_same_types::run();
340 test_pixel_assigns_integer_same_types::run();
341
342 return ::boost::report_errors();
343 }
344