iLab Neuromorphic Robotics Toolkit  0.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ImageImpl.H
Go to the documentation of this file.
1 /*! @file
2  @author Randolph Voorhies
3  @copyright GNU Public License (GPL v3)
4  @section License
5  @verbatim
6  // ////////////////////////////////////////////////////////////////////////
7  // The iLab Neuromorphic Robotics Toolkit (NRT) //
8  // Copyright 2010-2012 by the University of Southern California (USC) //
9  // and the iLab at USC. //
10  // //
11  // iLab - University of Southern California //
12  // Hedco Neurociences Building, Room HNB-10 //
13  // Los Angeles, Ca 90089-2520 - USA //
14  // //
15  // See http://ilab.usc.edu for information about this project. //
16  // ////////////////////////////////////////////////////////////////////////
17  // This file is part of The iLab Neuromorphic Robotics Toolkit. //
18  // //
19  // The iLab Neuromorphic Robotics Toolkit is free software: you can //
20  // redistribute it and/or modify it under the terms of the GNU General //
21  // Public License as published by the Free Software Foundation, either //
22  // version 3 of the License, or (at your option) any later version. //
23  // //
24  // The iLab Neuromorphic Robotics Toolkit is distributed in the hope //
25  // that it will be useful, but WITHOUT ANY WARRANTY; without even the //
26  // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //
27  // PURPOSE. See the GNU General Public License for more details. //
28  // //
29  // You should have received a copy of the GNU General Public License //
30  // along with The iLab Neuromorphic Robotics Toolkit. If not, see //
31  // <http://www.gnu.org/licenses/>. //
32  // ////////////////////////////////////////////////////////////////////////
33  @endverbatim */
34 
35 
36 #ifndef INCLUDE_NRT_CORE_IMAGE_DETAILS_IMAGEIMPL_H
37 #define INCLUDE_NRT_CORE_IMAGE_DETAILS_IMAGEIMPL_H
38 
39 // ######################################################################
40 template <class T, nrt::uint32 Flags> inline
42  Array2D<T>(){
43  static_assert(nrt_traits<T>::is_pixel,
44  "nrt::Image can only hold pixels which derive from nrt::PixelBase!");
45 }
46 
47 // ######################################################################
48 template<class T, nrt::uint32 Flags> inline
50  Array2D<T>()
51 {
52  static_assert(nrt_traits<T>::is_pixel,
53  "nrt::Image can only hold pixels which derive from nrt::PixelBase!");
56  if (p == nrt::ImageInitPolicy::Zeros) Array2D<T>::itsArray = nrt::Array<T>(size, T());
58 }
59 
60 // ######################################################################
61 template<class T, nrt::uint32 Flags> inline
62 nrt::Image<T, Flags>::Image(int width, int height, nrt::ImageInitPolicy const p) :
63  Array2D<T>()
64 {
65  static_assert(nrt_traits<T>::is_pixel,
66  "nrt::Image can only hold pixels which derive from nrt::PixelBase!");
67 
70  if (p == nrt::ImageInitPolicy::Zeros) Array2D<T>::itsArray = nrt::Array<T>(size, T());
72 }
73 // ######################################################################
74 template <class T, nrt::uint32 Flags> inline
75 nrt::Image<T, Flags>::Image(DimsType const& dims, T const val) :
76  Array2D<T>(dims, val)
77 {
78  static_assert(nrt_traits<T>::is_pixel,
79  "nrt::Image can only hold pixels which derive from nrt::PixelBase!");
80 }
81 
82 // ######################################################################
83 template <class T, nrt::uint32 Flags> inline
84 nrt::Image<T, Flags>::Image(std::initializer_list<std::initializer_list<T> > vals) :
85  Array2D<T>(vals)
86 {
87  static_assert(nrt_traits<T>::is_pixel,
88  "nrt::Image can only hold pixels which derive from nrt::PixelBase!");
89 }
90 
91 // ######################################################################
92 template<class T, nrt::uint32 Flags>
93 template<nrt::uint32 OtherFlags> inline
95  Array2D<T>()
96 {
97  static_assert(nrt_traits<T>::is_pixel,
98  "nrt::Image can only hold pixels which derive from nrt::PixelBase!");
99 
100  nrt::Array2D<T>::itsDims = other.itsDims;
101  nrt::Array2D<T>::itsArray = other.itsArray;
102 }
103 
104 // ######################################################################
105 template<class T, nrt::uint32 Flags> template<class U, nrt::uint32 OtherFlags> inline
107  nrt::Array2D<T>(other.dims())
108 {
109  static_assert(nrt_traits<T>::is_pixel,
110  "nrt::Image can only hold pixels which derive from nrt::PixelBase!");
111 
112  auto thisIt = begin();
113  auto otherIt = other.const_begin();
114  auto otherEnd = other.const_end();
115 
116  for (; otherIt != otherEnd; ++otherIt, ++thisIt)
117  *thisIt = T(*otherIt);
118 }
119 
120 // ######################################################################
121 template<class T, nrt::uint32 Flags>
122 nrt::Image<T, Flags>::Image(T* data, DimsType const& dims) :
123  Array2D<T>(data, dims)
124 {
125  static_assert(nrt_traits<T>::is_pixel,
126  "nrt::Image can only hold pixels which derive from nrt::PixelBase!");
127 }
128 
129 // ######################################################################
130 template<class T, nrt::uint32 Flags>
131  template <nrt::uint32 OtherFlags> inline
133 {
134  if(reinterpret_cast<const nrt::Image<T, Flags>*>(&other) == this) return *this;
135 
136  nrt::Array2D<T>::itsDims = other.dims();
137  nrt::Array2D<T>::itsArray = other.itsArray;
138  return *this;
139 }
140 
141 // ######################################################################
142 template<class T, nrt::uint32 Flags> template<class U, nrt::uint32 OtherFlags> inline
144 {
145  nrt::Array2D<T>::itsArray = Array<T>(other.width()*other.height());
146  nrt::Array2D<T>::itsDims = other.dims();
147 
148  auto thisIt = begin();
149  auto otherIt = other.const_begin();
150  auto otherEnd = other.const_end();
151 
152  for (; otherIt != otherEnd; ++otherIt, ++thisIt)
153  *thisIt = T(*otherIt);
154 
155  return *this;
156 }
157 
158 // ######################################################################
159 template <class T, nrt::uint32 Flags> inline
160 void nrt::Image<T, Flags>::clear(T const & val)
161 { for (T & pix : nrt::Array2D<T>::itsArray) pix = val; }
162 
163 // ######################################################################
164 template <class T, nrt::uint32 Flags> inline
166 {
167  T mi(at(0,0)), ma(mi);
168 
169  for (T const & pix : nrt::Array2D<T>::itsArray) { mi = std::min(mi, pix); ma = std::max(ma, pix); }
170 
171  return nrt::Range<T>(mi, ma);
172 }
173 
174 // ######################################################################
175 template<class T, nrt::uint32 Flags> inline
176 T & nrt::Image<T, Flags>::operator()(nrt::int32 x, nrt::int32 y)
177 {
178  return operator_paren_helper(x, y, itsSafeAccess);
179 }
180 
181 template<class T, nrt::uint32 Flags> inline
182 T & nrt::Image<T, Flags>::operator_paren_helper(int32 x, int32 y, /*safeaccess*/boost::mpl::bool_<false> )
183 {
184  return begin()[y*nrt::Array2D<T>::itsDims.width() + x];
185 }
186 
187 template<class T, nrt::uint32 Flags> inline
188 T & nrt::Image<T, Flags>::operator_paren_helper(int32 x, int32 y, /*safeaccess*/boost::mpl::bool_<true> )
189 {
190  if (!nrt::Array2D<T>::itsDims.contains(nrt::Point2D<int32>(x, y)))
191  throw nrt::exception::OutOfBoundsArray2DException(Point2D<int32>(x,y), nrt::Array2D<T>::itsDims);
192  return begin()[y*nrt::Array2D<T>::itsDims.width() + x];
193 }
194 
195 // ######################################################################
196 template<class T, nrt::uint32 Flags> inline
197 T const & nrt::Image<T, Flags>::operator()(nrt::int32 x, nrt::int32 y) const
198 {
199  return operator_paren_helper(x, y, itsSafeAccess);
200 }
201 
202 template<class T, nrt::uint32 Flags> inline
203 T const & nrt::Image<T, Flags>::operator_paren_helper(nrt::int32 x, nrt::int32 y, /*safeaccess*/boost::mpl::bool_<false> ) const
204 {
205  return const_begin()[y*nrt::Array2D<T>::itsDims.width() + x];
206 }
207 
208 template<class T, nrt::uint32 Flags> inline
209 T const & nrt::Image<T, Flags>::operator_paren_helper(nrt::int32 x, nrt::int32 y, /*safeaccess*/boost::mpl::bool_<true> ) const
210 {
211  if (!nrt::Array2D<T>::itsDims.contains(Point2D<int32>(x, y)))
212  throw nrt::exception::OutOfBoundsArray2DException(Point2D<int32>(x, y), nrt::Array2D<T>::itsDims);
213  return const_begin()[y*nrt::Array2D<T>::itsDims.width() + x];
214 }
215 
216 // ######################################################################
217 template<class T, nrt::uint32 Flags> inline
219 {
220  return operator_paren_helper(p, itsSafeAccess);
221 }
222 
223 template<class T, nrt::uint32 Flags> inline
224 T & nrt::Image<T, Flags>::operator_paren_helper(Point2D<int32> p, /*safeaccess*/boost::mpl::bool_<false> )
225 {
226  return begin()[p.y()*nrt::Array2D<T>::itsDims.width() + p.x()];
227 }
228 
229 template<class T, nrt::uint32 Flags> inline
230 T & nrt::Image<T, Flags>::operator_paren_helper(Point2D<int32> p, /*safeaccess*/boost::mpl::bool_<true> )
231 {
232  if (!nrt::Array2D<T>::itsDims.contains(p))
233  throw nrt::exception::OutOfBoundsArray2DException(p, nrt::Array2D<T>::itsDims);
234  return begin()[p.y()*nrt::Array2D<T>::itsDims.width() + p.x()];
235 }
236 
237 // ######################################################################
238 template<class T, nrt::uint32 Flags> inline
240 {
241  return operator_paren_helper(p, itsSafeAccess);
242 }
243 
244 template<class T, nrt::uint32 Flags> inline
245 T const & nrt::Image<T, Flags>::operator_paren_helper(Point2D<int32> p, /*safeaccess*/boost::mpl::bool_<false> ) const
246 {
247  return const_begin()[p.y()*nrt::Array2D<T>::itsDims.width() + p.x()];
248 }
249 
250 template<class T, nrt::uint32 Flags> inline
251 T const & nrt::Image<T, Flags>::operator_paren_helper(Point2D<int32> p, /*safeaccess*/boost::mpl::bool_<true> ) const
252 {
253  if (!nrt::Array2D<T>::itsDims.contains(p))
254  throw nrt::exception::OutOfBoundsArray2DException(p, nrt::Array2D<T>::itsDims);
255  return const_begin()[p.y()*nrt::Array2D<T>::itsDims.width() + p.x()];
256 }
257 
258 // ######################################################################
259 template<class T, nrt::uint32 Flags> inline
261 {
262  return operator_paren_helper(idx, itsSafeAccess);
263 }
264 
265 template<class T, nrt::uint32 Flags> inline
266 T & nrt::Image<T, Flags>::operator_paren_helper(uint32 idx, /*safeaccess*/boost::mpl::bool_<false> )
267 {
268  return begin()[idx];
269 }
270 
271 template<class T, nrt::uint32 Flags> inline
272 T & nrt::Image<T, Flags>::operator_paren_helper(uint32 idx, /*safeaccess*/boost::mpl::bool_<true> )
273 {
274  if(idx >= nrt::Array2D<T>::itsArray.size())
275  throw nrt::exception::OutOfBoundsArray2DException(Point2D<int32>(idx,-1), nrt::Array2D<T>::itsDims);
276  return begin()[idx];
277 }
278 
279 // ######################################################################
280 template<class T, nrt::uint32 Flags> inline
281 T const & nrt::Image<T, Flags>::operator()(uint32 idx) const
282 {
283  return operator_paren_helper(idx, itsSafeAccess);
284 }
285 
286 template<class T, nrt::uint32 Flags> inline
287 T const & nrt::Image<T, Flags>::operator_paren_helper(uint32 idx, /*safeaccess*/boost::mpl::bool_<false> ) const
288 {
289  return const_begin()[idx];
290 }
291 
292 template<class T, nrt::uint32 Flags> inline
293 T const & nrt::Image<T, Flags>::operator_paren_helper(uint32 idx, /*safeaccess*/boost::mpl::bool_<true> ) const
294 {
295  if(idx >= nrt::Array2D<T>::itsArray.size())
296  throw nrt::exception::OutOfBoundsArray2DException(Point2D<int32>(idx, 0), nrt::Array2D<T>::itsDims);
297  return const_begin()[idx];
298 }
299 
300 // ######################################################################
301 template<class T, nrt::uint32 Flags> inline
302 T const & nrt::Image<T, Flags>::at(nrt::int32 x, nrt::int32 y) const
303 {
304  return at_helper(x, y, itsSafeAccess);
305 }
306 
307 template<class T, nrt::uint32 Flags> inline
308 T const & nrt::Image<T, Flags>::at_helper(int32 x, int32 y, /*safeaccess*/boost::mpl::bool_<false> ) const
309 {
310  return const_begin()[y*nrt::Array2D<T>::itsDims.width() + x];
311 }
312 
313 template<class T, nrt::uint32 Flags> inline
314 T const & nrt::Image<T, Flags>::at_helper(int32 x, int32 y, /*safeaccess*/boost::mpl::bool_<true> ) const
315 {
316  if (!nrt::Array2D<T>::itsDims.contains(nrt::Point2D<int32>(x, y)))
317  throw nrt::exception::OutOfBoundsArray2DException(Point2D<int32>(x,y), nrt::Array2D<T>::itsDims);
318  return const_begin()[y*nrt::Array2D<T>::itsDims.width() + x];
319 }
320 
321 // ######################################################################
322 template<class T, nrt::uint32 Flags> inline
324 {
325  return at_helper(p, itsSafeAccess);
326 }
327 
328 template<class T, nrt::uint32 Flags> inline
329 T const & nrt::Image<T, Flags>::at_helper(Point2D<int32> p, /*safeaccess*/boost::mpl::bool_<false> ) const
330 {
331  return const_begin()[p.y()*nrt::Array2D<T>::itsDims.width() + p.x()];
332 }
333 
334 template<class T, nrt::uint32 Flags> inline
335 T const & nrt::Image<T, Flags>::at_helper(Point2D<int32> p, /*safeaccess*/boost::mpl::bool_<true> ) const
336 {
337  if (!nrt::Array2D<T>::itsDims.contains(p))
338  throw nrt::exception::OutOfBoundsArray2DException(p, nrt::Array2D<T>::itsDims);
339  return const_begin()[p.y()*nrt::Array2D<T>::itsDims.width() + p.x()];
340 }
341 
342 // ######################################################################
343 template<class T, nrt::uint32 Flags> inline
344 T const & nrt::Image<T, Flags>::at(uint32 idx) const
345 {
346  return at_helper(idx, itsSafeAccess);
347 }
348 
349 template<class T, nrt::uint32 Flags> inline
350 T const & nrt::Image<T, Flags>::at_helper(uint32 idx, /*safeaccess*/boost::mpl::bool_<false> ) const
351 {
352  return const_begin()[idx];
353 }
354 
355 template<class T, nrt::uint32 Flags> inline
356 T const & nrt::Image<T, Flags>::at_helper(uint32 idx, /*safeaccess*/boost::mpl::bool_<true> ) const
357 {
358  if(idx >= nrt::Array2D<T>::itsArray.size())
359  throw nrt::exception::OutOfBoundsArray2DException(Point2D<int32>(idx, 0), nrt::Array2D<T>::itsDims);
360  return const_begin()[idx];
361 }
362 
363 // ######################################################################
364 template<class T, nrt::uint32 Flags> inline
365 T nrt::Image<T, Flags>::interpolate(float x, float y) const
366 {
367  auto const sptr = const_begin();
368  const int wid = width(), hei = height();
369 
370  const int y0 = int(y);
371  const int y1 = std::min(y0 + 1, hei - 1);
372  const float fy = y - float(y0);
373 
374  const int wy0 = wid * y0;
375  const int wy1 = wid * y1;
376 
377  const int x0 = int(x);
378  const int x1 = std::min(x0 + 1, wid - 1);
379  const float fx = x - float(x0);
380 
381  if(!coordsOk(x0, y0)) throw nrt::exception::OutOfBoundsArray2DException(Point2D<int32>(x,y), nrt::Array2D<T>::itsDims);
382  typename nrt::promote<T,float>::type const
383  d00( sptr[x0 + wy0] ), d10( sptr[x1 + wy0] ),
384  d01( sptr[x0 + wy1] ), d11( sptr[x1 + wy1] ),
385  dx0( d00 + (d10 - d00) * fx ),
386  dx1( d01 + (d11 - d01) * fx );
387 
388  return T( dx0 + (dx1 - dx0) * fy );
389 }
390 
391 // ######################################################################
392 template<class T, nrt::uint32 Flags> inline
394 { return interpolate(p.x(), p.y()); }
395 
396 // ######################################################################
397 template<class T, nrt::uint32 Flags> template<class U, template<typename> class ColorType> inline
398 typename std::enable_if<std::is_base_of<nrt::PixelWithAlpha<U>, ColorType<U>>::value, void>::type
399  nrt::Image<T, Flags>::draw(Point2D<int32> const& p, ColorType<U> color)
400 {
401  if (nrt::Array2D<T>::itsDims.contains(p))
402  {
403  double normAlpha = color.alpha/255.0;
404  nrt::int32 pos = p.y()*nrt::Array2D<T>::itsDims.width() + p.x();
405  T newColor = (1.0-normAlpha)*const_begin()[pos] + normAlpha*T(color);
406  begin()[pos] = newColor;
407  }
408 }
409 
410 // ######################################################################
411 template<class T, nrt::uint32 Flags> template<class U> inline
413 {
414  if (nrt::Array2D<T>::itsDims.contains(p)) begin()[p.y()*nrt::Array2D<T>::itsDims.width() + p.x()] = T(color);
415 }
416 
417 //! Test whether point falls inside array boundaries
418 template <class T, nrt::uint32 Flags>
419 template <class U> inline
420 bool nrt::Image<T, Flags>::coordsOk(const U x, const U y) const
421 {
422  return (x >= 0 && y >= 0 && x < width() && y < height());
423 }
424 
425 
426 //! Test whether rectangle falls inside array boundaries
427 template <class T, nrt::uint32 Flags>
428 template <class U> inline
430 {
431  return (coordsOk(rect.topLeft()) && coordsOk(rect.bottomRight()));
432 }
433 
434 
435 //! Convenient overload of coordsOk(int32 x, int32 y)
436 template <class T, nrt::uint32 Flags>
437 template <class U> inline
439 {
440  return (P.x() >= 0 && P.y() >= 0 && P.x() < width() && P.y() < height());
441 }
442 
443 // ######################################################################
444 template <class T, nrt::uint32 Flags> inline
446 { return nrt::Array2D<T>::itsDims; }
447 
448 // ######################################################################
449 template <class T, nrt::uint32 Flags> inline
451 { return nrt::Rectangle<nrt::int32>(nrt::Point2D<nrt::int32>(0,0),nrt::Array2D<T>::itsDims); }
452 
453 // ######################################################################
454 template <class T, nrt::uint32 Flags> inline
455 nrt::int32 const nrt::Image<T, Flags>::width() const
456 { return nrt::Array2D<T>::itsDims.width(); }
457 
458 // ######################################################################
459 template <class T, nrt::uint32 Flags> inline
460 nrt::int32 const nrt::Image<T, Flags>::height() const
461 { return nrt::Array2D<T>::itsDims.height(); }
462 
463 // ######################################################################
464 template <class T, nrt::uint32 Flags> inline
465 nrt::int32 const nrt::Image<T, Flags>::size() const
466 { return nrt::Array2D<T>::itsArray.size(); }
467 
468 // ######################################################################
469 template <class T, nrt::uint32 Flags> inline
470 bool const nrt::Image<T, Flags>::empty() const
471 { return (nrt::Array2D<T>::itsArray.size() == 0); }
472 
473 // ######################################################################
474 template <class T, nrt::uint32 Flags> inline
476 {
477  if (newdims.size() != size()) throw nrt::exception::BadDimsArray2DException(newdims);
478  nrt::Array2D<T>::itsDims = newdims;
479 }
480 
481 // ######################################################################
482 template <class T, nrt::uint32 Flags> inline
483 void nrt::Image<T, Flags>::reshape(int32 newWidth, int32 newHeight)
484 { reshape(nrt::Dims<nrt::int32>(newWidth, newHeight)); }
485 
486 // ######################################################################
487 template <class T, nrt::uint32 Flags>
489 {
490  assert(chan < T::numChannels);
491  nrt::Image<nrt::PixGray<PODType>> ret(nrt::Array2D<T>::itsDims, ImageInitPolicy::None);
492  std::transform(const_begin(), const_end(), ret.begin(),
493  [chan](T const& p) { return p.channels[chan]; });
494  return ret;
495 }
496 
497 // ######################################################################
498 template<class T, nrt::uint32 Flags> inline
500 { return begin_helper(itsUniqueAccess); }
501 
502 // ######################################################################
503 template<class T, nrt::uint32 Flags> inline
505 { return nrt::Array2D<T>::itsArray.end(); }
506 
507 // ######################################################################
508 template<class T, nrt::uint32 Flags> inline
511 
512 // ######################################################################
513 template<class T, nrt::uint32 Flags> inline
516 
517 // ######################################################################
518 template<class T, nrt::uint32 Flags> inline
521 
522 // ######################################################################
523 template<class T, nrt::uint32 Flags> inline
526 
527 // ######################################################################
528 template<class T, nrt::uint32 Flags> inline
530 { return begin()->channels.begin(); }
531 
532 // ######################################################################
533 template<class T, nrt::uint32 Flags> inline
535 { return (end()-1)->channels.end(); }
536 
537 // ######################################################################
538 template<class T, nrt::uint32 Flags> inline
540 { return const_begin()->channels.begin(); }
541 
542 // ######################################################################
543 template<class T, nrt::uint32 Flags> inline
545 { return (const_end()-1)->channels.end(); }
546 
547 // ######################################################################
548 template<class T, nrt::uint32 Flags> inline
550 { return const_begin()->channels.begin(); }
551 
552 // ######################################################################
553 template<class T, nrt::uint32 Flags> inline
555 { return (const_end()-1)->channels.end(); }
556 
557 // ######################################################################
558 template<class T, nrt::uint32 Flags> inline
560 { return *this; }
561 
562 // ######################################################################
563 template<class T, nrt::uint32 Flags> inline
565 { return nrt::Array2D<T>::itsArray.begin() + row * nrt::Array2D<T>::itsDims.width(); }
566 
567 // ######################################################################
568 template<class T, nrt::uint32 Flags> inline
570 { return nrt::Array2D<T>::itsArray.begin() + row * nrt::Array2D<T>::itsDims.width() + nrt::Array2D<T>::itsDims.width(); }
571 
572 // ######################################################################
573 template<class T, nrt::uint32 Flags> inline
575 { return nrt::Array2D<T>::itsArray.const_begin() + row * nrt::Array2D<T>::itsDims.width(); }
576 
577 // ######################################################################
578 template<class T, nrt::uint32 Flags> inline
580 { return nrt::Array2D<T>::itsArray.const_begin() + row * nrt::Array2D<T>::itsDims.width() + nrt::Array2D<T>::itsDims.width(); }
581 
582 // ######################################################################
583 template<class T, nrt::uint32 Flags> inline
585 { return nrt::Array2D<T>::itsArray.const_begin() + row * nrt::Array2D<T>::itsDims.width(); }
586 
587 // ######################################################################
588 template<class T, nrt::uint32 Flags> inline
590 { return nrt::Array2D<T>::itsArray.const_begin() + row * nrt::Array2D<T>::itsDims.width() + nrt::Array2D<T>::itsDims.width(); }
591 
592 
593 // ######################################################################
594 template<class T, nrt::uint32 Flags>
595 class nrt::Image<T, Flags>::col_iterator
596  : public boost::iterator_facade<nrt::Image<T, Flags>::col_iterator, T, boost::bidirectional_traversal_tag>
597 {
598  public:
599  inline col_iterator(nrt::int32 stepSize)
600  : itsStepSize(stepSize)
601  {}
602 
603  inline explicit col_iterator(T* p, nrt::int32 stepSize)
604  : itsPtr(p), itsStepSize(stepSize)
605  {}
606 
607  private:
608  friend class boost::iterator_core_access;
609 
610  inline void increment() { itsPtr += itsStepSize; }
611  inline void decrement() { itsPtr -= itsStepSize; }
612 
613  inline bool equal(nrt::Image<T, Flags>::col_iterator const& other) const
614  { return itsPtr == other.itsPtr; }
615 
616  inline T& dereference() const { return *itsPtr; }
617 
618  private:
619  T* itsPtr;
620  const nrt::int32 itsStepSize;
621 };
622 
623 // ######################################################################
624 template<class T, nrt::uint32 Flags> inline
626 {
627  return nrt::Image<T, Flags>::col_iterator(nrt::Array2D<T>::itsArray.begin() + col, nrt::Array2D<T>::itsDims.width());
628 }
629 
630 // ######################################################################
631 template<class T, nrt::uint32 Flags> inline
633 {
634  return nrt::Image<T, Flags>::col_iterator(nrt::Array2D<T>::itsArray.end() - nrt::Array2D<T>::itsDims.width() + col, nrt::Array2D<T>::itsDims.width());
635 }
636 
637 // ######################################################################
638 template<class T, nrt::uint32 Flags> inline
640 {
641  return nrt::Image<T, Flags>::const_col_iterator(nrt::Array2D<T>::itsArray.begin() + col, nrt::Array2D<T>::itsDims.width());
642 }
643 
644 // ######################################################################
645 template<class T, nrt::uint32 Flags> inline
647 {
648  return nrt::Image<T, Flags>::const_col_iterator(nrt::Array2D<T>::itsArray.end() - nrt::Array2D<T>::itsDims.width() + col, nrt::Array2D<T>::itsDims.width());
649 }
650 
651 // ######################################################################
652 template<class T, nrt::uint32 Flags>
653 class nrt::Image<T, Flags>::const_col_iterator
654  : public boost::iterator_facade<nrt::Image<T, Flags>::const_col_iterator, T const, boost::bidirectional_traversal_tag>
655 {
656  public:
657  inline const_col_iterator(nrt::int32 stepSize)
658  : itsStepSize(stepSize)
659  {}
660 
661  inline explicit const_col_iterator(T const* p, nrt::int32 stepSize)
662  : itsPtr(p), itsStepSize(stepSize)
663  {}
664 
665  private:
666  friend class boost::iterator_core_access;
667 
668  inline void increment() { itsPtr += itsStepSize; }
669  inline void decrement() { itsPtr -= itsStepSize; }
670 
671  inline bool equal(nrt::Image<T, Flags>::const_col_iterator const& other) const
672  { return itsPtr == other.itsPtr; }
673 
674  inline T const& dereference() const { return *itsPtr; }
675 
676  private:
677  T const * itsPtr;
678  const nrt::int32 itsStepSize;
679 };
680 
681 // ######################################################################
682 template<class T, nrt::uint32 Flags> inline
684 {
685  return nrt::Image<T, Flags>::const_col_iterator(nrt::Array2D<T>::itsArray.const_begin() + col, nrt::Array2D<T>::itsDims.width());
686 }
687 
688 // ######################################################################
689 template<class T, nrt::uint32 Flags> inline
691 {
692  return nrt::Image<T, Flags>::const_col_iterator(nrt::Array2D<T>::itsArray.const_end() + col, nrt::Array2D<T>::itsDims.width());
693 }
694 
695 // ######################################################################
696 template<class T, nrt::uint32 Flags>
697 class nrt::Image<T, Flags>::rect_iterator
698  : public boost::iterator_facade<nrt::Image<T, Flags>::rect_iterator, T, boost::random_access_traversal_tag>
699 {
700  public:
701  inline rect_iterator(nrt::int32 moveLength, nrt::int32 skipSize, nrt::int32 initRow = 0)
702  : itsMoveLength(moveLength), itsSkipSize(skipSize), itsCtr(0), itsRowCtr(initRow)
703  {}
704 
705  inline explicit rect_iterator(T * p, nrt::int32 moveLength, nrt::int32 skipSize, nrt::int32 initRow = 0)
706  : itsPtr(p), itsMoveLength(moveLength), itsSkipSize(skipSize), itsCtr(0), itsRowCtr(initRow)
707  {}
708 
709  typedef typename boost::iterator_facade<
710  nrt::Image<T, Flags>::rect_iterator, T, boost::random_access_traversal_tag>::difference_type difference_type;
711 
712  private:
713  friend class boost::iterator_core_access;
714 
715  inline void increment()
716  {
717  itsCtr++;
718  if(itsCtr == itsMoveLength) {itsPtr += itsSkipSize; itsCtr=0; ++itsRowCtr; }
719  else {itsPtr++;}
720  }
721  inline void decrement()
722  {
723  if(itsCtr == 0) {itsPtr -= itsSkipSize; itsCtr=itsMoveLength; --itsRowCtr; }
724  else {itsCtr--; itsPtr--;}
725  }
726 
727  inline void advance( difference_type n )
728  {
729  difference_type row = n / itsMoveLength;
730  difference_type col = n % itsMoveLength;
731 
732  itsCtr += col; if( itsCtr == itsMoveLength ) itsCtr = 0;
733  itsRowCtr += row;
734  itsPtr += row * itsSkipSize + col;
735  }
736 
737  inline difference_type distance_to( rect_iterator const & other ) const
738  {
739  return (other.itsRowCtr - itsRowCtr) * itsMoveLength + (other.itsCtr - itsCtr);
740  }
741 
742  inline bool equal(nrt::Image<T, Flags>::rect_iterator const& other) const
743  { return itsPtr == other.itsPtr; }
744 
745  inline T & dereference() const { return *itsPtr; }
746 
747  private:
748  T * itsPtr;
749  const nrt::int32 itsMoveLength;
750  const nrt::int32 itsSkipSize;
751  nrt::int32 itsCtr;
752  nrt::int32 itsRowCtr;
753 };
754 
755 // ######################################################################
756 template<class T, nrt::uint32 Flags> inline
758 {
760  (nrt::Array2D<T>::itsArray.begin() + rect.left() + rect.top() * nrt::Array2D<T>::itsDims.width(),
761  rect.width(),
762  nrt::Array2D<T>::itsDims.width() - rect.width() + 1);
763 }
764 
765 // ######################################################################
766 template<class T, nrt::uint32 Flags> inline
768 {
770  (nrt::Array2D<T>::itsArray.begin() + rect.left() + rect.bottomO() * nrt::Array2D<T>::itsDims.width(),
771  rect.width(),
772  nrt::Array2D<T>::itsDims.width() - rect.width() + 1, rect.height() - 1);
773 }
774 
775 // ######################################################################
776 template<class T, nrt::uint32 Flags> inline
778 {
780  (nrt::Array2D<T>::itsArray.const_begin() + rect.left() + rect.top() * nrt::Array2D<T>::itsDims.width(),
781  rect.width(),
782  nrt::Array2D<T>::itsDims.width() - rect.width() + 1);
783 }
784 
785 // ######################################################################
786 template<class T, nrt::uint32 Flags> inline
788 {
790  (nrt::Array2D<T>::itsArray.const_begin() + rect.left() + rect.bottomO() * nrt::Array2D<T>::itsDims.width(),
791  rect.width(),
792  nrt::Array2D<T>::itsDims.width() - rect.width() + 1, rect.height() - 1);
793 }
794 
795 // ######################################################################
796 template<class T, nrt::uint32 Flags>
797 class nrt::Image<T, Flags>::const_rect_iterator
798  : public boost::iterator_facade<nrt::Image<T, Flags>::const_rect_iterator, T const, boost::random_access_traversal_tag>
799 {
800  public:
801  inline const_rect_iterator(nrt::int32 moveLength, nrt::int32 skipSize, nrt::int32 initRow = 0)
802  : itsMoveLength(moveLength), itsSkipSize(skipSize), itsCtr(0), itsRowCtr(initRow)
803  {}
804 
805  inline explicit const_rect_iterator(T const* p, nrt::int32 moveLength, nrt::int32 skipSize, nrt::int32 initRow = 0)
806  : itsPtr(p), itsMoveLength(moveLength), itsSkipSize(skipSize), itsCtr(0), itsRowCtr(initRow)
807  {}
808 
809  typedef typename boost::iterator_facade<
810  nrt::Image<T, Flags>::const_rect_iterator, T const, boost::random_access_traversal_tag>::difference_type difference_type;
811 
812  private:
813  friend class boost::iterator_core_access;
814 
815  inline void increment()
816  {
817  itsCtr++;
818  if(itsCtr == itsMoveLength) {itsPtr += itsSkipSize; itsCtr=0;}
819  else {itsPtr++;}
820  }
821  inline void decrement()
822  {
823  if(itsCtr == 0) {itsPtr -= itsSkipSize; itsCtr=itsMoveLength;}
824  else {itsCtr--; itsPtr--;}
825  }
826 
827  inline void advance( difference_type n )
828  {
829  difference_type row = n / itsMoveLength;
830  difference_type col = n % itsMoveLength;
831 
832  itsCtr += col; if( itsCtr == itsMoveLength ) itsCtr = 0;
833  itsRowCtr += row;
834  itsPtr += row * itsSkipSize + col;
835  }
836 
837  inline difference_type distance_to( const_rect_iterator const & other ) const
838  {
839  return (other.itsRowCtr - itsRowCtr) * itsMoveLength + (other.itsCtr - itsCtr);
840  }
841 
842  inline bool equal(nrt::Image<T, Flags>::const_rect_iterator const& other) const
843  { return itsPtr == other.itsPtr; }
844 
845  inline T const& dereference() const { return *itsPtr; }
846 
847  private:
848  T const * itsPtr;
849  const nrt::int32 itsMoveLength;
850  const nrt::int32 itsSkipSize;
851  nrt::int32 itsCtr;
852  nrt::int32 itsRowCtr;
853 };
854 
855 // ######################################################################
856 template<class T, nrt::uint32 Flags> inline
858 {
860  (nrt::Array2D<T>::itsArray.const_begin() + rect.left() + rect.top() * nrt::Array2D<T>::itsDims.width(),
861  rect.width(),
862  nrt::Array2D<T>::itsDims.width() - rect.width() + 1);
863 }
864 
865 // ######################################################################
866 template<class T, nrt::uint32 Flags> inline
868 {
870  (nrt::Array2D<T>::itsArray.const_begin() + rect.left() + rect.bottomO() * nrt::Array2D<T>::itsDims.width(),
871  rect.width(),
872  nrt::Array2D<T>::itsDims.width() - rect.width() + 1, rect.height() - 1);
873 }
874 
875 
876 // ######################################################################
877 template<class T, nrt::uint32 Flags> inline
878 typename nrt::Image<T, Flags>::iterator nrt::Image<T, Flags>::begin_helper(/*uniqueaccess*/boost::mpl::bool_<true>)
879 {
881 }
882 
883 template<class T, nrt::uint32 Flags> inline
884 typename nrt::Image<T, Flags>::iterator nrt::Image<T, Flags>::begin_helper(/*uniqueaccess*/boost::mpl::bool_<false>)
885 {
887 }
888 
889 #include "ConvexPolyIterImpl.H"
890 
891 #endif // INCLUDE_NRT_CORE_IMAGE_DETAILS_IMAGEIMPL_H