Commit 142b7d63 authored by Guillaume Pasero's avatar Guillaume Pasero
Browse files

ENH: allow masked iterator to use different types, and an optional mask

parent 15c04ac8
......@@ -18,7 +18,9 @@
#ifndef otbMaskedIteratorDecorator_h
#define otbMaskedIteratorDecorator_h
#include <boost/move/utility_core.hpp>
#include "itkMacro.h"
#define MY_NEW_IMPLEMENTATION
namespace otb
{
......@@ -34,38 +36,29 @@ namespace otb
* \ingroup ImageIterator
* \ingroup OTBCommon
*/
template <typename TIteratorType>
template <typename TIteratorType,typename TMaskIteratorType = TIteratorType>
class MaskedIteratorDecorator
{
public:
typedef MaskedIteratorDecorator<TIteratorType> Self;
typedef typename TIteratorType::ImageType MaskType;
typedef MaskedIteratorDecorator
<TIteratorType,TMaskIteratorType> Self;
typedef typename TMaskIteratorType::ImageType MaskType;
typedef typename TIteratorType::ImageType ImageType;
typedef typename ImageType::IndexType IndexType;
typedef typename ImageType::RegionType RegionType;
typedef typename ImageType::PixelType PixelType;
typedef typename MaskType::PixelType MaskPixelType;
// Run-time type information
itkTypeMacroNoParent(MaskedIteratorDecorator);
// Constructors forward arguments to both iterators
template <typename T1>
MaskedIteratorDecorator(typename MaskType::Pointer mask,
typename ImageType::Pointer image,
BOOST_FWD_REF(T1) arg1);
template <typename T1, typename T2>
MaskedIteratorDecorator(typename MaskType::Pointer mask,
typename ImageType::Pointer image,
BOOST_FWD_REF(T1) arg1,
BOOST_FWD_REF(T2) arg2);
template <typename T1, typename T2, typename T3>
MaskedIteratorDecorator(typename MaskType::Pointer mask,
typename ImageType::Pointer image,
BOOST_FWD_REF(T1) arg1,
BOOST_FWD_REF(T2) arg2,
BOOST_FWD_REF(T3) arg3);
/** Constructors forward arguments to both iterators
* Beware that the iterator is in a undefinite state after construction
* GoToBegin() or GoToEnd() should be called */
MaskedIteratorDecorator(MaskType* mask,
ImageType* image,
const RegionType& region);
/** Current iterator index. Wraps the underlying iterator GetIndex() */
IndexType GetIndex() const;
......@@ -77,10 +70,10 @@ public:
/** Move one pixel past the last valid iteration index */
void GoToEnd();
/** True iff the iterator is at the beginning */
/** True if the iterator is at the beginning */
bool IsAtBegin() const;
/** True iff the iterator is at the end */
/** True if the iterator is at the end */
bool IsAtEnd() const;
/** Advance to the next valid iteration position. That is the next non masked
......@@ -101,16 +94,18 @@ public:
// So provide access to inner iterators:
/** Underlying mask iterator accessor */
TIteratorType& GetMaskIterator();
TMaskIteratorType& GetMaskIterator();
/** Underlying mask iterator const accessor */
const TIteratorType& GetMaskIterator() const;
const TMaskIteratorType& GetMaskIterator() const;
/** Underlying image iterator accessor */
TIteratorType& GetImageIterator();
/** Underlying image iterator const accessor */
const TIteratorType& GetImageIterator() const;
const bool& HasMask() const;
private:
/** Private method to compute the begin iterator position taking into account
......@@ -119,11 +114,19 @@ private:
private:
// Inner iterators on the image and mask
TIteratorType m_ItMask;
TMaskIteratorType m_ItMask;
TIteratorType m_ItImage;
// flag to check if mask is present
bool m_UseMask;
// Unmasked bounds
#ifdef MY_NEW_IMPLEMENTATION
TMaskIteratorType m_StartMask;
TIteratorType m_StartImage;
#else
IndexType m_Begin;
#endif
};
}
......
......@@ -23,161 +23,215 @@
namespace otb
{
/*
For documentation on constructor argument forwarding with boost see:
http://www.boost.org/doc/libs/1_60_0/doc/html/move/construct_forwarding.html
*/
template <typename TIteratorType>
template <typename T1>
MaskedIteratorDecorator<TIteratorType>::MaskedIteratorDecorator(
typename MaskType::Pointer mask,
typename ImageType::Pointer image,
BOOST_FWD_REF(T1) arg1):
m_ItMask(mask,
boost::forward<T1>(arg1)),
m_ItImage(image,
boost::forward<T1>(arg1))
template <typename TIteratorType, typename TMaskIteratorType>
MaskedIteratorDecorator<TIteratorType,TMaskIteratorType>
::MaskedIteratorDecorator( MaskType* mask,
ImageType* image,
const RegionType& region)
{
ComputeMaskedBegin();
}
template <typename TIteratorType>
template <typename T1, typename T2>
MaskedIteratorDecorator<TIteratorType>::MaskedIteratorDecorator(
typename MaskType::Pointer mask,
typename ImageType::Pointer image,
BOOST_FWD_REF(T1) arg1,
BOOST_FWD_REF(T2) arg2):
m_ItMask(mask,
boost::forward<T1>(arg1),
boost::forward<T2>(arg2)),
TIteratorType(image,
boost::forward<T1>(arg1),
boost::forward<T2>(arg2))
{
ComputeMaskedBegin();
}
template <typename TIteratorType>
template <typename T1, typename T2, typename T3>
MaskedIteratorDecorator<TIteratorType>::MaskedIteratorDecorator(
typename MaskType::Pointer mask,
typename ImageType::Pointer image,
BOOST_FWD_REF(T1) arg1,
BOOST_FWD_REF(T2) arg2,
BOOST_FWD_REF(T3) arg3):
m_ItMask(mask,
boost::forward<T1>(arg1),
boost::forward<T2>(arg2),
boost::forward<T3>(arg3)),
TIteratorType(image,
boost::forward<T1>(arg1),
boost::forward<T2>(arg2),
boost::forward<T2>(arg3))
{
ComputeMaskedBegin();
m_ItImage = TIteratorType(image,region);
if (mask == NULL)
{
m_UseMask = false;
}
else
{
m_UseMask = true;
m_ItMask = TMaskIteratorType(mask,region);
#ifdef MY_NEW_IMPLEMENTATION
m_StartMask = TMaskIteratorType(mask,region);
m_StartImage = TIteratorType(image,region);
#else
this->ComputeMaskedBegin();
#endif
}
}
template <typename TIteratorType>
typename MaskedIteratorDecorator<TIteratorType>::IndexType MaskedIteratorDecorator<TIteratorType>::GetIndex() const
template <typename TIteratorType, typename TMaskIteratorType>
typename MaskedIteratorDecorator<TIteratorType,TMaskIteratorType>::IndexType
MaskedIteratorDecorator<TIteratorType,TMaskIteratorType>
::GetIndex() const
{
return m_ItMask.GetIndex();
return m_ItImage.GetIndex();
}
template <typename TIteratorType>
void MaskedIteratorDecorator<TIteratorType>::GoToBegin()
template <typename TIteratorType, typename TMaskIteratorType>
void
MaskedIteratorDecorator<TIteratorType,TMaskIteratorType>
::GoToBegin()
{
m_ItMask.SetIndex(m_Begin);
m_ItImage.SetIndex(m_Begin);
if (m_UseMask)
{
#ifdef MY_NEW_IMPLEMENTATION
this->ComputeMaskedBegin();
#else
m_ItMask.SetIndex(m_Begin);
m_ItImage.SetIndex(m_Begin);
#endif
}
else
{
m_ItImage.GoToBegin();
}
}
template <typename TIteratorType>
void MaskedIteratorDecorator<TIteratorType>::GoToEnd()
template <typename TIteratorType, typename TMaskIteratorType>
void
MaskedIteratorDecorator<TIteratorType,TMaskIteratorType>
::GoToEnd()
{
m_ItMask.GoToEnd();
m_ItImage.GoToEnd();
if (m_UseMask)
{
// make sure masked begin is computed as next calls might be operator--()
// and IsAtBegin() (for a reverse iteration)
#ifdef MY_NEW_IMPLEMENTATION
this->ComputeMaskedBegin();
#endif
m_ItImage.GoToEnd();
m_ItMask.GoToEnd();
}
else
{
m_ItImage.GoToEnd();
}
}
template <typename TIteratorType>
bool MaskedIteratorDecorator<TIteratorType>::IsAtBegin() const
template <typename TIteratorType, typename TMaskIteratorType>
bool
MaskedIteratorDecorator<TIteratorType,TMaskIteratorType>
::IsAtBegin() const
{
return m_ItMask.GetIndex() == m_Begin || m_ItImage.GetIndex() == m_Begin;
if (m_UseMask)
{
#ifdef MY_NEW_IMPLEMENTATION
return m_ItMask == m_StartMask || m_ItImage == m_StartImage;
#else
return m_ItMask.GetIndex() == m_Begin || m_ItImage.GetIndex() == m_Begin;
#endif
}
return m_ItImage.IsAtBegin();
}
template <typename TIteratorType>
bool MaskedIteratorDecorator<TIteratorType>::IsAtEnd() const
template <typename TIteratorType, typename TMaskIteratorType>
bool
MaskedIteratorDecorator<TIteratorType,TMaskIteratorType>
::IsAtEnd() const
{
return m_ItMask.IsAtEnd() || m_ItImage.IsAtEnd();
if (m_UseMask)
{
return m_ItMask.IsAtEnd() || m_ItImage.IsAtEnd();
}
return m_ItImage.IsAtEnd();
}
// Wrap the underlying iterators to skip masked pixels
template <typename TIteratorType>
MaskedIteratorDecorator<TIteratorType>& MaskedIteratorDecorator<TIteratorType>::operator++()
template <typename TIteratorType, typename TMaskIteratorType>
MaskedIteratorDecorator<TIteratorType,TMaskIteratorType>&
MaskedIteratorDecorator<TIteratorType,TMaskIteratorType>
::operator++()
{
do
{
++m_ItMask;
if (m_UseMask)
{
do
{
++m_ItMask;
++m_ItImage;
} while (m_ItMask.Value() == 0 && !this->IsAtEnd());
}
else
{
++m_ItImage;
} while (m_ItMask.Value() == 0 && !this->IsAtEnd());
}
return *this;
}
// Wrap the underlying iterators to skip masked pixels
template <typename TIteratorType>
MaskedIteratorDecorator<TIteratorType>& MaskedIteratorDecorator<TIteratorType>::operator--()
template <typename TIteratorType, typename TMaskIteratorType>
MaskedIteratorDecorator<TIteratorType,TMaskIteratorType>&
MaskedIteratorDecorator<TIteratorType,TMaskIteratorType>
::operator--()
{
do
{
--m_ItMask;
if (m_UseMask)
{
do
{
--m_ItMask;
--m_ItImage;
} while (m_ItMask.Value() == 0 && !this->IsAtBegin());
}
else
{
--m_ItImage;
} while (m_ItMask.Value() == 0 && !this->IsAtBegin());
}
return *this;
}
/*
template <typename TIteratorType>
void MaskedIteratorDecorator<TIteratorType>::Set(const PixelType& value) const
template <typename TIteratorType, typename TMaskIteratorType>
void MaskedIteratorDecorator<TIteratorType,TMaskIteratorType>::Set(const PixelType& value) const
{
m_ItImage.Set(value);
}
*/
template <typename TIteratorType>
const typename MaskedIteratorDecorator<TIteratorType>::PixelType& MaskedIteratorDecorator<TIteratorType>::Value(void) const
template <typename TIteratorType, typename TMaskIteratorType>
const typename MaskedIteratorDecorator<TIteratorType,TMaskIteratorType>::PixelType&
MaskedIteratorDecorator<TIteratorType,TMaskIteratorType>
::Value(void) const
{
return m_ItImage.Value();
}
template <typename TIteratorType>
TIteratorType& MaskedIteratorDecorator<TIteratorType>::GetMaskIterator()
template <typename TIteratorType, typename TMaskIteratorType>
TMaskIteratorType&
MaskedIteratorDecorator<TIteratorType,TMaskIteratorType>
::GetMaskIterator()
{
return m_ItMask;
}
template <typename TIteratorType>
const TIteratorType& MaskedIteratorDecorator<TIteratorType>::GetMaskIterator() const
template <typename TIteratorType, typename TMaskIteratorType>
const TMaskIteratorType&
MaskedIteratorDecorator<TIteratorType,TMaskIteratorType>
::GetMaskIterator() const
{
return m_ItMask;
}
template <typename TIteratorType>
TIteratorType& MaskedIteratorDecorator<TIteratorType>::GetImageIterator()
template <typename TIteratorType, typename TMaskIteratorType>
TIteratorType&
MaskedIteratorDecorator<TIteratorType,TMaskIteratorType>
::GetImageIterator()
{
return m_ItImage;
}
template <typename TIteratorType>
const TIteratorType& MaskedIteratorDecorator<TIteratorType>::GetImageIterator() const
template <typename TIteratorType, typename TMaskIteratorType>
const TIteratorType&
MaskedIteratorDecorator<TIteratorType,TMaskIteratorType>
::GetImageIterator() const
{
return m_ItImage;
}
template <typename TIteratorType, typename TMaskIteratorType>
const bool&
MaskedIteratorDecorator<TIteratorType,TMaskIteratorType>
::HasMask() const
{
return m_UseMask;
}
// Compute begin iterator position taking into account the mask
template <typename TIteratorType>
void MaskedIteratorDecorator<TIteratorType>::ComputeMaskedBegin()
template <typename TIteratorType, typename TMaskIteratorType>
void
MaskedIteratorDecorator<TIteratorType,TMaskIteratorType>
::ComputeMaskedBegin()
{
// We must search for the first index where the image is not masked
// Start searching at the begining
#ifdef MY_NEW_IMPLEMENTATION
m_ItMask.GoToBegin();
m_ItImage.GoToBegin();
......@@ -187,8 +241,19 @@ void MaskedIteratorDecorator<TIteratorType>::ComputeMaskedBegin()
++m_ItMask;
++m_ItImage;
}
// Remember it so that GoToBegin and IsAtBegin can check it
m_StartMask.SetIndex(m_ItMask.GetIndex());
m_StartImage.SetIndex(m_ItImage.GetIndex());
#else
m_ItMask.GoToBegin();
m_ItImage.GoToBegin();
while (m_ItMask.Value() == 0 && !m_ItMask.IsAtEnd() && !m_ItImage.IsAtEnd())
{
++m_ItMask;
++m_ItImage;
}
this->m_Begin = m_ItMask.GetIndex();
#endif
}
} // namespace otb
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment