21 #ifndef otbPixelComponentIterator_h
22 #define otbPixelComponentIterator_h
27 #include "itkNumericTraits.h"
28 #include <boost/type_traits/is_complex.hpp>
29 #include <type_traits>
62 template <
typename TPixel,
typename ConstOrMutable,
class Dispatch =
void>
69 template <
typename TPixel,
typename ConstOrMutable>
73 typename std::enable_if_t<mpl::is_array_v<std::decay_t<TPixel>>>>
75 static_assert(
mpl::is_array_v<std::decay_t<TPixel>>,
"This specialization is reserved to array pixel types");
80 static constexpr
bool is_const = std::is_same<ConstOrMutable, ConstTag>::value;
81 static constexpr
bool is_mutable = std::is_same<ConstOrMutable, MutableTag>::value;
86 static constexpr
bool is_scalar_array = std::is_arithmetic<InternalPixelType>::value;
91 using ComponentType =
typename SubPixelComponentIteratorType::ComponentType;
100 using value_type = std::conditional_t<is_mutable, InternalPixelType, InternalPixelType const>;
126 template <
bool IsConst_ = is_const,
class = std::enable_if_t<IsConst_>>
128 : m_pixel(rhs.m_pixel)
129 , m_component(rhs.m_component)
130 , m_subiter(rhs.m_subiter)
137 template <
bool IsConst_ = is_const,
class = std::enable_if_t<IsConst_>>
139 : m_pixel(rhs.m_pixel)
140 , m_component(rhs.m_component)
141 , m_subiter(rhs.m_subiter)
152 , m_component(component)
153 , m_subiter(SubPixelComponentIteratorType(get_current_pixel()))
168 bool is_at_end() const noexcept
175 assert(lhs.m_pixel == rhs.m_pixel);
178 return (lhs.m_component == rhs.m_component) && (is_scalar_array || (lhs.m_subiter == rhs.m_subiter));
181 {
return ! (lhs == rhs); }
185 assert(lhs.m_pixel == rhs.m_pixel);
188 return (lhs.m_component <= rhs.m_component)
189 || ( !is_scalar_array &&
190 (lhs.m_component == rhs.m_component) && (lhs.m_subiter <= rhs.m_subiter) );
194 assert(lhs.m_pixel == rhs.m_pixel);
195 return (lhs.m_component < rhs.m_component)
196 || ( !is_scalar_array &&
197 (lhs.m_component == rhs.m_component) && (lhs.m_subiter < rhs.m_subiter) );
200 {
return ! (lhs < rhs); }
202 {
return ! (lhs <= rhs); }
214 #if defined(__cpp_if_constexpr)
216 if constexpr(std::is_arithmetic<InternalPixelType>::value)
223 if (m_subiter.is_at_end())
226 m_subiter = SubPixelComponentIteratorType{get_current_pixel()};
242 decltype(
auto) operator*()
247 #if defined(__cpp_if_constexpr)
248 if constexpr (is_scalar_array)
250 return get_current_pixel();
255 decltype(
auto) operator*()
const
260 #if defined(__cpp_if_constexpr)
261 if constexpr (is_scalar_array)
263 return get_current_pixel();
272 assert(! is_at_end());
274 return shallow_size ? shallow_size * m_subiter.size() : 0U;
278 template <
bool IsMutable_ = is_mutable,
class = std::enable_if_t<IsMutable_>>
279 decltype(
auto) get_current_pixel()
281 return (*m_pixel)[m_component];
284 decltype(
auto) get_current_pixel()
const
286 return (*m_pixel)[m_component];
290 std::size_t m_component;
302 template <
typename TPixel,
typename ConstOrMutable>
306 typename std::enable_if_t<boost::is_complex<std::decay_t<TPixel>>::value>>
312 static constexpr
bool is_const = std::is_same<ConstOrMutable, ConstTag>::value;
313 static constexpr
bool is_mutable = std::is_same<ConstOrMutable, MutableTag>::value;
318 using InternalPixelType = std::remove_reference_t<typename PixelType::value_type>;
332 using value_type = std::conditional_t<is_mutable, InternalPixelType, InternalPixelType const>;
358 template <
bool IsConst_ = is_const,
class = std::enable_if_t<IsConst_>>
360 : m_pixel(rhs.m_pixel)
361 , m_component(rhs.m_component)
368 template <
bool IsConst_ = is_const,
class = std::enable_if_t<IsConst_>>
370 : m_pixel(rhs.m_pixel)
371 , m_component(rhs.m_component)
382 , m_component(component)
384 assert(component <= 2);
397 bool is_at_end() const noexcept
399 return m_component == 2;
404 assert(lhs.m_pixel == rhs.m_pixel);
405 return lhs.m_component == rhs.m_component;
408 {
return ! (lhs == rhs); }
412 assert(lhs.m_pixel == rhs.m_pixel);
413 return lhs.m_component <= rhs.m_component;
417 assert(lhs.m_pixel == rhs.m_pixel);
418 return lhs.m_component < rhs.m_component;
421 {
return ! (lhs < rhs); }
423 {
return ! (lhs <= rhs); }
450 decltype(
auto) operator*()
455 return get_current_pixel();
457 decltype(
auto) operator*()
const
462 return get_current_pixel();
466 constexpr std::size_t size() const noexcept {
467 assert(! is_at_end());
472 template <
bool IsMutable_ = is_mutable,
class = std::enable_if_t<IsMutable_>>
473 decltype(
auto) get_current_pixel()
475 return reinterpret_cast<value_type(&)[2]
>((*m_pixel))[m_component];
478 decltype(
auto) get_current_pixel()
const
481 return reinterpret_cast<value_type(&)[2]
>((*m_pixel))[m_component];
485 std::size_t m_component;
492 template <
typename TPixel,
typename ConstOrMutable>
493 class PixelComponentIterator<TPixel, ConstOrMutable, typename std::enable_if_t<std::is_arithmetic<TPixel>::value>>
495 static_assert(std::is_arithmetic<TPixel>::value,
"Specialization for scalar pixels");
500 static constexpr
bool is_const = std::is_same<ConstOrMutable, ConstTag>::value;
501 static constexpr
bool is_mutable = std::is_same<ConstOrMutable, MutableTag>::value;
517 using value_type = std::conditional_t<is_mutable, PixelType, PixelType const>;
543 template <
bool IsConst_ = is_const,
class = std::enable_if_t<IsConst_>>
545 : m_pixel(rhs.m_pixel)
546 , m_component(rhs.m_component)
553 template <
bool IsConst_ = is_const,
class = std::enable_if_t<IsConst_>>
555 : m_pixel(rhs.m_pixel)
556 , m_component(rhs.m_component)
567 , m_component(component)
580 bool is_at_end() const noexcept
587 assert(lhs.m_pixel == rhs.m_pixel);
588 return lhs.m_component == rhs.m_component;
591 {
return ! (lhs == rhs); }
595 assert(lhs.m_pixel == rhs.m_pixel);
596 return lhs.m_component <= rhs.m_component;
600 assert(lhs.m_pixel == rhs.m_pixel);
601 return lhs.m_component < rhs.m_component;
604 {
return ! (lhs < rhs); }
606 {
return ! (lhs <= rhs); }
615 Self& operator++() noexcept
617 assert(m_component < 1);
625 Self operator++(
int) noexcept
634 PixelType & get_current_pixel() noexcept
638 PixelType
const& get_current_pixel() const noexcept
643 decltype(
auto) operator*() const noexcept
647 decltype(
auto) operator*() noexcept
653 bool end() const noexcept {
return m_component > 0; }
655 constexpr std::size_t size() const noexcept {
656 assert(! is_at_end());
662 std::size_t m_component;
667 template <
typename TPixel>
669 template <
typename TPixel>
682 template <
typename TPixel>
706 return sh_size ?
begin().size() : 0U;
713 template <
typename TPixel>
718 static_assert(! std::is_rvalue_reference<decltype(std::forward<TPixel>(pixel))>::value,
"Cannot build component iterator over rvalue pixels");
723 template <
typename TPixel>
727 return internals::PixelRange_t<TPixel>{pixel};
730 template <
typename TPixel>
734 return internals::PixelRange_t<TPixel const>{pixel};