Boost GIL


kernel.hpp
1 //
2 // Copyright 2005-2007 Adobe Systems Incorporated
3 // Copyright 2019 Miral Shah <miralshah2211@gmail.com>
4 // Copyright 2022 Pranam Lashkari <plashkari628@gmail.com>
5 //
6 // Distributed under the Boost Software License, Version 1.0
7 // See accompanying file LICENSE_1_0.txt or copy at
8 // http://www.boost.org/LICENSE_1_0.txt
9 //
10 
11 #ifndef BOOST_GIL_IMAGE_PROCESSING_KERNEL_HPP
12 #define BOOST_GIL_IMAGE_PROCESSING_KERNEL_HPP
13 
14 #include <boost/gil/utilities.hpp>
15 #include <boost/gil/point.hpp>
16 
17 #include <boost/assert.hpp>
18 
19 #include <algorithm>
20 #include <array>
21 #include <cstddef>
22 #include <memory>
23 #include <vector>
24 #include <cmath>
25 #include <stdexcept>
26 
27 namespace boost { namespace gil {
28 
29 // Definitions of 1D fixed-size and variable-size kernels and related operations
30 
31 namespace detail {
32 
36 template <typename Core>
37 class kernel_1d_adaptor : public Core
38 {
39 public:
40  kernel_1d_adaptor() = default;
41 
42  explicit kernel_1d_adaptor(std::size_t center)
43  : center_(center)
44  {
45  BOOST_ASSERT(center_ < this->size());
46  }
47 
48  kernel_1d_adaptor(std::size_t size, std::size_t center)
49  : Core(size) , center_(center)
50  {
51  BOOST_ASSERT(this->size() > 0);
52  BOOST_ASSERT(center_ < this->size()); // also implies `size() > 0`
53  }
54 
56  : Core(other), center_(other.center_)
57  {
58  BOOST_ASSERT(this->size() > 0);
59  BOOST_ASSERT(center_ < this->size()); // also implies `size() > 0`
60  }
61 
62  kernel_1d_adaptor& operator=(kernel_1d_adaptor const& other)
63  {
64  Core::operator=(other);
65  center_ = other.center_;
66  return *this;
67  }
68 
69  std::size_t left_size() const
70  {
71  BOOST_ASSERT(center_ < this->size());
72  return center_;
73  }
74 
75  std::size_t right_size() const
76  {
77  BOOST_ASSERT(center_ < this->size());
78  return this->size() - center_ - 1;
79  }
80 
81  auto center() -> std::size_t&
82  {
83  BOOST_ASSERT(center_ < this->size());
84  return center_;
85  }
86 
87  auto center() const -> std::size_t const&
88  {
89  BOOST_ASSERT(center_ < this->size());
90  return center_;
91  }
92 
93 private:
94  std::size_t center_{0};
95 };
96 
97 } // namespace detail
98 
100 template <typename T, typename Allocator = std::allocator<T> >
101 class kernel_1d : public detail::kernel_1d_adaptor<std::vector<T, Allocator>>
102 {
104 public:
105 
106  kernel_1d() = default;
107  kernel_1d(std::size_t size, std::size_t center) : parent_t(size, center) {}
108 
109  template <typename FwdIterator>
110  kernel_1d(FwdIterator elements, std::size_t size, std::size_t center)
111  : parent_t(size, center)
112  {
113  detail::copy_n(elements, size, this->begin());
114  }
115 
116  kernel_1d(kernel_1d const& other) : parent_t(other) {}
117  kernel_1d& operator=(kernel_1d const& other) = default;
118 };
119 
121 template <typename T,std::size_t Size>
122 class kernel_1d_fixed : public detail::kernel_1d_adaptor<std::array<T, Size>>
123 {
125 public:
126  static constexpr std::size_t static_size = Size;
127  static_assert(static_size > 0, "kernel must have size greater than 0");
128  static_assert(static_size % 2 == 1, "kernel size must be odd to ensure validity at the center");
129 
130  kernel_1d_fixed() = default;
131  explicit kernel_1d_fixed(std::size_t center) : parent_t(center) {}
132 
133  template <typename FwdIterator>
134  explicit kernel_1d_fixed(FwdIterator elements, std::size_t center)
135  : parent_t(center)
136  {
137  detail::copy_n(elements, Size, this->begin());
138  }
139 
140  kernel_1d_fixed(kernel_1d_fixed const& other) : parent_t(other) {}
141  kernel_1d_fixed& operator=(kernel_1d_fixed const& other) = default;
142 };
143 
144 // TODO: This data member is odr-used and definition at namespace scope
145 // is required by C++11. Redundant and deprecated in C++17.
146 template <typename T,std::size_t Size>
147 constexpr std::size_t kernel_1d_fixed<T, Size>::static_size;
148 
150 template <typename Kernel>
151 inline Kernel reverse_kernel(Kernel const& kernel)
152 {
153  Kernel result(kernel);
154  result.center() = kernel.right_size();
155  std::reverse(result.begin(), result.end());
156  return result;
157 }
158 
159 
160 namespace detail {
161 
162 template <typename Core>
163 class kernel_2d_adaptor : public Core
164 {
165 public:
166  kernel_2d_adaptor() = default;
167 
168  explicit kernel_2d_adaptor(std::size_t center_y, std::size_t center_x)
169  : center_(center_x, center_y)
170  {
171  BOOST_ASSERT(center_.y < this->size() && center_.x < this->size());
172  }
173 
174  kernel_2d_adaptor(std::size_t size, std::size_t center_y, std::size_t center_x)
175  : Core(size * size), square_size(size), center_(center_x, center_y)
176  {
177  BOOST_ASSERT(this->size() > 0);
178  BOOST_ASSERT(center_.y < this->size() && center_.x < this->size()); // implies `size() > 0`
179  }
180 
181  kernel_2d_adaptor(kernel_2d_adaptor const& other)
182  : Core(other), square_size(other.square_size), center_(other.center_.x, other.center_.y)
183  {
184  BOOST_ASSERT(this->size() > 0);
185  BOOST_ASSERT(center_.y < this->size() && center_.x < this->size()); // implies `size() > 0`
186  }
187 
188  kernel_2d_adaptor& operator=(kernel_2d_adaptor const& other)
189  {
190  Core::operator=(other);
191  center_.y = other.center_.y;
192  center_.x = other.center_.x;
193  square_size = other.square_size;
194  return *this;
195  }
196 
197  std::size_t upper_size() const
198  {
199  BOOST_ASSERT(center_.y < this->size());
200  return center_.y;
201  }
202 
203  std::size_t lower_size() const
204  {
205  BOOST_ASSERT(center_.y < this->size());
206  return this->size() - center_.y - 1;
207  }
208 
209  std::size_t left_size() const
210  {
211  BOOST_ASSERT(center_.x < this->size());
212  return center_.x;
213  }
214 
215  std::size_t right_size() const
216  {
217  BOOST_ASSERT(center_.x < this->size());
218  return this->size() - center_.x - 1;
219  }
220 
221  auto center_y() -> std::size_t&
222  {
223  BOOST_ASSERT(center_.y < this->size());
224  return center_.y;
225  }
226 
227  auto center_y() const -> std::size_t const&
228  {
229  BOOST_ASSERT(center_.y < this->size());
230  return center_.y;
231  }
232 
233  auto center_x() -> std::size_t&
234  {
235  BOOST_ASSERT(center_.x < this->size());
236  return center_.x;
237  }
238 
239  auto center_x() const -> std::size_t const&
240  {
241  BOOST_ASSERT(center_.x < this->size());
242  return center_.x;
243  }
244 
245  std::size_t size() const
246  {
247  return square_size;
248  }
249 
250  typename Core::value_type at(std::size_t x, std::size_t y) const
251  {
252  if (x >= this->size() || y >= this->size())
253  {
254  throw std::out_of_range("Index out of range");
255  }
256  return this->begin()[y * this->size() + x];
257  }
258 
259 protected:
260  std::size_t square_size{0};
261 
262 private:
263  point<std::size_t> center_{0, 0};
264 };
265 
267 template
268 <
269  typename T,
270  typename Allocator = std::allocator<T>
271 >
272 class kernel_2d : public detail::kernel_2d_adaptor<std::vector<T, Allocator>>
273 {
274  using parent_t = detail::kernel_2d_adaptor<std::vector<T, Allocator>>;
275 
276 public:
277 
278  kernel_2d() = default;
279  kernel_2d(std::size_t size,std::size_t center_y, std::size_t center_x)
280  : parent_t(size, center_y, center_x)
281  {}
282 
283  template <typename FwdIterator>
284  kernel_2d(FwdIterator elements, std::size_t size, std::size_t center_y, std::size_t center_x)
285  : parent_t(static_cast<int>(std::sqrt(size)), center_y, center_x)
286  {
287  detail::copy_n(elements, size, this->begin());
288  }
289 
290  kernel_2d(kernel_2d const& other) : parent_t(other) {}
291  kernel_2d& operator=(kernel_2d const& other) = default;
292 };
293 
295 template <typename T, std::size_t Size>
297  public detail::kernel_2d_adaptor<std::array<T, Size * Size>>
298 {
299  using parent_t = detail::kernel_2d_adaptor<std::array<T, Size * Size>>;
300 public:
301  static constexpr std::size_t static_size = Size;
302  static_assert(static_size > 0, "kernel must have size greater than 0");
303  static_assert(static_size % 2 == 1, "kernel size must be odd to ensure validity at the center");
304 
306  {
307  this->square_size = Size;
308  }
309 
310  explicit kernel_2d_fixed(std::size_t center_y, std::size_t center_x) :
311  parent_t(center_y, center_x)
312  {
313  this->square_size = Size;
314  }
315 
316  template <typename FwdIterator>
317  explicit kernel_2d_fixed(FwdIterator elements, std::size_t center_y, std::size_t center_x)
318  : parent_t(center_y, center_x)
319  {
320  this->square_size = Size;
321  detail::copy_n(elements, Size * Size, this->begin());
322  }
323 
324  kernel_2d_fixed(kernel_2d_fixed const& other) : parent_t(other) {}
325  kernel_2d_fixed& operator=(kernel_2d_fixed const& other) = default;
326 };
327 
328 // TODO: This data member is odr-used and definition at namespace scope
329 // is required by C++11. Redundant and deprecated in C++17.
330 template <typename T, std::size_t Size>
331 constexpr std::size_t kernel_2d_fixed<T, Size>::static_size;
332 
333 template <typename Kernel>
334 inline Kernel reverse_kernel_2d(Kernel const& kernel)
335 {
336  Kernel result(kernel);
337  result.center_x() = kernel.lower_size();
338  result.center_y() = kernel.right_size();
339  std::reverse(result.begin(), result.end());
340  return result;
341 }
342 
343 
345 template<typename T, typename Allocator>
346 inline kernel_2d<T, Allocator> reverse_kernel(kernel_2d<T, Allocator> const& kernel)
347 {
348  return reverse_kernel_2d(kernel);
349 }
350 
352 template<typename T, std::size_t Size>
353 inline kernel_2d_fixed<T, Size> reverse_kernel(kernel_2d_fixed<T, Size> const& kernel)
354 {
355  return reverse_kernel_2d(kernel);
356 }
357 
358 } //namespace detail
359 
360 }} // namespace boost::gil
361 
362 #endif
kernel adaptor for one-dimensional cores Core needs to provide size(),begin(),end(),...
Definition: kernel.hpp:38
static-size kernel
Definition: kernel.hpp:298
variable-size kernel
Definition: kernel.hpp:273
static-size kernel
Definition: kernel.hpp:123
variable-size kernel
Definition: kernel.hpp:102
defined(BOOST_NO_CXX17_HDR_MEMORY_RESOURCE)
Definition: algorithm.hpp:36
Returns an integral constant type specifying the number of elements in a color base.
Definition: color_base_algorithm.hpp:42