2 // Copyright 2005-2007 Adobe Systems Incorporated
3 // Copyright 2019 Miral Shah <miralshah2211@gmail.com>
5 // Distributed under the Boost Software License, Version 1.0
6 // See accompanying file LICENSE_1_0.txt or copy at
7 // http://www.boost.org/LICENSE_1_0.txt
10 #ifndef BOOST_GIL_EXTENSION_NUMERIC_KERNEL_HPP
11 #define BOOST_GIL_EXTENSION_NUMERIC_KERNEL_HPP
13 #include <boost/gil/utilities.hpp>
14 #include <boost/gil/point.hpp>
16 #include <boost/assert.hpp>
25 namespace boost { namespace gil {
27 // Definitions of 1D fixed-size and variable-size kernels and related operations
31 /// \brief kernel adaptor for one-dimensional cores
32 /// Core needs to provide size(),begin(),end(),operator[],
33 /// value_type,iterator,const_iterator,reference,const_reference
34 template <typename Core>
35 class kernel_1d_adaptor : public Core
38 kernel_1d_adaptor() = default;
40 explicit kernel_1d_adaptor(std::size_t center)
43 BOOST_ASSERT(center_ < this->size());
46 kernel_1d_adaptor(std::size_t size, std::size_t center)
47 : Core(size) , center_(center)
49 BOOST_ASSERT(this->size() > 0);
50 BOOST_ASSERT(center_ < this->size()); // also implies `size() > 0`
53 kernel_1d_adaptor(kernel_1d_adaptor const& other)
54 : Core(other), center_(other.center_)
56 BOOST_ASSERT(this->size() > 0);
57 BOOST_ASSERT(center_ < this->size()); // also implies `size() > 0`
60 kernel_1d_adaptor& operator=(kernel_1d_adaptor const& other)
62 Core::operator=(other);
63 center_ = other.center_;
67 std::size_t left_size() const
69 BOOST_ASSERT(center_ < this->size());
73 std::size_t right_size() const
75 BOOST_ASSERT(center_ < this->size());
76 return this->size() - center_ - 1;
79 auto center() -> std::size_t&
81 BOOST_ASSERT(center_ < this->size());
85 auto center() const -> std::size_t const&
87 BOOST_ASSERT(center_ < this->size());
92 std::size_t center_{0};
97 /// \brief variable-size kernel
98 template <typename T, typename Allocator = std::allocator<T> >
99 class kernel_1d : public detail::kernel_1d_adaptor<std::vector<T, Allocator>>
101 using parent_t = detail::kernel_1d_adaptor<std::vector<T, Allocator>>;
104 kernel_1d() = default;
105 kernel_1d(std::size_t size, std::size_t center) : parent_t(size, center) {}
107 template <typename FwdIterator>
108 kernel_1d(FwdIterator elements, std::size_t size, std::size_t center)
109 : parent_t(size, center)
111 detail::copy_n(elements, size, this->begin());
114 kernel_1d(kernel_1d const& other) : parent_t(other) {}
115 kernel_1d& operator=(kernel_1d const& other) = default;
118 /// \brief static-size kernel
119 template <typename T,std::size_t Size>
120 class kernel_1d_fixed : public detail::kernel_1d_adaptor<std::array<T, Size>>
122 using parent_t = detail::kernel_1d_adaptor<std::array<T, Size>>;
124 static constexpr std::size_t static_size = Size;
125 static_assert(static_size > 0, "kernel must have size greater than 0");
126 static_assert(static_size % 2 == 1, "kernel size must be odd to ensure validity at the center");
128 kernel_1d_fixed() = default;
129 explicit kernel_1d_fixed(std::size_t center) : parent_t(center) {}
131 template <typename FwdIterator>
132 explicit kernel_1d_fixed(FwdIterator elements, std::size_t center)
135 detail::copy_n(elements, Size, this->begin());
138 kernel_1d_fixed(kernel_1d_fixed const& other) : parent_t(other) {}
139 kernel_1d_fixed& operator=(kernel_1d_fixed const& other) = default;
142 // TODO: This data member is odr-used and definition at namespace scope
143 // is required by C++11. Redundant and deprecated in C++17.
144 template <typename T,std::size_t Size>
145 constexpr std::size_t kernel_1d_fixed<T, Size>::static_size;
147 /// \brief reverse a kernel
148 template <typename Kernel>
149 inline Kernel reverse_kernel(Kernel const& kernel)
151 Kernel result(kernel);
152 result.center() = kernel.right_size();
153 std::reverse(result.begin(), result.end());
160 template <typename Core>
161 class kernel_2d_adaptor : public Core
164 kernel_2d_adaptor() = default;
166 explicit kernel_2d_adaptor(std::size_t center_y, std::size_t center_x)
167 : center_(center_x, center_y)
169 BOOST_ASSERT(center_.y < this->size() && center_.x < this->size());
172 kernel_2d_adaptor(std::size_t size, std::size_t center_y, std::size_t center_x)
173 : Core(size * size), square_size(size), center_(center_x, center_y)
175 BOOST_ASSERT(this->size() > 0);
176 BOOST_ASSERT(center_.y < this->size() && center_.x < this->size()); // implies `size() > 0`
179 kernel_2d_adaptor(kernel_2d_adaptor const& other)
180 : Core(other), square_size(other.square_size), center_(other.center_.x, other.center_.y)
182 BOOST_ASSERT(this->size() > 0);
183 BOOST_ASSERT(center_.y < this->size() && center_.x < this->size()); // implies `size() > 0`
186 kernel_2d_adaptor& operator=(kernel_2d_adaptor const& other)
188 Core::operator=(other);
189 center_.y = other.center_.y;
190 center_.x = other.center_.x;
191 square_size = other.square_size;
195 std::size_t upper_size() const
197 BOOST_ASSERT(center_.y < this->size());
201 std::size_t lower_size() const
203 BOOST_ASSERT(center_.y < this->size());
204 return this->size() - center_.y - 1;
207 std::size_t left_size() const
209 BOOST_ASSERT(center_.x < this->size());
213 std::size_t right_size() const
215 BOOST_ASSERT(center_.x < this->size());
216 return this->size() - center_.x - 1;
219 auto center_y() -> std::size_t&
221 BOOST_ASSERT(center_.y < this->size());
225 auto center_y() const -> std::size_t const&
227 BOOST_ASSERT(center_.y < this->size());
231 auto center_x() -> std::size_t&
233 BOOST_ASSERT(center_.x < this->size());
237 auto center_x() const -> std::size_t const&
239 BOOST_ASSERT(center_.x < this->size());
243 std::size_t size() const
248 typename Core::value_type at(std::size_t x, std::size_t y) const
250 if (x >= this->size() || y >= this->size())
252 throw std::out_of_range("Index out of range");
254 return this->begin()[y * this->size() + x];
258 std::size_t square_size{0};
261 point<std::size_t> center_{0, 0};
264 /// \brief variable-size kernel
268 typename Allocator = std::allocator<T>
270 class kernel_2d : public detail::kernel_2d_adaptor<std::vector<T, Allocator>>
272 using parent_t = detail::kernel_2d_adaptor<std::vector<T, Allocator>>;
276 kernel_2d() = default;
277 kernel_2d(std::size_t size,std::size_t center_y, std::size_t center_x)
278 : parent_t(size, center_y, center_x)
281 template <typename FwdIterator>
282 kernel_2d(FwdIterator elements, std::size_t size, std::size_t center_y, std::size_t center_x)
283 : parent_t(static_cast<int>(std::sqrt(size)), center_y, center_x)
285 detail::copy_n(elements, size, this->begin());
288 kernel_2d(kernel_2d const& other) : parent_t(other) {}
289 kernel_2d& operator=(kernel_2d const& other) = default;
292 /// \brief static-size kernel
293 template <typename T, std::size_t Size>
294 class kernel_2d_fixed :
295 public detail::kernel_2d_adaptor<std::array<T, Size * Size>>
297 using parent_t = detail::kernel_2d_adaptor<std::array<T, Size * Size>>;
299 static constexpr std::size_t static_size = Size;
300 static_assert(static_size > 0, "kernel must have size greater than 0");
301 static_assert(static_size % 2 == 1, "kernel size must be odd to ensure validity at the center");
305 this->square_size = Size;
308 explicit kernel_2d_fixed(std::size_t center_y, std::size_t center_x) :
309 parent_t(center_y, center_x)
311 this->square_size = Size;
314 template <typename FwdIterator>
315 explicit kernel_2d_fixed(FwdIterator elements, std::size_t center_y, std::size_t center_x)
316 : parent_t(center_y, center_x)
318 this->square_size = Size;
319 detail::copy_n(elements, Size * Size, this->begin());
322 kernel_2d_fixed(kernel_2d_fixed const& other) : parent_t(other) {}
323 kernel_2d_fixed& operator=(kernel_2d_fixed const& other) = default;
326 // TODO: This data member is odr-used and definition at namespace scope
327 // is required by C++11. Redundant and deprecated in C++17.
328 template <typename T, std::size_t Size>
329 constexpr std::size_t kernel_2d_fixed<T, Size>::static_size;
333 /// \brief reverse a kernel
334 //template <typename Kernel>
335 //inline Kernel reverse_kernel(Kernel const& kernel)
337 // Kernel result(kernel);
338 // result.center() = kernel.right_size();
339 // std::reverse(result.begin(), result.end());
343 }} // namespace boost::gil