accessor.hxx   accessor.hxx 
skipping to change at line 54 skipping to change at line 54
/** \addtogroup DataAccessors Data Accessors /** \addtogroup DataAccessors Data Accessors
Basic templates to encapsulate access to the data of an iterator. Basic templates to encapsulate access to the data of an iterator.
Data accessors are used to allow for flexible access to the data Data accessors are used to allow for flexible access to the data
an iterator points to. When we access the data directly, we an iterator points to. When we access the data directly, we
are bound to what <TT>operator*()</TT> returns, if this method exists a t are bound to what <TT>operator*()</TT> returns, if this method exists a t
all. Encapsulating access in an accessor enables a better all. Encapsulating access in an accessor enables a better
decoupling of data structures and algorithms. decoupling of data structures and algorithms.
<a href="documents/DataAccessors.ps">This paper</a> contains <a href="http://hci.iwr.uni-heidelberg.de/vigra/documents/DataAccessors .ps">This paper</a> contains
a detailed description of the concept. Here is a brief list of the basi c a detailed description of the concept. Here is a brief list of the basi c
accessor requirements: accessor requirements:
<p> <p>
<table border=2 cellspacing=0 cellpadding=2 width="100%"> <table border=2 cellspacing=0 cellpadding=2 width="100%">
<tr><th> <tr><th>
Operation Operation
</th><th> </th><th>
Result Result
</th><th> </th><th>
Semantics Semantics
</th> </th>
</tr> </tr>
<tr> <tr>
<td><tt>accessor(iter)</tt></td><td>convertible to <br><tt>Iterator::va lue_type const &</tt></td> <td><tt>accessor(iter)</tt></td><td>convertible to <br><tt>Accessor::va lue_type const &</tt></td>
<td>read data at the current position of the iterator</td> <td>read data at the current position of the iterator</td>
</tr> </tr>
<tr> <tr>
<td><tt>accessor(iter, index)</tt></td><td>convertible to <br><tt>Acces sor::value_type const &</tt></td> <td><tt>accessor(iter, index)</tt></td><td>convertible to <br><tt>Acces sor::value_type const &</tt></td>
<td>read data at offset <tt>index</tt> relative to iterator's current p osition <td>read data at offset <tt>index</tt> relative to iterator's current p osition
(random-access iterator only)</td> (random-access iterator only)</td>
</tr> </tr>
<tr> <tr>
<td><tt>accessor.set(value, iter)</tt></td><td><tt>void</tt></td> <td><tt>accessor.set(value, iter)</tt></td><td><tt>void</tt></td>
<td>write data <tt>value</tt> at the current position of the iterator ( mutable iterator only)</td> <td>write data <tt>value</tt> at the current position of the iterator ( mutable iterator only)</td>
 End of changes. 2 change blocks. 
2 lines changed or deleted 2 lines changed or added


 algorithm.hxx   algorithm.hxx 
skipping to change at line 41 skipping to change at line 41
/* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */ /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */
/* OTHER DEALINGS IN THE SOFTWARE. */ /* OTHER DEALINGS IN THE SOFTWARE. */
/* */ /* */
/************************************************************************/ /************************************************************************/
#ifndef VIGRA_ALGORITHM_HXX #ifndef VIGRA_ALGORITHM_HXX
#define VIGRA_ALGORITHM_HXX #define VIGRA_ALGORITHM_HXX
#include "sized_int.hxx" #include "sized_int.hxx"
#include "numerictraits.hxx" #include "numerictraits.hxx"
#include "inspector_passes.hxx"
#include <algorithm> #include <algorithm>
#include <functional> #include <functional>
#include <iterator> #include <iterator>
namespace vigra { namespace vigra {
/** \addtogroup MathFunctions /** \addtogroup MathFunctions
*/ */
//@{ //@{
/*! Find the minimum element in a sequence. /*! Find the minimum element in a sequence.
skipping to change at line 227 skipping to change at line 228
} }
template <class Iterator> template <class Iterator>
void linearSequence(Iterator first, Iterator last) void linearSequence(Iterator first, Iterator last)
{ {
typedef typename std::iterator_traits<Iterator>::value_type Value; typedef typename std::iterator_traits<Iterator>::value_type Value;
linearSequence(first, last, NumericTraits<Value>::zero()); linearSequence(first, last, NumericTraits<Value>::zero());
} }
/** \brief Call an analyzing functor at every element of a sequence.
This function can be used to collect statistics of the sequence
<tt>[first, last)</tt> defined by these two input interators.
The results must be stored in the functor, which serves as a return
value.
<b> Declarations:</b>
\code
namespace vigra {
template <class InputIterator, class Functor>
void
inspectSequence(InputIterator first, InputIterator last, Functor &
f);
}
\endcode
<b> Usage:</b>
<b>\#include</b> \<vigra/algorithm.hxx\><br>
Namespace: vigra
\code
std::vector array(100);
// init functor
vigra::FindMinMax<int> minmax;
vigra::inspectSequence(array.begin(), array.end(), minmax);
cout << "Min: " << minmax.min << " Max: " << minmax.max;
\endcode
*/
doxygen_overloaded_function(template <...> void inspectSequence)
namespace detail {
template <class InputIterator>
struct inspectSequence_binder
{
InputIterator first;
InputIterator last;
inspectSequence_binder(InputIterator first_, InputIterator last_)
: first(first_), last(last_) {}
template <class Functor>
void operator()(Functor & f)
{
for (InputIterator i = first; i != last; ++i)
f(*i);
}
};
} // namespace detail
template <class InputIterator, class Functor>
inline void
inspectSequence(InputIterator first, InputIterator last, Functor & f)
{
detail::inspectSequence_binder<InputIterator> g(first, last);
detail::extra_passes_select(g, f);
}
namespace detail { namespace detail {
template <class Iterator, class Compare> template <class Iterator, class Compare>
struct IndexCompare struct IndexCompare
{ {
Iterator i_; Iterator i_;
Compare c_; Compare c_;
IndexCompare(Iterator i, Compare c) IndexCompare(Iterator i, Compare c)
: i_(i), : i_(i),
skipping to change at line 627 skipping to change at line 692
} }
/*! Concatenate a byte array to an existing CRC-32 checksum. /*! Concatenate a byte array to an existing CRC-32 checksum.
*/ */
inline UInt32 concatenateChecksum(UInt32 checksum, const char * data, unsig ned int size) inline UInt32 concatenateChecksum(UInt32 checksum, const char * data, unsig ned int size)
{ {
return detail::checksumImpl(data, size, ~checksum); return detail::checksumImpl(data, size, ~checksum);
} }
template <class T>
void updateMin(T & x, const T & y)
{
using std::min;
x = min(x, y);
}
template <class T>
void updateMax(T & x, const T & y)
{
using std::max;
x = max(x, y);
}
//@} //@}
} // namespace vigra } // namespace vigra
#endif /* VIGRA_ALGORITHM_HXX */ #endif /* VIGRA_ALGORITHM_HXX */
 End of changes. 3 change blocks. 
0 lines changed or deleted 80 lines changed or added


 array_vector.hxx   array_vector.hxx 
skipping to change at line 861 skipping to change at line 861
template <class T, class Alloc> template <class T, class Alloc>
template <class Iter> template <class Iter>
inline void inline void
ArrayVector<T, Alloc>::initImpl( Iter i, Iter end, VigraFalseType /*isInteg ral*/) ArrayVector<T, Alloc>::initImpl( Iter i, Iter end, VigraFalseType /*isInteg ral*/)
{ {
this->size_ = std::distance(i, end); this->size_ = std::distance(i, end);
capacity_ = this->size_; capacity_ = this->size_;
this->data_ = reserve_raw(capacity_); this->data_ = reserve_raw(capacity_);
if(this->size_ > 0) if(this->size_ > 0)
std::uninitialized_copy(i, end, this->data_); detail::uninitializedCopy(i, end, this->data_);
} }
template <class T, class Alloc> template <class T, class Alloc>
inline void inline void
ArrayVector<T, Alloc>::swap(this_type & rhs) ArrayVector<T, Alloc>::swap(this_type & rhs)
{ {
std::swap(this->size_, rhs.size_); std::swap(this->size_, rhs.size_);
std::swap(capacity_, rhs.capacity_); std::swap(capacity_, rhs.capacity_);
std::swap(this->data_, rhs.data_); std::swap(this->data_, rhs.data_);
} }
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 bordertreatment.hxx   bordertreatment.hxx 
skipping to change at line 70 skipping to change at line 70
BORDER_TREATMENT_CLIP, BORDER_TREATMENT_CLIP,
// repeat the nearest valid pixel // repeat the nearest valid pixel
BORDER_TREATMENT_REPEAT, BORDER_TREATMENT_REPEAT,
// reflect image at last row/column // reflect image at last row/column
BORDER_TREATMENT_REFLECT, BORDER_TREATMENT_REFLECT,
// wrap image around (periodic boundary conditions) // wrap image around (periodic boundary conditions)
BORDER_TREATMENT_WRAP BORDER_TREATMENT_WRAP
// assume that all outside points have value zero
BORDER_TREATMENT_ZEROPAD
}; };
\endcode \endcode
*/ */
enum BorderTreatmentMode enum BorderTreatmentMode
{ {
BORDER_TREATMENT_AVOID, BORDER_TREATMENT_AVOID,
BORDER_TREATMENT_CLIP, BORDER_TREATMENT_CLIP,
BORDER_TREATMENT_REPEAT, BORDER_TREATMENT_REPEAT,
BORDER_TREATMENT_REFLECT, BORDER_TREATMENT_REFLECT,
BORDER_TREATMENT_WRAP BORDER_TREATMENT_WRAP,
BORDER_TREATMENT_ZEROPAD
}; };
} // namespace vigra } // namespace vigra
#endif // VIGRA_BORDERTREATMENT_HXX #endif // VIGRA_BORDERTREATMENT_HXX
 End of changes. 2 change blocks. 
1 lines changed or deleted 5 lines changed or added


 bucket_queue.hxx   bucket_queue.hxx 
skipping to change at line 277 skipping to change at line 277
// clamp index to the allowed range // clamp index to the allowed range
if(index > BaseType::maxIndex()) if(index > BaseType::maxIndex())
index = BaseType::maxIndex(); index = BaseType::maxIndex();
else if (index < 0) else if (index < 0)
index = 0; index = 0;
BaseType::push(v, index); BaseType::push(v, index);
} }
}; };
/** \brief Heap-based priority queue compatible to BucketQueue.
This template is compatible to \ref vigra::BucketQueue, but except arbi
trary priority
types. Internally, it uses a <tt>std::priority_queue</tt>, but implemen
ts an
API where priorities and payload data are separate, like in \ref vigra:
:BucketQueue.
<b>\#include</b> \<vigra/bucket_queue.hxx\><br>
Namespace: vigra
*/
template <class ValueType,
class PriorityType,
bool Ascending = false> // std::priority_queue is descending
class PriorityQueue
{
typedef std::pair<ValueType, PriorityType> ElementType;
struct Compare
{
typename IfBool<Ascending, std::greater<PriorityType>,
std::less<PriorityType> >::type cmp;
bool operator()(ElementType const & l, ElementType const & r) const
{
return cmp(l.second, r.second);
}
};
typedef std::priority_queue<ElementType, std::vector<ElementType>, Comp
are> Heap;
Heap heap_;
public:
typedef ValueType value_type;
typedef ValueType & reference;
typedef ValueType const & const_reference;
typedef typename Heap::size_type size_type;
typedef PriorityType priority_type;
/** \brief Create empty priority queue.
*/
PriorityQueue()
: heap_()
{}
/** \brief Number of elements in this queue.
*/
size_type size() const
{
return heap_.size();
}
/** \brief Queue contains no elements.
Equivalent to <tt>size() == 0</tt>.
*/
bool empty() const
{
return size() == 0;
}
/** \brief Maximum index (i.e. priority) allowed in this queue.
Equivalent to <tt>bucket_count - 1</tt>.
*/
priority_type maxIndex() const
{
return NumericTraits<priority_type>::max();
}
/** \brief Priority of the current top element.
*/
priority_type topPriority() const
{
return heap_.top().second;
}
/** \brief The current top element.
*/
const_reference top() const
{
return heap_.top().first;
}
/** \brief Remove the current top element.
*/
void pop()
{
heap_.pop();
}
/** \brief Insert new element \arg v with given \arg priority.
*/
void push(value_type const & v, priority_type priority)
{
heap_.push(ElementType(v, priority));
}
};
} // namespace vigra } // namespace vigra
#endif // VIGRA_BUCKET_QUEUE_HXX #endif // VIGRA_BUCKET_QUEUE_HXX
 End of changes. 1 change blocks. 
0 lines changed or deleted 102 lines changed or added


 codec.hxx   codec.hxx 
skipping to change at line 148 skipping to change at line 148
// Decoder and Encoder are virtual types that define a common // Decoder and Encoder are virtual types that define a common
// interface for all image file formats impex supports. // interface for all image file formats impex supports.
struct Decoder struct Decoder
{ {
virtual ~Decoder() {}; virtual ~Decoder() {};
virtual void init( const std::string & ) = 0; virtual void init( const std::string & ) = 0;
// initialize with an image index. For codecs that do not support t his feature, the standard init is called. // initialize with an image index. For codecs that do not support t his feature, the standard init is called.
virtual void init( const std::string & fileName, unsigned int image Index) virtual void init( const std::string & fileName, unsigned int)
{ {
init(fileName); init(fileName);
} }
virtual void close() = 0; virtual void close() = 0;
virtual void abort() = 0; virtual void abort() = 0;
virtual std::string getFileType() const = 0; virtual std::string getFileType() const = 0;
virtual std::string getPixelType() const = 0; virtual std::string getPixelType() const = 0;
skipping to change at line 221 skipping to change at line 221
ICCProfile iccProfile_; ICCProfile iccProfile_;
}; };
struct Encoder struct Encoder
{ {
virtual ~Encoder() {}; virtual ~Encoder() {};
virtual void init( const std::string & ) = 0; virtual void init( const std::string & ) = 0;
// initialize with file access mode. For codecs that do not support this feature, the standard init is called. // initialize with file access mode. For codecs that do not support this feature, the standard init is called.
virtual void init( const std::string & fileName, const std::string & mode ) virtual void init( const std::string & fileName, const std::string & )
{ {
init(fileName); init(fileName);
} }
virtual void close() = 0; virtual void close() = 0;
virtual void abort() = 0; virtual void abort() = 0;
virtual std::string getFileType() const = 0; virtual std::string getFileType() const = 0;
virtual unsigned int getOffset() const = 0; virtual unsigned int getOffset() const = 0;
skipping to change at line 269 skipping to change at line 269
virtual void nextScanline() = 0; virtual void nextScanline() = 0;
struct TIFFCompressionException {}; struct TIFFCompressionException {};
}; };
// codec factory for registration at the codec manager // codec factory for registration at the codec manager
struct CodecFactory struct CodecFactory
{ {
virtual CodecDesc getCodecDesc() const = 0; virtual CodecDesc getCodecDesc() const = 0;
virtual std::auto_ptr<Decoder> getDecoder() const = 0; virtual VIGRA_UNIQUE_PTR<Decoder> getDecoder() const = 0;
virtual std::auto_ptr<Encoder> getEncoder() const = 0; virtual VIGRA_UNIQUE_PTR<Encoder> getEncoder() const = 0;
virtual ~CodecFactory() {}; virtual ~CodecFactory() {};
}; };
// factory functions to encapsulate the codec managers // factory functions to encapsulate the codec managers
// //
// codecs are selected according to the following order: // codecs are selected according to the following order:
// - (if provided) the FileType // - (if provided) the FileType
// - (in case of decoders) the file's magic string // - (in case of decoders) the file's magic string
// - the filename extension // - the filename extension
VIGRA_EXPORT std::auto_ptr<Decoder> VIGRA_EXPORT VIGRA_UNIQUE_PTR<Decoder>
getDecoder( const std::string &, const std::string & = "undefined", uns igned int = 0 ); getDecoder( const std::string &, const std::string & = "undefined", uns igned int = 0 );
VIGRA_EXPORT std::auto_ptr<Encoder> VIGRA_EXPORT VIGRA_UNIQUE_PTR<Encoder>
getEncoder( const std::string &, const std::string & = "undefined", con st std::string & = "w" ); getEncoder( const std::string &, const std::string & = "undefined", con st std::string & = "w" );
VIGRA_EXPORT std::string VIGRA_EXPORT std::string
getEncoderType( const std::string &, const std::string & = "undefined" ); getEncoderType( const std::string &, const std::string & = "undefined" );
// functions to query the capabilities of certain codecs // functions to query the capabilities of certain codecs
VIGRA_EXPORT std::vector<std::string> queryCodecPixelTypes( const std:: string & ); VIGRA_EXPORT std::vector<std::string> queryCodecPixelTypes( const std:: string & );
VIGRA_EXPORT bool negotiatePixelType( std::string const & codecname, VIGRA_EXPORT bool negotiatePixelType( std::string const & codecname,
 End of changes. 5 change blocks. 
6 lines changed or deleted 6 lines changed or added


 config.hxx   config.hxx 
skipping to change at line 106 skipping to change at line 106
#ifndef CMATH_NOT_IN_STD #ifndef CMATH_NOT_IN_STD
} }
#endif // CMATH_NOT_IN_STD #endif // CMATH_NOT_IN_STD
#endif // _MSC_EXTENSIONS #endif // _MSC_EXTENSIONS
#endif // _MSC_VER < 1310 #endif // _MSC_VER < 1310
#if _MSC_VER < 1400 #if _MSC_VER < 1400
#define VIGRA_NO_WORKING_STRINGSTREAM #define VIGRA_NO_WORKING_STRINGSTREAM
#endif #endif
#if _MSC_VER >= 1600
#define VIGRA_HAS_UNIQUE_PTR
#endif
#define VIGRA_NEED_BIN_STREAMS #define VIGRA_NEED_BIN_STREAMS
#ifndef VIGRA_ENABLE_ANNOYING_WARNINGS
#pragma warning ( disable: 4244 4267) // implicit integer conversio
n warnings
#endif
#ifdef VIGRA_DLL #ifdef VIGRA_DLL
#define VIGRA_EXPORT __declspec(dllexport) #define VIGRA_EXPORT __declspec(dllexport)
#elif defined(VIGRA_STATIC_LIB) #elif defined(VIGRA_STATIC_LIB)
#define VIGRA_EXPORT #define VIGRA_EXPORT
#else #else
#define VIGRA_EXPORT __declspec(dllimport) #define VIGRA_EXPORT __declspec(dllimport)
#endif #endif
#endif // _MSC_VER #endif // _MSC_VER
/////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////
skipping to change at line 136 skipping to change at line 144
#endif #endif
#if __GNUC__ < 3 #if __GNUC__ < 3
#define VIGRA_NO_WORKING_STRINGSTREAM #define VIGRA_NO_WORKING_STRINGSTREAM
#endif #endif
#define HAS_HASH_CONTAINERS #define HAS_HASH_CONTAINERS
// these warnings produce too many false positives to be useful // these warnings produce too many false positives to be useful
#pragma GCC diagnostic ignored "-Wstrict-aliasing" #pragma GCC diagnostic ignored "-Wstrict-aliasing"
#pragma GCC diagnostic ignored "-Wshadow" #pragma GCC diagnostic ignored "-Wshadow"
#if defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L
#define VIGRA_HAS_UNIQUE_PTR
#endif
#endif // __GNUC__ #endif // __GNUC__
/////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////
// // // //
// MingW // // MingW //
// // // //
/////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////
#if defined(__MINGW32__) #if defined(__MINGW32__)
#define VIGRA_NEED_BIN_STREAMS #define VIGRA_NEED_BIN_STREAMS
skipping to change at line 212 skipping to change at line 224
#endif #endif
#ifdef NO_EXPLICIT #ifdef NO_EXPLICIT
#define explicit #define explicit
#endif #endif
#ifndef VIGRA_EXPORT #ifndef VIGRA_EXPORT
#define VIGRA_EXPORT #define VIGRA_EXPORT
#endif #endif
#ifdef VIGRA_HAS_UNIQUE_PTR
# define VIGRA_UNIQUE_PTR std::unique_ptr
#else
# define VIGRA_UNIQUE_PTR std::auto_ptr
#endif
namespace vigra { namespace vigra {
#ifndef SPECIAL_STDEXCEPTION_DEFINITION_NEEDED #ifndef SPECIAL_STDEXCEPTION_DEFINITION_NEEDED
typedef std::exception StdException; typedef std::exception StdException;
#endif #endif
} // namespace vigra } // namespace vigra
#ifdef DOXYGEN #ifdef DOXYGEN
# define doxygen_overloaded_function(fun) fun(...); # define doxygen_overloaded_function(fun) fun(...);
 End of changes. 4 change blocks. 
0 lines changed or deleted 19 lines changed or added


 configVersion.hxx   configVersion.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 1998-2010 by Ullrich Koethe */ /* Copyright 1998-2012 by Ullrich Koethe */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://hci.iwr.uni-heidelberg.de/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
skipping to change at line 40 skipping to change at line 40
/* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */ /* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */
/* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */ /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */
/* OTHER DEALINGS IN THE SOFTWARE. */ /* OTHER DEALINGS IN THE SOFTWARE. */
/* */ /* */
/************************************************************************/ /************************************************************************/
#ifndef VIGRA_CONFIG_VERSION_HXX #ifndef VIGRA_CONFIG_VERSION_HXX
#define VIGRA_CONFIG_VERSION_HXX #define VIGRA_CONFIG_VERSION_HXX
#define VIGRA_VERSION_MAJOR 1 #define VIGRA_VERSION_MAJOR 1
#define VIGRA_VERSION_MINOR 8 #define VIGRA_VERSION_MINOR 9
#define VIGRA_VERSION_PATCH 0 #define VIGRA_VERSION_PATCH 0
#define VIGRA_VERSION "1.8.0" #define VIGRA_VERSION "1.9.0"
#endif /* VIGRA_CONFIG_VERSION_HXX */ #endif /* VIGRA_CONFIG_VERSION_HXX */
 End of changes. 3 change blocks. 
3 lines changed or deleted 3 lines changed or added


 eigensystem.hxx   eigensystem.hxx 
skipping to change at line 1024 skipping to change at line 1024
ev.copy(a); // does nothing if &ev == &a ev.copy(a); // does nothing if &ev == &a
Matrix<T> de(acols, 2); Matrix<T> de(acols, 2);
detail::housholderTridiagonalization(ev, de); detail::housholderTridiagonalization(ev, de);
if(!detail::tridiagonalMatrixEigensystem(de, ev)) if(!detail::tridiagonalMatrixEigensystem(de, ev))
return false; return false;
ew.copy(columnVector(de, 0)); ew.copy(columnVector(de, 0));
return true; return true;
} }
namespace detail{
template <class T, class C1, class C2, class C3>
bool
symmetricEigensystem2x2(MultiArrayView<2, T, C1> const & a,
MultiArrayView<2, T, C2> & ew, MultiArrayView<2, T, C3> & ev)
{
vigra_precondition(isSymmetric(a),
"symmetricEigensystem(): symmetric input matrix required.");
double evec[2]={0,0};
/* Eigenvectors*/
if (a(0,1)==0){
if (fabs(a(1,1))>fabs(a(0,0))){
evec[0]=0.;
evec[1]=1.;
ew(0,0)=a(1,1);
ew(1,0)=a(0,0);
}
else if(fabs(a(0,0))>fabs(a(1,1))) {
evec[0]=1.;
evec[1]=0.;
ew(0,0)=a(0,0);
ew(1,0)=a(1,1);
}
else {
evec[0]=.5* M_SQRT2;
evec[1]=.5* M_SQRT2;
ew(0,0)=a(0,0);
ew(1,0)=a(1,1);
}
}
else{
double temp=a(1,1)-a(0,0);
double coherence=sqrt(temp*temp+4*a(0,1)*a(0,1));
evec[0]=2*a(0,1);
evec[1]=temp+coherence;
temp=std::sqrt(evec[0]*evec[0]+evec[1]*evec[1]);
if (temp==0){
evec[0]=.5* M_SQRT2;
evec[1]=.5* M_SQRT2;
ew(0,0)=1.;
ew(1,0)=1.;
}
else{
evec[0]/=temp;
evec[1]/=temp;
/* Eigenvalues */
ew(0,0)=.5*(a(0,0)+a(1,1)+coherence);
ew(1,0)=.5*(a(0,0)+a(1,1)-coherence);
}
}
ev(0,0)= evec[0];
ev(1,0)= evec[1];
ev(0,1)=-evec[1];
ev(1,1)= evec[0];
return true;
}
} // closing namespace detail
/** Compute the eigensystem of a square, but /** Compute the eigensystem of a square, but
not necessarily symmetric matrix. not necessarily symmetric matrix.
\a a is a real square matrix, \a ew is a single-column matrix \a a is a real square matrix, \a ew is a single-column matrix
holding the possibly complex eigenvalues, and \a ev is a matrix of holding the possibly complex eigenvalues, and \a ev is a matrix of
the same size as \a a whose columns are the corresponding eigenvect ors. the same size as \a a whose columns are the corresponding eigenvect ors.
Eigenvalues will be sorted from largest to smallest magnitude. Eigenvalues will be sorted from largest to smallest magnitude.
The algorithm returns <tt>false</tt> when it doesn't The algorithm returns <tt>false</tt> when it doesn't
converge. It can be applied in-place, i.e. <tt>&a == &ev</tt> is al lowed. converge. It can be applied in-place, i.e. <tt>&a == &ev</tt> is al lowed.
The code of this function was adapted from JAMA. The code of this function was adapted from JAMA.
 End of changes. 1 change blocks. 
0 lines changed or deleted 62 lines changed or added


 error.hxx   error.hxx 
skipping to change at line 206 skipping to change at line 206
public: public:
InvariantViolation(char const * message, const char * file, int line) InvariantViolation(char const * message, const char * file, int line)
: ContractViolation("Invariant violation!", message, file, line) : ContractViolation("Invariant violation!", message, file, line)
{} {}
InvariantViolation(char const * message) InvariantViolation(char const * message)
: ContractViolation("Invariant violation!", message) : ContractViolation("Invariant violation!", message)
{} {}
}; };
#ifndef NDEBUG //#ifndef NDEBUG
#if 1
inline inline
void throw_invariant_error(bool predicate, char const * message, char const * file, int line) void throw_invariant_error(bool predicate, char const * message, char const * file, int line)
{ {
if(!predicate) if(!predicate)
throw vigra::InvariantViolation(message, file, line); throw vigra::InvariantViolation(message, file, line);
} }
inline inline
void throw_invariant_error(bool predicate, std::string message, char const * file, int line) void throw_invariant_error(bool predicate, std::string message, char const * file, int line)
 End of changes. 1 change blocks. 
1 lines changed or deleted 3 lines changed or added


 fixedpoint.hxx   fixedpoint.hxx 
skipping to change at line 274 skipping to change at line 274
*/ */
FixedPoint(const FixedPoint &other) FixedPoint(const FixedPoint &other)
: value(other.value) : value(other.value)
{} {}
/** Construct from a FixedPoint with different layout. It rounds as appropriate and raises /** Construct from a FixedPoint with different layout. It rounds as appropriate and raises
a compile-time error when the target type has too few integer b its. a compile-time error when the target type has too few integer b its.
*/ */
template <unsigned Int2, unsigned Frac2> template <unsigned Int2, unsigned Frac2>
FixedPoint(const FixedPoint<Int2, Frac2> &other) FixedPoint(const FixedPoint<Int2, Frac2> &other)
: value(detail::FPAssignWithRound<(Frac2 > FractionalBits)>::template e xec<Frac2 - FractionalBits>(other.value)) : value(detail::FPAssignWithRound<(Frac2 > FractionalBits)>::template e xec<int(Frac2) - int(FractionalBits)>(other.value))
{ {
VIGRA_STATIC_ASSERT((FixedPoint_overflow_error__More_than_31_bits_r equested<(IntBits + FractionalBits)>)); VIGRA_STATIC_ASSERT((FixedPoint_overflow_error__More_than_31_bits_r equested<(IntBits + FractionalBits)>));
VIGRA_STATIC_ASSERT((FixedPoint_assignment_error__Target_object_has _too_few_integer_bits<(IntBits >= Int2)>)); VIGRA_STATIC_ASSERT((FixedPoint_assignment_error__Target_object_has _too_few_integer_bits<(IntBits >= Int2)>));
} }
/** Assignment from int. The fractional part will become zero. /** Assignment from int. The fractional part will become zero.
A PreconditionViolation exception is raised when A PreconditionViolation exception is raised when
the integer part is too small to represent the number. the integer part is too small to represent the number.
*/ */
FixedPoint &operator=(int rhs) FixedPoint &operator=(int rhs)
skipping to change at line 319 skipping to change at line 319
return *this; return *this;
} }
/** Assignment from a FixedPoint with different layout. It rounds a s appropriate and raises /** Assignment from a FixedPoint with different layout. It rounds a s appropriate and raises
a compile-time error when the target type has too few integer b its. a compile-time error when the target type has too few integer b its.
*/ */
template <unsigned Int2, unsigned Frac2> template <unsigned Int2, unsigned Frac2>
FixedPoint & operator=(const FixedPoint<Int2, Frac2> &other) FixedPoint & operator=(const FixedPoint<Int2, Frac2> &other)
{ {
VIGRA_STATIC_ASSERT((FixedPoint_assignment_error__Target_object_has _too_few_integer_bits<(IntBits >= Int2)>)); VIGRA_STATIC_ASSERT((FixedPoint_assignment_error__Target_object_has _too_few_integer_bits<(IntBits >= Int2)>));
value = detail::FPAssignWithRound<(Frac2 > FractionalBits)>::templa te exec<Frac2 - FractionalBits>(other.value); value = detail::FPAssignWithRound<(Frac2 > FractionalBits)>::templa te exec<int(Frac2) - int(FractionalBits)>(other.value);
return *this; return *this;
} }
/** Negation. /** Negation.
*/ */
FixedPoint operator-() const FixedPoint operator-() const
{ {
return FixedPoint(-value, FPNoShift); return FixedPoint(-value, FPNoShift);
} }
 End of changes. 2 change blocks. 
2 lines changed or deleted 2 lines changed or added


 functorexpression.hxx   functorexpression.hxx 
skipping to change at line 42 skipping to change at line 42
/* OTHER DEALINGS IN THE SOFTWARE. */ /* OTHER DEALINGS IN THE SOFTWARE. */
/* */ /* */
/************************************************************************/ /************************************************************************/
#ifndef VIGRA_FUNCTOREXPRESSION_HXX #ifndef VIGRA_FUNCTOREXPRESSION_HXX
#define VIGRA_FUNCTOREXPRESSION_HXX #define VIGRA_FUNCTOREXPRESSION_HXX
/** \page FunctorExpressions Functor Expressions /** \page FunctorExpressions Functor Expressions
Simple automatic functor creation by means of expression templates Simple automatic functor creation by means of expression templates
(also known as a "lambda library"). (also known as a "lambda library"). Note, however, that the \ref
MultiMathModule module offers similar functionality with an easier
syntax.
<b>\#include</b> \<vigra/functorexpression.hxx\><br> <b>\#include</b> \<vigra/functorexpression.hxx\><br>
Namespace: vigra::functor Namespace: vigra::functor
<b> Motivation</b> <b> Motivation</b>
Many generic algorithms are made more flexible by means of functors Many generic algorithms are made more flexible by means of functors
which define part of the algorithms' behavior according to the which define part of the algorithms' behavior according to the
needs of a specific situation. For example, we can apply an exponential needs of a specific situation. For example, we can apply an exponential
to each pixel by passing a pointer to the <TT>exp</TT> function to each pixel by passing a pointer to the <TT>exp</TT> function
skipping to change at line 111 skipping to change at line 113
<li> Functors cannot be implemented directly at the point of use. <li> Functors cannot be implemented directly at the point of use.
Thus, to find out exactly what a functor is doing, one needs Thus, to find out exactly what a functor is doing, one needs
to look somewhere else. This complicates use and maintenance to look somewhere else. This complicates use and maintenance
ot generic code. ot generic code.
</UL> </UL>
Therefore, it is necessary to provide a means to generate functors on Therefore, it is necessary to provide a means to generate functors on
the fly where they are needed. The C++ standard library contains so cal led the fly where they are needed. The C++ standard library contains so cal led
"functor combinators" that allow to construct complicated functors from "functor combinators" that allow to construct complicated functors from
simpler ones. The above problem "apply <TT>exp(-beta*v)</TT> to every p ixel" simpler ones. The above problem "apply exp(-beta*v) to every pixel"
would be solved like this: would be solved like this:
\code \code
float beta = ...; float beta = ...;
vigra::transformImage(srcImageRange(src), destImage(dest), vigra::transformImage(srcImageRange(src), destImage(dest),
std::compose1(std::ptr_fun(exp), std::compose1(std::ptr_fun(exp),
std::bind1st(std::multiplies<float>(), -be ta))); std::bind1st(std::multiplies<float>(), -be ta)));
\endcode \endcode
skipping to change at line 320 skipping to change at line 322
int count = -1; int count = -1;
initImageWithFunctor(destImageRange(img), initImageWithFunctor(destImageRange(img),
( (
Var(count) += Param(1), Var(count) += Param(1),
Var(count) // this is the result of the c omma expression Var(count) // this is the result of the c omma expression
)); ));
\endcode \endcode
Further information about how this mechanism works can be found in Further information about how this mechanism works can be found in
<a href="documents/FunctorFactory.ps">this paper</a> (sorry, slightly o ut of date). <a href="http://hci.iwr.uni-heidelberg.de/vigra/documents/FunctorFactor y.ps">this paper</a> (sorry, slightly out of date).
*/ */
#ifndef DOXYGEN #ifndef DOXYGEN
#if !defined(NO_PARTIAL_TEMPLATE_SPECIALIZATION) #if !defined(NO_PARTIAL_TEMPLATE_SPECIALIZATION)
#include <cmath> #include <cmath>
#include "numerictraits.hxx" #include "numerictraits.hxx"
#include "mathutil.hxx" #include "mathutil.hxx"
#include "functortraits.hxx" #include "functortraits.hxx"
 End of changes. 3 change blocks. 
3 lines changed or deleted 5 lines changed or added


 hdf5impex.hxx   hdf5impex.hxx 
skipping to change at line 79 skipping to change at line 79
#else #else
# include <hdf5_hl.h> # include <hdf5_hl.h>
#endif #endif
#include "impex.hxx" #include "impex.hxx"
#include "multi_array.hxx" #include "multi_array.hxx"
#include "multi_impex.hxx" #include "multi_impex.hxx"
#include "utilities.hxx" #include "utilities.hxx"
#include "error.hxx" #include "error.hxx"
#include <algorithm>
namespace vigra { namespace vigra {
/** \addtogroup VigraHDF5Impex Import/Export of Images and Arrays in HDF5 F ormat /** \addtogroup VigraHDF5Impex Import/Export of Images and Arrays in HDF5 F ormat
Supports arrays with arbitrary element types and arbitrary many dimensi ons. Supports arrays with arbitrary element types and arbitrary many dimensi ons.
See the <a href="http://www.hdfgroup.org/HDF5/">HDF5 Website</a> for mo re See the <a href="http://www.hdfgroup.org/HDF5/">HDF5 Website</a> for mo re
information on the HDF5 file format. information on the HDF5 file format.
*/ */
//@{ //@{
/** \brief Wrapper for hid_t objects. /** \brief Wrapper for hid_t objects.
Newly created or opened HDF5 handles are usually stored as objects of t ype 'hid_t'. When the handle Newly created or opened HDF5 handles are usually stored as objects of t ype 'hid_t'. When the handle
is no longer needed, the appropriate close function must be called. How ever, if a function is is no longer needed, the appropriate close function must be called. How ever, if a function is
aborted by an exception, this is difficult to ensure. Class HDF5Handle is a smart pointer that aborted by an exception, this is difficult to ensure. Class HDF5Handle is a smart pointer that
solves this problem by calling the close function in the destructor (Th is is analogous to how solves this problem by calling the close function in the destructor (Th is is analogous to how
std::auto_ptr calls 'delete' on the contained pointer). A pointer to th e close function must be VIGRA_UNIQUE_PTR calls 'delete' on the contained pointer). A pointer to the close function must be
passed to the constructor, along with an error message that is raised w hen creation/opening fails. passed to the constructor, along with an error message that is raised w hen creation/opening fails.
Since HDF5Handle objects are convertible to hid_t, they can be used in the code in place Since HDF5Handle objects are convertible to hid_t, they can be used in the code in place
of the latter. of the latter.
<b>Usage:</b> <b>Usage:</b>
\code \code
HDF5Handle file_id(H5Fopen(filename, H5F_ACC_RDWR, H5P_DEFAULT), HDF5Handle file_id(H5Fopen(filename, H5F_ACC_RDWR, H5P_DEFAULT),
&H5Fclose, &H5Fclose,
skipping to change at line 161 skipping to change at line 163
*/ */
HDF5Handle(hid_t h, Destructor destructor, const char * error_message) HDF5Handle(hid_t h, Destructor destructor, const char * error_message)
: handle_( h ), : handle_( h ),
destructor_(destructor) destructor_(destructor)
{ {
if(handle_ < 0) if(handle_ < 0)
vigra_fail(error_message); vigra_fail(error_message);
} }
/** \brief Copy constructor. /** \brief Copy constructor.
Hands over ownership of the RHS handle (analogous to std::auto_ ptr). Hands over ownership of the RHS handle (analogous to VIGRA_UNIQ UE_PTR).
*/ */
HDF5Handle(HDF5Handle const & h) HDF5Handle(HDF5Handle const & h)
: handle_( h.handle_ ), : handle_( h.handle_ ),
destructor_(h.destructor_) destructor_(h.destructor_)
{ {
const_cast<HDF5Handle &>(h).handle_ = 0; const_cast<HDF5Handle &>(h).handle_ = 0;
} }
/** \brief Assignment. /** \brief Assignment.
Calls close() for the LHS handle and hands over ownership of th e Calls close() for the LHS handle and hands over ownership of th e
RHS handle (analogous to std::auto_ptr). RHS handle (analogous to VIGRA_UNIQUE_PTR).
*/ */
HDF5Handle & operator=(HDF5Handle const & h) HDF5Handle & operator=(HDF5Handle const & h)
{ {
if(h.handle_ != handle_) if(h.handle_ != handle_)
{ {
close(); close();
handle_ = h.handle_; handle_ = h.handle_;
destructor_ = h.destructor_; destructor_ = h.destructor_;
const_cast<HDF5Handle &>(h).handle_ = 0; const_cast<HDF5Handle &>(h).handle_ = 0;
} }
skipping to change at line 312 skipping to change at line 314
/** Get a handle to the dataset represented by this info object. /** Get a handle to the dataset represented by this info object.
*/ */
VIGRA_EXPORT hid_t getDatasetHandle() const; VIGRA_EXPORT hid_t getDatasetHandle() const;
/** Get the number of dimensions of the dataset represented by this info object. /** Get the number of dimensions of the dataset represented by this info object.
*/ */
VIGRA_EXPORT MultiArrayIndex numDimensions() const; VIGRA_EXPORT MultiArrayIndex numDimensions() const;
/** Get the shape of the dataset represented by this info object. /** Get the shape of the dataset represented by this info object.
Note that the memory order between VIGRA and HDF5 files differs
: VIGRA uses
Fortran-order, while HDF5 uses C-order. This function therefore
reverses the axis
order relative to the file contents. That is, when the axes in
the file are
ordered as 'z', 'y', 'x', this function will return the shape i
n the order
'x', 'y', 'z'.
*/ */
VIGRA_EXPORT ArrayVector<hsize_t> const & shape() const VIGRA_EXPORT ArrayVector<hsize_t> const & shape() const
{ {
return m_dims; return m_dims;
} }
/** Get the shape (length) of the dataset along dimension \a dim. /** Get the shape (length) of the dataset along dimension \a dim.
Note that the memory order between VIGRA and HDF5 files differs
: VIGRA uses
Fortran-order, while HDF5 uses C-order. This function therefore
reverses the axis
order relative to the file contents. That is, when the axes in
the file are
ordered as 'z', 'y', 'x', this function will return the shape i
n the order
'x', 'y', 'z'.
*/ */
VIGRA_EXPORT MultiArrayIndex shapeOfDimension(const int dim) const; VIGRA_EXPORT MultiArrayIndex shapeOfDimension(const int dim) const;
/** Query the pixel type of the dataset. /** Query the pixel type of the dataset.
Possible values are: Possible values are:
<DL> <DL>
<DT>"UINT8"<DD> 8-bit unsigned integer (unsigned char) <DT>"UINT8"<DD> 8-bit unsigned integer (unsigned char)
<DT>"INT16"<DD> 16-bit signed integer (short) <DT>"INT16"<DD> 16-bit signed integer (short)
<DT>"UINT16"<DD> 16-bit unsigned integer (unsigned short) <DT>"UINT16"<DD> 16-bit unsigned integer (unsigned short)
skipping to change at line 473 skipping to change at line 487
/** \brief Access to HDF5 files /** \brief Access to HDF5 files
HDF5File provides a convenient way of accessing data in HDF5 files. vigra:: MultiArray HDF5File provides a convenient way of accessing data in HDF5 files. vigra:: MultiArray
structures of any dimension can be stored to / loaded from HDF5 files. Typi cal structures of any dimension can be stored to / loaded from HDF5 files. Typi cal
HDF5 features like subvolume access, chunks and data compression are availa ble, HDF5 features like subvolume access, chunks and data compression are availa ble,
string attributes can be attached to any dataset or group. Group- or datase t-handles string attributes can be attached to any dataset or group. Group- or datase t-handles
are encapsulated in the class and managed automatically. The internal file- system like are encapsulated in the class and managed automatically. The internal file- system like
structure can be accessed by functions like "cd()" or "mkdir()". structure can be accessed by functions like "cd()" or "mkdir()".
Note that the memory order between VIGRA and HDF5 files differs: VIGRA uses
Fortran-order, while HDF5 uses C-order. This means that a VIGRA MultiArray,
whose indices represent the 'x'-, 'y'-, and 'z'-axis in that order, is reve
rsed
upon writing to an HDF5 file, i.e. in the file the axis order is 'z', 'y',
'x'.
Likewise, the order is reversed upon reading.
<b>Example:</b> <b>Example:</b>
Write the MultiArray out_multi_array to file. Change the current directory to Write the MultiArray out_multi_array to file. Change the current directory to
"/group" and read in the same MultiArray as in_multi_array. "/group" and read in the same MultiArray as in_multi_array.
\code \code
HDF5File file("/path/to/file",HDF5File::New); HDF5File file("/path/to/file",HDF5File::New);
file.mkdir("group"); file.mkdir("group");
file.write("/group/dataset", out_multi_array); file.write("/group/dataset", out_multi_array);
file.cd("/group"); file.cd("/group");
file.read("dataset", in_multi_array); file.read("dataset", in_multi_array);
\endcode \endcode
<b>\#include</b> \<vigra/hdf5impex.hxx\><br> <b>\#include</b> \<vigra/hdf5impex.hxx\><br>
Namespace: vigra Namespace: vigra
*/ */
class HDF5File class HDF5File
{ {
private: protected:
HDF5Handle fileHandle_; HDF5Handle fileHandle_;
// current group handle // current group handle
HDF5Handle cGroupHandle_; HDF5Handle cGroupHandle_;
private:
// time tagging of datasets, turned off (= 0) by default. // time tagging of datasets, turned off (= 0) by default.
int track_time; int track_time;
// helper class for ls() // helper class for ls()
struct ls_closure struct ls_closure
{ {
virtual void insert(const std::string &) = 0; virtual void insert(const std::string &) = 0;
virtual ~ls_closure() {} virtual ~ls_closure() {}
}; };
// datastructure to hold a list of dataset and group names // datastructure to hold a list of dataset and group names
skipping to change at line 530 skipping to change at line 551
Container & objects; Container & objects;
ls_container_data(Container & o) : objects(o) {} ls_container_data(Container & o) : objects(o) {}
void insert(const std::string & x) void insert(const std::string & x)
{ {
objects.insert(std::string(x)); objects.insert(std::string(x));
} }
}; };
public: public:
// helper for callback HDF5_ls_inserter_callback(), used by ls() // helper for callback HDF5_ls_inserter_callback(), used by ls()
friend void HDF5_ls_insert(void*, const std::string &); friend void HDF5_ls_insert(void*, const std::string &);
/** \brief Set how a file is opened. /** \brief Set how a file is opened.
OpenMode::New creates a new file. If the file already exists, overwri
te it.
OpenMode::Open opens a file for reading/writing. The file will be cre OpenMode::New creates a new file. If the file already exists, o
ated, verwrite it.
if necessary.
*/ OpenMode::Open opens a file for reading/writing. The file will
be created,
if necessary.
*/
enum OpenMode { enum OpenMode {
New, // Create new empty file (existing file will be dele ted). New, // Create new empty file (existing file will be dele ted).
Open // Open file. Create if not existing. Open, // Open file. Create if not existing.
OpenReadOnly // Open file in read-only mode.
}; };
/** \brief Create an HDF5File object. /** \brief Default constructor.
A file can later be opened via the open() function.
Creates or opens HDF5 file at position filename. The current group is s If \a track_creation_times is non-zero, time tagging of datasets wi
et ll be enabled (it is disabled
to "/". by default).
*/ */
HDF5File(int track_creation_times = 0)
: track_time(track_creation_times)
{}
/** \brief Open or create an HDF5File object.
Creates or opens HDF5 file with given filename.
The current group is set to "/".
Note that the HDF5File class is not copyable (the copy constructor
is
private to enforce this).
*/
HDF5File(std::string filename, OpenMode mode, int track_creation_times = 0) HDF5File(std::string filename, OpenMode mode, int track_creation_times = 0)
: track_time(track_creation_times) : track_time(track_creation_times)
{ {
std::string errorMessage = "HDF5File: Could not create file '" + fi open(filename, mode);
lename + "'.";
fileHandle_ = HDF5Handle(createFile_(filename, mode), &H5Fclose, er
rorMessage.c_str());
cGroupHandle_ = HDF5Handle(openCreateGroup_("/"), &H5Gclose, "HDF5F
ile(): Failed to open root group.");
} }
/** \brief Destructor to make sure that all data is flushed before clos /** \brief The destructor flushes and closes the file.
ing the file. */
*/
~HDF5File() ~HDF5File()
{ {
//Write everything to disk before closing // The members fileHandle_ and cGroupHandle_ are automatically clos
H5Fflush(fileHandle_, H5F_SCOPE_GLOBAL); ed
// as they are of type HDF5Handle and are properly initialised.
// The closing of fileHandle_ implies flushing the file to
// the operating system, see
// http://www.hdfgroup.org/HDF5/doc/RM/RM_H5F.html#File-Close .
} }
/** \brief Change current group to "/". // copying is not permitted.
*/ private:
HDF5File(const HDF5File &);
void operator=(const HDF5File &);
public:
/** \brief Open or create the given file in the given mode and set
the group to "/".
If another file is currently open, it is first closed.
*/
void open(std::string filename, OpenMode mode)
{
close();
std::string errorMessage = "HDF5File.open(): Could not open or crea
te file '" + filename + "'.";
fileHandle_ = HDF5Handle(createFile_(filename, mode), &H5Fclose, er
rorMessage.c_str());
cGroupHandle_ = HDF5Handle(openCreateGroup_("/"), &H5Gclose, "HDF5F
ile.open(): Failed to open root group.");
}
/** \brief Close the current file.
*/
void close()
{
bool success = cGroupHandle_.close() >= 0 && fileHandle_.close() >=
0;
vigra_postcondition(success, "HDF5File.close() failed.");
}
/** \brief Change current group to "/".
*/
inline void root() inline void root()
{ {
std::string message = "HDF5File::root(): Could not open group '/'." ; std::string message = "HDF5File::root(): Could not open group '/'." ;
cGroupHandle_ = HDF5Handle(H5Gopen(fileHandle_, "/", H5P_DEFAULT),& H5Gclose,message.c_str()); cGroupHandle_ = HDF5Handle(H5Gopen(fileHandle_, "/", H5P_DEFAULT),& H5Gclose,message.c_str());
} }
/** \brief Change the current group. /** \brief Change the current group.
Both absolute and relative group names are allowed. Both absolute and relative group names are allowed.
*/ */
inline void cd(std::string groupName) inline void cd(std::string groupName)
{ {
std::string message = "HDF5File::cd(): Could not open group '" + gr oupName + "'.\n"; std::string message = "HDF5File::cd(): Could not open group '" + gr oupName + "'.\n";
// make groupName clean // make groupName clean
groupName = get_absolute_path(groupName); groupName = get_absolute_path(groupName);
if(groupName == "/"){ if(groupName == "/")
{
cGroupHandle_ = HDF5Handle(openCreateGroup_("/"),&H5Gclose,mess age.c_str()); cGroupHandle_ = HDF5Handle(openCreateGroup_("/"),&H5Gclose,mess age.c_str());
return;
} }
else{ else
if (H5Lexists(fileHandle_, groupName.c_str(), H5P_DEFAULT) == 0 {
) vigra_precondition(H5Lexists(fileHandle_, groupName.c_str(), H5
{ P_DEFAULT) != 0, message);
std::cerr << message;
return;
}
cGroupHandle_ = HDF5Handle(openCreateGroup_(groupName),&H5Gclos e,message.c_str()); cGroupHandle_ = HDF5Handle(openCreateGroup_(groupName),&H5Gclos e,message.c_str());
} }
} }
/** \brief Change the current group to its parent group. /** \brief Change the current group to its parent group.
returns true if successful, false otherwise. Returns true if successful, false otherwise. If unsuccessful,
*/ the group will not change.
*/
inline bool cd_up() inline bool cd_up()
{ {
std::string groupName = currentGroupName_(); std::string groupName = currentGroupName_();
//do not try to move up if we already in "/" //do not try to move up if we already in "/"
if(groupName == "/"){ if(groupName == "/"){
return false; return false;
} }
size_t lastSlash = groupName.find_last_of('/'); size_t lastSlash = groupName.find_last_of('/');
std::string parentGroup (groupName.begin(), groupName.begin()+lastS lash+1); std::string parentGroup (groupName.begin(), groupName.begin()+lastS lash+1);
cd(parentGroup); cd(parentGroup);
return true; return true;
} }
inline void cd_up(int levels)
/** \brief Change the current group to its parent group.
Returns true if successful, false otherwise. If unsuccessful,
the group will not change.
*/
inline bool cd_up(int levels)
{ {
std::string groupName = currentGroupName_();
for(int i = 0; i<levels; i++) for(int i = 0; i<levels; i++)
cd_up(); {
if(!cd_up())
{
// restore old group if neccessary
if(groupName != currentGroupName_())
cd(groupName);
return false;
}
}
return true;
} }
/** \brief Create a new group. /** \brief Create a new group.
If the first character is a "/", the path will be interpreted as abso If the first character is a "/", the path will be interpreted
lute path, as absolute path,
otherwise it will be interpreted as path relative to the current grou otherwise it will be interpreted as path relative to the curre
p. nt group.
*/ */
inline void mkdir(std::string groupName) inline void mkdir(std::string groupName)
{ {
std::string message = "HDF5File::mkdir(): Could not create group '"
+ groupName + "'.\n";
// make groupName clean // make groupName clean
groupName = get_absolute_path(groupName); groupName = get_absolute_path(groupName);
hid_t handle = openCreateGroup_(groupName.c_str()); HDF5Handle(openCreateGroup_(groupName.c_str()),&H5Gclose,message.c_
if (handle != cGroupHandle_){ str());
H5Gclose(handle);
}
} }
/** \brief Change the current group; create it if necessary. /** \brief Change the current group; create it if necessary.
If the first character is a "/", the path will be interpreted as abso If the first character is a "/", the path will be interpreted
lute path, as absolute path,
otherwise it will be interpreted as path relative to the current grou otherwise it will be interpreted as path relative to the curre
p. nt group.
*/ */
inline void cd_mk(std::string groupName) inline void cd_mk(std::string groupName)
{ {
std::string message = "HDF5File::cd_mk(): Could not create group '
" + groupName + "'.";
// make groupName clean // make groupName clean
groupName = get_absolute_path(groupName); groupName = get_absolute_path(groupName);
std::string message = "HDF5File::cd_mk(): Could not create group ' " + groupName + "'.";
cGroupHandle_ = HDF5Handle(openCreateGroup_(groupName.c_str()),&H5G close,message.c_str()); cGroupHandle_ = HDF5Handle(openCreateGroup_(groupName.c_str()),&H5G close,message.c_str());
} }
// helper function for the various ls() variants. // helper function for the various ls() variants.
void ls_H5Literate(ls_closure & data) void ls_H5Literate(ls_closure & data) const
{ {
H5Literate(cGroupHandle_, H5_INDEX_NAME, H5_ITER_NATIVE, NULL, H5Literate(cGroupHandle_, H5_INDEX_NAME, H5_ITER_NATIVE, NULL,
HDF5_ls_inserter_callback, static_cast<void*>(&data)); HDF5_ls_inserter_callback, static_cast<void*>(&data));
} }
/** \brief List the contents of the current group. /** \brief List the contents of the current group.
The function returns a vector of strings holding the entries of the The function returns a vector of strings holding the entries of
current group. Only datasets and groups are listed, other objects the
(e.g. datatypes) are ignored. Group names always have an ending "/". current group. Only datasets and groups are listed, other objec
*/ ts
/** (e.g. datatypes) are ignored. Group names always have a trailin
* g "/".
*/ */
inline std::vector<std::string> ls() inline std::vector<std::string> ls() const
{ {
std::vector<std::string> list; std::vector<std::string> list;
lsOpData data(list); lsOpData data(list);
ls_H5Literate(data); ls_H5Literate(data);
return list; return list;
} }
/** \brief List the contents of the current group into a container-like /** \brief List the contents of the current group into a container-
object via insert(). Only datasets and groups are inserted, like
other object via insert().
objects (e.g., datatypes) are ignored. Group names always ha
ve an Only datasets and groups are inserted, other objects (e.g., dat
ending "/". atypes) are ignored.
Group names always have a trailing "/".
The argument cont is presumably an associative container, however,
only its member function <tt>cont.insert(std::string)</tt> will be The argument cont is presumably an associative container, howev
called. er,
\param cont reference to a container supplying a member functi only its member function <tt>cont.insert(std::string)</tt> will
on be
<tt>insert(const i_type &)</tt>, where <tt>i_type< called.
/tt> \param cont reference to a container supplying a member fu
is convertible to <tt>std::string</tt>. nction
*/ <tt>insert(const i_type &)</tt>, where <tt>i_t
ype</tt>
is convertible to <tt>std::string</tt>.
*/
template<class Container> template<class Container>
void ls(Container & cont) void ls(Container & cont) const
{ {
ls_container_data<Container> data(cont); ls_container_data<Container> data(cont);
ls_H5Literate(data); ls_H5Literate(data);
} }
/** \brief Get the path of the current group. /** \brief Get the path of the current group.
*/ */
inline std::string pwd() inline std::string pwd() const
{ {
return currentGroupName_(); return currentGroupName_();
} }
/** \brief Get the name of the associated file. /** \brief Get the name of the associated file.
*/ */
inline std::string filename() inline std::string filename() const
{ {
return fileName_(); return fileName_();
} }
/** \brief Get the number of dimensions of a certain dataset /** \brief Get the number of dimensions of a certain dataset
If the first character is a "/", the path will be interpreted as abso If the first character is a "/", the path will be interpreted
lute path, as absolute path,
otherwise it will be interpreted as path relative to the current grou otherwise it will be interpreted as path relative to the curre
p. nt group.
*/ */
inline hssize_t getDatasetDimensions(std::string datasetName) inline hssize_t getDatasetDimensions(std::string datasetName)
{ {
// make datasetName clean // make datasetName clean
datasetName = get_absolute_path(datasetName); datasetName = get_absolute_path(datasetName);
//Open dataset and dataspace //Open dataset and dataspace
std::string errorMessage = "HDF5File::getDatasetDimensions(): Unabl e to open dataset '" + datasetName + "'."; std::string errorMessage = "HDF5File::getDatasetDimensions(): Unabl e to open dataset '" + datasetName + "'.";
HDF5Handle datasetHandle = HDF5Handle(getDatasetHandle_(datasetName ), &H5Dclose, errorMessage.c_str()); HDF5Handle datasetHandle = HDF5Handle(getDatasetHandle_(datasetName ), &H5Dclose, errorMessage.c_str());
errorMessage = "HDF5File::getDatasetDimensions(): Unable to access dataspace."; errorMessage = "HDF5File::getDatasetDimensions(): Unable to access dataspace.";
HDF5Handle dataspaceHandle(H5Dget_space(datasetHandle), &H5Sclose, errorMessage.c_str()); HDF5Handle dataspaceHandle(H5Dget_space(datasetHandle), &H5Sclose, errorMessage.c_str());
//return dimension information //return dimension information
return H5Sget_simple_extent_ndims(dataspaceHandle); return H5Sget_simple_extent_ndims(dataspaceHandle);
} }
/** \brief Get the shape of each dimension of a certain dataset. /** \brief Get the shape of each dimension of a certain dataset.
Normally, this function is called after determining the dimension of
the Normally, this function is called after determining the dimensio
dataset using \ref getDatasetDimensions(). n of the
If the first character is a "/", the path will be interpreted as abso dataset using \ref getDatasetDimensions().
lute path, If the first character is a "/", the path will be interpreted a
otherwise it will be interpreted as path relative to the current grou s absolute path,
p. otherwise it will be interpreted as path relative to the curren
*/ t group.
Note that the memory order between VIGRA and HDF5 files differs
: VIGRA uses
Fortran-order, while HDF5 uses C-order. This function therefore
reverses the axis
order relative to the file contents. That is, when the axes in
the file are
ordered as 'z', 'y', 'x', this function will return the shape i
n the order
'x', 'y', 'z'.
*/
inline ArrayVector<hsize_t> getDatasetShape(std::string datasetName) inline ArrayVector<hsize_t> getDatasetShape(std::string datasetName)
{ {
// make datasetName clean // make datasetName clean
datasetName = get_absolute_path(datasetName); datasetName = get_absolute_path(datasetName);
//Open dataset and dataspace //Open dataset and dataspace
std::string errorMessage = "HDF5File::getDatasetShape(): Unable to open dataset '" + datasetName + "'."; std::string errorMessage = "HDF5File::getDatasetShape(): Unable to open dataset '" + datasetName + "'.";
HDF5Handle datasetHandle = HDF5Handle(getDatasetHandle_(datasetName ), &H5Dclose, errorMessage.c_str()); HDF5Handle datasetHandle = HDF5Handle(getDatasetHandle_(datasetName ), &H5Dclose, errorMessage.c_str());
errorMessage = "HDF5File::getDatasetShape(): Unable to access datas pace."; errorMessage = "HDF5File::getDatasetShape(): Unable to access datas pace.";
HDF5Handle dataspaceHandle(H5Dget_space(datasetHandle), &H5Sclose, errorMessage.c_str()); HDF5Handle dataspaceHandle(H5Dget_space(datasetHandle), &H5Sclose, errorMessage.c_str());
//get dimension information //get dimension information
ArrayVector<hsize_t>::size_type dimensions = H5Sget_simple_extent_n dims(dataspaceHandle); ArrayVector<hsize_t>::size_type dimensions = H5Sget_simple_extent_n dims(dataspaceHandle);
ArrayVector<hsize_t> shape(dimensions); ArrayVector<hsize_t> shape(dimensions);
ArrayVector<hsize_t> maxdims(dimensions); ArrayVector<hsize_t> maxdims(dimensions);
H5Sget_simple_extent_dims(dataspaceHandle, shape.data(), maxdims.da ta()); H5Sget_simple_extent_dims(dataspaceHandle, shape.data(), maxdims.da ta());
// invert the dimensions to guarantee c-order // invert the dimensions to guarantee VIGRA-compatible order.
ArrayVector<hsize_t> shape_inv(dimensions); std::reverse(shape.begin(), shape.end());
for(ArrayVector<hsize_t>::size_type i=0; i<shape.size(); i++) { return shape;
shape_inv[i] = shape[dimensions-1-i];
}
return shape_inv;
} }
/** \brief Obtain the HDF5 handle of a dataset. /** \brief Obtain the HDF5 handle of a dataset.
*/ */
inline hid_t getDatasetHandle(std::string dataset_name) inline HDF5Handle getDatasetHandle(std::string dataset_name)
{ {
return getDatasetHandle_(dataset_name); std::string errorMessage = "HDF5File::getDatasetHandle(): Unable to
open dataset '" + dataset_name + "'.";
return HDF5Handle(getDatasetHandle_(dataset_name), &H5Dclose, error
Message.c_str());
} }
/** \brief Obtain the HDF5 handle of a group. /** \brief Obtain the HDF5 handle of a group.
*/ */
inline hid_t getGroupHandle(std::string group_name) inline HDF5Handle getGroupHandle(std::string group_name)
{ {
std::string errorMessage = "HDF5File::getGroupHandle(): Group '" +
group_name + "' not found.";
// make group_name clean // make group_name clean
group_name = get_absolute_path(group_name); group_name = get_absolute_path(group_name);
// group must exist // group must exist
vigra_precondition((H5Lexists(fileHandle_, group_name.c_str(), H5P_ vigra_precondition(H5Lexists(fileHandle_, group_name.c_str(), H5P_D
DEFAULT) == 1), "Error: Group '" + group_name + "' does not exist."); EFAULT) == 1,
errorMessage.c_str());
//open group and return group handle // open group and return group handle
return openCreateGroup_( group_name); return HDF5Handle(openCreateGroup_(group_name), &H5Gclose, "Interna
l error");
} }
/** \brief Obtain the HDF5 handle of a attribute. /** \brief Obtain the HDF5 handle of a attribute.
*/ */
inline hid_t getAttributeHandle(std::string dataset_name, std::string a inline HDF5Handle getAttributeHandle(std::string dataset_name, std::str
ttribute_name) ing attribute_name)
{ {
HDF5Handle dset (getDatasetHandle_(dataset_name),&H5Dclose,std::str std::string message = "HDF5File::getAttributeHandle(): Attribute '"
ing("Error: Dataset '"+dataset_name+"' not found.").c_str()); + attribute_name + "' not found.";
return HDF5Handle(H5Aopen(getDatasetHandle(dataset_name), attribute
return H5Aopen(dset, attribute_name.c_str(),H5P_DEFAULT); _name.c_str(), H5P_DEFAULT),
&H5Aclose, message.c_str());
} }
/* Writing Attributes */ /* Writing Attributes */
/** \brief Write MultiArray Attributes. /** \brief Write MultiArray Attributes.
* In contrast to datasets, subarray access, chunks and compression ar * In contrast to datasets, subarray access, chunks and compressio
e not available. n are not available.
*/ */
template<unsigned int N, class T> template<unsigned int N, class T>
inline void writeAttribute(std::string object_name, std::string attribu te_name, const MultiArrayView<N, T, UnstridedArrayTag> & array) inline void writeAttribute(std::string object_name, std::string attribu te_name, const MultiArrayView<N, T, UnstridedArrayTag> & array)
{ {
// make object_name clean // make object_name clean
object_name = get_absolute_path(object_name); object_name = get_absolute_path(object_name);
write_attribute_(object_name, attribute_name, array, detail::getH5D ataType<T>(), 1); write_attribute_(object_name, attribute_name, array, detail::getH5D ataType<T>(), 1);
} }
template<unsigned int N, class T, int SIZE> template<unsigned int N, class T, int SIZE>
skipping to change at line 823 skipping to change at line 907
template<unsigned int N, class T> template<unsigned int N, class T>
inline void writeAttribute(std::string datasetName, std::string attribu teName, const MultiArrayView<N, RGBValue<T>, UnstridedArrayTag> & array) inline void writeAttribute(std::string datasetName, std::string attribu teName, const MultiArrayView<N, RGBValue<T>, UnstridedArrayTag> & array)
{ {
// make datasetName clean // make datasetName clean
datasetName = get_absolute_path(datasetName); datasetName = get_absolute_path(datasetName);
write_attribute_(datasetName, attributeName, array, detail::getH5Da taType<T>(), 3); write_attribute_(datasetName, attributeName, array, detail::getH5Da taType<T>(), 3);
} }
/** \brief Write a single value. /** \brief Write a single value.
Specialization of the write function for simple datatypes Specialization of the write function for simple datatypes
*/ */
inline void writeAttribute(std::string object_name, std::string attribu te_name, char data) inline void writeAttribute(std::string object_name, std::string attribu te_name, char data)
{ writeAtomicAttribute(object_name,attribute_name,data); } { writeAtomicAttribute(object_name,attribute_name,data); }
inline void writeAttribute(std::string datasetName, std::string attribu teName, signed char data) inline void writeAttribute(std::string datasetName, std::string attribu teName, signed char data)
{ writeAtomicAttribute(datasetName,attributeName,data); } { writeAtomicAttribute(datasetName,attributeName,data); }
inline void writeAttribute(std::string datasetName, std::string attribu teName, signed short data) inline void writeAttribute(std::string datasetName, std::string attribu teName, signed short data)
{ writeAtomicAttribute(datasetName,attributeName,data); } { writeAtomicAttribute(datasetName,attributeName,data); }
inline void writeAttribute(std::string datasetName, std::string attribu teName, signed int data) inline void writeAttribute(std::string datasetName, std::string attribu teName, signed int data)
{ writeAtomicAttribute(datasetName,attributeName,data); } { writeAtomicAttribute(datasetName,attributeName,data); }
inline void writeAttribute(std::string datasetName, std::string attribu teName, signed long data) inline void writeAttribute(std::string datasetName, std::string attribu teName, signed long data)
{ writeAtomicAttribute(datasetName,attributeName,data); } { writeAtomicAttribute(datasetName,attributeName,data); }
skipping to change at line 859 skipping to change at line 943
{ writeAtomicAttribute(datasetName,attributeName,data); } { writeAtomicAttribute(datasetName,attributeName,data); }
inline void writeAttribute(std::string datasetName, std::string attribu teName, double data) inline void writeAttribute(std::string datasetName, std::string attribu teName, double data)
{ writeAtomicAttribute(datasetName,attributeName,data); } { writeAtomicAttribute(datasetName,attributeName,data); }
inline void writeAttribute(std::string datasetName, std::string attribu teName, long double data) inline void writeAttribute(std::string datasetName, std::string attribu teName, long double data)
{ writeAtomicAttribute(datasetName,attributeName,data); } { writeAtomicAttribute(datasetName,attributeName,data); }
inline void writeAttribute(std::string datasetName, std::string attribu teName, const char* data) inline void writeAttribute(std::string datasetName, std::string attribu teName, const char* data)
{ writeAtomicAttribute(datasetName,attributeName,data); } { writeAtomicAttribute(datasetName,attributeName,data); }
inline void writeAttribute(std::string datasetName, std::string attribu teName, std::string const & data) inline void writeAttribute(std::string datasetName, std::string attribu teName, std::string const & data)
{ writeAtomicAttribute(datasetName,attributeName,data.c_str()); } { writeAtomicAttribute(datasetName,attributeName,data.c_str()); }
/** \brief Test if attribute exists. /** \brief Test if attribute exists.
*/
*/
bool existsAttribute(std::string object_name, std::string attribute_nam e) bool existsAttribute(std::string object_name, std::string attribute_nam e)
{ {
std::string obj_path = get_absolute_path(object_name); std::string obj_path = get_absolute_path(object_name);
htri_t exists = H5Aexists_by_name(fileHandle_, obj_path.c_str(), htri_t exists = H5Aexists_by_name(fileHandle_, obj_path.c_str(),
attribute_name.c_str(), H5P_DEFAU LT); attribute_name.c_str(), H5P_DEFAU LT);
vigra_precondition(exists >= 0, "HDF5File::existsAttribute(): " vigra_precondition(exists >= 0, "HDF5File::existsAttribute(): "
"object \"" + object_name + "\" " "object '" + object_name + "' "
"not found."); "not found.");
return exists != 0; return exists != 0;
} }
// Reading Attributes // Reading Attributes
/** \brief Read MultiArray Attributes. /** \brief Read MultiArray Attributes.
* In contrast to datasets, subarray access is not available. * In contrast to datasets, subarray access is not available.
*/ */
template<unsigned int N, class T> template<unsigned int N, class T>
inline void readAttribute(std::string object_name, std::string attribut e_name, const MultiArrayView<N, T, UnstridedArrayTag> & array) inline void readAttribute(std::string object_name, std::string attribut e_name, const MultiArrayView<N, T, UnstridedArrayTag> & array)
{ {
// make object_name clean // make object_name clean
object_name = get_absolute_path(object_name); object_name = get_absolute_path(object_name);
read_attribute_(object_name, attribute_name, array, detail::getH5Da taType<T>(), 1); read_attribute_(object_name, attribute_name, array, detail::getH5Da taType<T>(), 1);
} }
template<unsigned int N, class T, int SIZE> template<unsigned int N, class T, int SIZE>
skipping to change at line 905 skipping to change at line 988
template<unsigned int N, class T> template<unsigned int N, class T>
inline void readAttribute(std::string datasetName, std::string attribut eName, const MultiArrayView<N, RGBValue<T>, UnstridedArrayTag> & array) inline void readAttribute(std::string datasetName, std::string attribut eName, const MultiArrayView<N, RGBValue<T>, UnstridedArrayTag> & array)
{ {
// make datasetName clean // make datasetName clean
datasetName = get_absolute_path(datasetName); datasetName = get_absolute_path(datasetName);
read_attribute_(datasetName, attributeName, array, detail::getH5Dat aType<T>(), 3); read_attribute_(datasetName, attributeName, array, detail::getH5Dat aType<T>(), 3);
} }
/** \brief Read a single value. /** \brief Read a single value.
Specialization of the read function for simple datatypes Specialization of the read function for simple datatypes
*/ */
inline void readAttribute(std::string object_name, std::string attribut e_name, char &data) inline void readAttribute(std::string object_name, std::string attribut e_name, char &data)
{ readAtomicAttribute(object_name,attribute_name,data); } { readAtomicAttribute(object_name,attribute_name,data); }
inline void readAttribute(std::string datasetName, std::string attribut eName, signed char &data) inline void readAttribute(std::string datasetName, std::string attribut eName, signed char &data)
{ readAtomicAttribute(datasetName,attributeName,data); } { readAtomicAttribute(datasetName,attributeName,data); }
inline void readAttribute(std::string datasetName, std::string attribut eName, signed short &data) inline void readAttribute(std::string datasetName, std::string attribut eName, signed short &data)
{ readAtomicAttribute(datasetName,attributeName,data); } { readAtomicAttribute(datasetName,attributeName,data); }
inline void readAttribute(std::string datasetName, std::string attribut eName, signed int &data) inline void readAttribute(std::string datasetName, std::string attribut eName, signed int &data)
{ readAtomicAttribute(datasetName,attributeName,data); } { readAtomicAttribute(datasetName,attributeName,data); }
inline void readAttribute(std::string datasetName, std::string attribut eName, signed long &data) inline void readAttribute(std::string datasetName, std::string attribut eName, signed long &data)
{ readAtomicAttribute(datasetName,attributeName,data); } { readAtomicAttribute(datasetName,attributeName,data); }
skipping to change at line 941 skipping to change at line 1024
{ readAtomicAttribute(datasetName,attributeName,data); } { readAtomicAttribute(datasetName,attributeName,data); }
inline void readAttribute(std::string datasetName, std::string attribut eName, double &data) inline void readAttribute(std::string datasetName, std::string attribut eName, double &data)
{ readAtomicAttribute(datasetName,attributeName,data); } { readAtomicAttribute(datasetName,attributeName,data); }
inline void readAttribute(std::string datasetName, std::string attribut eName, long double &data) inline void readAttribute(std::string datasetName, std::string attribut eName, long double &data)
{ readAtomicAttribute(datasetName,attributeName,data); } { readAtomicAttribute(datasetName,attributeName,data); }
inline void readAttribute(std::string datasetName, std::string attribut eName, std::string &data) inline void readAttribute(std::string datasetName, std::string attribut eName, std::string &data)
{ readAtomicAttribute(datasetName,attributeName,data); } { readAtomicAttribute(datasetName,attributeName,data); }
// Writing data // Writing data
/** \brief Write multi arrays. /** \brief Write multi arrays.
Chunks can be activated by setting
\code iChunkSize = size; //size \> 0
\endcode .
The chunks will be hypercubes with edge length size.
Compression can be activated by setting
\code compression = parameter; // 0 \< parameter \<= 9
\endcode
where 0 stands for no compression and 9 for maximum compression
.
If the first character of datasetName is a "/", the path will b
e interpreted as absolute path,
otherwise it will be interpreted as path relative to the curren
t group.
Chunks can be activated by setting Note that the memory order between VIGRA and HDF5 files differs
\code iChunkSize = size; //size \> 0 : VIGRA uses
\endcode . Fortran-order, while HDF5 uses C-order. This means that a VIGRA
The chunks will be hypercubes with edge length size. MultiArray,
whose indices represent the 'x'-, 'y'-, and 'z'-axis in that or
Compression can be activated by setting der, is reversed
\code compression = parameter; // 0 \< parameter \<= 9 upon writing to an HDF5 file, i.e. in the file the axis order i
\endcode s 'z', 'y', 'x'.
where 0 stands for no compression and 9 for maximum compression. */
If the first character of datasetName is a "/", the path will be inte
rpreted as absolute path,
otherwise it will be interpreted as path relative to the current grou
p.
*/
template<unsigned int N, class T> template<unsigned int N, class T>
inline void write(std::string datasetName, const MultiArrayView<N, T, U nstridedArrayTag> & array, int iChunkSize = 0, int compression = 0) inline void write(std::string datasetName, const MultiArrayView<N, T, U nstridedArrayTag> & array, int iChunkSize = 0, int compression = 0)
{ {
// make datasetName clean // make datasetName clean
datasetName = get_absolute_path(datasetName); datasetName = get_absolute_path(datasetName);
typename MultiArrayShape<N>::type chunkSize; typename MultiArrayShape<N>::type chunkSize;
for(int i = 0; i < N; i++){ for(unsigned int i = 0; i < N; i++){
chunkSize[i] = iChunkSize; chunkSize[i] = iChunkSize;
} }
write_(datasetName, array, detail::getH5DataType<T>(), 1, chunkSize , compression); write_(datasetName, array, detail::getH5DataType<T>(), 1, chunkSize , compression);
} }
/** \brief Write multi arrays. /** \brief Write multi arrays.
Chunks can be activated by providing a MultiArrayShape as chunkSize. Chunks can be activated by providing a MultiArrayShape as chunk
chunkSize must have equal dimension as array. Size.
chunkSize must have equal dimension as array.
Compression can be activated by setting
\code compression = parameter; // 0 \< parameter \<= 9 Compression can be activated by setting
\endcode \code compression = parameter; // 0 \< parameter \<= 9
where 0 stands for no compression and 9 for maximum compression. \endcode
where 0 stands for no compression and 9 for maximum compression
If the first character of datasetName is a "/", the path will be inte .
rpreted as absolute path,
otherwise it will be interpreted as path relative to the current grou If the first character of datasetName is a "/", the path will b
p. e interpreted as absolute path,
*/ otherwise it will be interpreted as path relative to the curren
t group.
Note that the memory order between VIGRA and HDF5 files differs
: VIGRA uses
Fortran-order, while HDF5 uses C-order. This means that a VIGRA
MultiArray,
whose indices represent the 'x'-, 'y'-, and 'z'-axis in that or
der, is reversed
upon writing to an HDF5 file, i.e. in the file the axis order i
s 'z', 'y', 'x'.
*/
template<unsigned int N, class T> template<unsigned int N, class T>
inline void write(std::string datasetName, const MultiArrayView<N, T, U nstridedArrayTag> & array, typename MultiArrayShape<N>::type chunkSize, int compression = 0) inline void write(std::string datasetName, const MultiArrayView<N, T, U nstridedArrayTag> & array, typename MultiArrayShape<N>::type chunkSize, int compression = 0)
{ {
// make datasetName clean // make datasetName clean
datasetName = get_absolute_path(datasetName); datasetName = get_absolute_path(datasetName);
write_(datasetName, array, detail::getH5DataType<T>(), 1, chunkSize , compression); write_(datasetName, array, detail::getH5DataType<T>(), 1, chunkSize , compression);
} }
/** \brief Write a multi array into a larger volume. /** \brief Write a multi array into a larger volume.
blockOffset determines the position, where array is written. blockOffset determines the position, where array is written.
Chunks can be activated by providing a MultiArrayShape as chunk
Size.
chunkSize must have equal dimension as array.
Compression can be activated by setting
\code compression = parameter; // 0 \< parameter \<= 9
\endcode
where 0 stands for no compression and 9 for maximum compression
.
Chunks can be activated by providing a MultiArrayShape as chunkSize. If the first character of datasetName is a "/", the path will b
chunkSize must have equal dimension as array. e interpreted as absolute path,
otherwise it will be interpreted as path relative to the curren
t group.
Compression can be activated by setting Note that the memory order between VIGRA and HDF5 files differs
\code compression = parameter; // 0 \< parameter \<= 9 : VIGRA uses
\endcode Fortran-order, while HDF5 uses C-order. This means that a VIGRA
where 0 stands for no compression and 9 for maximum compression. MultiArray,
whose indices represent the 'x'-, 'y'-, and 'z'-axis in that or
If the first character of datasetName is a "/", the path will be inte der, is reversed
rpreted as absolute path, upon writing to an HDF5 file, i.e. in the file the axis order i
otherwise it will be interpreted as path relative to the current grou s 'z', 'y', 'x'.
p. */
*/
template<unsigned int N, class T> template<unsigned int N, class T>
inline void writeBlock(std::string datasetName, typename MultiArrayShap e<N>::type blockOffset, const MultiArrayView<N, T, UnstridedArrayTag> & arr ay) inline void writeBlock(std::string datasetName, typename MultiArrayShap e<N>::type blockOffset, const MultiArrayView<N, T, UnstridedArrayTag> & arr ay)
{ {
// make datasetName clean // make datasetName clean
datasetName = get_absolute_path(datasetName); datasetName = get_absolute_path(datasetName);
writeBlock_(datasetName, blockOffset, array, detail::getH5DataType< T>(), 1); writeBlock_(datasetName, blockOffset, array, detail::getH5DataType< T>(), 1);
} }
// non-scalar (TinyVector) and unstrided multi arrays // non-scalar (TinyVector) and unstrided multi arrays
skipping to change at line 1036 skipping to change at line 1134
template<unsigned int N, class T, int SIZE> template<unsigned int N, class T, int SIZE>
inline void write(std::string datasetName, const MultiArrayView<N, Tiny Vector<T, SIZE>, UnstridedArrayTag> & array, typename MultiArrayShape<N>::t ype chunkSize, int compression = 0) inline void write(std::string datasetName, const MultiArrayView<N, Tiny Vector<T, SIZE>, UnstridedArrayTag> & array, typename MultiArrayShape<N>::t ype chunkSize, int compression = 0)
{ {
// make datasetName clean // make datasetName clean
datasetName = get_absolute_path(datasetName); datasetName = get_absolute_path(datasetName);
write_(datasetName, array, detail::getH5DataType<T>(), SIZE, chunkS ize, compression); write_(datasetName, array, detail::getH5DataType<T>(), SIZE, chunkS ize, compression);
} }
/** \brief Write array vectors. /** \brief Write array vectors.
Compression can be activated by setting
\code compression = parameter; // 0 \< parameter \<= 9
\endcode
where 0 stands for no compression and 9 for maximum compression
.
Compression can be activated by setting If the first character of datasetName is a "/", the path will b
\code compression = parameter; // 0 \< parameter \<= 9 e interpreted as absolute path,
\endcode otherwise it will be interpreted as path relative to the curren
where 0 stands for no compression and 9 for maximum compression. t group.
*/
If the first character of datasetName is a "/", the path will be inte
rpreted as absolute path,
otherwise it will be interpreted as path relative to the current grou
p.
*/
template<class T> template<class T>
void write(const std::string & datasetName, void write(const std::string & datasetName,
const ArrayVectorView<T> & array, const ArrayVectorView<T> & array,
int compression = 0) int compression = 0)
{ {
// convert to a (trivial) MultiArrayView and forward. // convert to a (trivial) MultiArrayView and forward.
MultiArrayShape<1>::type shape(array.size()); MultiArrayShape<1>::type shape(array.size());
const MultiArrayView<1, T> m_array(shape, const_cast<T*>(array.data ())); const MultiArrayView<1, T> m_array(shape, const_cast<T*>(array.data ()));
write(datasetName, m_array, compression); write(datasetName, m_array, compression);
} }
skipping to change at line 1098 skipping to change at line 1196
template<unsigned int N, class T> template<unsigned int N, class T>
inline void writeBlock(std::string datasetName, typename MultiArrayShap e<N>::type blockOffset, const MultiArrayView<N, RGBValue<T>, UnstridedArray Tag> & array) inline void writeBlock(std::string datasetName, typename MultiArrayShap e<N>::type blockOffset, const MultiArrayView<N, RGBValue<T>, UnstridedArray Tag> & array)
{ {
// make datasetName clean // make datasetName clean
datasetName = get_absolute_path(datasetName); datasetName = get_absolute_path(datasetName);
writeBlock_(datasetName, blockOffset, array, detail::getH5DataType< T>(), 3); writeBlock_(datasetName, blockOffset, array, detail::getH5DataType< T>(), 3);
} }
/** \brief Write a single value. /** \brief Write a single value.
Specialization of the write function for simple datatypes Specialization of the write function for simple datatypes
*/ */
inline void write(std::string datasetName, char data) { writeAtomic(dat asetName,data); } inline void write(std::string datasetName, char data) { writeAtomic(dat asetName,data); }
inline void write(std::string datasetName, signed char data) { writeAto mic(datasetName,data); } inline void write(std::string datasetName, signed char data) { writeAto mic(datasetName,data); }
inline void write(std::string datasetName, signed short data) { writeAt omic(datasetName,data); } inline void write(std::string datasetName, signed short data) { writeAt omic(datasetName,data); }
inline void write(std::string datasetName, signed int data) { writeAtom ic(datasetName,data); } inline void write(std::string datasetName, signed int data) { writeAtom ic(datasetName,data); }
inline void write(std::string datasetName, signed long data) { writeAto mic(datasetName,data); } inline void write(std::string datasetName, signed long data) { writeAto mic(datasetName,data); }
inline void write(std::string datasetName, signed long long data) { wri teAtomic(datasetName,data); } inline void write(std::string datasetName, signed long long data) { wri teAtomic(datasetName,data); }
inline void write(std::string datasetName, unsigned char data) { writeA tomic(datasetName,data); } inline void write(std::string datasetName, unsigned char data) { writeA tomic(datasetName,data); }
inline void write(std::string datasetName, unsigned short data) { write Atomic(datasetName,data); } inline void write(std::string datasetName, unsigned short data) { write Atomic(datasetName,data); }
inline void write(std::string datasetName, unsigned int data) { writeAt omic(datasetName,data); } inline void write(std::string datasetName, unsigned int data) { writeAt omic(datasetName,data); }
inline void write(std::string datasetName, unsigned long data) { writeA tomic(datasetName,data); } inline void write(std::string datasetName, unsigned long data) { writeA tomic(datasetName,data); }
inline void write(std::string datasetName, unsigned long long data) { w riteAtomic(datasetName,data); } inline void write(std::string datasetName, unsigned long long data) { w riteAtomic(datasetName,data); }
inline void write(std::string datasetName, float data) { writeAtomic(da tasetName,data); } inline void write(std::string datasetName, float data) { writeAtomic(da tasetName,data); }
inline void write(std::string datasetName, double data) { writeAtomic(d atasetName,data); } inline void write(std::string datasetName, double data) { writeAtomic(d atasetName,data); }
inline void write(std::string datasetName, long double data) { writeAto mic(datasetName,data); } inline void write(std::string datasetName, long double data) { writeAto mic(datasetName,data); }
inline void write(std::string datasetName, const char* data) { writeAto mic(datasetName,data); } inline void write(std::string datasetName, const char* data) { writeAto mic(datasetName,data); }
inline void write(std::string datasetName, std::string const & data) { writeAtomic(datasetName,data.c_str()); } inline void write(std::string datasetName, std::string const & data) { writeAtomic(datasetName,data.c_str()); }
// Reading data // Reading data
/** \brief Read data into a multi array. /** \brief Read data into a multi array.
If the first character of datasetName is a "/", the path will be inte If the first character of datasetName is a "/", the path will b
rpreted as absolute path, e interpreted as absolute path,
otherwise it will be interpreted as path relative to the current grou otherwise it will be interpreted as path relative to the curren
p. t group.
*/
Note that the memory order between VIGRA and HDF5 files differs
: VIGRA uses
Fortran-order, while HDF5 uses C-order. This means that a HDF5
dataset,
whose indices represent the 'z'-, 'y'-, and 'x'-axis in that or
der, is reversed
upon reading into a MultiArrayView, i.e. in the array axis orde
r must be 'x', 'y', 'z'.
*/
template<unsigned int N, class T> template<unsigned int N, class T>
inline void read(std::string datasetName, MultiArrayView<N, T, Unstride dArrayTag> & array) inline void read(std::string datasetName, MultiArrayView<N, T, Unstride dArrayTag> & array)
{ {
// make datasetName clean // make datasetName clean
datasetName = get_absolute_path(datasetName); datasetName = get_absolute_path(datasetName);
read_(datasetName, array, detail::getH5DataType<T>(), 1); read_(datasetName, array, detail::getH5DataType<T>(), 1);
} }
/** \brief Read data into a MultiArray. Resize MultiArray to the correc /** \brief Read data into a MultiArray. Resize MultiArray to the co
t size. rrect size.
If the first character of datasetName is a "/", the path will be inte If the first character of datasetName is a "/", the path will b
rpreted as absolute path, e interpreted as absolute path,
otherwise it will be interpreted as path relative to the current grou otherwise it will be interpreted as path relative to the curren
p. t group.
*/
Note that the memory order between VIGRA and HDF5 files differs
: VIGRA uses
Fortran-order, while HDF5 uses C-order. This means that a HDF5
dataset,
whose indices represent the 'z'-, 'y'-, and 'x'-axis in that or
der, is reversed
upon reading into a MultiArray, i.e. in the array axis order wi
ll be 'x', 'y', 'z'.
*/
template<unsigned int N, class T> template<unsigned int N, class T>
inline void readAndResize(std::string datasetName, MultiArray<N, T> & a rray) inline void readAndResize(std::string datasetName, MultiArray<N, T> & a rray)
{ {
// make datasetName clean // make datasetName clean
datasetName = get_absolute_path(datasetName); datasetName = get_absolute_path(datasetName);
// get dataset dimension // get dataset dimension
ArrayVector<hsize_t> dimshape = getDatasetShape(datasetName); ArrayVector<hsize_t> dimshape = getDatasetShape(datasetName);
hssize_t dimensions = getDatasetDimensions(datasetName);
// check if dimensions are correct // check if dimensions are correct
vigra_precondition((N == MultiArrayIndex(dimensions)), // the ob ject in the HDF5 file may have one additional dimension which we then inter pret as the pixel type bands vigra_precondition(N == MultiArrayIndex(dimshape.size()), // the ob ject in the HDF5 file may have one additional dimension which we then inter pret as the pixel type bands
"HDF5File::readAndResize(): Array dimension disagrees with data set dimension."); "HDF5File::readAndResize(): Array dimension disagrees with data set dimension.");
typename MultiArrayShape<N>::type shape;
for(int k=0; k< MultiArrayIndex(dimensions); ++k) {
shape[k] = MultiArrayIndex(dimshape[k]);
}
// reshape target MultiArray // reshape target MultiArray
typename MultiArrayShape<N>::type shape;
for(int k=0; k < (int)dimshape.size(); ++k)
shape[k] = (MultiArrayIndex)dimshape[k];
array.reshape(shape); array.reshape(shape);
read_(datasetName, array, detail::getH5DataType<T>(), 1); read_(datasetName, array, detail::getH5DataType<T>(), 1);
} }
/** \brief Read data into an array vector. /** \brief Read data into an array vector.
If the first character of datasetName is a "/", the path will be inte If the first character of datasetName is a "/", the path will be
rpreted as absolute path, interpreted as absolute path,
otherwise it will be interpreted as path relative to the current grou otherwise it will be interpreted as path relative to the current
p. group.
*/ */
template<class T> template<class T>
inline void read(const std::string & datasetName, ArrayVectorView<T> & array) inline void read(const std::string & datasetName, ArrayVectorView<T> & array)
{ {
// convert to a (trivial) MultiArrayView and forward. // convert to a (trivial) MultiArrayView and forward.
MultiArrayShape<1>::type shape(array.size()); MultiArrayShape<1>::type shape(array.size());
MultiArrayView<1, T> m_array(shape, (array.data())); MultiArrayView<1, T> m_array(shape, (array.data()));
read(datasetName, m_array); read(datasetName, m_array);
} }
/** \brief Read data into an array vector. Resize the array vector to t /** \brief Read data into an array vector. Resize the array vector
he correct size. to the correct size.
If the first character of datasetName is a "/", the path will be inte If the first character of datasetName is a "/", the path will b
rpreted as absolute path, e interpreted as absolute path,
otherwise it will be interpreted as path relative to the current grou otherwise it will be interpreted as path relative to the curren
p. t group.
*/ */
template<class T> template<class T>
inline void readAndResize(std::string datasetName, inline void readAndResize(std::string datasetName,
ArrayVector<T> & array) ArrayVector<T> & array)
{ {
// make dataset name clean // make dataset name clean
datasetName = get_absolute_path(datasetName); datasetName = get_absolute_path(datasetName);
// get dataset dimension // get dataset dimension
ArrayVector<hsize_t> dimshape = getDatasetShape(datasetName); ArrayVector<hsize_t> dimshape = getDatasetShape(datasetName);
hssize_t dimensions = getDatasetDimensions(datasetName);
// check if dimensions are correct // check if dimensions are correct
vigra_precondition((1 == MultiArrayIndex(dimensions)), vigra_precondition(1 == MultiArrayIndex(dimshape.size()),
"HDF5File::readAndResize(): Array dimension disagrees with Data set dimension must equal one for vigra::ArrayVector."); "HDF5File::readAndResize(): Array dimension disagrees with Data set dimension must equal one for vigra::ArrayVector.");
// resize target array vector // resize target array vector
array.resize((typename ArrayVector<T>::size_type)dimshape[0]); array.resize((typename ArrayVector<T>::size_type)dimshape[0]);
// convert to a (trivial) MultiArrayView and forward. // convert to a (trivial) MultiArrayView and forward.
MultiArrayShape<1>::type shape(array.size()); MultiArrayShape<1>::type shape(array.size());
MultiArrayView<1, T> m_array(shape, (array.data())); MultiArrayView<1, T> m_array(shape, (array.data()));
read_(datasetName, m_array, detail::getH5DataType<T>(), 1); read_(datasetName, m_array, detail::getH5DataType<T>(), 1);
} }
/** \brief Read a block of data into a multi array. /** \brief Read a block of data into a multi array.
This function allows to read a small block out of a larger volume sto This function allows to read a small block out of a larger volu
red me stored
in an HDF5 dataset. in an HDF5 dataset.
blockOffset determines the position of the block. blockOffset determines the position of the block.
blockSize determines the size in each dimension of the block. blockSize determines the size in each dimension of the block.
If the first character of datasetName is a "/", the path will be inte If the first character of datasetName is a "/", the path will b
rpreted as absolute path, e interpreted as absolute path,
otherwise it will be interpreted as path relative to the current grou otherwise it will be interpreted as path relative to the curren
p. t group.
*/
Note that the memory order between VIGRA and HDF5 files differs
: VIGRA uses
Fortran-order, while HDF5 uses C-order. This means that a HDF5
dataset,
whose indices represent the 'z'-, 'y'-, and 'x'-axis in that or
der, is reversed
upon reading into a MultiArray, i.e. in the array axis order wi
ll be 'x', 'y', 'z'.
*/
template<unsigned int N, class T> template<unsigned int N, class T>
inline void readBlock(std::string datasetName, typename MultiArrayShape <N>::type blockOffset, typename MultiArrayShape<N>::type blockShape, MultiA rrayView<N, T, UnstridedArrayTag> & array) inline void readBlock(std::string datasetName, typename MultiArrayShape <N>::type blockOffset, typename MultiArrayShape<N>::type blockShape, MultiA rrayView<N, T, UnstridedArrayTag> & array)
{ {
// make datasetName clean // make datasetName clean
datasetName = get_absolute_path(datasetName); datasetName = get_absolute_path(datasetName);
readBlock_(datasetName, blockOffset, blockShape, array, detail::get H5DataType<T>(), 1); readBlock_(datasetName, blockOffset, blockShape, array, detail::get H5DataType<T>(), 1);
} }
// non-scalar (TinyVector) and unstrided target MultiArrayView // non-scalar (TinyVector) and unstrided target MultiArrayView
skipping to change at line 1240 skipping to change at line 1350
// non-scalar (TinyVector) MultiArray // non-scalar (TinyVector) MultiArray
template<unsigned int N, class T, int SIZE> template<unsigned int N, class T, int SIZE>
inline void readAndResize(std::string datasetName, MultiArray<N, TinyVe ctor<T, SIZE> > & array) inline void readAndResize(std::string datasetName, MultiArray<N, TinyVe ctor<T, SIZE> > & array)
{ {
// make datasetName clean // make datasetName clean
datasetName = get_absolute_path(datasetName); datasetName = get_absolute_path(datasetName);
// get dataset dimension // get dataset dimension
ArrayVector<hsize_t> dimshape = getDatasetShape(datasetName); ArrayVector<hsize_t> dimshape = getDatasetShape(datasetName);
hssize_t dimensions = getDatasetDimensions(datasetName);
// check if dimensions are correct // check if dimensions are correct
vigra_precondition(((N+1) == MultiArrayIndex(dimensions)), // the vigra_precondition((N+1) == MultiArrayIndex(dimshape.size()) &&
object in the HDF5 file may have one additional dimension which we then int SIZE == dimshape[0], // the object in the HDF5 f
erpret as the pixel type bands ile must have one additional dimension which we interpret as the pixel type
bands
"HDF5File::readAndResize(): Array dimension disagrees with data set dimension."); "HDF5File::readAndResize(): Array dimension disagrees with data set dimension.");
typename MultiArrayShape<N>::type shape;
for(int k=1; k< MultiArrayIndex(dimensions); ++k) {
shape[k-1] = MultiArrayIndex(dimshape[k]);
}
// reshape target MultiArray // reshape target MultiArray
typename MultiArrayShape<N>::type shape;
for(int k=1; k < (int)dimshape.size(); ++k)
shape[k-1] = (MultiArrayIndex)dimshape[k];
array.reshape(shape); array.reshape(shape);
read_(datasetName, array, detail::getH5DataType<T>(), SIZE); read_(datasetName, array, detail::getH5DataType<T>(), SIZE);
} }
template<unsigned int N, class T, int SIZE> template<unsigned int N, class T, int SIZE>
inline void readBlock(std::string datasetName, typename MultiArrayShape <N>::type blockOffset, typename MultiArrayShape<N>::type blockShape, MultiA rrayView<N, TinyVector<T, SIZE>, UnstridedArrayTag> & array) inline void readBlock(std::string datasetName, typename MultiArrayShape <N>::type blockOffset, typename MultiArrayShape<N>::type blockShape, MultiA rrayView<N, TinyVector<T, SIZE>, UnstridedArrayTag> & array)
{ {
// make datasetName clean // make datasetName clean
datasetName = get_absolute_path(datasetName); datasetName = get_absolute_path(datasetName);
skipping to change at line 1285 skipping to change at line 1393
// non-scalar (RGBValue) MultiArray // non-scalar (RGBValue) MultiArray
template<unsigned int N, class T> template<unsigned int N, class T>
inline void readAndResize(std::string datasetName, MultiArray<N, RGBVal ue<T> > & array) inline void readAndResize(std::string datasetName, MultiArray<N, RGBVal ue<T> > & array)
{ {
// make datasetName clean // make datasetName clean
datasetName = get_absolute_path(datasetName); datasetName = get_absolute_path(datasetName);
// get dataset dimension // get dataset dimension
ArrayVector<hsize_t> dimshape = getDatasetShape(datasetName); ArrayVector<hsize_t> dimshape = getDatasetShape(datasetName);
hssize_t dimensions = getDatasetDimensions(datasetName);
// check if dimensions are correct // check if dimensions are correct
vigra_precondition(((N+1) == MultiArrayIndex(dimensions)), // the vigra_precondition((N+1) == MultiArrayIndex(dimshape.size()) &&
object in the HDF5 file may have one additional dimension which we then int 3 == dimshape[0], // the object in the HDF5 file
erpret as the pixel type bands must have one additional dimension which we interpret as the pixel type ba
nds
"HDF5File::readAndResize(): Array dimension disagrees with data set dimension."); "HDF5File::readAndResize(): Array dimension disagrees with data set dimension.");
typename MultiArrayShape<N>::type shape;
for(int k=1; k< MultiArrayIndex(dimensions); ++k) {
shape[k-1] = MultiArrayIndex(dimshape[k]);
}
// reshape target MultiArray // reshape target MultiArray
typename MultiArrayShape<N>::type shape;
for(int k=1; k < (int)dimshape.size(); ++k)
shape[k-1] = (MultiArrayIndex)dimshape[k];
array.reshape(shape); array.reshape(shape);
read_(datasetName, array, detail::getH5DataType<T>(), 3); read_(datasetName, array, detail::getH5DataType<T>(), 3);
} }
template<unsigned int N, class T> template<unsigned int N, class T>
inline void readBlock(std::string datasetName, typename MultiArrayShape <N>::type blockOffset, typename MultiArrayShape<N>::type blockShape, MultiA rrayView<N, RGBValue<T>, UnstridedArrayTag> & array) inline void readBlock(std::string datasetName, typename MultiArrayShape <N>::type blockOffset, typename MultiArrayShape<N>::type blockShape, MultiA rrayView<N, RGBValue<T>, UnstridedArrayTag> & array)
{ {
// make datasetName clean // make datasetName clean
datasetName = get_absolute_path(datasetName); datasetName = get_absolute_path(datasetName);
readBlock_(datasetName, blockOffset, blockShape, array, detail::get H5DataType<T>(), 3); readBlock_(datasetName, blockOffset, blockShape, array, detail::get H5DataType<T>(), 3);
} }
/** \brief Read a single value. /** \brief Read a single value.
Specialization of the read function for simple datatypes Specialization of the read function for simple datatypes
*/ */
inline void read(std::string datasetName, char &data) { readAtomic(data setName,data); } inline void read(std::string datasetName, char &data) { readAtomic(data setName,data); }
inline void read(std::string datasetName, signed char &data) { readAtom ic(datasetName,data); } inline void read(std::string datasetName, signed char &data) { readAtom ic(datasetName,data); }
inline void read(std::string datasetName, signed short &data) { readAto mic(datasetName,data); } inline void read(std::string datasetName, signed short &data) { readAto mic(datasetName,data); }
inline void read(std::string datasetName, signed int &data) { readAtomi c(datasetName,data); } inline void read(std::string datasetName, signed int &data) { readAtomi c(datasetName,data); }
inline void read(std::string datasetName, signed long &data) { readAtom ic(datasetName,data); } inline void read(std::string datasetName, signed long &data) { readAtom ic(datasetName,data); }
inline void read(std::string datasetName, signed long long &data) { rea dAtomic(datasetName,data); } inline void read(std::string datasetName, signed long long &data) { rea dAtomic(datasetName,data); }
inline void read(std::string datasetName, unsigned char &data) { readAt omic(datasetName,data); } inline void read(std::string datasetName, unsigned char &data) { readAt omic(datasetName,data); }
inline void read(std::string datasetName, unsigned short &data) { readA tomic(datasetName,data); } inline void read(std::string datasetName, unsigned short &data) { readA tomic(datasetName,data); }
inline void read(std::string datasetName, unsigned int &data) { readAto mic(datasetName,data); } inline void read(std::string datasetName, unsigned int &data) { readAto mic(datasetName,data); }
inline void read(std::string datasetName, unsigned long &data) { readAt omic(datasetName,data); } inline void read(std::string datasetName, unsigned long &data) { readAt omic(datasetName,data); }
inline void read(std::string datasetName, unsigned long long &data) { r eadAtomic(datasetName,data); } inline void read(std::string datasetName, unsigned long long &data) { r eadAtomic(datasetName,data); }
inline void read(std::string datasetName, float &data) { readAtomic(dat asetName,data); } inline void read(std::string datasetName, float &data) { readAtomic(dat asetName,data); }
inline void read(std::string datasetName, double &data) { readAtomic(da tasetName,data); } inline void read(std::string datasetName, double &data) { readAtomic(da tasetName,data); }
inline void read(std::string datasetName, long double &data) { readAtom ic(datasetName,data); } inline void read(std::string datasetName, long double &data) { readAtom ic(datasetName,data); }
inline void read(std::string datasetName, std::string &data) { readAtom ic(datasetName,data); } inline void read(std::string datasetName, std::string &data) { readAtom ic(datasetName,data); }
/** \brief Create a new dataset. /** \brief Create a new dataset.
This function can be used to create a dataset filled with a default v This function can be used to create a dataset filled with a def
alue, ault value,
for example before writing data into it using \ref writeBlock(). for example before writing data into it using \ref writeBlock()
Attention: only atomic datatypes are provided. For spectral data, add .
an Attention: only atomic datatypes are provided. For spectral dat
dimension (case RGB: add one dimension of size 3). a, add an
dimension (case RGB: add one dimension of size 3).
shape determines the dimension and the size of the dataset.
shape determines the dimension and the size of the dataset.
Chunks can be activated by providing a MultiArrayShape as chunkSize.
chunkSize must have equal dimension as array. Chunks can be activated by providing a MultiArrayShape as chunk
Size.
Compression can be activated by setting chunkSize must have equal dimension as array.
\code compression = parameter; // 0 \< parameter \<= 9
\endcode Compression can be activated by setting
where 0 stands for no compression and 9 for maximum compression. \code compression = parameter; // 0 \< parameter \<= 9
\endcode
If the first character of datasetName is a "/", the path will be inte where 0 stands for no compression and 9 for maximum compression
rpreted as absolute path, .
otherwise it will be interpreted as path relative to the current grou
p. If the first character of datasetName is a "/", the path will b
*/ e interpreted as absolute path,
otherwise it will be interpreted as path relative to the curren
t group.
Note that the memory order between VIGRA and HDF5 files differs
: VIGRA uses
Fortran-order, while HDF5 uses C-order. This means that a VIGRA
MultiArray,
whose indices represent the 'x'-, 'y'-, and 'z'-axis in that or
der, is reversed
upon writing to an HDF5 file, i.e. in the file the axis order i
s 'z', 'y', 'x'.
*/
template<unsigned int N, class T> template<unsigned int N, class T>
inline void createDataset(std::string datasetName, typename MultiArrayS inline void createDataset(std::string datasetName,
hape<N>::type shape, T init = T(), int iChunkSize = 0, int compressionParam typename MultiArrayShape<N>::type shape,
eter = 0) T init = T(),
int iChunkSize = 0,
int compressionParameter = 0)
{ {
// make datasetName clean // make datasetName clean
datasetName = get_absolute_path(datasetName); datasetName = get_absolute_path(datasetName);
typename MultiArrayShape<N>::type chunkSize; typename MultiArrayShape<N>::type chunkSize;
for(int i = 0; i < N; i++){ for(int i = 0; i < N; i++){
chunkSize[i] = iChunkSize; chunkSize[i] = iChunkSize;
} }
createDataset<N,T>(datasetName, shape, init, chunkSize, compression Parameter); createDataset<N,T>(datasetName, shape, init, chunkSize, compression Parameter);
} }
template<unsigned int N, class T> template<unsigned int N, class T>
inline void createDataset(std::string datasetName, typename MultiArrayS inline void createDataset(std::string datasetName,
hape<N>::type shape, T init, typename MultiArrayShape<N>::type chunkSize, i typename MultiArrayShape<N>::type shape,
nt compressionParameter = 0) T init,
typename MultiArrayShape<N>::type chunkSize,
int compressionParameter = 0)
{ {
// make datasetName clean // make datasetName clean
datasetName = get_absolute_path(datasetName); datasetName = get_absolute_path(datasetName);
std::string groupname = SplitString(datasetName).first(); std::string groupname = SplitString(datasetName).first();
std::string setname = SplitString(datasetName).last(); std::string setname = SplitString(datasetName).last();
hid_t parent = openCreateGroup_(groupname); hid_t parent = openCreateGroup_(groupname);
// delete the dataset if it already exists // delete the dataset if it already exists
skipping to change at line 1420 skipping to change at line 1539
H5Pset_deflate(plist, compressionParameter); H5Pset_deflate(plist, compressionParameter);
} }
//create the dataset. //create the dataset.
HDF5Handle datasetHandle ( H5Dcreate(parent, setname.c_str(), detai l::getH5DataType<T>(), dataspaceHandle, H5P_DEFAULT, plist, H5P_DEFAULT), HDF5Handle datasetHandle ( H5Dcreate(parent, setname.c_str(), detai l::getH5DataType<T>(), dataspaceHandle, H5P_DEFAULT, plist, H5P_DEFAULT),
&H5Dclose, "HDF5File::createDataset(): un able to create dataset."); &H5Dclose, "HDF5File::createDataset(): un able to create dataset.");
if(parent != cGroupHandle_) if(parent != cGroupHandle_)
H5Gclose(parent); H5Gclose(parent);
} }
/** \brief Immediately write all data to disk /** \brief Immediately write all data to disk
*/ */
inline void flushToDisk() inline void flushToDisk()
{ {
H5Fflush(fileHandle_, H5F_SCOPE_GLOBAL); H5Fflush(fileHandle_, H5F_SCOPE_GLOBAL);
} }
private: private:
/* Simple extension of std::string for splitting into two parts /* Simple extension of std::string for splitting into two parts
* *
* Strings (in particular: file/dataset paths) will be split into two * Strings (in particular: file/dataset paths) will be split into
* parts. The split is made at the last occurrence of the delimiter. two
* * parts. The split is made at the last occurrence of the delimite
* For example, "/path/to/some/file" will be split (delimiter = "/") i r.
nto *
* first() = "/path/to/some" and last() = "file". * For example, "/path/to/some/file" will be split (delimiter = "/
*/ ") into
* first() = "/path/to/some" and last() = "file".
*/
class SplitString: public std::string { class SplitString: public std::string {
public: public:
SplitString(std::string &sstring): std::string(sstring) {}; SplitString(std::string &sstring): std::string(sstring) {};
// return the part of the string before the delimiter // return the part of the string before the delimiter
std::string first(char delimiter = '/') std::string first(char delimiter = '/')
{ {
size_t last = find_last_of(delimiter); size_t last = find_last_of(delimiter);
if(last == std::string::npos) // delimiter not found --> no fir st if(last == std::string::npos) // delimiter not found --> no fir st
return ""; return "";
skipping to change at line 1463 skipping to change at line 1582
{ {
size_t last = find_last_of(delimiter); size_t last = find_last_of(delimiter);
if(last == std::string::npos) // delimiter not found --> only l ast if(last == std::string::npos) // delimiter not found --> only l ast
return std::string(*this); return std::string(*this);
return std::string(begin()+last+1, end()); return std::string(begin()+last+1, end());
} }
}; };
public: public:
/** \brief takes any path and converts it into an absolute path /** \brief takes any path and converts it into an absolute path
in the current file. in the current file.
Elements like "." and ".." are treated as expected. Elements like "." and ".." are treated as expected.
Links are not supported or resolved. Links are not supported or resolved.
*/ */
inline std::string get_absolute_path(std::string path) { inline std::string get_absolute_path(std::string path) const {
// check for empty input or "." and return the current folder // check for empty input or "." and return the current folder
if(path.length() == 0 || path == "."){ if(path.length() == 0 || path == "."){
return currentGroupName_(); return currentGroupName_();
} }
std::string str; std::string str;
// convert to absolute path // convert to absolute path
if(relativePath_(path)){ if(relativePath_(path)){
std::string cname = currentGroupName_(); std::string cname = currentGroupName_();
if (cname == "/") if (cname == "/")
skipping to change at line 1530 skipping to change at line 1649
// find second slash before ".." // find second slash before ".."
std::string::size_type begin = str.rfind("/",prev_slash-1); std::string::size_type begin = str.rfind("/",prev_slash-1);
// cut out part of the string // cut out part of the string
str = str.substr(0,begin+1) + str.substr(end,str.length()-end); str = str.substr(0,begin+1) + str.substr(end,str.length()-end);
} }
return str; return str;
} }
private: protected:
/* checks if the given path is a relative path. /* checks if the given path is a relative path.
*/ */
inline bool relativePath_(std::string & path) inline bool relativePath_(std::string & path) const
{ {
std::string::size_type pos = path.find('/') ; std::string::size_type pos = path.find('/') ;
if(pos == 0) if(pos == 0)
return false; return false;
return true; return true;
} }
/* return the name of the current group /* return the name of the current group
*/ */
inline std::string currentGroupName_() inline std::string currentGroupName_() const
{ {
int len = H5Iget_name(cGroupHandle_,NULL,1000); int len = H5Iget_name(cGroupHandle_,NULL,1000);
ArrayVector<char> name (len+1,0); ArrayVector<char> name (len+1,0);
H5Iget_name(cGroupHandle_,name.begin(),len+1); H5Iget_name(cGroupHandle_,name.begin(),len+1);
return std::string(name.begin()); return std::string(name.begin());
} }
/* return the name of the current file /* return the name of the current file
*/ */
inline std::string fileName_() inline std::string fileName_() const
{ {
int len = H5Fget_name(fileHandle_,NULL,1000); int len = H5Fget_name(fileHandle_,NULL,1000);
ArrayVector<char> name (len+1,0); ArrayVector<char> name (len+1,0);
H5Fget_name(fileHandle_,name.begin(),len+1); H5Fget_name(fileHandle_,name.begin(),len+1);
return std::string(name.begin()); return std::string(name.begin());
} }
/* create an empty file and open is /* create an empty file and open is
*/ */
inline hid_t createFile_(std::string filePath, OpenMode mode = Open) inline hid_t createFile_(std::string filePath, OpenMode mode = Open)
{ {
// try to open file // try to open file
FILE * pFile; FILE * pFile;
pFile = fopen ( filePath.c_str(), "r" ); pFile = fopen ( filePath.c_str(), "r" );
hid_t fileId; hid_t fileId;
// check if opening was successful (= file exists) // check if opening was successful (= file exists)
if ( pFile == NULL ) if ( pFile == NULL )
{ {
fileId = H5Fcreate(filePath.c_str(), H5F_ACC_TRUNC, H5P_DEFAULT , H5P_DEFAULT); fileId = H5Fcreate(filePath.c_str(), H5F_ACC_TRUNC, H5P_DEFAULT , H5P_DEFAULT);
} }
else if(mode == Open) else if(mode == Open)
{ {
fclose( pFile ); fclose( pFile );
fileId = H5Fopen(filePath.c_str(), H5F_ACC_RDWR, H5P_DEFAULT); fileId = H5Fopen(filePath.c_str(), H5F_ACC_RDWR, H5P_DEFAULT);
} }
else if(mode == OpenReadOnly) {
fclose( pFile );
fileId = H5Fopen(filePath.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT)
;
}
else else
{ {
fclose(pFile); fclose(pFile);
std::remove(filePath.c_str()); std::remove(filePath.c_str());
fileId = H5Fcreate(filePath.c_str(), H5F_ACC_TRUNC, H5P_DEFAULT , H5P_DEFAULT); fileId = H5Fcreate(filePath.c_str(), H5F_ACC_TRUNC, H5P_DEFAULT , H5P_DEFAULT);
} }
return fileId; return fileId;
} }
/* open a group and subgroups. Create if necessary. /* open a group and subgroups. Create if necessary.
*/ */
inline hid_t openCreateGroup_(std::string groupName) inline hid_t openCreateGroup_(std::string groupName)
{ {
// make groupName clean // make groupName clean
groupName = get_absolute_path(groupName); groupName = get_absolute_path(groupName);
// open root group // open root group
hid_t parent = H5Gopen(fileHandle_, "/", H5P_DEFAULT); hid_t parent = H5Gopen(fileHandle_, "/", H5P_DEFAULT);
if(groupName == "/") if(groupName == "/")
{ {
return parent; return parent;
skipping to change at line 1616 skipping to change at line 1739
// remove leading / // remove leading /
groupName = std::string(groupName.begin()+1, groupName.end()); groupName = std::string(groupName.begin()+1, groupName.end());
// check if the groupName has finishing slash // check if the groupName has finishing slash
if( groupName.size() != 0 && *groupName.rbegin() != '/') if( groupName.size() != 0 && *groupName.rbegin() != '/')
{ {
groupName = groupName + '/'; groupName = groupName + '/';
} }
//open or create subgroups one by one // open or create subgroups one by one
std::string::size_type begin = 0, end = groupName.find('/'); std::string::size_type begin = 0, end = groupName.find('/');
int ii = 0;
while (end != std::string::npos) while (end != std::string::npos)
{ {
std::string group(groupName.begin()+begin, groupName.begin()+en d); std::string group(groupName.begin()+begin, groupName.begin()+en d);
hid_t prevParent = parent; hid_t prevParent = parent;
if(H5LTfind_dataset(parent, group.c_str()) == 0) if(H5LTfind_dataset(parent, group.c_str()) == 0)
{ {
parent = H5Gcreate(prevParent, group.c_str(), H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); parent = H5Gcreate(prevParent, group.c_str(), H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
} else { } else {
parent = H5Gopen(prevParent, group.c_str(), H5P_DEFAULT); parent = H5Gopen(prevParent, group.c_str(), H5P_DEFAULT);
} }
H5Gclose(prevParent);
if(ii != 0)
{
H5Gclose(prevParent);
}
if(parent < 0) if(parent < 0)
{ {
return parent; return parent;
} }
++ii;
begin = end + 1; begin = end + 1;
end = groupName.find('/', begin); end = groupName.find('/', begin);
} }
return parent; return parent;
} }
/* delete a dataset by unlinking it from the file structure. This does /* delete a dataset by unlinking it from the file structure. This d
not oes not
delete the data! delete the data!
*/ */
inline void deleteDataset_(hid_t parent, std::string datasetName) inline void deleteDataset_(hid_t parent, std::string datasetName)
{ {
// delete existing data and create new dataset // delete existing data and create new dataset
if(H5LTfind_dataset(parent, datasetName.c_str())) if(H5LTfind_dataset(parent, datasetName.c_str()))
{ {
#if (H5_VERS_MAJOR == 1 && H5_VERS_MINOR <= 6) #if (H5_VERS_MAJOR == 1 && H5_VERS_MINOR <= 6)
if(H5Gunlink(parent, datasetName.c_str()) < 0) if(H5Gunlink(parent, datasetName.c_str()) < 0)
{ {
vigra_postcondition(false, "HDF5File::deleteDataset_(): Una ble to delete existing data."); vigra_postcondition(false, "HDF5File::deleteDataset_(): Una ble to delete existing data.");
} }
#else #else
if(H5Ldelete(parent, datasetName.c_str(), H5P_DEFAULT ) < 0) if(H5Ldelete(parent, datasetName.c_str(), H5P_DEFAULT ) < 0)
{ {
vigra_postcondition(false, "HDF5File::deleteDataset_(): Una ble to delete existing data."); vigra_postcondition(false, "HDF5File::deleteDataset_(): Una ble to delete existing data.");
} }
#endif #endif
} }
} }
/* get the handle of a dataset specified by a string /* get the handle of a dataset specified by a string
*/ */
inline hid_t getDatasetHandle_(std::string datasetName) inline hid_t getDatasetHandle_(std::string datasetName)
{ {
// make datasetName clean // make datasetName clean
datasetName = get_absolute_path(datasetName); datasetName = get_absolute_path(datasetName);
std::string groupname = SplitString(datasetName).first(); std::string groupname = SplitString(datasetName).first();
std::string setname = SplitString(datasetName).last(); std::string setname = SplitString(datasetName).last();
if (H5Lexists(fileHandle_, datasetName.c_str(), H5P_DEFAULT) <= 0) if(H5Lexists(fileHandle_, datasetName.c_str(), H5P_DEFAULT) <= 0)
{ {
std::cerr << "HDF5File::getDatasetHandle_(): Dataset '" << data setName << "' does not exist.\n"; std::cerr << "HDF5File::getDatasetHandle_(): Dataset '" << data setName << "' does not exist.\n";
return -1; return -1;
} }
//Open parent group // Open parent group
hid_t groupHandle = openCreateGroup_(groupname); HDF5Handle groupHandle(openCreateGroup_(groupname), &H5Gclose, "Int
ernal error");
hid_t datasetHandle = H5Dopen(groupHandle, setname.c_str(), H5P_DEF
AULT);
if(groupHandle != cGroupHandle_)
{
H5Gclose(groupHandle);
}
//return dataset handle
return datasetHandle;
return H5Dopen(groupHandle, setname.c_str(), H5P_DEFAULT);
} }
/* get the type of an object specified by a string /* get the type of an object specified by a string
*/ */
H5O_type_t get_object_type_(std::string name) H5O_type_t get_object_type_(std::string name)
{ {
name = get_absolute_path(name); name = get_absolute_path(name);
std::string group_name = SplitString(name).first(); std::string group_name = SplitString(name).first();
std::string object_name = SplitString(name).last(); std::string object_name = SplitString(name).last();
if (!object_name.size()) if (!object_name.size())
return H5O_TYPE_GROUP; return H5O_TYPE_GROUP;
htri_t exists = H5Lexists(fileHandle_, name.c_str(), H5P_DEFAULT); htri_t exists = H5Lexists(fileHandle_, name.c_str(), H5P_DEFAULT);
vigra_precondition(exists > 0, "HDF5File::get_object_type_(): " vigra_precondition(exists > 0, "HDF5File::get_object_type_(): "
"object \"" + name + "\" " "object \"" + name + "\" "
"not found."); "not found.");
// open parent group // open parent group
hid_t group_handle = openCreateGroup_(group_name); HDF5Handle group_handle(openCreateGroup_(group_name), &H5Gclose, "I
H5O_type_t h5_type = HDF5_get_type(group_handle, name.c_str()); nternal error");
if (group_handle != cGroupHandle_) return HDF5_get_type(group_handle, name.c_str());
{
H5Gclose(group_handle);
}
return h5_type;
} }
/* low-level write function to write vigra MultiArray data as an attrib /* low-level write function to write vigra MultiArray data as an at
ute tribute
*/ */
template<unsigned int N, class T> template<unsigned int N, class T>
void write_attribute_(std::string name, const std::string & attribute_n ame, void write_attribute_(std::string name, const std::string & attribute_n ame,
const MultiArrayView<N, T, UnstridedArrayTag> & a rray, const MultiArrayView<N, T, UnstridedArrayTag> & a rray,
const hid_t datatype, const int numBandsOfType) const hid_t datatype,
const int numBandsOfType)
{ {
// shape of the array. Add one dimension, if array contains non-sca lars. // shape of the array. Add one dimension, if array contains non-sca lars.
ArrayVector<hsize_t> shape(N + (numBandsOfType > 1),0); ArrayVector<hsize_t> shape(array.shape().begin(), array.shape().end
for(unsigned int i = 0; i < N; i++){ ());
shape[N-1-i] = array.shape(i); // reverse order std::reverse(shape.begin(), shape.end());
}
if(numBandsOfType > 1) if(numBandsOfType > 1)
shape[N] = numBandsOfType; shape.push_back(numBandsOfType);
HDF5Handle dataspace(H5Screate_simple(N + (numBandsOfType > 1), HDF5Handle dataspace(H5Screate_simple(shape.size(),
shape.begin(), NULL), shape.begin(), NULL),
&H5Sclose, "HDF5File::writeAttribute(): Can no t" &H5Sclose, "HDF5File::writeAttribute(): Can no t"
" create dataspace."); " create dataspace.");
std::string errorMessage ("HDF5File::writeAttribute(): can not find " std::string errorMessage ("HDF5File::writeAttribute(): can not find "
"object '" + name + "'."); "object '" + name + "'.");
H5O_type_t h5_type = get_object_type_(name); H5O_type_t h5_type = get_object_type_(name);
bool is_group = h5_type == H5O_TYPE_GROUP; bool is_group = h5_type == H5O_TYPE_GROUP;
if (!is_group && h5_type != H5O_TYPE_DATASET) if (!is_group && h5_type != H5O_TYPE_DATASET)
skipping to change at line 1782 skipping to change at line 1883
dataspace, H5P_DEFAULT, dataspace, H5P_DEFAULT,
H5P_DEFAULT), H5P_DEFAULT),
&H5Aclose, &H5Aclose,
"HDF5File::writeAttribute(): Can not cre ate" "HDF5File::writeAttribute(): Can not cre ate"
" attribute."); " attribute.");
// Write the data to the HDF5 object // Write the data to the HDF5 object
H5Awrite(attributeHandle, datatype, array.data()); H5Awrite(attributeHandle, datatype, array.data());
} }
/* Write single value attribute /* Write single value attribute
This function allows to write data of atomic datatypes (int, long, do This function allows to write data of atomic datatypes (int, lon
uble) g, double)
as an attribute in the HDF5 file. So it is not necessary to create a as an attribute in the HDF5 file. So it is not necessary to crea
MultiArray te a MultiArray
of size 1 to write a single number. of size 1 to write a single number.
*/ */
template<class T> template<class T>
inline void writeAtomicAttribute(std::string datasetName, std::string a ttributeName, const T data) inline void writeAtomicAttribute(std::string datasetName, std::string a ttributeName, const T data)
{ {
// make datasetName clean // make datasetName clean
datasetName = get_absolute_path(datasetName); datasetName = get_absolute_path(datasetName);
typename MultiArrayShape<1>::type chunkSize; typename MultiArrayShape<1>::type chunkSize;
chunkSize[0] = 0; chunkSize[0] = 0;
MultiArray<1,T> array(MultiArrayShape<1>::type(1)); MultiArray<1,T> array(MultiArrayShape<1>::type(1));
array[0] = data; array[0] = data;
write_attribute_(datasetName, attributeName, array, detail::getH5Da taType<T>(), 1); write_attribute_(datasetName, attributeName, array, detail::getH5Da taType<T>(), 1);
} }
/* low-level read function to write vigra MultiArray data from attribut /* low-level read function to write vigra MultiArray data from attr
es ibutes
*/ */
template<unsigned int N, class T> template<unsigned int N, class T>
inline void read_attribute_(std::string datasetName, std::string attrib uteName, MultiArrayView<N, T, UnstridedArrayTag> array, const hid_t datatyp e, const int numBandsOfType) inline void read_attribute_(std::string datasetName, std::string attrib uteName, MultiArrayView<N, T, UnstridedArrayTag> array, const hid_t datatyp e, const int numBandsOfType)
{ {
std::string dataset_path = get_absolute_path(datasetName); std::string dataset_path = get_absolute_path(datasetName);
// open Attribute handle // open Attribute handle
std::string message = "Error: could not get handle for attribute '" +attributeName+"'' of object '"+dataset_path+"'."; std::string message = "Error: could not get handle for attribute '" +attributeName+"'' of object '"+dataset_path+"'.";
HDF5Handle attr_handle (H5Aopen_by_name(fileHandle_,dataset_path.c_ str(),attributeName.c_str(),H5P_DEFAULT,H5P_DEFAULT),&H5Aclose, message.c_s tr()); HDF5Handle attr_handle (H5Aopen_by_name(fileHandle_,dataset_path.c_ str(),attributeName.c_str(),H5P_DEFAULT,H5P_DEFAULT),&H5Aclose, message.c_s tr());
// get Attribute dataspace // get Attribute dataspace
message = "Error: could not get dataspace for attribute '"+attribut eName+"'' of object '"+dataset_path+"'."; message = "Error: could not get dataspace for attribute '"+attribut eName+"'' of object '"+dataset_path+"'.";
HDF5Handle attr_dataspace_handle (H5Aget_space(attr_handle),&H5Sclo se,message.c_str()); HDF5Handle attr_dataspace_handle (H5Aget_space(attr_handle),&H5Sclo se,message.c_str());
// obtain Attribute shape // obtain Attribute shape
int dims = H5Sget_simple_extent_ndims(attr_dataspace_handle); int dims = H5Sget_simple_extent_ndims(attr_dataspace_handle);
ArrayVector<hsize_t> shape_inv(dims);
H5Sget_simple_extent_dims(attr_dataspace_handle, shape_inv.data(),
NULL);
// invert the dimensions to guarantee c-order
ArrayVector<hsize_t> dimshape(dims); ArrayVector<hsize_t> dimshape(dims);
for(ArrayVector<hsize_t>::size_type i=0; i<shape_inv.size(); i++) { H5Sget_simple_extent_dims(attr_dataspace_handle, dimshape.data(), N
dimshape[i] = shape_inv[dims-1-i]; ULL);
}
int offset = (numBandsOfType > 1); // invert the dimensions to guarantee VIGRA-compatible order
std::reverse(dimshape.begin(), dimshape.end());
int offset = (numBandsOfType > 1)
? 1
: 0;
message = "Error: Array dimension disagrees with dataset dimension. "; message = "Error: Array dimension disagrees with dataset dimension. ";
// the object in the HDF5 file may have one additional dimension wh ich we then interpret as the pixel type bands // the object in the HDF5 file may have one additional dimension wh ich we then interpret as the pixel type bands
vigra_precondition( ( (N + offset ) == MultiArrayIndex(dims)), mes sage); vigra_precondition((N + offset) == MultiArrayIndex(dims), message);
typename MultiArrayShape<N>::type shape; typename MultiArrayShape<N>::type shape;
for(int k=offset; k< MultiArrayIndex(dims); ++k) { for(int k=offset; k < (int)dimshape.size(); ++k)
shape[k-offset] = MultiArrayIndex(dimshape[k]); shape[k-offset] = (MultiArrayIndex)dimshape[k];
}
message = "Error: Array shape disagrees with dataset shape"; message = "Error: Array shape disagrees with dataset shape";
vigra_precondition(shape == array.shape(),message); vigra_precondition(shape == array.shape(), message);
// simply read in the data as is // simply read in the data as is
H5Aread( attr_handle, datatype, array.data()); H5Aread( attr_handle, datatype, array.data());
} }
/* Read a single value attribute. /* Read a single value attribute.
This functions allows to read a single value attribute of atomic data This functions allows to read a single value attribute of atomic
type (int, long, double) datatype (int, long, double)
from the HDF5 file. So it is not necessary to create a MultiArray from the HDF5 file. So it is not necessary to create a MultiArra
of size 1 to read a single number. y
*/ of size 1 to read a single number.
*/
template<class T> template<class T>
inline void readAtomicAttribute(std::string datasetName, std::string at tributeName, T & data) inline void readAtomicAttribute(std::string datasetName, std::string at tributeName, T & data)
{ {
// make datasetName clean // make datasetName clean
datasetName = get_absolute_path(datasetName); datasetName = get_absolute_path(datasetName);
MultiArray<1,T> array(MultiArrayShape<1>::type(1)); MultiArray<1,T> array(MultiArrayShape<1>::type(1));
read_attribute_(datasetName, attributeName, array, detail::getH5Dat aType<T>(), 1); read_attribute_(datasetName, attributeName, array, detail::getH5Dat aType<T>(), 1);
data = array[0]; data = array[0];
} }
skipping to change at line 1868 skipping to change at line 1967
inline void readAtomicAttribute(std::string datasetName, std::string at tributeName, std::string & data) inline void readAtomicAttribute(std::string datasetName, std::string at tributeName, std::string & data)
{ {
// make datasetName clean // make datasetName clean
datasetName = get_absolute_path(datasetName); datasetName = get_absolute_path(datasetName);
MultiArray<1,const char *> array(MultiArrayShape<1>::type(1)); MultiArray<1,const char *> array(MultiArrayShape<1>::type(1));
read_attribute_(datasetName, attributeName, array, detail::getH5Dat aType<const char *>(), 1); read_attribute_(datasetName, attributeName, array, detail::getH5Dat aType<const char *>(), 1);
data = std::string(array[0]); data = std::string(array[0]);
} }
/* low-level write function to write vigra unstrided MultiArray data /* low-level write function to write vigra unstrided MultiArray dat
*/ a
*/
template<unsigned int N, class T> template<unsigned int N, class T>
inline void write_(std::string &datasetName, const MultiArrayView<N, T, inline void write_(std::string &datasetName,
UnstridedArrayTag> & array, const hid_t datatype, const int numBandsOfType const MultiArrayView<N, T, UnstridedArrayTag> & arra
, typename MultiArrayShape<N>::type &chunkSize, int compressionParameter = y,
0) const hid_t datatype,
const int numBandsOfType,
typename MultiArrayShape<N>::type &chunkSize,
int compressionParameter = 0)
{ {
std::string groupname = SplitString(datasetName).first(); std::string groupname = SplitString(datasetName).first();
std::string setname = SplitString(datasetName).last(); std::string setname = SplitString(datasetName).last();
// shape of the array. Add one dimension, if array contains non-sca lars. // shape of the array. Add one dimension, if array contains non-sca lars.
ArrayVector<hsize_t> shape(N + (numBandsOfType > 1),0); ArrayVector<hsize_t> shape(array.shape().begin(), array.shape().end
for(unsigned int i = 0; i < N; i++){ ());
shape[N-1-i] = array.shape(i); // reverse order std::reverse(shape.begin(), shape.end());
}
if(numBandsOfType > 1) if(numBandsOfType > 1)
shape[N] = numBandsOfType; shape.push_back(numBandsOfType);
HDF5Handle dataspace ( H5Screate_simple(N + (numBandsOfType > 1), s HDF5Handle dataspace(H5Screate_simple(shape.size(), shape.begin(),
hape.begin(), NULL), &H5Sclose, "HDF5File::write(): Can not create dataspac NULL), &H5Sclose,
e."); "HDF5File::write(): Can not create dataspace."
);
// create and open group: // create and open group:
std::string errorMessage ("HDF5File::write(): can not create group '" + groupname + "'."); std::string errorMessage ("HDF5File::write(): can not create group '" + groupname + "'.");
hid_t groupHandle = openCreateGroup_(groupname); HDF5Handle groupHandle(openCreateGroup_(groupname), &H5Gclose, erro
if(groupHandle <= 0) rMessage.c_str());
{
std::cerr << errorMessage << "\n";
}
// delete dataset, if it already exists // delete dataset, if it already exists
deleteDataset_(groupHandle, setname.c_str()); deleteDataset_(groupHandle, setname.c_str());
// set up properties list // set up properties list
HDF5Handle plist ( H5Pcreate(H5P_DATASET_CREATE), &H5Pclose, "HDF5F HDF5Handle plist(H5Pcreate(H5P_DATASET_CREATE), &H5Pclose,
ile::write(): unable to create property list." ); "HDF5File::write(): unable to create property list
." );
// turn off time tagging of datasets by default. // turn off time tagging of datasets by default.
H5Pset_obj_track_times(plist, track_time); H5Pset_obj_track_times(plist, track_time);
// enable chunks // enable chunks
if(chunkSize[0] > 0) if(chunkSize[0] > 0)
{ {
ArrayVector<hsize_t> cSize(N + (numBandsOfType > 1),0); ArrayVector<hsize_t> cSize(chunkSize.begin(), chunkSize.end());
for(unsigned int i = 0; i<N; i++) std::reverse(cSize.begin(), cSize.end());
{
cSize[i] = chunkSize[N-1-i];
}
if(numBandsOfType > 1) if(numBandsOfType > 1)
cSize[N] = numBandsOfType; cSize.push_back(numBandsOfType);
H5Pset_chunk (plist, N + (numBandsOfType > 1), cSize.begin()); H5Pset_chunk (plist, cSize.size(), cSize.begin());
} }
// enable compression // enable compression
if(compressionParameter > 0) if(compressionParameter > 0)
{ {
H5Pset_deflate(plist, compressionParameter); H5Pset_deflate(plist, compressionParameter);
} }
// create dataset // create dataset
HDF5Handle datasetHandle (H5Dcreate(groupHandle, setname.c_str(), d HDF5Handle datasetHandle(H5Dcreate(groupHandle, setname.c_str(), da
atatype, dataspace,H5P_DEFAULT, plist, H5P_DEFAULT), &H5Dclose, "HDF5File:: tatype, dataspace,H5P_DEFAULT, plist, H5P_DEFAULT),
write(): Can not create dataset."); &H5Dclose, "HDF5File::write(): Can not cre
ate dataset.");
// Write the data to the HDF5 dataset as is // Write the data to the HDF5 dataset as is
herr_t write_status = H5Dwrite(datasetHandle, datatype, H5S_ALL, herr_t write_status = H5Dwrite(datasetHandle, datatype, H5S_ALL,
H5S_ALL, H5P_DEFAULT, array.data()); H5S_ALL, H5P_DEFAULT, array.data());
vigra_precondition(write_status >= 0, "HDF5File::write_(): write to " vigra_precondition(write_status >= 0, "HDF5File::write_(): write to "
"dataset \"" + datasetName + "\" " "dataset \"" + datasetName + "\" "
"failed."); "failed.");
if(groupHandle != cGroupHandle_)
{
H5Gclose(groupHandle);
}
} }
/* Write single value as dataset. /* Write single value as dataset.
This functions allows to write data of atomic datatypes (int, long, d This functions allows to write data of atomic datatypes (int, lo
ouble) ng, double)
as a dataset in the HDF5 file. So it is not necessary to create a Mul as a dataset in the HDF5 file. So it is not necessary to create
tiArray a MultiArray
of size 1 to write a single number. of size 1 to write a single number.
If the first character of datasetName is a "/", the path will be inte If the first character of datasetName is a "/", the path will be
rpreted as absolute path, interpreted as absolute path,
otherwise it will be interpreted as path relative to the current grou otherwise it will be interpreted as path relative to the current
p. group.
*/ */
template<class T> template<class T>
inline void writeAtomic(std::string datasetName, const T data) inline void writeAtomic(std::string datasetName, const T data)
{ {
// make datasetName clean // make datasetName clean
datasetName = get_absolute_path(datasetName); datasetName = get_absolute_path(datasetName);
typename MultiArrayShape<1>::type chunkSize; typename MultiArrayShape<1>::type chunkSize;
chunkSize[0] = 0; chunkSize[0] = 0;
MultiArray<1,T> array(MultiArrayShape<1>::type(1)); MultiArray<1,T> array(MultiArrayShape<1>::type(1));
array[0] = data; array[0] = data;
write_(datasetName, array, detail::getH5DataType<T>(), 1, chunkSize ,0); write_(datasetName, array, detail::getH5DataType<T>(), 1, chunkSize ,0);
} }
/* low-level read function to read vigra unstrided MultiArray data /* low-level read function to read vigra unstrided MultiArray data
*/ */
template<unsigned int N, class T> template<unsigned int N, class T>
inline void read_(std::string datasetName, MultiArrayView<N, T, Unstrid inline void read_(std::string datasetName,
edArrayTag> array, const hid_t datatype, const int numBandsOfType) MultiArrayView<N, T, UnstridedArrayTag> array,
const hid_t datatype, const int numBandsOfType)
{ {
//Prepare to read without using HDF5ImportInfo //Prepare to read without using HDF5ImportInfo
ArrayVector<hsize_t> dimshape = getDatasetShape(datasetName); ArrayVector<hsize_t> dimshape = getDatasetShape(datasetName);
hssize_t dimensions = getDatasetDimensions(datasetName);
std::string errorMessage ("HDF5File::read(): Unable to open dataset '" + datasetName + "'."); std::string errorMessage ("HDF5File::read(): Unable to open dataset '" + datasetName + "'.");
HDF5Handle datasetHandle (getDatasetHandle_(datasetName), &H5Dclose , errorMessage.c_str()); HDF5Handle datasetHandle(getDatasetHandle_(datasetName), &H5Dclose, errorMessage.c_str());
int offset = (numBandsOfType > 1); int offset = (numBandsOfType > 1)
? 1
: 0;
vigra_precondition(( (N + offset ) == MultiArrayIndex(dimensions)) , // the object in the HDF5 file may have one additional dimension which we then interpret as the pixel type bands vigra_precondition((N + offset ) == MultiArrayIndex(dimshape.size() ), // the object in the HDF5 file may have one additional dimension which w e then interpret as the pixel type bands
"HDF5File::read(): Array dimension disagrees with dataset dimen sion."); "HDF5File::read(): Array dimension disagrees with dataset dimen sion.");
typename MultiArrayShape<N>::type shape; typename MultiArrayShape<N>::type shape;
for(int k=offset; k< MultiArrayIndex(dimensions); ++k) { for(int k=offset; k < (int)dimshape.size(); ++k)
shape[k-offset] = MultiArrayIndex(dimshape[k]); shape[k-offset] = (MultiArrayIndex)dimshape[k];
}
vigra_precondition(shape == array.shape(), vigra_precondition(shape == array.shape(),
"HDF5File::read(): Array shape disagrees with da taset shape."); "HDF5File::read(): Array shape disagrees with da taset shape.");
if (offset)
vigra_precondition(dimshape[0] == static_cast<hsize_t>(numBands
OfType),
"HDF5File::read(): Band count doesn't match
destination array compound type.");
// simply read in the data as is // simply read in the data as is
H5Dread( datasetHandle, datatype, H5S_ALL, H5S_ALL, H5P_DEFAULT, ar ray.data() ); // .data() possible since void pointer! H5Dread( datasetHandle, datatype, H5S_ALL, H5S_ALL, H5P_DEFAULT, ar ray.data() ); // .data() possible since void pointer!
} }
/* Read a single value. /* Read a single value.
This functions allows to read a single datum of atomic datatype (int, This functions allows to read a single datum of atomic datatype
long, double) (int, long, double)
from the HDF5 file. So it is not necessary to create a MultiArray from the HDF5 file. So it is not necessary to create a MultiArra
of size 1 to read a single number. y
of size 1 to read a single number.
If the first character of datasetName is a "/", the path will be inte
rpreted as absolute path, If the first character of datasetName is a "/", the path will be
otherwise it will be interpreted as path relative to the current grou interpreted as absolute path,
p. otherwise it will be interpreted as path relative to the current
*/ group.
*/
template<class T> template<class T>
inline void readAtomic(std::string datasetName, T & data) inline void readAtomic(std::string datasetName, T & data)
{ {
// make datasetName clean // make datasetName clean
datasetName = get_absolute_path(datasetName); datasetName = get_absolute_path(datasetName);
MultiArray<1,T> array(MultiArrayShape<1>::type(1)); MultiArray<1,T> array(MultiArrayShape<1>::type(1));
read_(datasetName, array, detail::getH5DataType<T>(), 1); read_(datasetName, array, detail::getH5DataType<T>(), 1);
data = array[0]; data = array[0];
} }
inline void readAtomic(std::string datasetName, std::string & data) inline void readAtomic(std::string datasetName, std::string & data)
{ {
// make datasetName clean // make datasetName clean
datasetName = get_absolute_path(datasetName); datasetName = get_absolute_path(datasetName);
MultiArray<1,const char *> array(MultiArrayShape<1>::type(1)); MultiArray<1,const char *> array(MultiArrayShape<1>::type(1));
read_(datasetName, array, detail::getH5DataType<const char *>(), 1) ; read_(datasetName, array, detail::getH5DataType<const char *>(), 1) ;
data = std::string(array[0]); data = std::string(array[0]);
} }
/* low-level write function to write vigra unstrided MultiArray data in /* low-level write function to write vigra unstrided MultiArray data
to a sub-block of a dataset into a sub-block of a dataset
*/ */
template<unsigned int N, class T> template<unsigned int N, class T>
inline void writeBlock_(std::string datasetName, typename MultiArraySha pe<N>::type &blockOffset, const MultiArrayView<N, T, UnstridedArrayTag> & a rray, const hid_t datatype, const int numBandsOfType) inline void writeBlock_(std::string datasetName, typename MultiArraySha pe<N>::type &blockOffset, const MultiArrayView<N, T, UnstridedArrayTag> & a rray, const hid_t datatype, const int numBandsOfType)
{ {
// open dataset if it exists // open dataset if it exists
std::string errorMessage = "HDF5File::writeBlock(): Error opening d ataset '" + datasetName + "'."; std::string errorMessage = "HDF5File::writeBlock(): Error opening d ataset '" + datasetName + "'.";
HDF5Handle datasetHandle (getDatasetHandle_(datasetName), &H5Dclose , errorMessage.c_str()); HDF5Handle datasetHandle (getDatasetHandle_(datasetName), &H5Dclose , errorMessage.c_str());
// hyperslab parameters for position, size, ... // hyperslab parameters for position, size, ...
hsize_t boffset [N]; hsize_t boffset [N];
hsize_t bshape [N]; hsize_t bshape [N];
skipping to change at line 2049 skipping to change at line 2148
HDF5Handle memspace_handle (H5Screate_simple(N,bshape,NULL),&H5Sclo se,"Unable to get origin dataspace"); HDF5Handle memspace_handle (H5Screate_simple(N,bshape,NULL),&H5Sclo se,"Unable to get origin dataspace");
// get file dataspace and select the desired block // get file dataspace and select the desired block
HDF5Handle dataspaceHandle (H5Dget_space(datasetHandle),&H5Sclose," Unable to create target dataspace"); HDF5Handle dataspaceHandle (H5Dget_space(datasetHandle),&H5Sclose," Unable to create target dataspace");
H5Sselect_hyperslab(dataspaceHandle, H5S_SELECT_SET, boffset, bones , bones, bshape); H5Sselect_hyperslab(dataspaceHandle, H5S_SELECT_SET, boffset, bones , bones, bshape);
// Write the data to the HDF5 dataset as is // Write the data to the HDF5 dataset as is
H5Dwrite( datasetHandle, datatype, memspace_handle, dataspaceHandle , H5P_DEFAULT, array.data()); // .data() possible since void pointer! H5Dwrite( datasetHandle, datatype, memspace_handle, dataspaceHandle , H5P_DEFAULT, array.data()); // .data() possible since void pointer!
} }
/* low-level read function to read vigra unstrided MultiArray data from /* low-level read function to read vigra unstrided MultiArray data
a sub-block of a dataset from a sub-block of a dataset
*/ */
template<unsigned int N, class T> template<unsigned int N, class T>
inline void readBlock_(std::string datasetName, typename MultiArrayShap e<N>::type &blockOffset, typename MultiArrayShape<N>::type &blockShape, Mul tiArrayView<N, T, UnstridedArrayTag> &array, const hid_t datatype, const in t numBandsOfType) inline void readBlock_(std::string datasetName, typename MultiArrayShap e<N>::type &blockOffset, typename MultiArrayShape<N>::type &blockShape, Mul tiArrayView<N, T, UnstridedArrayTag> &array, const hid_t datatype, const in t numBandsOfType)
{ {
//Prepare to read without using HDF5ImportInfo //Prepare to read without using HDF5ImportInfo
//ArrayVector<hsize_t> dimshape = getDatasetShape(datasetName) ; //ArrayVector<hsize_t> dimshape = getDatasetShape(datasetName) ;
hssize_t dimensions = getDatasetDimensions(datasetName); hssize_t dimensions = getDatasetDimensions(datasetName);
std::string errorMessage ("HDF5File::readBlock(): Unable to open da taset '" + datasetName + "'."); std::string errorMessage ("HDF5File::readBlock(): Unable to open da taset '" + datasetName + "'.");
HDF5Handle datasetHandle (getDatasetHandle_(datasetName), &H5Dclose , errorMessage.c_str()); HDF5Handle datasetHandle (getDatasetHandle_(datasetName), &H5Dclose , errorMessage.c_str());
int offset = (numBandsOfType > 1); int offset = (numBandsOfType > 1)
? 1
: 0;
vigra_precondition(( (N + offset ) == MultiArrayIndex(dimensions)) , // the object in the HDF5 file may have one additional dimension which we then interpret as the pixel type bands vigra_precondition(( (N + offset ) == MultiArrayIndex(dimensions)) , // the object in the HDF5 file may have one additional dimension which we then interpret as the pixel type bands
"readHDF5_block(): Array dimension disagrees with data dimensio n."); "readHDF5_block(): Array dimension disagrees with data dimensio n.");
vigra_precondition(blockShape == array.shape(), vigra_precondition(blockShape == array.shape(),
"readHDF5_block(): Array shape disagrees with block size."); "readHDF5_block(): Array shape disagrees with block size.");
// hyperslab parameters for position, size, ... // hyperslab parameters for position, size, ...
hsize_t boffset [N]; hsize_t boffset [N];
hsize_t bshape [N]; hsize_t bshape [N];
skipping to change at line 2084 skipping to change at line 2185
for(int i = 0; i < N; i++){ for(int i = 0; i < N; i++){
// vigra and hdf5 use different indexing // vigra and hdf5 use different indexing
boffset[i] = blockOffset[N-1-i]; boffset[i] = blockOffset[N-1-i];
//bshape[i] = blockShape[i]; //bshape[i] = blockShape[i];
bshape[i] = blockShape[N-1-i]; bshape[i] = blockShape[N-1-i];
//boffset[i] = blockOffset[N-1-i]; //boffset[i] = blockOffset[N-1-i];
bones[i] = 1; bones[i] = 1;
} }
// create a target dataspace in memory with the shape of the desire d block // create a target dataspace in memory with the shape of the desire d block
HDF5Handle memspace_handle (H5Screate_simple(N,bshape,NULL),&H5Sclo HDF5Handle memspace_handle(H5Screate_simple(N,bshape,NULL),&H5Sclos
se,"Unable to create target dataspace"); e,
"Unable to create target dataspace");
// get file dataspace and select the desired block // get file dataspace and select the desired block
HDF5Handle dataspaceHandle (H5Dget_space(datasetHandle),&H5Sclose," HDF5Handle dataspaceHandle(H5Dget_space(datasetHandle),&H5Sclose,
Unable to get dataspace"); "Unable to get dataspace");
H5Sselect_hyperslab(dataspaceHandle, H5S_SELECT_SET, boffset, bones , bones, bshape); H5Sselect_hyperslab(dataspaceHandle, H5S_SELECT_SET, boffset, bones , bones, bshape);
// now read the data // now read the data
H5Dread( datasetHandle, datatype, memspace_handle, dataspaceHandle, H5P_DEFAULT, array.data() ); // .data() possible since void pointer! H5Dread( datasetHandle, datatype, memspace_handle, dataspaceHandle, H5P_DEFAULT, array.data() ); // .data() possible since void pointer!
} }
}; /* class HDF5File */ }; /* class HDF5File */
namespace detail { namespace detail {
skipping to change at line 2166 skipping to change at line 2269
counter++; counter++;
//std::cout << "numBandsOfType: " << numBandsOfType << std::endl; //std::cout << "numBandsOfType: " << numBandsOfType << std::endl;
DestIterator dend = d + shape[0]; DestIterator dend = d + shape[0];
int k = 0; int k = 0;
for(; d < dend; ++d, k++) for(; d < dend; ++d, k++)
{ {
*d = buffer[k]; *d = buffer[k];
//std::cout << buffer[k] << "| "; //std::cout << buffer[k] << "| ";
} }
} }
template <class DestIterator, class Shape, class T, int N> template <class DestIterator, class Shape, class T, int N>
void void
readHDF5Impl(DestIterator d, Shape const & shape, const hid_t dataset_id, c onst hid_t datatype, ArrayVector<T> & buffer, int & counter, const int elem ents, const int numBandsOfType, MetaInt<N>) readHDF5Impl(DestIterator d, Shape const & shape, const hid_t dataset_id, c onst hid_t datatype, ArrayVector<T> & buffer, int & counter, const int elem ents, const int numBandsOfType, MetaInt<N>)
{ {
DestIterator dend = d + shape[N]; DestIterator dend = d + shape[N];
for(; d < dend; ++d) for(; d < dend; ++d)
{ {
readHDF5Impl(d.begin(), shape, dataset_id, datatype, buffer, counte r, elements, numBandsOfType, MetaInt<N-1>()); readHDF5Impl(d.begin(), shape, dataset_id, datatype, buffer, counte r, elements, numBandsOfType, MetaInt<N-1>());
skipping to change at line 2188 skipping to change at line 2290
} }
} // namespace detail } // namespace detail
/** \brief Read the data specified by the given \ref vigra::HDF5ImportInfo object /** \brief Read the data specified by the given \ref vigra::HDF5ImportInfo object
and write the into the given 'array'. and write the into the given 'array'.
The array must have the correct number of dimensions and shape for the dataset The array must have the correct number of dimensions and shape for the dataset
represented by 'info'. When the element type of 'array' differs from th e stored element represented by 'info'. When the element type of 'array' differs from th e stored element
type, HDF5 will convert the type on the fly (except when the HDF5 versi on is 1.6 or below, type, HDF5 will convert the type on the fly (except when the HDF5 versi on is 1.6 or below,
in which case an error will result). Multi-channel element types (i.e. in which case an error will result). Multi-channel element types (i.e.
\ref vigra::RGBValue \ref vigra::RGBValue,
and \ref vigra::TinyVector) are recognized and handled correctly. \ref vigra::TinyVector, and \ref vigra::FFTWComplex) are recognized and
handled correctly.
<b> Declaration:</b> <b> Declaration:</b>
\code \code
namespace vigra { namespace vigra {
template<unsigned int N, class T, class StrideTag> template<unsigned int N, class T, class StrideTag>
void void
readHDF5(const HDF5ImportInfo &info, MultiArrayView<N, T, StrideTag > array); readHDF5(const HDF5ImportInfo &info, MultiArrayView<N, T, StrideTag > array);
} }
\endcode \endcode
skipping to change at line 2240 skipping to change at line 2342
readHDF5(info, array, detail::getH5DataType<T>(), SIZE); readHDF5(info, array, detail::getH5DataType<T>(), SIZE);
} }
// non-scalar (RGBValue) and unstrided target multi array // non-scalar (RGBValue) and unstrided target multi array
template<unsigned int N, class T> template<unsigned int N, class T>
inline void readHDF5(const HDF5ImportInfo &info, MultiArrayView<N, RGBValue <T>, UnstridedArrayTag> array) inline void readHDF5(const HDF5ImportInfo &info, MultiArrayView<N, RGBValue <T>, UnstridedArrayTag> array)
{ {
readHDF5(info, array, detail::getH5DataType<T>(), 3); readHDF5(info, array, detail::getH5DataType<T>(), 3);
} }
// non-scalar (FFTWComplex) and unstrided target multi array
template<unsigned int N, class T>
inline void readHDF5(const HDF5ImportInfo &info, MultiArrayView<N, FFTWComp
lex<T>, UnstridedArrayTag> array)
{
readHDF5(info, array, detail::getH5DataType<T>(), 2);
}
// unstrided target multi array // unstrided target multi array
template<unsigned int N, class T> template<unsigned int N, class T>
void readHDF5(const HDF5ImportInfo &info, MultiArrayView<N, T, UnstridedArr ayTag> array, const hid_t datatype, const int numBandsOfType) void readHDF5(const HDF5ImportInfo &info, MultiArrayView<N, T, UnstridedArr ayTag> array, const hid_t datatype, const int numBandsOfType)
{ {
int offset = (numBandsOfType > 1); int offset = (numBandsOfType > 1);
//std::cout << "offset: " << offset << ", N: " << N << ", dims: " << in fo.numDimensions() << std::endl; //std::cout << "offset: " << offset << ", N: " << N << ", dims: " << in fo.numDimensions() << std::endl;
vigra_precondition(( (N + offset ) == info.numDimensions()), // the obj ect in the HDF5 file may have one additional dimension which we then interp ret as the pixel type bands vigra_precondition(( (N + offset ) == info.numDimensions()), // the obj ect in the HDF5 file may have one additional dimension which we then interp ret as the pixel type bands
"readHDF5(): Array dimension disagrees with HDF5ImportInfo.numDimen sions()."); "readHDF5(): Array dimension disagrees with HDF5ImportInfo.numDimen sions().");
skipping to change at line 2514 skipping to change at line 2623
} }
} }
} // namespace detail } // namespace detail
/** \brief Store array data in an HDF5 file. /** \brief Store array data in an HDF5 file.
The number of dimensions, shape and element type of the stored dataset is automatically The number of dimensions, shape and element type of the stored dataset is automatically
determined from the properties of the given \a array. Strided arrays ar e stored in an determined from the properties of the given \a array. Strided arrays ar e stored in an
unstrided way, i.e. in contiguous scan-order. Multi-channel element typ es unstrided way, i.e. in contiguous scan-order. Multi-channel element typ es
(i.e. \ref vigra::RGBValue and \ref vigra::TinyVector) are recognized a (i.e. \ref vigra::RGBValue, \ref vigra::TinyVector and \ref vigra::FFTW
nd handled correctly Complex)
are recognized and handled correctly
(in particular, the will form the innermost dimension of the stored dat aset). (in particular, the will form the innermost dimension of the stored dat aset).
\a pathInFile may contain '/'-separated group names, but must end with the name \a pathInFile may contain '/'-separated group names, but must end with the name
of the dataset to be created. of the dataset to be created.
<b> Declaration:</b> <b> Declaration:</b>
\code \code
namespace vigra { namespace vigra {
template<unsigned int N, class T, class StrideTag> template<unsigned int N, class T, class StrideTag>
void void
skipping to change at line 2608 skipping to change at line 2718
writeHDF5(filePath, pathInFile, array, detail::getH5DataType<T>(), SIZE ); writeHDF5(filePath, pathInFile, array, detail::getH5DataType<T>(), SIZE );
} }
// non-scalar (RGBValue) and strided multi arrays // non-scalar (RGBValue) and strided multi arrays
template<unsigned int N, class T> template<unsigned int N, class T>
inline void writeHDF5(const char* filePath, const char* pathInFile, const M ultiArrayView<N, RGBValue<T>, StridedArrayTag> & array) inline void writeHDF5(const char* filePath, const char* pathInFile, const M ultiArrayView<N, RGBValue<T>, StridedArrayTag> & array)
{ {
writeHDF5(filePath, pathInFile, array, detail::getH5DataType<T>(), 3); writeHDF5(filePath, pathInFile, array, detail::getH5DataType<T>(), 3);
} }
// non-scalar (RGBValue) and strided multi arrays // non-scalar (FFTWComplex) and strided multi arrays
template<unsigned int N, class T> template<unsigned int N, class T>
inline void writeHDF5(const char* filePath, const char* pathInFile, const M ultiArrayView<N, FFTWComplex<T>, StridedArrayTag> & array) inline void writeHDF5(const char* filePath, const char* pathInFile, const M ultiArrayView<N, FFTWComplex<T>, StridedArrayTag> & array)
{ {
writeHDF5(filePath, pathInFile, array, detail::getH5DataType<T>(), 2); writeHDF5(filePath, pathInFile, array, detail::getH5DataType<T>(), 2);
} }
// strided multi arrays // strided multi arrays
template<unsigned int N, class T> template<unsigned int N, class T>
void writeHDF5(const char* filePath, const char* pathInFile, const MultiArr ayView<N, T, StridedArrayTag> & array, const hid_t datatype, const int numB andsOfType) void writeHDF5(const char* filePath, const char* pathInFile, const MultiArr ayView<N, T, StridedArrayTag> & array, const hid_t datatype, const int numB andsOfType)
{ {
 End of changes. 162 change blocks. 
510 lines changed or deleted 693 lines changed or added


 imageinfo.hxx   imageinfo.hxx 
skipping to change at line 368 skipping to change at line 368
private: private:
std::string m_filename, m_filetype, m_pixeltype, m_comp, m_mode; std::string m_filename, m_filetype, m_pixeltype, m_comp, m_mode;
float m_x_res, m_y_res; float m_x_res, m_y_res;
Diff2D m_pos; Diff2D m_pos;
ICCProfile m_icc_profile; ICCProfile m_icc_profile;
Size2D m_canvas_size; Size2D m_canvas_size;
double fromMin_, fromMax_, toMin_, toMax_; double fromMin_, fromMax_, toMin_, toMax_;
}; };
// return an encoder for a given ImageExportInfo object // return an encoder for a given ImageExportInfo object
VIGRA_EXPORT std::auto_ptr<Encoder> encoder( const ImageExportInfo & info ) ; VIGRA_EXPORT VIGRA_UNIQUE_PTR<Encoder> encoder( const ImageExportInfo & inf o );
/********************************************************/ /********************************************************/
/* */ /* */
/* ImageImportInfo */ /* ImageImportInfo */
/* */ /* */
/********************************************************/ /********************************************************/
/** \brief Argument object for the function importImage(). /** \brief Argument object for the function importImage().
See \ref importImage() for a usage example. This object must be See \ref importImage() for a usage example. This object must be
skipping to change at line 554 skipping to change at line 554
int m_width, m_height, m_num_bands, m_num_extra_bands, m_num_images, m_ image_index; int m_width, m_height, m_num_bands, m_num_extra_bands, m_num_images, m_ image_index;
float m_x_res, m_y_res; float m_x_res, m_y_res;
Diff2D m_pos; Diff2D m_pos;
Size2D m_canvas_size; Size2D m_canvas_size;
ICCProfile m_icc_profile; ICCProfile m_icc_profile;
void readHeader_(); void readHeader_();
}; };
// return a decoder for a given ImageImportInfo object // return a decoder for a given ImageImportInfo object
VIGRA_EXPORT std::auto_ptr<Decoder> decoder( const ImageImportInfo & info ) ; VIGRA_EXPORT VIGRA_UNIQUE_PTR<Decoder> decoder( const ImageImportInfo & inf o );
//@} //@}
} // namespace vigra } // namespace vigra
#endif // VIGRA_IMAGEINFO_HXX #endif // VIGRA_IMAGEINFO_HXX
 End of changes. 2 change blocks. 
2 lines changed or deleted 2 lines changed or added


 imageiterator.hxx   imageiterator.hxx 
skipping to change at line 554 skipping to change at line 554
The usage examples assume that you constructed two iterators like The usage examples assume that you constructed two iterators like
this: this:
\code \code
vigra::ImageIterator<SomePixelType> iterator(base, width); vigra::ImageIterator<SomePixelType> iterator(base, width);
vigra::ImageIterator<SomePixelType> iterator1(base, width); vigra::ImageIterator<SomePixelType> iterator1(base, width);
\endcode \endcode
See the paper: U. Koethe: See the paper: U. Koethe:
<a href="documents/GenericProg2D.ps">Reusable Algorithms in Image Proce ssing</a> <a href="http://hci.iwr.uni-heidelberg.de/vigra/documents/GenericProg2D .ps">Reusable Algorithms in Image Processing</a>
for a discussion of the concepts behind ImageIterators. for a discussion of the concepts behind ImageIterators.
*/ */
template <class IMAGEITERATOR, template <class IMAGEITERATOR,
class PIXELTYPE, class REFERENCE, class POINTER, class PIXELTYPE, class REFERENCE, class POINTER,
class StridedOrUnstrided = UnstridedArrayTag> class StridedOrUnstrided = UnstridedArrayTag>
class ImageIteratorBase class ImageIteratorBase
{ {
typedef typename typedef typename
detail::LinearIteratorSelector<StridedOrUnstrided>::template type<I mageIteratorBase> vigra::detail::LinearIteratorSelector<StridedOrUnstrided>::template type<ImageIteratorBase>
RowIteratorSelector; RowIteratorSelector;
typedef typename typedef typename
detail::LinearIteratorSelector<StridedArrayTag>::template type<Imag eIteratorBase> vigra::detail::LinearIteratorSelector<StridedArrayTag>::template ty pe<ImageIteratorBase>
ColumnIteratorSelector; ColumnIteratorSelector;
public: public:
typedef ImageIteratorBase<IMAGEITERATOR, typedef ImageIteratorBase<IMAGEITERATOR,
PIXELTYPE, REFERENCE, POINTER, StridedOrUnstrided> self_ty pe; PIXELTYPE, REFERENCE, POINTER, StridedOrUnstrided> self_ty pe;
/** The underlying image's pixel type. /** The underlying image's pixel type.
*/ */
typedef PIXELTYPE value_type; typedef PIXELTYPE value_type;
/** deprecated, use <TT>value_type</TT> instead. /** deprecated, use <TT>value_type</TT> instead.
skipping to change at line 612 skipping to change at line 612
*/ */
typedef typename RowIteratorSelector::res row_iterator; typedef typename RowIteratorSelector::res row_iterator;
/** The associated column iterator. /** The associated column iterator.
*/ */
typedef typename ColumnIteratorSelector::res column_iterator; typedef typename ColumnIteratorSelector::res column_iterator;
/** Let operations act in X direction /** Let operations act in X direction
*/ */
typedef typename typedef typename
detail::DirectionSelector<StridedOrUnstrided>::template type<pointe r> MoveX; vigra::detail::DirectionSelector<StridedOrUnstrided>::template type <pointer> MoveX;
/** Let operations act in Y direction /** Let operations act in Y direction
*/ */
typedef typename typedef typename
detail::DirectionSelector<StridedArrayTag>::template type<int> Move Y; vigra::detail::DirectionSelector<StridedArrayTag>::template type<in t> MoveY;
/** @name Comparison of Iterators */ /** @name Comparison of Iterators */
//@{ //@{
/** usage: <TT> iterator == iterator1 </TT> /** usage: <TT> iterator == iterator1 </TT>
*/ */
bool operator==(ImageIteratorBase const & rhs) const bool operator==(ImageIteratorBase const & rhs) const
{ {
return (x == rhs.x) && (y == rhs.y); return (x == rhs.x) && (y == rhs.y);
} }
skipping to change at line 838 skipping to change at line 838
/* ImageIterator */ /* ImageIterator */
/* */ /* */
/********************************************************/ /********************************************************/
/** \brief Standard 2D random access iterator for images that store the /** \brief Standard 2D random access iterator for images that store the
data in a linear array. data in a linear array.
Most functions and local types are inherited from ImageIteratorBase. Most functions and local types are inherited from ImageIteratorBase.
See the paper: U. Koethe: See the paper: U. Koethe:
<a href="documents/GenericProg2D.ps">Reusable Algorithms in Image Proce ssing</a> <a href="http://hci.iwr.uni-heidelberg.de/vigra/documents/GenericProg2D .ps">Reusable Algorithms in Image Processing</a>
for a discussion of the concepts behind ImageIterators. for a discussion of the concepts behind ImageIterators.
<b>\#include</b> \<vigra/imageiterator.hxx\> <b>\#include</b> \<vigra/imageiterator.hxx\>
Namespace: vigra Namespace: vigra
*/ */
template <class PIXELTYPE> template <class PIXELTYPE>
class ImageIterator class ImageIterator
: public ImageIteratorBase<ImageIterator<PIXELTYPE>, : public ImageIteratorBase<ImageIterator<PIXELTYPE>,
 End of changes. 6 change blocks. 
6 lines changed or deleted 6 lines changed or added


 impex.hxx   impex.hxx 
/************************************************************************/ /************************************************************************/
/* */ /* */
/* Copyright 2001-2002 by Gunnar Kedenburg */ /* Copyright 2001-2002 by Gunnar Kedenburg */
/* Copyright 2012 Christoph Spiel and Ullrich Koethe */
/* */ /* */
/* This file is part of the VIGRA computer vision library. */ /* This file is part of the VIGRA computer vision library. */
/* The VIGRA Website is */ /* The VIGRA Website is */
/* http://hci.iwr.uni-heidelberg.de/vigra/ */ /* http://hci.iwr.uni-heidelberg.de/vigra/ */
/* Please direct questions, bug reports, and contributions to */ /* Please direct questions, bug reports, and contributions to */
/* ullrich.koethe@iwr.uni-heidelberg.de or */ /* ullrich.koethe@iwr.uni-heidelberg.de or */
/* vigra@informatik.uni-hamburg.de */ /* vigra@informatik.uni-hamburg.de */
/* */ /* */
/* Permission is hereby granted, free of charge, to any person */ /* Permission is hereby granted, free of charge, to any person */
/* obtaining a copy of this software and associated documentation */ /* obtaining a copy of this software and associated documentation */
skipping to change at line 35 skipping to change at line 36
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND */ /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES */ /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES */
/* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */ /* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */
/* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT */ /* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT */
/* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */ /* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */
/* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */ /* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */
/* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */ /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */
/* OTHER DEALINGS IN THE SOFTWARE. */ /* OTHER DEALINGS IN THE SOFTWARE. */
/* */ /* */
/************************************************************************/ /************************************************************************/
/* Modifications by Pablo d'Angelo
* updated to vigra 1.4 by Douglas Wilkins
* as of 18 February 2006:
* - Added import/export of UINT16 and UINT32 image types.
* Modifications by Andrew Mihal
* updated to vigra 1.4 by Douglas Wilkins
* as of 18 February 2006:
* - Moved some RowIterator declarations around to avoid using default cto
rs
* (cachedfileimages do not have default ctors for row iterators).
* - Added some case-specific optimizations
*/
/*! /*!
\file impex.hxx * \file impex.hxx
\brief image import and export functions * \brief image import and export functions
*
this file provides the declarations and implementations of importImage() * This module implements functions importImage() and exportImage().
and exportImage(). the matching implementation for the given datatype is * The matching implementation for any given datatype is selected by
selected by template metacode. * template meta code.
*/ *
*/
#ifndef VIGRA_IMPEX_HXX #ifndef VIGRA_IMPEX_HXX
#define VIGRA_IMPEX_HXX #define VIGRA_IMPEX_HXX
#include "sized_int.hxx"
#include "stdimage.hxx" #include "stdimage.hxx"
#include "tinyvector.hxx"
#include "imageinfo.hxx" #include "imageinfo.hxx"
#include "numerictraits.hxx" #include "impexbase.hxx"
#include "codec.hxx"
#include "accessor.hxx"
#include "inspectimage.hxx"
#include "transformimage.hxx"
#include "copyimage.hxx"
#include "multi_array.hxx"
#include <typeinfo>
#include <iostream>
// TODO
// next refactoring: pluggable conversion algorithms
namespace vigra namespace vigra
{ {
/** \addtogroup VigraImpex /** \addtogroup VigraImpex
**/ * @{
//@{ */
namespace detail
/*! {
\brief used for reading bands after the source data type has been fig template <class ValueType,
ured out. class ImageIterator, class ImageAccessor>
void
<b>\#include</b> \<vigra/impex.hxx\><br> read_image_band(Decoder* decoder,
Namespace: vigra ImageIterator image_iterator, ImageAccessor image_a
ccessor)
{
typedef typename ImageIterator::row_iterator ImageRowIterator;
<b> Declaration:</b> const unsigned width(decoder->getWidth());
const unsigned height(decoder->getHeight());
const unsigned offset(decoder->getOffset());
\code for (unsigned y = 0U; y != height; ++y)
namespace vigra { {
template< class ImageIterator, class Accessor, class SrcValueTy decoder->nextScanline();
pe >
void read_bands( Decoder * dec, ImageIterator ys, Accessor a, S
rcValueType )
}
\endcode
\param dec decoder object through which the source data will be acces const ValueType* scanline = static_cast<const ValueType*>(d
sed ecoder->currentScanlineOfBand(0));
\param ys image iterator referencing the upper left pixel of the des
tination image
\param a image accessor for the destination image
*/
template< class ImageIterator, class Accessor, class SrcValueType >
void read_bands( Decoder * dec, ImageIterator ys, Accessor a, SrcValueT
ype )
{
typedef unsigned int size_type; ImageRowIterator is(image_iterator.rowIterator());
typedef typename ImageIterator::row_iterator DstRowIterator; const ImageRowIterator is_end(is + width);
typedef typename Accessor::value_type AccessorValueType;
typedef typename AccessorValueType::value_type DstValueType;
const size_type width = dec->getWidth();
const size_type height = dec->getHeight();
const size_type num_bands = dec->getNumBands();
vigra_precondition(num_bands == (size_type)a.size(ys),
"importImage(): number of bands (color channels) in file and de
stination image differ.");
SrcValueType const * scanline;
// MIHAL no default constructor available for cachedfileimages.
DstRowIterator xs = ys.rowIterator();
// iterate while (is != is_end)
if (num_bands == 4)
{
// Speedup for this particular case
unsigned int offset = dec->getOffset();
SrcValueType const * scanline0;
SrcValueType const * scanline1;
SrcValueType const * scanline2;
SrcValueType const * scanline3;
for( size_type y = 0; y < height; ++y, ++ys.y )
{
dec->nextScanline();
xs = ys.rowIterator();
scanline0 = static_cast< SrcValueType const * >
(dec->currentScanlineOfBand(0));
scanline1 = static_cast< SrcValueType const * >
(dec->currentScanlineOfBand(1));
scanline2 = static_cast< SrcValueType const * >
(dec->currentScanlineOfBand(2));
scanline3 = static_cast< SrcValueType const * >
(dec->currentScanlineOfBand(3));
for( size_type x = 0; x < width; ++x, ++xs )
{ {
a.setComponent( *scanline0, xs, 0); image_accessor.set(*scanline, is);
a.setComponent( *scanline1, xs, 1); scanline += offset;
a.setComponent( *scanline2, xs, 2); ++is;
a.setComponent( *scanline3, xs, 3);
scanline0 += offset;
scanline1 += offset;
scanline2 += offset;
scanline3 += offset;
} }
}
}
else
{
// General case
for( size_type y = 0; y < height; ++y, ++ys.y )
{
dec->nextScanline();
for( size_type b = 0; b < num_bands; ++b )
{
xs = ys.rowIterator();
scanline = static_cast< SrcValueType const * >
(dec->currentScanlineOfBand(b));
for( size_type x = 0; x < width; ++x, ++xs )
{
a.setComponent( *scanline, xs, b );
scanline += dec->getOffset();
}
}
}
}
} // read_bands()
// specialization for speed-up (the standard version would also work,
// but causes a stupid gcc waring)
template< class ImageIterator, class RGBType,
class SrcValueType >
void read_bands( Decoder * dec, ImageIterator ys,
RGBAccessor<RGBType> a, SrcValueType )
{
typedef unsigned int size_type;
typedef typename ImageIterator::row_iterator DstRowIterator;
typedef RGBType AccessorValueType;
typedef typename AccessorValueType::value_type DstValueType;
const size_type width = dec->getWidth();
const size_type height = dec->getHeight();
const size_type num_bands = dec->getNumBands();
vigra_precondition(num_bands == (size_type)a.size(ys),
"importImage(): number of bands (color channels) in file and des
tination image differ.");
// MIHAL no default constructor available for cachedfileimages.
DstRowIterator xs = ys.rowIterator();
// Speedup for this particular case
unsigned int offset = dec->getOffset();
SrcValueType const * scanline0;
SrcValueType const * scanline1;
SrcValueType const * scanline2;
for( size_type y = 0; y < height; ++y, ++ys.y )
{
dec->nextScanline();
xs = ys.rowIterator();
scanline0 = static_cast< SrcValueType const * >
(dec->currentScanlineOfBand(0));
scanline1 = static_cast< SrcValueType const * >
(dec->currentScanlineOfBand(1));
scanline2 = static_cast< SrcValueType const * >
(dec->currentScanlineOfBand(2));
for( size_type x = 0; x < width; ++x, ++xs )
{
a.setComponent( *scanline0, xs, 0);
a.setComponent( *scanline1, xs, 1);
a.setComponent( *scanline2, xs, 2);
scanline0 += offset;
scanline1 += offset;
scanline2 += offset;
}
}
} // read_bands()
// specialization for speed-up (the standard version would also work, ++image_iterator.y;
// but causes a stupid gcc waring)
template< class ImageIterator, class ComponentType, class SrcValueType
>
void read_bands( Decoder * dec, ImageIterator ys,
VectorAccessor<TinyVector<ComponentType, 3> > a, SrcVa
lueType )
{
typedef unsigned int size_type;
typedef typename ImageIterator::row_iterator DstRowIterator;
typedef TinyVector<ComponentType, 3> AccessorValueType;
typedef typename AccessorValueType::value_type DstValueType;
const size_type width = dec->getWidth();
const size_type height = dec->getHeight();
const size_type num_bands = dec->getNumBands();
vigra_precondition(num_bands == (size_type)a.size(ys),
"importImage(): number of bands (color channels) in file and des
tination image differ.");
// MIHAL no default constructor available for cachedfileimages.
DstRowIterator xs = ys.rowIterator();
// Speedup for this particular case
unsigned int offset = dec->getOffset();
SrcValueType const * scanline0;
SrcValueType const * scanline1;
SrcValueType const * scanline2;
for( size_type y = 0; y < height; ++y, ++ys.y )
{
dec->nextScanline();
xs = ys.rowIterator();
scanline0 = static_cast< SrcValueType const * >
(dec->currentScanlineOfBand(0));
scanline1 = static_cast< SrcValueType const * >
(dec->currentScanlineOfBand(1));
scanline2 = static_cast< SrcValueType const * >
(dec->currentScanlineOfBand(2));
for( size_type x = 0; x < width; ++x, ++xs )
{
a.setComponent( *scanline0, xs, 0);
a.setComponent( *scanline1, xs, 1);
a.setComponent( *scanline2, xs, 2);
scanline0 += offset;
scanline1 += offset;
scanline2 += offset;
} }
} }
} // read_bands()
// specialization for speed-up (the standard version would also work, template <class ValueType,
// but causes a stupid gcc waring) class ImageIterator, class ImageAccessor>
template< class ImageIterator, class ComponentType, class SrcValueType void
> read_image_bands(Decoder* decoder,
void read_bands( Decoder * dec, ImageIterator ys, ImageIterator image_iterator, ImageAccessor image_
VectorAccessor<TinyVector<ComponentType, 4> > a, SrcVa accessor)
lueType )
{
typedef unsigned int size_type;
typedef typename ImageIterator::row_iterator DstRowIterator;
typedef TinyVector<ComponentType, 4> AccessorValueType;
typedef typename AccessorValueType::value_type DstValueType;
const size_type width = dec->getWidth();
const size_type height = dec->getHeight();
const size_type num_bands = dec->getNumBands();
vigra_precondition(num_bands == (size_type)a.size(ys),
"importImage(): number of bands (color channels) in file and des
tination image differ.");
// MIHAL no default constructor available for cachedfileimages.
DstRowIterator xs = ys.rowIterator();
// Speedup for this particular case
unsigned int offset = dec->getOffset();
SrcValueType const * scanline0;
SrcValueType const * scanline1;
SrcValueType const * scanline2;
SrcValueType const * scanline3;
for( size_type y = 0; y < height; ++y, ++ys.y )
{ {
dec->nextScanline(); typedef typename ImageIterator::row_iterator ImageRowIterator;
xs = ys.rowIterator();
scanline0 = static_cast< SrcValueType const * >
(dec->currentScanlineOfBand(0));
scanline1 = static_cast< SrcValueType const * >
(dec->currentScanlineOfBand(1));
scanline2 = static_cast< SrcValueType const * >
(dec->currentScanlineOfBand(2));
scanline3 = static_cast< SrcValueType const * >
(dec->currentScanlineOfBand(3));
for( size_type x = 0; x < width; ++x, ++xs )
{
a.setComponent( *scanline0, xs, 0);
a.setComponent( *scanline1, xs, 1);
a.setComponent( *scanline2, xs, 2);
a.setComponent( *scanline3, xs, 3);
scanline0 += offset;
scanline1 += offset;
scanline2 += offset;
scanline3 += offset;
}
}
} // read_bands()
/*!
\brief used for reading bands after the source data type has been fig
ured out.
<b>\#include</b> \<vigra/impex.hxx\><br>
Namespace: vigra
<b> Declaration:</b>
\code
namespace vigra {
template< class ImageIterator, class Accessor, class SrcValueTy
pe >
void read_band( Decoder * dec, ImageIterator ys, Accessor a, Sr
cValueType )
}
\endcode
\param dec decoder object through which the source data will be acces
sed
\param ys image iterator referencing the upper left pixel of the des
tination image
\param a image accessor for the destination image
*/
template< class ImageIterator, class Accessor, class SrcValueType >
void read_band( Decoder * dec, ImageIterator ys, Accessor a, SrcValueTy
pe )
{
typedef unsigned int size_type;
typedef typename ImageIterator::row_iterator DstRowIterator;
typedef typename Accessor::value_type DstValueType;
const size_type width = dec->getWidth();
const size_type height = dec->getHeight();
SrcValueType const * scanline;
// MIHAL no default constructor available for cachedfileimages.
DstRowIterator xs = ys.rowIterator();
for( size_type y = 0; y < height; ++y, ++ys.y ) {
dec->nextScanline();
xs = ys.rowIterator();
scanline = static_cast< SrcValueType const * >(dec->currentScan
lineOfBand(0));
for( size_type x = 0; x < width; ++x, ++xs )
a.set( scanline[x], xs );
}
} // read_band()
/*!
\brief used for reading images of vector type, such as integer of flo
at rgb.
<b>\#include</b> \<vigra/impex.hxx\><br>
Namespace: vigra
<b> Declaration:</b>
\code
namespace vigra {
template< class ImageIterator, class Accessor >
void importVectorImage( const ImageImportInfo & info, ImageIter
ator iter, Accessor a )
}
\endcode
<b> Parameters:</b> const unsigned width(decoder->getWidth());
const unsigned height(decoder->getHeight());
const unsigned offset(decoder->getOffset());
const unsigned accessor_size(image_accessor.size(image_iterator
));
<DL> // OPTIMIZATION: Specialization for the most common case
<DT>ImageIterator<DD> the image iterator type for the destination i // of an RGB-image, i.e. 3 channels.
mage if (accessor_size == 3U)
<DT>Accessor<DD> the image accessor type for the destination image {
<DT>info<DD> user supplied image import information const ValueType* scanline_0;
<DT>iter<DD> image iterator referencing the upper left pixel of the const ValueType* scanline_1;
destination image const ValueType* scanline_2;
<DT>a<DD> image accessor for the destination image
</DL>
*/
doxygen_overloaded_function(template <...> void importVectorImage)
template< class ImageIterator, class Accessor >
void importVectorImage( const ImageImportInfo & info, ImageIterator ite
r, Accessor a )
{
std::auto_ptr<Decoder> dec = decoder(info);
std::string pixeltype = dec->getPixelType();
if ( pixeltype == "UINT8" )
read_bands( dec.get(), iter, a, (UInt8)0 );
else if ( pixeltype == "INT16" )
read_bands( dec.get(), iter, a, Int16() );
else if ( pixeltype == "UINT16" )
read_bands( dec.get(), iter, a, (UInt16)0 );
else if ( pixeltype == "INT32" )
read_bands( dec.get(), iter, a, Int32() );
else if ( pixeltype == "UINT32" )
read_bands( dec.get(), iter, a, (UInt32)0 );
else if ( pixeltype == "FLOAT" )
read_bands( dec.get(), iter, a, float() );
else if ( pixeltype == "DOUBLE" )
read_bands( dec.get(), iter, a, double() );
else
vigra_precondition( false, "invalid pixeltype" );
// close the decoder
dec->close();
}
/*! for (unsigned y = 0U; y != height; ++y)
\brief used for reading images of scalar type, such as integer and f {
loat grayscale. decoder->nextScanline();
<b>\#include</b> \<vigra/impex.hxx\><br> scanline_0 = static_cast<const ValueType*>(decoder->cur
Namespace: vigra rentScanlineOfBand(0));
scanline_1 = static_cast<const ValueType*>(decoder->cur
rentScanlineOfBand(1));
scanline_2 = static_cast<const ValueType*>(decoder->cur
rentScanlineOfBand(2));
<b> Declaration:</b> ImageRowIterator is(image_iterator.rowIterator());
const ImageRowIterator is_end(is + width);
\code while (is != is_end)
namespace vigra { {
template < class ImageIterator, class Accessor > image_accessor.setComponent(*scanline_0, is, 0);
void importScalarImage( const ImageImportInfo & info, ImageIter image_accessor.setComponent(*scanline_1, is, 1);
ator iter, Accessor a ) image_accessor.setComponent(*scanline_2, is, 2);
}
\endcode scanline_0 += offset;
scanline_1 += offset;
scanline_2 += offset;
<b> Parameters:</b> ++is;
}
<DL> ++image_iterator.y;
<DT>ImageIterator<DD> the image iterator type for the destination i }
mage }
<DT>Accessor<DD> the image accessor type for the destination image else
<DT>info<DD> user supplied image import information {
<DT>iter<DD> image iterator referencing the upper left pixel of the std::vector<const ValueType*> scanlines(accessor_size);
destination image
<DT>a<DD> image accessor for the destination image
</DL>
*/
doxygen_overloaded_function(template <...> void importScalarImage)
template < class ImageIterator, class Accessor > for (unsigned y = 0U; y != height; ++y)
void importScalarImage( const ImageImportInfo & info, ImageIterator ite {
r, Accessor a ) decoder->nextScanline();
{
std::auto_ptr<Decoder> dec = decoder(info);
std::string pixeltype = dec->getPixelType();
if ( pixeltype == "UINT8" ) for (unsigned i = 0U; i != accessor_size; ++i)
read_band( dec.get(), iter, a, (UInt8)0 ); {
else if ( pixeltype == "INT16" ) scanlines[i] = static_cast<const ValueType*>(decode
read_band( dec.get(), iter, a, Int16() ); r->currentScanlineOfBand(i));
else if ( pixeltype == "UINT16" ) }
read_band( dec.get(), iter, a, (UInt16)0 );
else if ( pixeltype == "INT32" )
read_band( dec.get(), iter, a, Int32() );
else if ( pixeltype == "UINT32" )
read_band( dec.get(), iter, a, (UInt32)0 );
else if ( pixeltype == "FLOAT" )
read_band( dec.get(), iter, a, float() );
else if ( pixeltype == "DOUBLE" )
read_band( dec.get(), iter, a, double() );
else
vigra_precondition( false, "invalid pixeltype" );
// close the decoder ImageRowIterator is(image_iterator.rowIterator());
dec->close(); const ImageRowIterator is_end(is + width);
}
/********************************************************/ while (is != is_end)
/* */ {
/* importImage */ for (unsigned i = 0U; i != accessor_size; ++i)
/* */ {
/********************************************************/ image_accessor.setComponent(*scanlines[i], is,
static_cast<int>(i));
/** \brief Read the image specified by the given \ref vigra::ImageImpor scanlines[i] += offset;
tInfo object. }
++is;
<b> Declarations:</b> }
pass arguments explicitly:
\code
namespace vigra {
template <class ImageIterator, class Accessor>
void
importImage(ImageImportInfo const & image, ImageIterator iter,
Accessor a)
}
\endcode
use argument objects in conjunction with \ref ArgumentObjectFactori ++image_iterator.y;
es : }
\code }
namespace vigra {
template <class ImageIterator, class Accessor>
inline void
importImage(ImageImportInfo const & image, pair<ImageIterator,
Accessor> dest)
} }
\endcode
<b> Usage:</b>
<b>\#include</b> \<vigra/impex.hxx\><br>
Namespace: vigra
\code
vigra::ImageImportInfo info("myimage.gif"); template <class ImageIterator, class ImageAccessor>
void
if(info.isGrayscale()) importImage(const ImageImportInfo& import_info,
ImageIterator image_iterator, ImageAccessor image_acces
sor,
/* isScalar? */ VigraTrueType)
{ {
// create byte image of appropriate size VIGRA_UNIQUE_PTR<Decoder> decoder(vigra::decoder(import_info));
vigra::BImage in(info.width(), info.height());
vigra::importImage(info, destImage(in)); // read the image switch (pixel_t_of_string(decoder->getPixelType()))
... {
} case UNSIGNED_INT_8:
else read_image_band<UInt8>(decoder.get(), image_iterator, image
_accessor);
break;
case UNSIGNED_INT_16:
read_image_band<UInt16>(decoder.get(), image_iterator, imag
e_accessor);
break;
case UNSIGNED_INT_32:
read_image_band<UInt32>(decoder.get(), image_iterator, imag
e_accessor);
break;
case SIGNED_INT_16:
read_image_band<Int16>(decoder.get(), image_iterator, image
_accessor);
break;
case SIGNED_INT_32:
read_image_band<Int32>(decoder.get(), image_iterator, image
_accessor);
break;
case IEEE_FLOAT_32:
read_image_band<float>(decoder.get(), image_iterator, image
_accessor);
break;
case IEEE_FLOAT_64:
read_image_band<double>(decoder.get(), image_iterator, imag
e_accessor);
break;
default:
vigra_fail("detail::importImage<scalar>: not reached");
}
decoder->close();
}
template <class ImageIterator, class ImageAccessor>
void
importImage(const ImageImportInfo& import_info,
ImageIterator image_iterator, ImageAccessor image_acces
sor,
/* isScalar? */ VigraFalseType)
{ {
// create byte RGB image of appropriate size VIGRA_UNIQUE_PTR<Decoder> decoder(vigra::decoder(import_info));
vigra::BRGBImage in(info.width(), info.height());
vigra::importImage(info, destImage(in)); // read the image switch (pixel_t_of_string(decoder->getPixelType()))
... {
} case UNSIGNED_INT_8:
read_image_bands<UInt8>(decoder.get(), image_iterator, imag
e_accessor);
break;
case UNSIGNED_INT_16:
read_image_bands<UInt16>(decoder.get(), image_iterator, ima
ge_accessor);
break;
case UNSIGNED_INT_32:
read_image_bands<UInt32>(decoder.get(), image_iterator, ima
ge_accessor);
break;
case SIGNED_INT_16:
read_image_bands<Int16>(decoder.get(), image_iterator, imag
e_accessor);
break;
case SIGNED_INT_32:
read_image_bands<Int32>(decoder.get(), image_iterator, imag
e_accessor);
break;
case IEEE_FLOAT_32:
read_image_bands<float>(decoder.get(), image_iterator, imag
e_accessor);
break;
case IEEE_FLOAT_64:
read_image_bands<double>(decoder.get(), image_iterator, ima
ge_accessor);
break;
default:
vigra_fail("vigra::detail::importImage<non-scalar>: not rea
ched");
}
decoder->close();
}
template<class ValueType,
class ImageIterator, class ImageAccessor, class ImageScale
r>
void
write_image_band(Encoder* encoder,
ImageIterator image_upper_left, ImageIterator imag
e_lower_right, ImageAccessor image_accessor,
const ImageScaler& image_scaler)
{
typedef typename ImageIterator::row_iterator ImageRowIterator;
typedef typename ImageAccessor::value_type ImageValueType;
typedef RequiresExplicitCast<ValueType> explicit_cast;
vigra_precondition(image_lower_right.x >= image_upper_left.x,
"vigra::detail::write_image_band: negative w
idth");
vigra_precondition(image_lower_right.y >= image_upper_left.y,
"vigra::detail::write_image_band: negative h
eight");
const unsigned width(static_cast<unsigned>(image_lower_right.x
- image_upper_left.x));
const unsigned height(static_cast<unsigned>(image_lower_right.y
- image_upper_left.y));
encoder->setWidth(width);
encoder->setHeight(height);
encoder->setNumBands(1);
encoder->finalizeSettings();
const unsigned offset(encoder->getOffset()); // correct offset
only _after_ finalizeSettings()
// IMPLEMENTATION NOTE: We avoid calling the default
// constructor to allow classes ImageIterator that do not
// define one.
ImageIterator image_iterator(image_upper_left);
\endcode for (unsigned y = 0U; y != height; ++y)
{
ValueType* scanline = static_cast<ValueType*>(encoder->curr
entScanlineOfBand(0));
<b> Preconditions:</b> ImageRowIterator is(image_iterator.rowIterator());
const ImageRowIterator is_end(is + width);
<UL> while (is != is_end)
{
*scanline = explicit_cast::cast(image_scaler(image_acce
ssor(is)));
scanline += offset;
++is;
}
<LI> the image file must be readable encoder->nextScanline();
<LI> the file type must be one of
<DL> ++image_iterator.y;
<DT>"BMP"<DD> Microsoft Windows bitmap image file. }
<DT>"EXR"<DD> OpenEXR high dynamic range image format. }
(only available if libopenexr is installed)
<DT>"GIF"<DD> CompuServe graphics interchange format; 8-bit col
or.
<DT>"HDR"<DD> Radiance RGBE high dynamic range image format.
<DT>"JPEG"<DD> Joint Photographic Experts Group JFIF format;
compressed 24-bit color (only available if libjpeg is installed
).
<DT>"PNG"<DD> Portable Network Graphic
(only available if libpng is installed).
<DT>"PBM"<DD> Portable bitmap format (black and white).
<DT>"PGM"<DD> Portable graymap format (gray scale).
<DT>"PNM"<DD> Portable anymap.
<DT>"PPM"<DD> Portable pixmap format (color).
<DT>"SUN"<DD> SUN Rasterfile.
<DT>"TIFF"<DD> Tagged Image File Format.
(only available if libtiff is installed.)
<DT>"VIFF"<DD> Khoros Visualization image file.
</DL>
</UL>
**/
doxygen_overloaded_function(template <...> void importImage)
template < class ImageIterator, class Accessor > template<class ValueType,
void importImage( const ImageImportInfo & info, ImageIterator iter, Acc class ImageIterator, class ImageAccessor, class ImageScale
essor a ) r>
{ void
typedef typename NumericTraits<typename Accessor::value_type>::isSc write_image_bands(Encoder* encoder,
alar is_scalar; ImageIterator image_upper_left, ImageIterator ima
importImage( info, iter, a, is_scalar() ); ge_lower_right, ImageAccessor image_accessor,
} const ImageScaler& image_scaler)
{
typedef typename ImageIterator::row_iterator ImageRowIterator;
typedef RequiresExplicitCast<ValueType> explicit_cast;
template < class ImageIterator, class Accessor > vigra_precondition(image_lower_right.x >= image_upper_left.x,
void importImage( const ImageImportInfo & info, pair< ImageIterator, Ac "vigra::detail::write_image_bands: negative
cessor > dest ) width");
{ vigra_precondition(image_lower_right.y >= image_upper_left.y,
importImage( info, dest.first, dest.second ); "vigra::detail::write_image_bands: negative
} height");
template < class ImageIterator, class Accessor > const unsigned width(static_cast<unsigned>(image_lower_right.x
void importImage( const ImageImportInfo & info, ImageIterator iter, Acc - image_upper_left.x));
essor a, VigraFalseType ) const unsigned height(static_cast<unsigned>(image_lower_right.y
{ - image_upper_left.y));
importVectorImage( info, iter, a ); const unsigned accessor_size(image_accessor.size(image_upper_le
} ft));
template < class ImageIterator, class Accessor > encoder->setWidth(width);
void importImage( const ImageImportInfo & info, ImageIterator iter, Acc encoder->setHeight(height);
essor a, VigraTrueType ) encoder->setNumBands(accessor_size);
{ encoder->finalizeSettings();
importScalarImage( info, iter, a );
}
/*! const unsigned offset(encoder->getOffset()); // correct offset
\brief used for writing bands after the source data type has been fig only _after_ finalizeSettings()
ured out.
<b>\#include</b> \<vigra/impex.hxx\><br> // IMPLEMENTATION NOTE: We avoid calling the default
Namespace: vigra // constructor to allow classes ImageIterator that do not
// define one.
ImageIterator image_iterator(image_upper_left);
<b> Declaration:</b> // OPTIMIZATION: Specialization for the most common case
// of an RGB-image, i.e. 3 channels.
if (accessor_size == 3U)
{
ValueType* scanline_0;
ValueType* scanline_1;
ValueType* scanline_2;
\code for (unsigned y = 0U; y != height; ++y)
namespace vigra { {
template< class ImageIterator, class Accessor, class DstValueTy scanline_0 = static_cast<ValueType*>(encoder->currentSc
pe > anlineOfBand(0));
void write_bands( Encoder * enc, ImageIterator ul, ImageIterato scanline_1 = static_cast<ValueType*>(encoder->currentSc
r lr, Accessor a, DstValueType ) anlineOfBand(1));
} scanline_2 = static_cast<ValueType*>(encoder->currentSc
\endcode anlineOfBand(2));
\param enc encoder object through which the destination data will be ImageRowIterator is(image_iterator.rowIterator());
accessed const ImageRowIterator is_end(is + width);
\param ul image iterator referencing the upper left pixel of the sou
rce image
\param lr image iterator referencing the lower right pixel of the so
urce image
\param a image accessor for the source image
*/
template< class ImageIterator, class Accessor, class DstValueType >
void write_bands( Encoder * enc, ImageIterator ul, ImageIterator lr, Ac
cessor a, DstValueType)
{
typedef unsigned int size_type;
typedef typename ImageIterator::row_iterator SrcRowIterator;
typedef typename Accessor::value_type AccessorValueType;
typedef typename AccessorValueType::value_type SrcValueType;
// complete decoder settings
const size_type width = lr.x - ul.x;
const size_type height = lr.y - ul.y;
enc->setWidth(width);
enc->setHeight(height);
const size_type num_bands = a.size(ul);
enc->setNumBands(num_bands);
enc->finalizeSettings();
DstValueType * scanline;
// iterate
ImageIterator ys(ul);
// MIHAL no default constructor available for cachedfileimages
SrcRowIterator xs = ys.rowIterator();
// Speedup for the common cases while (is != is_end)
switch (num_bands) {
{ *scanline_0 = explicit_cast::cast(image_scaler(imag
case 2: e_accessor.getComponent(is, 0)));
{ *scanline_1 = explicit_cast::cast(image_scaler(imag
unsigned int offset = enc->getOffset(); e_accessor.getComponent(is, 1)));
DstValueType * scanline0; *scanline_2 = explicit_cast::cast(image_scaler(imag
DstValueType * scanline1; e_accessor.getComponent(is, 2)));
for( size_type y = 0; y < height; ++y, ++ys.y ) {
xs = ys.rowIterator(); scanline_0 += offset;
scanline0 = static_cast< DstValueType * > scanline_1 += offset;
(enc->currentScanlineOfBand(0)); scanline_2 += offset;
scanline1 = static_cast< DstValueType * >
(enc->currentScanlineOfBand(1));
for( size_type x = 0; x < width; ++x, ++xs) {
*scanline0 = detail::RequiresExplicitCast<DstValueType>
::cast(a.getComponent( xs, 0));
*scanline1 = detail::RequiresExplicitCast<DstValueType>
::cast(a.getComponent( xs, 1));
scanline0 += offset;
scanline1 += offset;
}
enc->nextScanline();
} ++is;
break;
}
case 3:
{
unsigned int offset = enc->getOffset();
DstValueType * scanline0;
DstValueType * scanline1;
DstValueType * scanline2;
for( size_type y = 0; y < height; ++y, ++ys.y ) {
xs = ys.rowIterator();
scanline0 = static_cast< DstValueType * >
(enc->currentScanlineOfBand(0));
scanline1 = static_cast< DstValueType * >
(enc->currentScanlineOfBand(1));
scanline2 = static_cast< DstValueType * >
(enc->currentScanlineOfBand(2));
for( size_type x = 0; x < width; ++x, ++xs) {
*scanline0 = detail::RequiresExplicitCast<DstValueType>
::cast(a.getComponent( xs, 0));
*scanline1 = detail::RequiresExplicitCast<DstValueType>
::cast(a.getComponent( xs, 1));
*scanline2 = detail::RequiresExplicitCast<DstValueType>
::cast(a.getComponent( xs, 2));
scanline0 += offset;
scanline1 += offset;
scanline2 += offset;
}
enc->nextScanline();
}
break;
}
case 4:
{
unsigned int offset = enc->getOffset();
DstValueType * scanline0;
DstValueType * scanline1;
DstValueType * scanline2;
DstValueType * scanline3;
for( size_type y = 0; y < height; ++y, ++ys.y ) {
xs = ys.rowIterator();
scanline0 = static_cast< DstValueType * >
(enc->currentScanlineOfBand(0));
scanline1 = static_cast< DstValueType * >
(enc->currentScanlineOfBand(1));
scanline2 = static_cast< DstValueType * >
(enc->currentScanlineOfBand(2));
scanline3 = static_cast< DstValueType * >
(enc->currentScanlineOfBand(3));
for( size_type x = 0; x < width; ++x, ++xs) {
*scanline0 = detail::RequiresExplicitCast<DstValueType>
::cast(a.getComponent( xs, 0));
*scanline1 = detail::RequiresExplicitCast<DstValueType>
::cast(a.getComponent( xs, 1));
*scanline2 = detail::RequiresExplicitCast<DstValueType>
::cast(a.getComponent( xs, 2));
*scanline3 = detail::RequiresExplicitCast<DstValueType>
::cast(a.getComponent( xs, 3));
scanline0 += offset;
scanline1 += offset;
scanline2 += offset;
scanline3 += offset;
}
enc->nextScanline();
}
break;
}
default:
{
// General case
for( size_type y = 0; y < height; ++y, ++ys.y ) {
for( size_type b = 0; b < num_bands; ++b ) {
xs = ys.rowIterator();
scanline = static_cast< DstValueType * >
(enc->currentScanlineOfBand(b));
for( size_type x = 0; x < width; ++x, ++xs ) {
*scanline = detail::RequiresExplicitCast<DstValueTy
pe>::cast(a.getComponent( xs, b ));
scanline += enc->getOffset();
} }
}
enc->nextScanline();
}
}
}
} // write_bands()
template< class MArray, class DstValueType > encoder->nextScanline();
void write_bands( Encoder * enc, MArray const & array, DstValueType)
{
typedef unsigned int size_type;
// complete decoder settings ++image_iterator.y;
const size_type width = array.shape(0);
const size_type height = array.shape(1);
enc->setWidth(width);
enc->setHeight(height);
const size_type num_bands = array.shape(2);
enc->setNumBands(num_bands);
enc->finalizeSettings();
DstValueType * scanline;
// iterate
for( size_type y = 0; y < height; ++y ) {
for( size_type b = 0; b < num_bands; ++b ) {
scanline = static_cast< DstValueType * >
(enc->currentScanlineOfBand(b));
for( size_type x = 0; x < width; ++x) {
*scanline = array(x, y, b);
scanline += enc->getOffset();
} }
} }
enc->nextScanline(); else
} {
} // write_bands() std::vector<ValueType*> scanlines(accessor_size);
/*! for (unsigned y = 0U; y != height; ++y)
\brief used for writing bands after the source data type has been fig {
ured out. for (unsigned i = 0U; i != accessor_size; ++i)
{
scanlines[i] = static_cast<ValueType*>(encoder->cur
rentScanlineOfBand(i));
}
<b>\#include</b> \<vigra/impex.hxx\><br> ImageRowIterator is(image_iterator.rowIterator());
Namespace: vigra const ImageRowIterator is_end(is + width);
<b> Declaration:</b> while (is != is_end)
{
for (unsigned i = 0U; i != accessor_size; ++i)
{
*scanlines[i] = explicit_cast::cast(image_scale
r(image_accessor.getComponent(is, static_cast<int>(i))));
scanlines[i] += offset;
}
++is;
}
\code encoder->nextScanline();
namespace vigra {
template< class ImageIterator, class Accessor, class DstValueTy
pe >
void write_band( Encoder * enc, ImageIterator ul, ImageIterator
lr, Accessor a, DstValueType )
}
\endcode
\param enc encoder object through which the destination data will be ++image_iterator.y;
accessed }
\param ul image iterator referencing the upper left pixel of the sou }
rce image
\param lr image iterator referencing the lower right pixel of the so
urce image
\param a image accessor for the source image
*/
template< class ImageIterator, class Accessor, class DstValueType >
void write_band( Encoder * enc, ImageIterator ul, ImageIterator lr, Acc
essor a, DstValueType)
{
typedef unsigned int size_type;
typedef typename ImageIterator::row_iterator SrcRowIterator;
typedef typename Accessor::value_type SrcValueType;
// complete decoder settings
const size_type width = size_type(lr.x - ul.x);
const size_type height = size_type(lr.y - ul.y);
enc->setWidth(width);
enc->setHeight(height);
enc->setNumBands(1);
enc->finalizeSettings();
DstValueType * scanline;
// iterate
ImageIterator ys(ul);
// MIHAL no default constructor available for cachedfileimages.
SrcRowIterator xs = ys.rowIterator();
size_type y;
for( y = 0; y < height; ++y, ++ys.y ) {
xs = ys.rowIterator();
scanline = static_cast< DstValueType * >(enc->currentScanlineOf
Band(0));
for( size_type x = 0; x < width; ++x, ++xs, ++scanline )
*scanline = detail::RequiresExplicitCast<DstValueType>::cas
t(a(xs));
enc->nextScanline();
} }
} // write_band()
namespace detail { template <class ImageIterator, class ImageAccessor>
void
exportImage(ImageIterator image_upper_left, ImageIterator image_low
er_right, ImageAccessor image_accessor,
const ImageExportInfo& export_info,
/* isScalar? */ VigraTrueType)
{
typedef typename ImageAccessor::value_type ImageValueType;
// export scalar images without conversion VIGRA_UNIQUE_PTR<Encoder> encoder(vigra::encoder(export_info));
template < class SrcIterator, class SrcAccessor, class T >
void exportScalarImage(SrcIterator sul, SrcIterator slr, SrcAccessor sg
et,
Encoder * enc, T zero)
{
write_band( enc, sul, slr, sget, zero );
}
// export scalar images with conversion std::string pixel_type(export_info.getPixelType());
template < class SrcIterator, class SrcAccessor, class T > const bool downcast(negotiatePixelType(encoder->getFileType(),
void exportScalarImage(SrcIterator sul, SrcIterator slr, SrcAccessor sg TypeAsString<ImageValueType>::result(), pixel_type));
et, const pixel_t type(pixel_t_of_string(pixel_type));
Encoder * enc,
const ImageExportInfo & info,
T zero)
{
double fromMin, fromMax, toMin, toMax;
if(info.getFromMin() < info.getFromMax())
{
fromMin = info.getFromMin();
fromMax = info.getFromMax();
}
else
{
typedef typename SrcAccessor::value_type SrcValue;
FindMinMax<SrcValue> minmax;
inspectImage( sul, slr, sget, minmax );
fromMin = (double)minmax.min;
fromMax = (double)minmax.max;
if(fromMax <= fromMin)
fromMax = fromMin + 1.0;
}
if(info.getToMin() < info.getToMax()) encoder->setPixelType(pixel_type);
{
toMin = info.getToMin();
toMax = info.getToMax();
}
else
{
toMin = (double)NumericTraits<T>::min();
toMax = (double)NumericTraits<T>::max();
}
double scale = (toMax - toMin) / (fromMax - fromMin); const range_t image_source_range(find_source_value_range(export
double offset = (toMin / scale) - fromMin; _info,
BasicImage<T> image(slr-sul); image_
transformImage( sul, slr, sget, image.upperLeft(), image.accessor() upper_left, image_lower_right, image_accessor));
, const range_t destination_range(find_destination_value_range(ex
linearIntensityTransform(scale, offset)); port_info, type));
write_band( enc, image.upperLeft(),
image.lowerRight(), image.accessor(), zero );
}
// export vector images without conversion if ((downcast || export_info.hasForcedRangeMapping()) &&
template < class SrcIterator, class SrcAccessor, class T > (image_source_range.first != destination_range.first || ima
void exportVectorImage(SrcIterator sul, SrcIterator slr, SrcAccessor sg ge_source_range.second != destination_range.second))
et, {
Encoder * enc, T zero) const linear_transform image_rescaler(image_source_range, d
{ estination_range);
int bands = sget.size(sul);
vigra_precondition(isBandNumberSupported(enc->getFileType(), bands)
,
"exportImage(): file format does not support requested number of
bands (color channels)");
write_bands( enc, sul, slr, sget, zero );
}
// export vector images with conversion switch (type)
template < class SrcIterator, class SrcAccessor, class T > {
void exportVectorImage(SrcIterator sul, SrcIterator slr, SrcAccessor sg case UNSIGNED_INT_8:
et, write_image_band<UInt8>(encoder.get(),
Encoder * enc, image_upper_left, image_lower_r
const ImageExportInfo & info, ight, image_accessor, image_rescaler);
T zero) break;
{ case UNSIGNED_INT_16:
unsigned int bands = sget.size(sul); write_image_band<UInt16>(encoder.get(),
vigra_precondition(isBandNumberSupported(enc->getFileType(), bands) image_upper_left, image_lower_
, right, image_accessor, image_rescaler);
"exportImage(): file format does not support requested number of break;
bands (color channels)"); case UNSIGNED_INT_32:
write_image_band<UInt32>(encoder.get(),
typedef typename SrcAccessor::ElementAccessor SrcElementAccessor; image_upper_left, image_lower_
typedef typename SrcElementAccessor::value_type SrcComponent; right, image_accessor, image_rescaler);
double fromMin, fromMax, toMin, toMax; break;
if(info.getFromMin() < info.getFromMax()) case SIGNED_INT_16:
{ write_image_band<Int16>(encoder.get(),
fromMin = info.getFromMin(); image_upper_left, image_lower_r
fromMax = info.getFromMax(); ight, image_accessor, image_rescaler);
} break;
else case SIGNED_INT_32:
{ write_image_band<Int32>(encoder.get(),
FindMinMax<SrcComponent> minmax; image_upper_left, image_lower_r
for(unsigned int i=0; i<bands; ++i) ight, image_accessor, image_rescaler);
break;
case IEEE_FLOAT_32:
write_image_band<float>(encoder.get(),
image_upper_left, image_lower_r
ight, image_accessor, image_rescaler);
break;
case IEEE_FLOAT_64:
write_image_band<double>(encoder.get(),
image_upper_left, image_lower_
right, image_accessor, image_rescaler);
break;
default:
vigra_fail("vigra::detail::exportImage<scalar>: not rea
ched");
}
}
else
{ {
SrcElementAccessor band(i, sget); switch (type)
inspectImage( sul, slr, band, minmax ); {
case UNSIGNED_INT_8:
write_image_band<UInt8>(encoder.get(),
image_upper_left, image_lower_r
ight, image_accessor, identity());
break;
case UNSIGNED_INT_16:
write_image_band<UInt16>(encoder.get(),
image_upper_left, image_lower_
right, image_accessor, identity());
break;
case UNSIGNED_INT_32:
write_image_band<UInt32>(encoder.get(),
image_upper_left, image_lower_
right, image_accessor, identity());
break;
case SIGNED_INT_16:
write_image_band<Int16>(encoder.get(),
image_upper_left, image_lower_r
ight, image_accessor, identity());
break;
case SIGNED_INT_32:
write_image_band<Int32>(encoder.get(),
image_upper_left, image_lower_r
ight, image_accessor, identity());
break;
case IEEE_FLOAT_32:
write_image_band<float>(encoder.get(),
image_upper_left, image_lower_r
ight, image_accessor, identity());
break;
case IEEE_FLOAT_64:
write_image_band<double>(encoder.get(),
image_upper_left, image_lower_
right, image_accessor, identity());
break;
default:
vigra_fail("vigra::detail::exportImage<scalar>: not rea
ched");
}
} }
fromMin = (double)minmax.min; encoder->close();
fromMax = (double)minmax.max;
if(fromMax <= fromMin)
fromMax = fromMin + 1.0;
} }
if(info.getToMin() < info.getToMax()) template <class ImageIterator, class ImageAccessor>
void
exportImage(ImageIterator image_upper_left, ImageIterator image_low
er_right, ImageAccessor image_accessor,
const ImageExportInfo& export_info,
/* isScalar? */ VigraFalseType)
{ {
toMin = info.getToMin(); typedef typename ImageAccessor::value_type ImageBaseType;
toMax = info.getToMax(); typedef typename ImageBaseType::value_type ImageValueType;
}
else
{
toMin = (double)NumericTraits<T>::min();
toMax = (double)NumericTraits<T>::max();
}
double scale = (toMax - toMin) / (fromMax - fromMin);
double offset = (toMin / scale) - fromMin;
int w = slr.x - sul.x;
int h = slr.y - sul.y;
typedef vigra::MultiArray<3, T> MArray;
MArray array(typename MArray::difference_type(w, h, bands));
for(unsigned int i=0; i<bands; ++i)
{
BasicImageView<T> subImage = makeBasicImageView(array.bindOuter
(i));
SrcElementAccessor band(i, sget);
transformImage( sul, slr, band, subImage.upperLeft(), subImage.
accessor(),
linearIntensityTransform( scale, offset ) );
}
write_bands( enc, array, zero );
}
} // namespace detail VIGRA_UNIQUE_PTR<Encoder> encoder(vigra::encoder(export_info));
/*! std::string pixel_type(export_info.getPixelType());
\brief Deprecated. const bool downcast(negotiatePixelType(encoder->getFileType(),
TypeAsString<ImageValueType>::result(), pixel_type));
const pixel_t type(pixel_t_of_string(pixel_type));
Use \ref exportImage() instead. encoder->setPixelType(pixel_type);
<b> Declaration:</b> vigra_precondition(isBandNumberSupported(encoder->getFileType()
, image_accessor.size(image_upper_left)),
"exportImage(): file format does not support
requested number of bands (color channels)");
\code const range_t image_source_range(find_source_value_range(export
namespace vigra { _info,
template < class SrcIterator, class SrcAccessor > image_
void exportFloatingVectorImage( SrcIterator sul, SrcIterator sl upper_left, image_lower_right, image_accessor));
r, SrcAccessor sget, const range_t destination_range(find_destination_value_range(ex
const ImageExportInfo & info ) port_info, pixel_t_of_string(pixel_type)));
}
\endcode
*/
doxygen_overloaded_function(template <...> void exportFloatingVectorImage)
template < class SrcIterator, class SrcAccessor >
void exportFloatingVectorImage( SrcIterator sul, SrcIterator slr, SrcAc
cessor sget,
const ImageExportInfo & info )
{
exportImage(sul, slr, sget, info);
}
/*! if ((downcast || export_info.hasForcedRangeMapping()) &&
\brief Deprecated. (image_source_range.first != destination_range.first || ima
ge_source_range.second != destination_range.second))
Use \ref exportImage() instead. {
const linear_transform image_rescaler(image_source_range, d
estination_range);
<b> Declaration:</b> switch (type)
{
case UNSIGNED_INT_8:
write_image_bands<UInt8>(encoder.get(),
image_upper_left, image_lower_
right, image_accessor, image_rescaler);
break;
case UNSIGNED_INT_16:
write_image_bands<UInt16>(encoder.get(),
image_upper_left, image_lower
_right, image_accessor, image_rescaler);
break;
case UNSIGNED_INT_32:
write_image_bands<UInt32>(encoder.get(),
image_upper_left, image_lower
_right, image_accessor, image_rescaler);
break;
case SIGNED_INT_16:
write_image_bands<Int16>(encoder.get(),
image_upper_left, image_lower_
right, image_accessor, image_rescaler);
break;
case SIGNED_INT_32:
write_image_bands<Int32>(encoder.get(),
image_upper_left, image_lower_
right, image_accessor, image_rescaler);
break;
case IEEE_FLOAT_32:
write_image_bands<float>(encoder.get(),
image_upper_left, image_lower_
right, image_accessor, image_rescaler);
break;
case IEEE_FLOAT_64:
write_image_bands<double>(encoder.get(),
image_upper_left, image_lower
_right, image_accessor, image_rescaler);
break;
default:
vigra_fail("vigra::detail::exportImage<non-scalar>: not
reached");
}
}
else
{
switch (type)
{
case UNSIGNED_INT_8:
write_image_bands<UInt8>(encoder.get(),
image_upper_left, image_lower_
right, image_accessor, identity());
break;
case UNSIGNED_INT_16:
write_image_bands<UInt16>(encoder.get(),
image_upper_left, image_lower
_right, image_accessor, identity());
break;
case UNSIGNED_INT_32:
write_image_bands<UInt32>(encoder.get(),
image_upper_left, image_lower
_right, image_accessor, identity());
break;
case SIGNED_INT_16:
write_image_bands<Int16>(encoder.get(),
image_upper_left, image_lower_
right, image_accessor, identity());
break;
case SIGNED_INT_32:
write_image_bands<Int32>(encoder.get(),
image_upper_left, image_lower_
right, image_accessor, identity());
break;
case IEEE_FLOAT_32:
write_image_bands<float>(encoder.get(),
image_upper_left, image_lower_
right, image_accessor, identity());
break;
case IEEE_FLOAT_64:
write_image_bands<double>(encoder.get(),
image_upper_left, image_lower
_right, image_accessor, identity());
break;
default:
vigra_fail("vigra::detail::exportImage<non-scalar>: not
reached");
}
}
\code encoder->close();
namespace vigra {
template < class SrcIterator, class SrcAccessor >
void exportIntegralVectorImage( SrcIterator sul, SrcIterator sl
r, SrcAccessor sget,
const ImageExportInfo & info )
} }
\endcode } // end namespace detail
*/
doxygen_overloaded_function(template <...> void exportIntegralVectorImage)
template < class SrcIterator, class SrcAccessor >
void exportIntegralVectorImage( SrcIterator sul, SrcIterator slr, SrcAc
cessor sget,
const ImageExportInfo & info )
{
exportImage(sul, slr, sget, info);
}
/*! /*!
\brief Deprecated. * \brief Read the image specified by the given \ref
* vigra::ImageImportInfo object.
Use \ref exportImage() instead. *
* <B>Declarations</B>
<b> Declaration:</b> *
* Pass arguments explicitly:
\code * \code
namespace vigra { * namespace vigra {
template < class SrcIterator, class SrcAccessor > * template <class ImageIterator, class Accessor>
void exportFloatingScalarImage( SrcIterator sul, SrcIterator sl * void
r, SrcAccessor sget, * importImage(const ImageImportInfo& importInfo,
const ImageExportInfo & info ) * ImageIterator imageIterator, Accessor imageAccessor)
} * }
\endcode * \endcode
*/ *
doxygen_overloaded_function(template <...> void exportFloatingScalarImage) * Use argument objects in conjunction with \ref ArgumentObjectFactorie
s :
template < class SrcIterator, class SrcAccessor > * \code
void exportFloatingScalarImage( SrcIterator sul, SrcIterator slr, SrcAc * namespace vigra {
cessor sget, * template <class ImageIterator, class Accessor>
const ImageExportInfo & info ) * inline void
* importImage(const ImageImportInfo& importInfo,
* const pair<ImageIterator, Accessor>& image)
* }
* \endcode
*
* <B>Usage</B>
*
* <B>\#include \<vigra/impex.hxx\></B>
*
* Namespace: vigra
*
* \code
* ImageImportInfo info("myimage.gif");
*
* if (info.isGrayscale())
* {
* // create byte image of appropriate size
* BImage image(info.width(), info.height());
*
* importImage(info, destImage(image));
* ...
* }
* else
* {
* // create byte RGB image of appropriate size
* BRGBImage image(info.width(), info.height());
*
* importImage(info, destImage(image));
* ...
* }
* \endcode
*
* <B>Preconditions</B>
*
* - The image file must be readable and
* - the file type must be one of the following:
*
* | Type | Extension | Name
| Support Library |
* |------|-----------|------------------------------------------------
------------|-----------------|
* | BMP | bmp | Microsoft Windows bitmap image file
| |
* | EXR | exr | OpenEXR high dynamic range image format
| libopenexr |
* | GIF | gif | CompuServe graphics interchange format, 8-bit c
olor | |
* | HDR | hdr | Radiance RGBE high dynamic range image format
| libexr? |
* | JPEG | jpg, jpeg | Joint Photographic Experts Group JFIF format, 2
4-bit color | libjpeg |
* | PBM | pbm | Portable bitmap format (black and white)
| |
* | PGM | pgm | Portable graymap format (gray scale)
| |
* | PNG | png | Portable Network Graphic
| libpng |
* | PNM | pnm | Portable anymap
| |
* | PPM | ppm | Portable pixmap format (color)
| |
* | SUN | ras | SUN Rasterfile
| |
* | TIFF | tif, tiff | Tagged Image File Format
| libtiff |
* | VIFF | xv | Khoros Visualization image file
| |
*/
doxygen_overloaded_function(template <...> inline void importImage)
template <class ImageIterator, class ImageAccessor>
inline void
importImage(const ImageImportInfo& import_info,
ImageIterator image_iterator, ImageAccessor image_accessor)
{
typedef typename ImageAccessor::value_type ImageValueType;
typedef typename NumericTraits<ImageValueType>::isScalar is_scalar;
detail::importImage(import_info,
image_iterator, image_accessor,
is_scalar());
}
template <class ImageIterator, class ImageAccessor>
inline void
importImage(const ImageImportInfo& import_info,
const vigra::pair<ImageIterator, ImageAccessor>& image)
{ {
exportImage(sul, slr, sget, info); importImage(import_info,
image.first, image.second);
} }
/*! /*!
\brief Deprecated. * \brief Write an image given a \ref vigra::ImageExportInfo object.
*
Use \ref exportImage() instead. * If the file format to be exported to supports the pixel type of
* the source image, the pixel type will be kept
<b> Declaration:</b> * (e.g. <tt>float</tt> can be stored as TIFF without conversion,
* in contrast to most other image export toolkits). Otherwise,
\code * the pixel values are transformed to the range 0..255 and
namespace vigra { * converted to <tt>unsigned char</tt>. Currently, the following
template < class SrcIterator, class SrcAccessor > * file formats are supported. The pixel types given in brackets
void exportIntegralScalarImage( SrcIterator sul, SrcIterator sl * are those that are written without conversion:
r, SrcAccessor sget, * - BMP: Microsoft Windows bitmap image file (pixel types: UINT8 a
const ImageExportInfo & info ) s gray and RGB);
} * - GIF: CompuServe graphics interchange format, 8-bit color (pixe
\endcode l types: UINT8 as gray and RGB);
*/ * - JPEG: Joint Photographic Experts Group JFIF format, compressed
doxygen_overloaded_function(template <...> void exportIntegralScalarImage) 24-bit color
* (pixel types: UINT8 as gray and RGB), only available if
template < class SrcIterator, class SrcAccessor > libjpeg is installed;
void exportIntegralScalarImage( SrcIterator sul, SrcIterator slr, SrcAc * - PNG: Portable Network Graphic (pixel types: UINT8 and UINT16 w
cessor sget, ith up to 4 channels),
const ImageExportInfo & info ) * only available if libpng is installed;
{ * - PBM: Portable bitmap format (black and white);
exportImage(sul, slr, sget, info); * - PGM: Portable graymap format (pixel types: UINT8, INT16, INT32
} as gray scale);
* - PNM: Portable anymap (pixel types: UINT8, INT16, INT32 as gray
/********************************************************/ and RGB);
/* */ * - PPM: Portable pixmap format (pixel types: UINT8, INT16, INT32
/* exportImage */ as RGB);
/* */ * - SUN: SUN Rasterfile (pixel types: UINT8 as gray and RGB);
/********************************************************/ * - TIFF: Tagged Image File Format
* (pixel types: UINT8, INT16, INT32, FLOAT, DOUBLE with up t
/** \brief Write an image, given an \ref vigra::ImageExportInfo object. o 4 channels),
* only available if libtiff is installed;
If the file format to be exported to supports the pixel type of the * - VIFF: Khoros Visualization image file
source image, the pixel type will be kept (e.g. <tt>float</tt> * (pixel types: UINT8, INT16, INT32, FLOAT, DOUBLE with arbi
can be stored as TIFF without conversion, in contrast to most other trary many channels);
image export toolkits). Otherwise, the pixel values are transformed *
to the range 0.255 and converted to <tt>unsigned char</tt>. Currently, * <B>Declarations</B>
the following file formats are supported. The pixel types given in *
brackets are those that are written without conversion: * Pass arguments explicitly:
* \code
<DL> * namespace vigra {
<DT>"BMP"<DD> Microsoft Windows bitmap image file (pixel types: UINT8 a * template <class ImageIterator, class ImageAccessor>
s gray and RGB). * void
<DT>"GIF"<DD> CompuServe graphics interchange format; 8-bit color (pixe * exportImage(ImageIterator imageUpperLeft, ImageIterator imageLow
l types: UINT8 as gray and RGB). erRight, ImageAccessor imageAccessor,
<DT>"JPEG"<DD> Joint Photographic Experts Group JFIF format; compressed * const ImageExportInfo& exportInfo)
24-bit color * }
(pixel types: UINT8 as gray and RGB). (only available if * \endcode
libjpeg is installed) *
<DT>"PNG"<DD> Portable Network Graphic (pixel types: UINT8 and UINT16 w * Use argument objects in conjunction with \ref ArgumentObjectFactorie
ith up to 4 channels). s :
(only available if libpng is installed) * \code
<DT>"PBM"<DD> Portable bitmap format (black and white). * namespace vigra {
<DT>"PGM"<DD> Portable graymap format (pixel types: UINT8, INT16, INT32 * template <class ImageIterator, class ImageAccessor>
as gray scale)). * void exportImage(ImageIterator imageUpperLeft, ImageIterator
<DT>"PNM"<DD> Portable anymap (pixel types: UINT8, INT16, INT32 as gray imageLowerRight, ImageAccessor imageAccessor,
and RGB). * const ImageExportInfo& exportInfo)
<DT>"PPM"<DD> Portable pixmap format (pixel types: UINT8, INT16, INT32 * }
as RGB). * \endcode
<DT>"SUN"<DD> SUN Rasterfile (pixel types: UINT8 as gray and RGB). *
<DT>"TIFF"<DD> Tagged Image File Format * <B>Usage</B>
(pixel types: UINT8, INT16, INT32, FLOAT, DOUBLE with up to *
4 channels). * <B>\#include \<vigra/impex.hxx\></B>
(only available if libtiff is installed.) *
<DT>"VIFF"<DD> Khoros Visualization image file * Namespace: vigra
(pixel types: UINT8, INT16, INT32, FLOAT, DOUBLE with arbitrary man * \code
y channels). * BRGBImage image(width, height);
</DL> * ...
*
<b> Declarations:</b> * // write as JPEG image, using compression quality 80
* exportImage(srcImageRange(image),
pass arguments explicitly: * ImageExportInfo("my-image.jpg").setCompression("80")
\code );
namespace vigra { *
template <class SrcIterator, class SrcAccessor> * // Force it to a particular pixel type. The pixel type must be
void exportImage(SrcIterator sul, SrcIterator slr, SrcAccessor sget supported by the
, * // desired image file format, otherwise an \ref vigra::Precondit
ImageExportInfo const & info) ionViolation
} * // exception will be thrown.
\endcode * exportImage(srcImageRange(image),
* ImageExportInfo("my-INT16-image.tif").setPixelType("
use argument objects in conjunction with \ref ArgumentObjectFactories : INT16"));
\code * \endcode
namespace vigra { *
template <class SrcIterator, class SrcAccessor> * <B>Preconditions</B>
void exportImage(SrcIterator sul, SrcIterator slr, SrcAccessor sget *
, * - The image file must be writable and
ImageExportInfo const & info) * - the file type must be one of the supported file types.
} */
\endcode doxygen_overloaded_function(template <...> inline void exportImage)
<b> Usage:</b> template <class ImageIterator, class ImageAccessor>
inline void
<b>\#include</b> \<vigra/impex.hxx\><br> exportImage(ImageIterator image_upper_left, ImageIterator image_lower_r
Namespace: vigra ight, ImageAccessor image_accessor,
const ImageExportInfo& export_info)
\code
vigra::BRGBImage out(w, h);
...
// write as JPEG image, using compression quality 80
vigra::exportImage(srcImageRange(out),
vigra::ImageExportInfo("myimage.jpg").setCompression(
"80"));
// force it to a particular pixel type (the pixel type must be supporte
d by the
// desired image file format, otherwise an \ref vigra::PreconditionViol
ation exception will be thrown)
vigra::exportImage(srcImageRange(out),
vigra::ImageExportInfo("myINT16image.tif").setPixelTy
pe("INT16"));
\endcode
<b> Preconditions:</b>
<UL>
<LI> the image file must be writable.
<LI> the file type must be one of the supported file types.
</UL>
**/
doxygen_overloaded_function(template <...> void exportImage)
template < class SrcIterator, class SrcAccessor >
void exportImage( SrcIterator sul, SrcIterator slr, SrcAccessor sget,
const ImageExportInfo & info )
{ {
typedef typename NumericTraits<typename SrcAccessor::value_type>::i typedef typename ImageAccessor::value_type ImageValueType;
sScalar is_scalar; typedef typename NumericTraits<ImageValueType>::isScalar is_scalar;
try try
{ {
exportImage( sul, slr, sget, info, is_scalar() ); detail::exportImage(image_upper_left, image_lower_right, image_
accessor,
export_info,
is_scalar());
} }
catch(Encoder::TIFFCompressionException &) catch (Encoder::TIFFCompressionException&)
{ {
const_cast<ImageExportInfo &>(info).setCompression(""); ImageExportInfo info(export_info);
exportImage( sul, slr, sget, info, is_scalar() );
}
}
template < class SrcIterator, class SrcAccessor > info.setCompression("");
inline detail::exportImage(image_upper_left, image_lower_right, image_
void exportImage( triple<SrcIterator, SrcIterator, SrcAccessor> src, accessor,
const ImageExportInfo & info ) info,
{ is_scalar());
exportImage( src.first, src.second, src.third, info );
}
template < class SrcIterator, class SrcAccessor >
void exportImage( SrcIterator sul, SrcIterator slr, SrcAccessor sget,
const ImageExportInfo & info, VigraFalseType /*not sc
alar */)
{
typedef typename SrcAccessor::value_type AccessorValueType;
typedef typename AccessorValueType::value_type SrcValueType;
std::string pixeltype = info.getPixelType();
std::auto_ptr<Encoder> enc = encoder(info);
bool downcast = negotiatePixelType(enc->getFileType(),
TypeAsString<SrcValueType>::result(), pixeltype);
enc->setPixelType(pixeltype);
if(downcast || info.hasForcedRangeMapping())
{
if(pixeltype == "UINT8")
detail::exportVectorImage( sul, slr, sget, enc.get(), info,
(UInt8)0);
else if(pixeltype == "INT16")
detail::exportVectorImage( sul, slr, sget, enc.get(), info,
Int16());
else if(pixeltype == "UINT16")
detail::exportVectorImage( sul, slr, sget, enc.get(), info,
(UInt16)0);
else if(pixeltype == "INT32")
detail::exportVectorImage( sul, slr, sget, enc.get(), info,
Int32());
else if(pixeltype == "UINT32")
detail::exportVectorImage( sul, slr, sget, enc.get(), info,
(UInt32)0);
else if(pixeltype == "FLOAT")
detail::exportVectorImage( sul, slr, sget, enc.get(), info,
float());
else if(pixeltype == "DOUBLE")
detail::exportVectorImage( sul, slr, sget, enc.get(), info,
double());
} }
else
{
if(pixeltype == "UINT8")
detail::exportVectorImage( sul, slr, sget, enc.get(), (UInt
8)0);
else if(pixeltype == "INT16")
detail::exportVectorImage( sul, slr, sget, enc.get(), Int16
());
else if(pixeltype == "UINT16")
detail::exportVectorImage( sul, slr, sget, enc.get(), (UInt
16)0);
else if(pixeltype == "INT32")
detail::exportVectorImage( sul, slr, sget, enc.get(), Int32
());
else if(pixeltype == "UINT32")
detail::exportVectorImage( sul, slr, sget, enc.get(), (UInt
32)0);
else if(pixeltype == "FLOAT")
detail::exportVectorImage( sul, slr, sget, enc.get(), float
());
else if(pixeltype == "DOUBLE")
detail::exportVectorImage( sul, slr, sget, enc.get(), doubl
e());
}
enc->close();
} }
template < class SrcIterator, class SrcAccessor > template <class ImageIterator, class ImageAccessor>
void exportImage( SrcIterator sul, SrcIterator slr, SrcAccessor sget, inline void
const ImageExportInfo & info, VigraTrueType /*scalar* exportImage(const vigra::triple<ImageIterator, ImageIterator, ImageAcce
/ ) ssor>& image,
const ImageExportInfo& export_info)
{ {
typedef typename SrcAccessor::value_type SrcValueType; exportImage(image.first, image.second, image.third,
std::string pixeltype = info.getPixelType(); export_info);
std::auto_ptr<Encoder> enc = encoder(info);
bool downcast = negotiatePixelType(enc->getFileType(),
TypeAsString<SrcValueType>::result(), pixeltype)
;
enc->setPixelType(pixeltype);
if(downcast || info.hasForcedRangeMapping())
{
if(pixeltype == "UINT8")
detail::exportScalarImage( sul, slr, sget, enc.get(), info,
(UInt8)0);
else if(pixeltype == "INT16")
detail::exportScalarImage( sul, slr, sget, enc.get(), info,
Int16());
else if(pixeltype == "UINT16")
detail::exportScalarImage( sul, slr, sget, enc.get(), info,
(UInt16)0);
else if(pixeltype == "INT32")
detail::exportScalarImage( sul, slr, sget, enc.get(), info,
Int32());
else if(pixeltype == "UINT32")
detail::exportScalarImage( sul, slr, sget, enc.get(), info,
(UInt32)0);
else if(pixeltype == "FLOAT")
detail::exportScalarImage( sul, slr, sget, enc.get(), info,
float());
else if(pixeltype == "DOUBLE")
detail::exportScalarImage( sul, slr, sget, enc.get(), info,
double());
}
else
{
if(pixeltype == "UINT8")
detail::exportScalarImage( sul, slr, sget, enc.get(), (UInt
8)0);
else if(pixeltype == "INT16")
detail::exportScalarImage( sul, slr, sget, enc.get(), Int16
());
else if(pixeltype == "UINT16")
detail::exportScalarImage( sul, slr, sget, enc.get(), (UInt
16)0);
else if(pixeltype == "INT32")
detail::exportScalarImage( sul, slr, sget, enc.get(), Int32
());
else if(pixeltype == "UINT32")
detail::exportScalarImage( sul, slr, sget, enc.get(), (UInt
32)0);
else if(pixeltype == "FLOAT")
detail::exportScalarImage( sul, slr, sget, enc.get(), float
());
else if(pixeltype == "DOUBLE")
detail::exportScalarImage( sul, slr, sget, enc.get(), doubl
e());
}
enc->close();
} }
//@} /** @} */
} // namespace vigra } // end namespace vigra
#endif /* VIGRA_IMPEX_HXX */ #endif // VIGRA_IMPEX_HXX
 End of changes. 97 change blocks. 
1237 lines changed or deleted 800 lines changed or added


 inspectimage.hxx   inspectimage.hxx 
skipping to change at line 46 skipping to change at line 46
#ifndef VIGRA_INSPECTIMAGE_HXX #ifndef VIGRA_INSPECTIMAGE_HXX
#define VIGRA_INSPECTIMAGE_HXX #define VIGRA_INSPECTIMAGE_HXX
#include <vector> #include <vector>
#include <algorithm> #include <algorithm>
#include "utilities.hxx" #include "utilities.hxx"
#include "numerictraits.hxx" #include "numerictraits.hxx"
#include "iteratortraits.hxx" #include "iteratortraits.hxx"
#include "functortraits.hxx" #include "functortraits.hxx"
#include "rgbvalue.hxx" #include "rgbvalue.hxx"
#include "inspector_passes.hxx"
namespace vigra { namespace vigra {
/** \addtogroup InspectAlgo Algorithms to Inspect Images /** \addtogroup InspectAlgo Algorithms to Inspect Images
Apply read-only functor to every pixel Apply read-only functor to every pixel
*/ */
//@{ //@{
/********************************************************/ /********************************************************/
skipping to change at line 181 skipping to change at line 182
Accessor accessor; Accessor accessor;
Functor functor; Functor functor;
functor(accessor(ix)); // return not used functor(accessor(ix)); // return not used
\endcode \endcode
*/ */
doxygen_overloaded_function(template <...> void inspectImage) doxygen_overloaded_function(template <...> void inspectImage)
template <class ImageIterator, class Accessor>
struct inspectImage_binder
{
ImageIterator upperleft;
ImageIterator lowerright;
Accessor a;
inspectImage_binder(ImageIterator ul, ImageIterator lr, Accessor ac)
: upperleft(ul), lowerright(lr), a(ac) {}
template <class Functor>
void operator()(Functor & f)
{
int w = lowerright.x - upperleft.x;
for (ImageIterator t = upperleft; t.y < lowerright.y; ++t.y)
{
inspectLine(t.rowIterator(), t.rowIterator() + w, a, f);
}
}
};
template <class ImageIterator, class Accessor, class Functor> template <class ImageIterator, class Accessor, class Functor>
void void
inspectImage(ImageIterator upperleft, ImageIterator lowerright, inspectImage(ImageIterator upperleft, ImageIterator lowerright,
Accessor a, Functor & f) Accessor a, Functor & f)
{ {
int w = lowerright.x - upperleft.x; inspectImage_binder<ImageIterator, Accessor> g(upperleft, lowerright, a
);
for(; upperleft.y<lowerright.y; ++upperleft.y) detail::extra_passes_select(g, f);
{
inspectLine(upperleft.rowIterator(),
upperleft.rowIterator() + w, a, f);
}
} }
template <class ImageIterator, class Accessor, class Functor> template <class ImageIterator, class Accessor, class Functor>
inline inline
void void
inspectImage(triple<ImageIterator, ImageIterator, Accessor> img, inspectImage(triple<ImageIterator, ImageIterator, Accessor> img,
Functor & f) Functor & f)
{ {
inspectImage(img.first, img.second, img.third, f); inspectImage(img.first, img.second, img.third, f);
} }
skipping to change at line 309 skipping to change at line 326
Functor functor; Functor functor;
if(mask_accessor(mx)) functor(accessor(ix)); if(mask_accessor(mx)) functor(accessor(ix));
\endcode \endcode
*/ */
doxygen_overloaded_function(template <...> void inspectImageIf) doxygen_overloaded_function(template <...> void inspectImageIf)
template <class ImageIterator, class Accessor, template <class ImageIterator, class Accessor,
class MaskImageIterator, class MaskAccessor>
struct inspectImageIf_binder
{
ImageIterator upperleft;
ImageIterator lowerright;
Accessor a;
MaskImageIterator mask_upperleft;
MaskAccessor ma;
inspectImageIf_binder(ImageIterator ul, ImageIterator lr, Accessor ac,
MaskImageIterator m_ul, MaskAccessor m_ac)
: upperleft(ul), lowerright(lr), a(ac), mask_upperleft(m_ul), ma(m_
ac)
{}
template <class Functor>
void operator()(Functor & f)
{
int w = lowerright.x - upperleft.x;
MaskImageIterator mt = mask_upperleft;
for (ImageIterator t = upperleft; t.y < lowerright.y; ++t.y, ++mt.y
)
{
inspectLineIf(t.rowIterator(),
t.rowIterator() + w, a,
mt.rowIterator(), ma, f);
}
}
};
template <class ImageIterator, class Accessor,
class MaskImageIterator, class MaskAccessor, class Functor> class MaskImageIterator, class MaskAccessor, class Functor>
void void
inspectImageIf(ImageIterator upperleft, inspectImageIf(ImageIterator upperleft,
ImageIterator lowerright, Accessor a, ImageIterator lowerright, Accessor a,
MaskImageIterator mask_upperleft, MaskAccessor ma, MaskImageIterator mask_upperleft, MaskAccessor ma,
Functor & f) Functor & f)
{ {
int w = lowerright.x - upperleft.x; inspectImageIf_binder<ImageIterator, Accessor, MaskImageIterator,
MaskAcce
for(; upperleft.y<lowerright.y; ++upperleft.y, ++mask_upperleft.y) ssor>
{ g(upperleft, lowerright, a, mask_upperleft, ma);
inspectLineIf(upperleft.rowIterator(), detail::extra_passes_select(g, f);
upperleft.rowIterator() + w, a,
mask_upperleft.rowIterator(), ma, f);
}
} }
template <class ImageIterator, class Accessor, template <class ImageIterator, class Accessor,
class MaskImageIterator, class MaskAccessor, class Functor> class MaskImageIterator, class MaskAccessor, class Functor>
inline inline
void void
inspectImageIf(triple<ImageIterator, ImageIterator, Accessor> img, inspectImageIf(triple<ImageIterator, ImageIterator, Accessor> img,
pair<MaskImageIterator, MaskAccessor> mask, pair<MaskImageIterator, MaskAccessor> mask,
Functor & f) Functor & f)
{ {
skipping to change at line 438 skipping to change at line 480
Accessor2 accessor2; Accessor2 accessor2;
Functor functor; Functor functor;
functor(accessor1(ix1), accessor2(ix2)); // return not used functor(accessor1(ix1), accessor2(ix2)); // return not used
\endcode \endcode
*/ */
doxygen_overloaded_function(template <...> void inspectTwoImages) doxygen_overloaded_function(template <...> void inspectTwoImages)
template <class ImageIterator1, class Accessor1, template <class ImageIterator1, class Accessor1,
class ImageIterator2, class Accessor2>
struct inspectTwoImages_binder
{
ImageIterator1 upperleft1;
ImageIterator1 lowerright1;
Accessor1 a1;
ImageIterator2 upperleft2;
Accessor2 a2;
inspectTwoImages_binder(ImageIterator1 u1, ImageIterator1 l1, Accessor1
a1_,
ImageIterator2 u2, Accessor2 a2_)
: upperleft1(u1), lowerright1(l1), a1(a1_), upperleft2(u2), a2(a2_)
{}
template <class Functor>
void operator()(Functor & f)
{
int w = lowerright1.x - upperleft1.x;
ImageIterator1 t1 = upperleft1;
ImageIterator2 t2 = upperleft2;
for (; t1.y < lowerright1.y; ++t1.y, ++t2.y)
{
inspectTwoLines(t1.rowIterator(),
t1.rowIterator() + w, a1,
t2.rowIterator(), a2, f);
}
}
};
template <class ImageIterator1, class Accessor1,
class ImageIterator2, class Accessor2, class ImageIterator2, class Accessor2,
class Functor> class Functor>
void void
inspectTwoImages(ImageIterator1 upperleft1, ImageIterator1 lowerright1, Acc inspectTwoImages(ImageIterator1 upperleft1, ImageIterator1 lowerright1,
essor1 a1, Accessor1 a1,
ImageIterator2 upperleft2, Accessor2 a2, ImageIterator2 upperleft2, Accessor2 a2,
Functor & f) Functor & f)
{ {
int w = lowerright1.x - upperleft1.x; inspectTwoImages_binder<ImageIterator1, Accessor1,
ImageIterator2, Accessor2>
for(; upperleft1.y<lowerright1.y; ++upperleft1.y, ++upperleft2.y) g(upperleft1, lowerright1, a1, upperleft2, a2);
{ detail::extra_passes_select(g, f);
inspectTwoLines(upperleft1.rowIterator(),
upperleft1.rowIterator() + w, a1,
upperleft2.rowIterator(), a2, f);
}
} }
template <class ImageIterator1, class Accessor1, template <class ImageIterator1, class Accessor1,
class ImageIterator2, class Accessor2, class ImageIterator2, class Accessor2,
class Functor> class Functor>
inline inline
void void
inspectTwoImages(triple<ImageIterator1, ImageIterator1, Accessor1> img1, inspectTwoImages(triple<ImageIterator1, ImageIterator1, Accessor1> img1,
pair<ImageIterator2, Accessor2> img2, pair<ImageIterator2, Accessor2> img2,
Functor & f) Functor & f)
skipping to change at line 581 skipping to change at line 648
Functor functor; Functor functor;
if(mask(mx)) if(mask(mx))
functor(accessor1(ix1), accessor2(ix2)); functor(accessor1(ix1), accessor2(ix2));
\endcode \endcode
*/ */
doxygen_overloaded_function(template <...> void inspectTwoImagesIf) doxygen_overloaded_function(template <...> void inspectTwoImagesIf)
template <class ImageIterator1, class Accessor1, template <class ImageIterator1, class Accessor1,
class ImageIterator2, class Accessor2, class ImageIterator2, class Accessor2,
class MaskImageIterator, class MaskAccessor, class MaskImageIterator, class MaskAccessor>
class Functor> struct inspectTwoImagesIf_binder
void
inspectTwoImagesIf(ImageIterator1 upperleft1, ImageIterator1 lowerright1, A
ccessor1 a1,
ImageIterator2 upperleft2, Accessor2 a2,
MaskImageIterator mupperleft, MaskAccessor mask,
Functor & f)
{ {
int w = lowerright1.x - upperleft1.x; ImageIterator1 upperleft1;
ImageIterator1 lowerright1;
for(; upperleft1.y<lowerright1.y; ++upperleft1.y, ++upperleft2.y, ++mup Accessor1 a1;
perleft.y) ImageIterator2 upperleft2;
{ Accessor2 a2;
inspectTwoLinesIf(upperleft1.rowIterator(), MaskImageIterator mupperleft;
upperleft1.rowIterator() + w, a1, MaskAccessor mask;
upperleft2.rowIterator(), a2, inspectTwoImagesIf_binder(ImageIterator1 u1, ImageIterator1 l1,
mupperleft.rowIterator(), mask, f); Accessor1 a1_, ImageIterator2 u2, Accessor2 a
2_,
MaskImageIterator mu, MaskAccessor ma)
: upperleft1(u1), lowerright1(l1), a1(a1_), upperleft2(u2), a2(a2_)
,
mupperleft(mu), mask(ma) {}
template <class Functor>
void operator()(Functor & f)
{
int w = lowerright1.x - upperleft1.x;
ImageIterator1 t1 = upperleft1;
ImageIterator2 t2 = upperleft2;
MaskImageIterator mu = mupperleft;
for(; t1.y < lowerright1.y; ++t1.y, ++t2.y, ++mu.y)
{
inspectTwoLinesIf(t1.rowIterator(),
t1.rowIterator() + w, a1,
t2.rowIterator(), a2,
mu.rowIterator(), mask, f);
}
} }
};
template <class ImageIterator1, class Accessor1,
class ImageIterator2, class Accessor2,
class MaskImageIterator, class MaskAccessor,
class Functor>
void
inspectTwoImagesIf(ImageIterator1 upperleft1, ImageIterator1 lowerright1,
Accessor1 a1,
ImageIterator2 upperleft2, Accessor2 a2,
MaskImageIterator mupperleft, MaskAccessor mask,
Functor & f)
{
inspectTwoImagesIf_binder<ImageIterator1, Accessor1,
ImageIterator2, Accessor2,
MaskImageIterator, MaskAccessor>
g(upperleft1, lowerright1, a1, upperleft2, a2, mupperleft, mask);
detail::extra_passes_select(g, f);
} }
template <class ImageIterator1, class Accessor1, template <class ImageIterator1, class Accessor1,
class ImageIterator2, class Accessor2, class ImageIterator2, class Accessor2,
class MaskImageIterator, class MaskAccessor, class MaskImageIterator, class MaskAccessor,
class Functor> class Functor>
inline inline
void void
inspectTwoImagesIf(triple<ImageIterator1, ImageIterator1, Accessor1> img1, inspectTwoImagesIf(triple<ImageIterator1, ImageIterator1, Accessor1> img1,
pair<ImageIterator2, Accessor2> img2, pair<ImageIterator2, Accessor2> img2,
skipping to change at line 1364 skipping to change at line 1463
<b>\#include</b> \<vigra/inspectimage.hxx\><br> <b>\#include</b> \<vigra/inspectimage.hxx\><br>
Namespace: vigra Namespace: vigra
\code \code
vigra::BImage img, mask; vigra::BImage img, mask;
... ...
vigra::FindBoundingRectangle roiRect; // init functor vigra::FindBoundingRectangle roiRect; // init functor
// Diff2D is used as the iterator for the source image. This // Diff2D is used as the iterator for the source image. This
// simulates an image where each pixel value equals that pixel's // simulates an image where each pixel value equals the pixel's
// coordinates. Tha image 'mask' determines the ROI. // coordinates. The image 'mask' determines the ROI.
vigra::inspectImageIf(srcIterRange(Diff2D(0,0), (Diff2D)img.size()), vigra::inspectImageIf(srcIterRange(Diff2D(0,0), (Diff2D)img.size()),
srcImage(mask), roiRect); srcImage(mask), roiRect);
cout << "Upper left of ROI: " << cout << "Upper left of ROI: " <<
roiRect.upperLeft.x << ", " << roiRect.upperLeft.y << endl; roiRect.upperLeft.x << ", " << roiRect.upperLeft.y << endl;
cout << "Lower right of ROI: " << cout << "Lower right of ROI: " <<
roiRect.lowerRight.x << ", " << roiRect.lowerRight.y << endl; roiRect.lowerRight.x << ", " << roiRect.lowerRight.y << endl;
\endcode \endcode
skipping to change at line 1776 skipping to change at line 1875
RegionStatistics::argument_type a; RegionStatistics::argument_type a;
RegionStatistics::result_type r; RegionStatistics::result_type r;
region(a); // update statistics region(a); // update statistics
r = region(); // return statistics r = region(); // return statistics
\endcode \endcode
*/ */
template <class RegionStatistics, class LabelType = int> template <class RegionStatistics, class LabelType = int>
class ArrayOfRegionStatistics class ArrayOfRegionStatistics
: public detail::get_extra_passes<RegionStatistics>
{ {
typedef std::vector<RegionStatistics> RegionArray; typedef std::vector<RegionStatistics> RegionArray;
public: public:
/** argument type of the contained statistics object /** argument type of the contained statistics object
becomes first argument of the analyser becomes first argument of the analyser
*/ */
typedef typename RegionStatistics::argument_type first_argument_type; typedef typename RegionStatistics::argument_type first_argument_type;
/** label type is used to determine the region to be updated /** label type is used to determine the region to be updated
skipping to change at line 1909 skipping to change at line 2009
/** iterator to the end of the region array /** iterator to the end of the region array
*/ */
iterator end() iterator end()
{ return regions.end(); } { return regions.end(); }
/** const iterator to the end of the region array /** const iterator to the end of the region array
*/ */
const_iterator end() const const_iterator end() const
{ return regions.end(); } { return regions.end(); }
/** prepare next pass for multi-pass RegionStatistics types
*/
void calc_sync()
{
for (iterator j = begin(); j != end(); ++j)
this->sync(*j);
}
// update: passes >= 2
struct pass_n_dispatch
{
ArrayOfRegionStatistics & x;
unsigned pass_number;
pass_n_dispatch(ArrayOfRegionStatistics & a, unsigned n)
: x(a), pass_number(n) {}
template <class S> // instantiate only when used.
void operator()(const first_argument_type & v, S label)
{
x.regions[static_cast<unsigned>(label)].updatePassN(v, pass_num
ber);
}
};
template <class N> // instantiate only when used.
pass_n_dispatch pass_n(N n)
{
if (n < 2 || static_cast<unsigned>(n) > this->max_passes)
vigra_fail("ArrayOfRegionStatistics::pass_n(): inconsistent use
.");
return pass_n_dispatch(*this, n);
}
std::vector<RegionStatistics> regions; std::vector<RegionStatistics> regions;
}; };
template <class RegionStatistics, class LabelType> template <class RegionStatistics, class LabelType>
class FunctorTraits<ArrayOfRegionStatistics<RegionStatistics, LabelType> > class FunctorTraits<ArrayOfRegionStatistics<RegionStatistics, LabelType> >
: public FunctorTraitsBase<ArrayOfRegionStatistics<RegionStatistics, LabelT ype> > : public FunctorTraitsBase<ArrayOfRegionStatistics<RegionStatistics, LabelT ype> >
{ {
public: public:
typedef VigraTrueType isUnaryFunctor; typedef VigraTrueType isUnaryFunctor;
typedef VigraTrueType isBinaryAnalyser; typedef VigraTrueType isBinaryAnalyser;
 End of changes. 14 change blocks. 
44 lines changed or deleted 179 lines changed or added


 linear_solve.hxx   linear_solve.hxx 
skipping to change at line 819 skipping to change at line 819
<b>\#include</b> \<vigra/linear_algebra.hxx\><br> <b>\#include</b> \<vigra/linear_algebra.hxx\><br>
Namespaces: vigra and vigra::linalg Namespaces: vigra and vigra::linalg
*/ */
template <class T, class C1> template <class T, class C1>
T determinant(MultiArrayView<2, T, C1> const & a, std::string method = "LU" ) T determinant(MultiArrayView<2, T, C1> const & a, std::string method = "LU" )
{ {
MultiArrayIndex n = columnCount(a); MultiArrayIndex n = columnCount(a);
vigra_precondition(rowCount(a) == n, vigra_precondition(rowCount(a) == n,
"determinant(): Square matrix required."); "determinant(): Square matrix required.");
for(unsigned int k=0; k<method.size(); ++k) method = tolower(method);
method[k] = tolower(method[k]);
if(n == 1) if(n == 1)
return a(0,0); return a(0,0);
if(n == 2) if(n == 2)
return a(0,0)*a(1,1) - a(0,1)*a(1,0); return a(0,0)*a(1,1) - a(0,1)*a(1,0);
if(method == "lu") if(method == "lu")
{ {
return detail::determinantByLUDecomposition(a); return detail::determinantByLUDecomposition(a);
} }
else if(method == "cholesky") else if(method == "cholesky")
skipping to change at line 1185 skipping to change at line 1184
const MultiArrayIndex n = columnCount(A); const MultiArrayIndex n = columnCount(A);
const MultiArrayIndex m = rowCount(A); const MultiArrayIndex m = rowCount(A);
vigra_precondition(n <= m, vigra_precondition(n <= m,
"linearSolve(): Coefficient matrix A must have at least as many row s as columns."); "linearSolve(): Coefficient matrix A must have at least as many row s as columns.");
vigra_precondition(n == rowCount(res) && vigra_precondition(n == rowCount(res) &&
m == rowCount(b) && columnCount(b) == columnCount(re s), m == rowCount(b) && columnCount(b) == columnCount(re s),
"linearSolve(): matrix shape mismatch."); "linearSolve(): matrix shape mismatch.");
for(unsigned int k=0; k<method.size(); ++k) method = tolower(method);
method[k] = (std::string::value_type)tolower(method[k]);
if(method == "cholesky") if(method == "cholesky")
{ {
vigra_precondition(columnCount(A) == rowCount(A), vigra_precondition(columnCount(A) == rowCount(A),
"linearSolve(): Cholesky method requires square coefficient mat rix."); "linearSolve(): Cholesky method requires square coefficient mat rix.");
Matrix<T> L(A.shape()); Matrix<T> L(A.shape());
if(!choleskyDecomposition(A, L)) if(!choleskyDecomposition(A, L))
return false; // false if A wasn't symmetric positive definite return false; // false if A wasn't symmetric positive definite
choleskySolve(L, b, res); choleskySolve(L, b, res);
} }
else if(method == "qr") else if(method == "qr")
 End of changes. 2 change blocks. 
5 lines changed or deleted 2 lines changed or added


 mathutil.hxx   mathutil.hxx 
skipping to change at line 147 skipping to change at line 147
VIGRA_DEFINE_UNSIGNED_ABS(bool) VIGRA_DEFINE_UNSIGNED_ABS(bool)
VIGRA_DEFINE_UNSIGNED_ABS(unsigned char) VIGRA_DEFINE_UNSIGNED_ABS(unsigned char)
VIGRA_DEFINE_UNSIGNED_ABS(unsigned short) VIGRA_DEFINE_UNSIGNED_ABS(unsigned short)
VIGRA_DEFINE_UNSIGNED_ABS(unsigned int) VIGRA_DEFINE_UNSIGNED_ABS(unsigned int)
VIGRA_DEFINE_UNSIGNED_ABS(unsigned long) VIGRA_DEFINE_UNSIGNED_ABS(unsigned long)
VIGRA_DEFINE_UNSIGNED_ABS(unsigned long long) VIGRA_DEFINE_UNSIGNED_ABS(unsigned long long)
#undef VIGRA_DEFINE_UNSIGNED_ABS #undef VIGRA_DEFINE_UNSIGNED_ABS
#define VIGRA_DEFINE_MISSING_ABS(T) \ #define VIGRA_DEFINE_MISSING_ABS(T) \
inline T abs(T t) { return t < 0 ? -t : t; } inline T abs(T t) { return t < 0 ? static_cast<T>(-t) : t; }
VIGRA_DEFINE_MISSING_ABS(signed char) VIGRA_DEFINE_MISSING_ABS(signed char)
VIGRA_DEFINE_MISSING_ABS(signed short) VIGRA_DEFINE_MISSING_ABS(signed short)
#if defined(_MSC_VER) && _MSC_VER < 1600 #if defined(_MSC_VER) && _MSC_VER < 1600
VIGRA_DEFINE_MISSING_ABS(signed long long) VIGRA_DEFINE_MISSING_ABS(signed long long)
#endif #endif
#undef VIGRA_DEFINE_MISSING_ABS #undef VIGRA_DEFINE_MISSING_ABS
// scalar dot is needed for generic functions that should work with
// scalars and vectors alike
#define VIGRA_DEFINE_SCALAR_DOT(T) \
inline NumericTraits<T>::Promote dot(T l, T r) { return l*r; }
VIGRA_DEFINE_SCALAR_DOT(unsigned char)
VIGRA_DEFINE_SCALAR_DOT(unsigned short)
VIGRA_DEFINE_SCALAR_DOT(unsigned int)
VIGRA_DEFINE_SCALAR_DOT(unsigned long)
VIGRA_DEFINE_SCALAR_DOT(unsigned long long)
VIGRA_DEFINE_SCALAR_DOT(signed char)
VIGRA_DEFINE_SCALAR_DOT(signed short)
VIGRA_DEFINE_SCALAR_DOT(signed int)
VIGRA_DEFINE_SCALAR_DOT(signed long)
VIGRA_DEFINE_SCALAR_DOT(signed long long)
VIGRA_DEFINE_SCALAR_DOT(float)
VIGRA_DEFINE_SCALAR_DOT(double)
VIGRA_DEFINE_SCALAR_DOT(long double)
#undef VIGRA_DEFINE_SCALAR_DOT
using std::pow;
// support 'double' exponents for all floating point versions of pow()
inline float pow(float v, double e)
{
return std::pow(v, (float)e);
}
inline long double pow(long double v, double e)
{
return std::pow(v, (long double)e);
}
/*! The rounding function. /*! The rounding function.
Defined for all floating point types. Rounds towards the nearest in teger Defined for all floating point types. Rounds towards the nearest in teger
such that <tt>abs(round(t)) == round(abs(t))</tt> for all <tt>t</tt >. such that <tt>abs(round(t)) == round(abs(t))</tt> for all <tt>t</tt >.
<b>\#include</b> \<vigra/mathutil.hxx\><br> <b>\#include</b> \<vigra/mathutil.hxx\><br>
Namespace: vigra Namespace: vigra
*/ */
#ifdef DOXYGEN // only for documentation #ifdef DOXYGEN // only for documentation
REAL round(REAL v); REAL round(REAL v);
skipping to change at line 311 skipping to change at line 347
*/ */
template <class T> template <class T>
inline inline
typename NumericTraits<T>::Promote sq(T t) typename NumericTraits<T>::Promote sq(T t)
{ {
return t*t; return t*t;
} }
namespace detail { namespace detail {
template <class V, unsigned>
struct cond_mult
{
static V call(const V & x, const V & y) { return x * y; }
};
template <class V>
struct cond_mult<V, 0>
{
static V call(const V &, const V & y) { return y; }
};
template <class V, unsigned n>
struct power_static
{
static V call(const V & x)
{
return n / 2
? cond_mult<V, n & 1>::call(x, power_static<V, n / 2>::call(x *
x))
: n & 1 ? x : V();
}
};
template <class V>
struct power_static<V, 0>
{
static V call(const V & x)
{
return V(1);
}
};
} // namespace detail
/*! Exponentiation to a positive integer power by squaring.
<b>\#include</b> \<vigra/mathutil.hxx\><br>
Namespace: vigra
*/
template <unsigned n, class V>
inline V power(const V & x)
{
return detail::power_static<V, n>::call(x);
}
//doxygen_overloaded_function(template <unsigned n, class V> power(const V
& x))
namespace detail {
template <class T> template <class T>
class IntSquareRoot class IntSquareRoot
{ {
public: public:
static UInt32 sqq_table[]; static UInt32 sqq_table[];
static UInt32 exec(UInt32 v); static UInt32 exec(UInt32 v);
}; };
template <class T> template <class T>
UInt32 IntSquareRoot<T>::sqq_table[] = { UInt32 IntSquareRoot<T>::sqq_table[] = {
skipping to change at line 761 skipping to change at line 843
Namespace: vigra Namespace: vigra
*/ */
inline double ellipticIntegralE(double x, double k) inline double ellipticIntegralE(double x, double k)
{ {
double c2 = sq(VIGRA_CSTD::cos(x)); double c2 = sq(VIGRA_CSTD::cos(x));
double s = VIGRA_CSTD::sin(x); double s = VIGRA_CSTD::sin(x);
k = sq(k*s); k = sq(k*s);
return s*(detail::ellipticRF(c2, 1.0-k, 1.0) - k/3.0*detail::ellipticRD (c2, 1.0-k, 1.0)); return s*(detail::ellipticRF(c2, 1.0-k, 1.0) - k/3.0*detail::ellipticRD (c2, 1.0-k, 1.0));
} }
#if _MSC_VER #ifdef _MSC_VER
namespace detail { namespace detail {
template <class T> template <class T>
double erfImpl(T x) double erfImpl(T x)
{ {
double t = 1.0/(1.0+0.5*VIGRA_CSTD::fabs(x)); double t = 1.0/(1.0+0.5*VIGRA_CSTD::fabs(x));
double ans = t*VIGRA_CSTD::exp(-x*x-1.26551223+t*(1.00002368+t*(0.37409 196+ double ans = t*VIGRA_CSTD::exp(-x*x-1.26551223+t*(1.00002368+t*(0.37409 196+
t*(0.09678418+t*(-0.18628806+t*(0.27886 807+ t*(0.09678418+t*(-0.18628806+t*(0.27886 807+
t*(-1.13520398+t*(1.48851587+t*(-0.8221 5223+ t*(-1.13520398+t*(1.48851587+t*(-0.8221 5223+
 End of changes. 4 change blocks. 
2 lines changed or deleted 86 lines changed or added


 matrix.hxx   matrix.hxx 
skipping to change at line 302 skipping to change at line 302
all objects (array views, iterators) depending on the matrix. all objects (array views, iterators) depending on the matrix.
\a rhs is assumed to be in column-major order already. \a rhs is assumed to be in column-major order already.
*/ */
template <class U, class C> template <class U, class C>
Matrix & operator=(const MultiArrayView<2, U, C> &rhs) Matrix & operator=(const MultiArrayView<2, U, C> &rhs)
{ {
BaseType::operator=(rhs); // has the correct semantics already BaseType::operator=(rhs); // has the correct semantics already
return *this; return *this;
} }
/** assignment from scalar.<br>
Equivalent to Matrix::init(v).
*/
Matrix & operator=(value_type const & v)
{
return init(v);
}
/** init elements with a constant /** init elements with a constant
*/ */
template <class U> template <class U>
Matrix & init(const U & init) Matrix & init(const U & init)
{ {
BaseType::init(init); BaseType::init(init);
return *this; return *this;
} }
/** reshape to the given shape and initialize with zero. /** reshape to the given shape and initialize with zero.
 End of changes. 1 change blocks. 
0 lines changed or deleted 8 lines changed or added


 memory.hxx   memory.hxx 
skipping to change at line 54 skipping to change at line 54
template<class T> template<class T>
struct CanSkipInitialization struct CanSkipInitialization
{ {
typedef typename TypeTraits<T>::isBuiltinType type; typedef typename TypeTraits<T>::isBuiltinType type;
static const bool value = type::asBool; static const bool value = type::asBool;
}; };
namespace detail { namespace detail {
// differs from std::uninitialized_copy by explicit type conversion
template <class Src, class Dest>
Dest uninitializedCopy(Src s, Src end, Dest d)
{
typedef typename std::iterator_traits<Dest>::value_type T;
for(; s != end; ++s, ++d)
new(d) T(static_cast<T const &>(*s));
return d;
}
template <class T> template <class T>
inline void destroy_n(T * /* p */, std::ptrdiff_t /* n */, VigraTrueType /* isPOD */) inline void destroy_n(T * /* p */, std::ptrdiff_t /* n */, VigraTrueType /* isPOD */)
{ {
} }
template <class T> template <class T>
inline void destroy_n(T * p, std::ptrdiff_t n, VigraFalseType /* isPOD */) inline void destroy_n(T * p, std::ptrdiff_t n, VigraFalseType /* isPOD */)
{ {
T * end = p + n; T * end = p + n;
for(; p != end; ++p) for(; p != end; ++p)
 End of changes. 1 change blocks. 
0 lines changed or deleted 10 lines changed or added


 metaprogramming.hxx   metaprogramming.hxx 
skipping to change at line 42 skipping to change at line 42
/* OTHER DEALINGS IN THE SOFTWARE. */ /* OTHER DEALINGS IN THE SOFTWARE. */
/* */ /* */
/************************************************************************/ /************************************************************************/
#ifndef VIGRA_METAPROGRAMMING_HXX #ifndef VIGRA_METAPROGRAMMING_HXX
#define VIGRA_METAPROGRAMMING_HXX #define VIGRA_METAPROGRAMMING_HXX
#include "config.hxx" #include "config.hxx"
#include <climits> #include <climits>
#include <limits> #include <limits>
#include <algorithm>
namespace vigra { namespace vigra {
// mask cl.exe shortcomings [begin]
#if defined(_MSC_VER)
#pragma warning( push )
#pragma warning( disable : 4503 )
#endif
template <int N> template <int N>
class MetaInt class MetaInt
{ {
public: public:
static const int value = N; static const int value = N;
}; };
template <int N1, int N2> template <int N1, int N2>
class MetaMax class MetaMax
{ {
skipping to change at line 436 skipping to change at line 443
template <class T> template <class T>
struct UnqualifiedType<T *> struct UnqualifiedType<T *>
: public UnqualifiedType<T> : public UnqualifiedType<T>
{}; {};
template <class T> template <class T>
struct UnqualifiedType<T const *> struct UnqualifiedType<T const *>
: public UnqualifiedType<T> : public UnqualifiedType<T>
{}; {};
template <bool, class T = void>
struct enable_if {};
template <class T> template <class T>
struct has_result_type struct enable_if<true, T> { typedef T type; };
struct sfinae_void;
template <class T, template<class> class USER>
struct sfinae_test
{ {
typedef char falseResult[1]; typedef char falseResult[1];
typedef char trueResult[2]; typedef char trueResult[2];
static falseResult * test(...); static falseResult * test(...);
template <class U> static trueResult * test(USER<sfinae_void>);
static trueResult * test(U *, typename U::result_type * = 0);
enum { resultSize = sizeof(*test((T*)0)) }; enum { resultSize = sizeof(*test((T*)0)) };
static const bool value = (resultSize == 2); static const bool value = (resultSize == 2);
typedef typename typedef typename
IfBool<value, VigraTrueType, VigraFalseType>::type IfBool<value, VigraTrueType, VigraFalseType>::type
type; type;
}; };
template <class T> template <class T>
struct has_value_type struct has_argument_type : public sfinae_test<T, has_argument_type>
{ {
typedef char falseResult[1]; template <class U> has_argument_type(U*, typename U::argument_type* = 0
typedef char trueResult[2]; );
static falseResult * test(...);
template <class U>
static trueResult * test(U *, typename U::value_type * = 0);
enum { resultSize = sizeof(*test((T*)0)) };
static const bool value = (resultSize == 2);
typedef typename
IfBool<value, VigraTrueType, VigraFalseType>::type
type;
}; };
template <class T> template <class T>
struct IsIterator struct has_result_type : public sfinae_test<T, has_result_type>
{ {
typedef char falseResult[1]; template <class U> has_result_type(U*, typename U::result_type* = 0);
typedef char trueResult[2]; };
static falseResult * test(...);
template <class U>
static trueResult * test(U *, typename U::iterator_category * = 0);
enum { resultSize = sizeof(*test((T*)0)) }; template <class T>
struct has_value_type : public sfinae_test<T, has_value_type>
{
template <class U> has_value_type(U*, typename U::value_type* = 0);
};
static const bool value = (resultSize == 2); template <class T>
typedef typename struct IsIterator : public sfinae_test<T, IsIterator>
IfBool<value, VigraTrueType, VigraFalseType>::type {
type; template <class U> IsIterator(U*, typename U::iterator_category* = 0);
}; };
template <class T> template <class T>
struct IsIterator<T*> struct IsIterator<T*>
{ {
static const bool value = true; static const bool value = true;
typedef VigraTrueType type; typedef VigraTrueType type;
}; };
template <class T> template <class T>
struct IsIterator<T const *> struct IsIterator<T const *>
{ {
static const bool value = true; static const bool value = true;
typedef VigraTrueType type; typedef VigraTrueType type;
}; };
template <class T> template <class T>
struct has_real_promote_type : public sfinae_test<T, has_real_promote_type>
{
template <class U>
has_real_promote_type(U*, typename U::real_promote_type* = 0);
};
template <class T, bool P = has_real_promote_type<T>::value>
struct get_optional_real_promote
{
typedef T type;
};
template <class T>
struct get_optional_real_promote<T, true>
{
typedef typename T::real_promote_type type;
};
template <class T>
struct IsArray struct IsArray
{ {
typedef char falseResult[1]; typedef char falseResult[1];
typedef char trueResult[2]; typedef char trueResult[2];
static falseResult * test(...); static falseResult * test(...);
template <class U, unsigned n> template <class U, unsigned n>
static trueResult * test(U (*)[n]); static trueResult * test(U (*)[n]);
enum { resultSize = sizeof(*test((T*)0)) }; enum { resultSize = sizeof(*test((T*)0)) };
static const bool value = (resultSize == 2); static const bool value = (resultSize == 2);
typedef typename typedef typename
IfBool<value, VigraTrueType, VigraFalseType>::type IfBool<value, VigraTrueType, VigraFalseType>::type
type; type;
}; };
template <class D, class B, class Z> inline
D & static_cast_2(Z & z)
{
return static_cast<D &>(static_cast<B &>(z));
}
template <class A>
class copy_if_same_as
{
const bool copied;
const A *const data;
copy_if_same_as(const copy_if_same_as &);
void operator=(const copy_if_same_as &);
public:
copy_if_same_as(const A & x, const A & y)
: copied(&x == &y), data(copied ? new A(y) : &x) {}
~copy_if_same_as()
{
if (copied)
delete data;
}
const A & operator()() const { return *data; }
};
template <class>
struct true_test : public VigraTrueType {};
template <class>
struct false_test : VigraFalseType {};
template <class PC, class T, class F>
struct ChooseBool
{
static const bool value = IfBool<PC::value, T, F>::type::value;
};
template <bool>
struct choose_type
{
template <class A, class B>
static const A & at(const A & a, const B &) { return a; }
template <class A, class B>
static A & at( A & a, B &) { return a; }
};
template <>
struct choose_type<false>
{
template <class A, class B>
static const B & at(const A &, const B & b) { return b; }
template <class A, class B>
static B & at( A &, B & b) { return b; }
};
template <class X>
struct HasMetaLog2
{
static const bool value = !std::numeric_limits<X>::is_signed
&& std::numeric_limits<X>::is_integer;
};
template <class X>
struct EnableMetaLog2
: public enable_if<HasMetaLog2<X>::value> {};
template <class>
class vigra_error_MetaLog2_accepts_only_unsigned_types_and_no_;
// use a conforming template depth here (below 15 for up to 128 bits)
template <class X = unsigned long,
X n = ~(X(0)), unsigned s = 1, unsigned t = 0, bool q = 1,
X m = 0, X z = 0, X u = 1, class = void>
class MetaLog2
: public vigra_error_MetaLog2_accepts_only_unsigned_types_and_no_<X>
{};
template <class X, X n, unsigned s, unsigned t, bool q, X m, X z, X u>
struct MetaLog2 <X, n, s, t, q, m, z, u, typename EnableMetaLog2<X>::type>
{
static const unsigned value
= t + MetaLog2<X, (n >> s), s * (1 + q), s, !q, n / 2, z, u>::value
;
};
template <class X, unsigned s, unsigned t, bool q, X m, X z, X u>
struct MetaLog2<X, z, s, t, q, m, z, u, typename EnableMetaLog2<X>::type>
{
static const unsigned value
= 1 + MetaLog2<X, m / 2, 2, 1, 1, 0, z, u>::value;
};
template <class X, unsigned s, unsigned t, bool q, X z, X u>
struct MetaLog2<X, z, s, t, q, u, z, u, typename EnableMetaLog2<X>::type>
{
static const unsigned value = 2;
};
template <class X, unsigned s, unsigned t, bool q, X z, X u>
struct MetaLog2<X, z, s, t, q, z, z, u, typename EnableMetaLog2<X>::type>
{
static const unsigned value = 1;
};
template <class X, X z, X u>
struct MetaLog2<X, z, 1, 0, 1, z, z, u, typename EnableMetaLog2<X>::type>
{
// A value of zero for MetaLog2<X, 0> is likely to cause most harm,
// such as division by zero or zero array sizes, this is actually inden
ded.
static const unsigned value = 0;
};
/**************************************************************************
**/
/*
*/
/* TypeList and its functions
*/
/*
*/
/**************************************************************************
**/
template<class HEAD, class TAIL=void>
struct TypeList
{
typedef TypeList<HEAD, TAIL> type;
typedef HEAD Head;
typedef TAIL Tail;
};
template <class List, class T>
struct Contains;
template <class Head, class Tail, class T>
struct Contains<TypeList<Head, Tail>, T>
{
typedef typename Contains<Tail, T>::type type;
};
template <class Head, class Tail>
struct Contains<TypeList<Head, Tail>, Head>
{
typedef VigraTrueType type;
};
template <class T>
struct Contains<void, T>
{
typedef VigraFalseType type;
};
template <class List, class T>
struct Remove;
template <class Head, class Tail, class T>
struct Remove<TypeList<Head, Tail>, T>
{
typedef TypeList<Head, typename Remove<Tail, T>::type> type;
};
template <class Head, class Tail>
struct Remove<TypeList<Head, Tail>, Head>
{
typedef Tail type;
};
template <class T>
struct Remove<void, T>
{
typedef void type;
};
template <class A, class Tail=void>
struct Push
{
typedef TypeList<A, typename Tail::type> type;
};
template <class Head, class Tail, class List>
struct Push<TypeList<Head, Tail>, List>
{
typedef typename Push<Tail, List>::type Rest;
typedef TypeList<Head, Rest> type;
};
template <class Head, class Tail>
struct Push<TypeList<Head, Tail>, void>
{
typedef TypeList<Head, Tail> type;
};
template <class A>
struct Push<A, void>
{
typedef TypeList<A> type;
};
template <class A>
struct Push<void, A>
{
typedef A type;
};
template <>
struct Push<void, void>
{
typedef void type;
};
template <class A, class Tail=void>
struct PushUnique
{
typedef typename Contains<Tail, A>::type AlreadyInList;
typedef typename If<AlreadyInList, typename Tail::type, TypeList<A, typ
ename Tail::type> >::type type;
};
template <class Head, class Tail, class List>
struct PushUnique<TypeList<Head, Tail>, List>
{
typedef typename PushUnique<Tail, List>::type Rest;
typedef typename Contains<Rest, Head>::type HeadAlreadyInList;
typedef typename If<HeadAlreadyInList, Rest, TypeList<Head, Rest> >::ty
pe type;
};
template <class Head, class Tail>
struct PushUnique<TypeList<Head, Tail>, void>
{
typedef TypeList<Head, Tail> type;
};
template <class A>
struct PushUnique<A, void>
{
typedef TypeList<A> type;
};
template <class A>
struct PushUnique<void, A>
{
typedef A type;
};
template <>
struct PushUnique<void, void>
{
typedef void type;
};
template <class T01=void, class T02=void, class T03=void, class T04=void, c
lass T05=void,
class T06=void, class T07=void, class T08=void, class T09=void, c
lass T10=void,
class T11=void, class T12=void, class T13=void, class T14=void, c
lass T15=void,
class T16=void, class T17=void, class T18=void, class T19=void, c
lass T20=void>
struct MakeTypeList
{
typedef typename Push<T19, T20>::type L19;
typedef typename Push<T18, L19>::type L18;
typedef typename Push<T17, L18>::type L17;
typedef typename Push<T16, L17>::type L16;
typedef typename Push<T15, L16>::type L15;
typedef typename Push<T14, L15>::type L14;
typedef typename Push<T13, L14>::type L13;
typedef typename Push<T12, L13>::type L12;
typedef typename Push<T11, L12>::type L11;
typedef typename Push<T10, L11>::type L10;
typedef typename Push<T09, L10>::type L09;
typedef typename Push<T08, L09>::type L08;
typedef typename Push<T07, L08>::type L07;
typedef typename Push<T06, L07>::type L06;
typedef typename Push<T05, L06>::type L05;
typedef typename Push<T04, L05>::type L04;
typedef typename Push<T03, L04>::type L03;
typedef typename Push<T02, L03>::type L02;
typedef typename Push<T01, L02>::type L01;
typedef L01 type;
};
template <class T01=void, class T02=void, class T03=void, class T04=void, c
lass T05=void,
class T06=void, class T07=void, class T08=void, class T09=void, c
lass T10=void,
class T11=void, class T12=void, class T13=void, class T14=void, c
lass T15=void,
class T16=void, class T17=void, class T18=void, class T19=void, c
lass T20=void>
struct MakeTypeListUnique
{
typedef typename PushUnique<T19, T20>::type L19;
typedef typename PushUnique<T18, L19>::type L18;
typedef typename PushUnique<T17, L18>::type L17;
typedef typename PushUnique<T16, L17>::type L16;
typedef typename PushUnique<T15, L16>::type L15;
typedef typename PushUnique<T14, L15>::type L14;
typedef typename PushUnique<T13, L14>::type L13;
typedef typename PushUnique<T12, L13>::type L12;
typedef typename PushUnique<T11, L12>::type L11;
typedef typename PushUnique<T10, L11>::type L10;
typedef typename PushUnique<T09, L10>::type L09;
typedef typename PushUnique<T08, L09>::type L08;
typedef typename PushUnique<T07, L08>::type L07;
typedef typename PushUnique<T06, L07>::type L06;
typedef typename PushUnique<T05, L06>::type L05;
typedef typename PushUnique<T04, L05>::type L04;
typedef typename PushUnique<T03, L04>::type L03;
typedef typename PushUnique<T02, L03>::type L02;
typedef typename PushUnique<T01, L02>::type L01;
typedef L01 type;
};
// mask cl.exe shortcomings [end]
#if defined(_MSC_VER)
#pragma warning( pop )
#endif
} // namespace vigra } // namespace vigra
#endif /* VIGRA_METAPROGRAMMING_HXX */ #endif /* VIGRA_METAPROGRAMMING_HXX */
 End of changes. 13 change blocks. 
29 lines changed or deleted 361 lines changed or added


 multi_array.hxx   multi_array.hxx 
skipping to change at line 147 skipping to change at line 147
{ {
template <int N> template <int N>
static void static void
exec(MultiArrayIndex d, const TinyVector <MultiArrayIndex, N> & /*shape */, exec(MultiArrayIndex d, const TinyVector <MultiArrayIndex, N> & /*shape */,
TinyVector <MultiArrayIndex, N> & result) TinyVector <MultiArrayIndex, N> & result)
{ {
result[N-1] = d; result[N-1] = d;
} }
}; };
template <int K>
struct CoordinateToScanOrder
{
template <int N>
static MultiArrayIndex
exec(const TinyVector <MultiArrayIndex, N> &shape,
const TinyVector <MultiArrayIndex, N> & coordinate)
{
return coordinate[N-K] + shape[N-K] * CoordinateToScanOrder<K-1>::e
xec(shape, coordinate);
}
};
template <>
struct CoordinateToScanOrder<1>
{
template <int N>
static MultiArrayIndex
exec(const TinyVector <MultiArrayIndex, N> & /*shape*/,
const TinyVector <MultiArrayIndex, N> & coordinate)
{
return coordinate[N-1];
}
};
template <class C> template <class C>
struct CoordinatesToOffest struct CoordinatesToOffest
{ {
template <int N> template <int N>
static MultiArrayIndex static MultiArrayIndex
exec(const TinyVector <MultiArrayIndex, N> & stride, MultiArrayIndex x) exec(const TinyVector <MultiArrayIndex, N> & stride, MultiArrayIndex x)
{ {
return stride[0] * x; return stride[0] * x;
} }
template <int N> template <int N>
skipping to change at line 332 skipping to change at line 308
void void
initMultiArrayData(DestIterator d, Shape const & shape, T const & init, Met aInt<N>) initMultiArrayData(DestIterator d, Shape const & shape, T const & init, Met aInt<N>)
{ {
DestIterator dend = d + shape[N]; DestIterator dend = d + shape[N];
for(; d < dend; ++d) for(; d < dend; ++d)
{ {
initMultiArrayData(d.begin(), shape, init, MetaInt<N-1>()); initMultiArrayData(d.begin(), shape, init, MetaInt<N-1>());
} }
} }
// FIXME: the explicit overload for MultiIterator<1, UInt8, ... > works aro und a compiler crash in VisualStudio 2010
#define VIGRA_COPY_MULTI_ARRAY_DATA(name, op) \ #define VIGRA_COPY_MULTI_ARRAY_DATA(name, op) \
template <class SrcIterator, class Shape, class DestIterator> \ template <class SrcIterator, class Shape, class DestIterator> \
inline void \ inline void \
name##MultiArrayData(SrcIterator s, Shape const & shape, DestIterator d, Me taInt<0>) \ name##MultiArrayData(SrcIterator s, Shape const & shape, DestIterator d, Me taInt<0>) \
{ \ { \
SrcIterator send = s + shape[0]; \ SrcIterator send = s + shape[0]; \
for(; s < send; ++s, ++d) \ for(; s < send; ++s, ++d) \
{ \ { \
*d op detail::RequiresExplicitCast<typename DestIterator::value_typ e>::cast(*s); \ *d op detail::RequiresExplicitCast<typename DestIterator::value_typ e>::cast(*s); \
} \ } \
} \ } \
\ \
template <class Ref, class Ptr, class Shape, class DestIterator> \
inline void \
name##MultiArrayData(MultiIterator<1, UInt8, Ref, Ptr> si, Shape const & sh
ape, DestIterator d, MetaInt<0>) \
{ \
Ptr s = &(*si), send = s + shape[0]; \
for(; s < send; ++s, ++d) \
{ \
*d op detail::RequiresExplicitCast<typename DestIterator::value_typ
e>::cast(*s); \
} \
} \
\
template <class SrcIterator, class Shape, class DestIterator, int N> \ template <class SrcIterator, class Shape, class DestIterator, int N> \
void \ void \
name##MultiArrayData(SrcIterator s, Shape const & shape, DestIterator d, Me taInt<N>) \ name##MultiArrayData(SrcIterator s, Shape const & shape, DestIterator d, Me taInt<N>) \
{ \ { \
SrcIterator send = s + shape[N]; \ SrcIterator send = s + shape[N]; \
for(; s < send; ++s, ++d) \ for(; s < send; ++s, ++d) \
{ \ { \
name##MultiArrayData(s.begin(), shape, d.begin(), MetaInt<N-1>()); \ name##MultiArrayData(s.begin(), shape, d.begin(), MetaInt<N-1>()); \
} \ } \
} \ } \
skipping to change at line 396 skipping to change at line 384
inline void inline void
uninitializedCopyMultiArrayData(SrcIterator s, Shape const & shape, T * & d , ALLOC & a, MetaInt<0>) uninitializedCopyMultiArrayData(SrcIterator s, Shape const & shape, T * & d , ALLOC & a, MetaInt<0>)
{ {
SrcIterator send = s + shape[0]; SrcIterator send = s + shape[0];
for(; s < send; ++s, ++d) for(; s < send; ++s, ++d)
{ {
a.construct(d, static_cast<T const &>(*s)); a.construct(d, static_cast<T const &>(*s));
} }
} }
// FIXME: this overload works around a compiler crash in VisualStudio 2010
template <class Ref, class Ptr, class Shape, class T, class ALLOC>
inline void
uninitializedCopyMultiArrayData(MultiIterator<1, UInt8, Ref, Ptr> si, Shape
const & shape, T * & d, ALLOC & a, MetaInt<0>)
{
Ptr s = &(*si), send = s + shape[0];
for(; s < send; ++s, ++d)
{
a.construct(d, static_cast<T const &>(*s));
}
}
template <class SrcIterator, class Shape, class T, class ALLOC, int N> template <class SrcIterator, class Shape, class T, class ALLOC, int N>
void void
uninitializedCopyMultiArrayData(SrcIterator s, Shape const & shape, T * & d , ALLOC & a, MetaInt<N>) uninitializedCopyMultiArrayData(SrcIterator s, Shape const & shape, T * & d , ALLOC & a, MetaInt<N>)
{ {
SrcIterator send = s + shape[N]; SrcIterator send = s + shape[N];
for(; s < send; ++s) for(; s < send; ++s)
{ {
uninitializedCopyMultiArrayData(s.begin(), shape, d, a, MetaInt<N-1 >()); uninitializedCopyMultiArrayData(s.begin(), shape, d, a, MetaInt<N-1 >());
} }
} }
skipping to change at line 938 skipping to change at line 938
*/ */
template<class U, class C1> template<class U, class C1>
MultiArrayView & operator=(MultiArrayView<N, U, C1> const & rhs) MultiArrayView & operator=(MultiArrayView<N, U, C1> const & rhs)
{ {
vigra_precondition(this->shape() == rhs.shape(), vigra_precondition(this->shape() == rhs.shape(),
"MultiArrayView::operator=() size mismatch."); "MultiArrayView::operator=() size mismatch.");
this->copyImpl(rhs); this->copyImpl(rhs);
return *this; return *this;
} }
/** Assignment of a scalar. Equivalent to MultiArrayView::init(v).
*/
MultiArrayView & operator=(value_type const & v)
{
return init(v);
}
/** Add-assignment of a compatible MultiArrayView. Fails with /** Add-assignment of a compatible MultiArrayView. Fails with
<tt>PreconditionViolation</tt> exception when the shapes do not match. <tt>PreconditionViolation</tt> exception when the shapes do not match.
*/ */
template<class U, class C1> template<class U, class C1>
MultiArrayView & operator+=(MultiArrayView<N, U, C1> const & rhs); MultiArrayView & operator+=(MultiArrayView<N, U, C1> const & rhs);
/** Subtract-assignment of a compatible MultiArrayView. Fails with /** Subtract-assignment of a compatible MultiArrayView. Fails with
<tt>PreconditionViolation</tt> exception when the shapes do not match. <tt>PreconditionViolation</tt> exception when the shapes do not match.
*/ */
template<class U, class C1> template<class U, class C1>
skipping to change at line 1062 skipping to change at line 1069
/** array access. /** array access.
*/ */
const_reference operator[] (const difference_type &d) const const_reference operator[] (const difference_type &d) const
{ {
VIGRA_ASSERT_INSIDE(d); VIGRA_ASSERT_INSIDE(d);
return m_ptr [dot (d, m_stride)]; return m_ptr [dot (d, m_stride)];
} }
/** equivalent to bindInner(), when M < N. /** equivalent to bindInner(), when M < N.
*/ */
template <unsigned int M> template <int M>
MultiArrayView <N-M, T, StridedArrayTag> operator[] (const TinyVector<M ultiArrayIndex, M> &d) const MultiArrayView <N-M, T, StridedArrayTag> operator[] (const TinyVector<M ultiArrayIndex, M> &d) const
{ {
return bindInner(d); return bindInner(d);
} }
/** Array access in scan-order sense. /** Array access in scan-order sense.
Mostly useful to support standard indexing for 1-dimensional mu lti-arrays, Mostly useful to support standard indexing for 1-dimensional mu lti-arrays,
but works for any N. Use scanOrderIndexToCoordinate() and but works for any N. Use scanOrderIndexToCoordinate() and
coordinateToScanOrderIndex() for conversion between indices and coordinates. coordinateToScanOrderIndex() for conversion between indices and coordinates.
skipping to change at line 1205 skipping to change at line 1212
{ {
VIGRA_ASSERT_INSIDE(difference_type(x,y,z,u,v)); VIGRA_ASSERT_INSIDE(difference_type(x,y,z,u,v));
return m_ptr [m_stride[0]*x + m_stride[1]*y + m_stride[2]*z + m_str ide[3]*u + m_stride[4]*v]; return m_ptr [m_stride[0]*x + m_stride[1]*y + m_stride[2]*z + m_str ide[3]*u + m_stride[4]*v];
} }
/** Init with a constant. /** Init with a constant.
*/ */
template <class U> template <class U>
MultiArrayView & init(const U & init) MultiArrayView & init(const U & init)
{ {
detail::copyScalarMultiArrayData(traverser_begin(), shape(), init, if(hasData())
MetaInt<actual_dimension-1>()); detail::copyScalarMultiArrayData(traverser_begin(), shape(), in
it, MetaInt<actual_dimension-1>());
return *this; return *this;
} }
/** Copy the data of the right-hand array (array shapes must match) . /** Copy the data of the right-hand array (array shapes must match) .
*/ */
void copy(const MultiArrayView & rhs) void copy(const MultiArrayView & rhs)
{ {
if(this == &rhs) if(this == &rhs)
return; return;
this->copyImpl(rhs); this->copyImpl(rhs);
skipping to change at line 1274 skipping to change at line 1282
<b>Usage:</b> <b>Usage:</b>
\code \code
// create a 3D array of size 40x30x20 // create a 3D array of size 40x30x20
typedef MultiArray<3, double>::difference_type Shape; typedef MultiArray<3, double>::difference_type Shape;
MultiArray<3, double> array3(Shape(40, 30, 20)); MultiArray<3, double> array3(Shape(40, 30, 20));
// get a 1D array by fixing index 1 to 12, and index 2 to 10 // get a 1D array by fixing index 1 to 12, and index 2 to 10
MultiArrayView <1, double> array1 = array3.bindOuter(TinyVector <MultiArrayIndex, 2>(12, 10)); MultiArrayView <1, double> array1 = array3.bindOuter(TinyVector <MultiArrayIndex, 2>(12, 10));
\endcode \endcode
*/ */
template <unsigned int M> template <int M, class Index>
MultiArrayView <N-M, T, StrideTag> bindOuter (const TinyVector <MultiAr MultiArrayView <N-M, T, StrideTag> bindOuter(const TinyVector <Index, M
rayIndex, M> &d) const; > &d) const;
/** bind the M innermost dimensions to certain indices. /** bind the M innermost dimensions to certain indices.
this reduces the dimensionality of the image to this reduces the dimensionality of the image to
max { 1, N-M }. max { 1, N-M }.
<b>Usage:</b> <b>Usage:</b>
\code \code
// create a 3D array of size 40x30x20 // create a 3D array of size 40x30x20
typedef MultiArray<3, double>::difference_type Shape; typedef MultiArray<3, double>::difference_type Shape;
MultiArray<3, double> array3(Shape(40, 30, 20)); MultiArray<3, double> array3(Shape(40, 30, 20));
// get a 1D array by fixing index 0 to 12, and index 1 to 10 // get a 1D array by fixing index 0 to 12, and index 1 to 10
MultiArrayView <1, double, StridedArrayTag> array1 = array3.bin dInner(TinyVector<MultiArrayIndex, 2>(12, 10)); MultiArrayView <1, double, StridedArrayTag> array1 = array3.bin dInner(TinyVector<MultiArrayIndex, 2>(12, 10));
\endcode \endcode
*/ */
template <unsigned int M> template <int M, class Index>
MultiArrayView <N-M, T, StridedArrayTag> MultiArrayView <N-M, T, StridedArrayTag> bindInner(const TinyVector <In
bindInner (const TinyVector <MultiArrayIndex, M> &d) const; dex, M> &d) const;
/** bind dimension M to index d. /** bind dimension M to index d.
this reduces the dimensionality of the image to this reduces the dimensionality of the image to
max { 1, N-1 }. max { 1, N-1 }.
<b>Usage:</b> <b>Usage:</b>
\code \code
// create a 3D array of size 40x30x20 // create a 3D array of size 40x30x20
typedef MultiArray<3, double>::difference_type Shape; typedef MultiArray<3, double>::difference_type Shape;
MultiArray<3, double> array3(Shape(40, 30, 20)); MultiArray<3, double> array3(Shape(40, 30, 20));
skipping to change at line 1441 skipping to change at line 1448
// temporarily add a singleton dimension to the destination arr ay // temporarily add a singleton dimension to the destination arr ay
transformMultiArray(srcMultiArrayRange(original), transformMultiArray(srcMultiArrayRange(original),
destMultiArrayRange(rowAverages.insertSingl etonDimension(0)), destMultiArrayRange(rowAverages.insertSingl etonDimension(0)),
FindAverage<double>()); FindAverage<double>());
\endcode \endcode
*/ */
MultiArrayView <N+1, T, StrideTag> MultiArrayView <N+1, T, StrideTag>
insertSingletonDimension (difference_type_1 i) const; insertSingletonDimension (difference_type_1 i) const;
/** Create a view to the diagonal elements of the array.
This produces a 1D array view whose size equals the size
of the shortest dimension of the original array.
<b>Usage:</b>
\code
// create a 3D array of size 40x30x20
typedef MultiArray<3, double>::difference_type Shape;
MultiArray<3, double> array3(Shape(40, 30, 20));
// get a view to the diagonal elements
MultiArrayView <1, double, StridedArrayTag> diagonal = array3.d
iagonal();
assert(diagonal.shape(0) == 20);
\endcode
*/
MultiArrayView<1, T, StridedArrayTag> diagonal() const
{
return MultiArrayView<1, T, StridedArrayTag>(Shape1(vigra::min(m_sh
ape)),
Shape1(vigra::sum(m_st
ride)), m_ptr);
}
/** create a rectangular subarray that spans between the /** create a rectangular subarray that spans between the
points p and q, where p is in the subarray, q not. points p and q, where p is in the subarray, q not.
<b>Usage:</b> <b>Usage:</b>
\code \code
// create a 3D array of size 40x30x20 // create a 3D array of size 40x30x20
typedef MultiArray<3, double>::difference_type Shape; typedef MultiArray<3, double>::difference_type Shape;
MultiArray<3, double> array3(Shape(40, 30, 20)); MultiArray<3, double> array3(Shape(40, 30, 20));
// get a subarray set is smaller by one element at all sides // get a subarray set is smaller by one element at all sides
skipping to change at line 1656 skipping to change at line 1685
{ {
bool res = false; bool res = false;
detail::reduceOverMultiArray(traverser_begin(), shape(), detail::reduceOverMultiArray(traverser_begin(), shape(),
res, res,
detail::AnyTrueReduceFunctor(), detail::AnyTrueReduceFunctor(),
MetaInt<actual_dimension-1>()); MetaInt<actual_dimension-1>());
return res; return res;
} }
/** Find the minimum and maximum element in this array. /** Find the minimum and maximum element in this array.
See \ref FeatureAccumulators for a general feature
extraction framework.
*/ */
void minmax(T * minimum, T * maximum) const void minmax(T * minimum, T * maximum) const
{ {
std::pair<T, T> res(NumericTraits<T>::max(), NumericTraits<T>::min( )); std::pair<T, T> res(NumericTraits<T>::max(), NumericTraits<T>::min( ));
detail::reduceOverMultiArray(traverser_begin(), shape(), detail::reduceOverMultiArray(traverser_begin(), shape(),
res, res,
detail::MinmaxReduceFunctor(), detail::MinmaxReduceFunctor(),
MetaInt<actual_dimension-1>()); MetaInt<actual_dimension-1>());
*minimum = res.first; *minimum = res.first;
*maximum = res.second; *maximum = res.second;
} }
/** Compute the mean and variance of the values in this array. /** Compute the mean and variance of the values in this array.
See \ref FeatureAccumulators for a general feature
extraction framework.
*/ */
template <class U> template <class U>
void meanVariance(U * mean, U * variance) const void meanVariance(U * mean, U * variance) const
{ {
typedef typename NumericTraits<U>::RealPromote R; typedef typename NumericTraits<U>::RealPromote R;
triple<R, R, R> res(0.0, 0.0, 0.0); R zero;
triple<double, R, R> res(0.0, zero, zero);
detail::reduceOverMultiArray(traverser_begin(), shape(), detail::reduceOverMultiArray(traverser_begin(), shape(),
res, res,
detail::MeanVarianceReduceFunctor(), detail::MeanVarianceReduceFunctor(),
MetaInt<actual_dimension-1>()); MetaInt<actual_dimension-1>());
*mean = res.second; *mean = res.second;
*variance = res.third / res.first; *variance = res.third / res.first;
} }
/** Compute the sum of the array elements. /** Compute the sum of the array elements.
skipping to change at line 1793 skipping to change at line 1827
typename NormTraits<MultiArrayView>::NormType typename NormTraits<MultiArrayView>::NormType
norm(int type = 2, bool useSquaredNorm = true) const; norm(int type = 2, bool useSquaredNorm = true) const;
/** return the pointer to the image data /** return the pointer to the image data
*/ */
pointer data () const pointer data () const
{ {
return m_ptr; return m_ptr;
} }
pointer & unsafePtr()
{
return m_ptr;
}
/** /**
* returns true iff this view refers to valid data, * returns true iff this view refers to valid data,
* i.e. data() is not a NULL pointer. (this is false after * i.e. data() is not a NULL pointer. (this is false after
* default construction.) * default construction.)
*/ */
bool hasData () const bool hasData () const
{ {
return m_ptr != 0; return m_ptr != 0;
} }
skipping to change at line 2053 skipping to change at line 2092
MultiArrayView <N, T, StridedArrayTag> MultiArrayView <N, T, StridedArrayTag>
MultiArrayView <N, T, StrideTag>::permuteStridesDescending() const MultiArrayView <N, T, StrideTag>::permuteStridesDescending() const
{ {
difference_type ordering(strideOrdering(m_stride)), permutation; difference_type ordering(strideOrdering(m_stride)), permutation;
for(MultiArrayIndex k=0; k<N; ++k) for(MultiArrayIndex k=0; k<N; ++k)
permutation[ordering[N-1-k]] = k; permutation[ordering[N-1-k]] = k;
return permuteDimensions(permutation); return permuteDimensions(permutation);
} }
template <unsigned int N, class T, class StrideTag> template <unsigned int N, class T, class StrideTag>
template <unsigned int M> template <int M, class Index>
MultiArrayView <N-M, T, StrideTag> MultiArrayView <N-M, T, StrideTag>
MultiArrayView <N, T, StrideTag>::bindOuter (const TinyVector <MultiArrayIn dex, M> &d) const MultiArrayView <N, T, StrideTag>::bindOuter (const TinyVector <Index, M> &d ) const
{ {
TinyVector <MultiArrayIndex, M> stride; TinyVector <MultiArrayIndex, M> stride;
stride.init (m_stride.begin () + N-M, m_stride.end ()); stride.init (m_stride.begin () + N-M, m_stride.end ());
pointer ptr = m_ptr + dot (d, stride); pointer ptr = m_ptr + dot (d, stride);
static const int NNew = (N-M == 0) ? 1 : N-M; static const int NNew = (N-M == 0) ? 1 : N-M;
TinyVector <MultiArrayIndex, NNew> inner_shape, inner_stride; TinyVector <MultiArrayIndex, NNew> inner_shape, inner_stride;
if (N-M == 0) if (N-M == 0)
{ {
inner_shape [0] = 1; inner_shape [0] = 1;
inner_stride [0] = 0; inner_stride [0] = 0;
} }
else else
{ {
inner_shape.init (m_shape.begin (), m_shape.end () - M); inner_shape.init (m_shape.begin (), m_shape.end () - M);
inner_stride.init (m_stride.begin (), m_stride.end () - M); inner_stride.init (m_stride.begin (), m_stride.end () - M);
} }
return MultiArrayView <N-M, T, StrideTag> (inner_shape, inner_stride, p tr); return MultiArrayView <N-M, T, StrideTag> (inner_shape, inner_stride, p tr);
} }
template <unsigned int N, class T, class StrideTag> template <unsigned int N, class T, class StrideTag>
template <unsigned int M> template <int M, class Index>
MultiArrayView <N - M, T, StridedArrayTag> MultiArrayView <N - M, T, StridedArrayTag>
MultiArrayView <N, T, StrideTag>::bindInner (const TinyVector <MultiArrayIn dex, M> &d) const MultiArrayView <N, T, StrideTag>::bindInner (const TinyVector <Index, M> &d ) const
{ {
TinyVector <MultiArrayIndex, M> stride; TinyVector <MultiArrayIndex, M> stride;
stride.init (m_stride.begin (), m_stride.end () - N + M); stride.init (m_stride.begin (), m_stride.end () - N + M);
pointer ptr = m_ptr + dot (d, stride); pointer ptr = m_ptr + dot (d, stride);
static const int NNew = (N-M == 0) ? 1 : N-M; static const int NNew = (N-M == 0) ? 1 : N-M;
TinyVector <MultiArrayIndex, NNew> outer_shape, outer_stride; TinyVector <MultiArrayIndex, NNew> outer_shape, outer_stride;
if (N-M == 0) if (N-M == 0)
{ {
outer_shape [0] = 1; outer_shape [0] = 1;
outer_stride [0] = 0; outer_stride [0] = 0;
skipping to change at line 2461 skipping to change at line 2500
{} {}
/** construct with given allocator /** construct with given allocator
*/ */
MultiArray (allocator_type const & alloc) MultiArray (allocator_type const & alloc)
: MultiArrayView <N, T> (difference_type (diff_zero_t(0)), : MultiArrayView <N, T> (difference_type (diff_zero_t(0)),
difference_type (diff_zero_t(0)), 0), difference_type (diff_zero_t(0)), 0),
m_alloc(alloc) m_alloc(alloc)
{} {}
/** construct with given length
Use only for 1-dimensional arrays (<tt>N==1</tt>).
*/
explicit MultiArray (difference_type_1 length,
allocator_type const & alloc = allocator_type());
/** construct with given shape /** construct with given shape
*/ */
explicit MultiArray (const difference_type &shape, explicit MultiArray (const difference_type &shape,
allocator_type const & alloc = allocator_type()); allocator_type const & alloc = allocator_type());
/** construct from shape with an initial value /** construct from shape with an initial value
*/ */
MultiArray (const difference_type &shape, const_reference init, MultiArray (const difference_type &shape, const_reference init,
allocator_type const & alloc = allocator_type()); allocator_type const & alloc = allocator_type());
skipping to change at line 2527 skipping to change at line 2573
the data are copied. Otherwise, new storage is allocated, which invalidates all the data are copied. Otherwise, new storage is allocated, which invalidates all
objects (array views, iterators) depending on the lhs array. objects (array views, iterators) depending on the lhs array.
*/ */
template <class U, class StrideTag> template <class U, class StrideTag>
MultiArray &operator= (const MultiArrayView<N, U, StrideTag> &rhs) MultiArray &operator= (const MultiArrayView<N, U, StrideTag> &rhs)
{ {
this->copyOrReshape(rhs); this->copyOrReshape(rhs);
return *this; return *this;
} }
/** assignment from scalar.<br>
Equivalent to MultiArray::init(v).
*/
MultiArray & operator=(value_type const & v)
{
return this->init(v);
}
/** Add-assignment from arbitrary MultiArrayView. Fails with /** Add-assignment from arbitrary MultiArrayView. Fails with
<tt>PreconditionViolation</tt> exception when the shapes do not match. <tt>PreconditionViolation</tt> exception when the shapes do not match.
If the left array has no data (hasData() is false), this functi
on is
equivalent to a normal assignment (i.e. an empty
array is interpreted as a zero-array of appropriate size).
*/ */
template <class U, class StrideTag> template <class U, class StrideTag>
MultiArray &operator+= (const MultiArrayView<N, U, StrideTag> &rhs) MultiArray &operator+= (const MultiArrayView<N, U, StrideTag> &rhs)
{ {
view_type::operator+=(rhs); if(this->hasData())
view_type::operator+=(rhs);
else
*this = rhs;
return *this; return *this;
} }
/** Subtract-assignment from arbitrary MultiArrayView. Fails with /** Subtract-assignment from arbitrary MultiArrayView. Fails with
<tt>PreconditionViolation</tt> exception when the shapes do not match. <tt>PreconditionViolation</tt> exception when the shapes do not match.
If the left array has no data (hasData() is false), this functi
on is
equivalent to an assignment of the negated rhs (i.e. an empty
array is interpreted as a zero-array of appropriate size).
*/ */
template <class U, class StrideTag> template <class U, class StrideTag>
MultiArray &operator-= (const MultiArrayView<N, U, StrideTag> &rhs) MultiArray &operator-= (const MultiArrayView<N, U, StrideTag> &rhs)
{ {
if(!this->hasData())
this->reshape(rhs.shape());
view_type::operator-=(rhs); view_type::operator-=(rhs);
return *this; return *this;
} }
/** Multiply-assignment from arbitrary MultiArrayView. Fails with /** Multiply-assignment from arbitrary MultiArrayView. Fails with
<tt>PreconditionViolation</tt> exception when the shapes do not match. <tt>PreconditionViolation</tt> exception when the shapes do not match.
If the left array has no data (hasData() is false), this functi
on is
equivalent to reshape(rhs.shape()) with zero initialisation (i.
e. an empty
array is interpreted as a zero-array of appropriate size).
*/ */
template <class U, class StrideTag> template <class U, class StrideTag>
MultiArray &operator*= (const MultiArrayView<N, U, StrideTag> &rhs) MultiArray &operator*= (const MultiArrayView<N, U, StrideTag> &rhs)
{ {
view_type::operator*=(rhs); if(this->hasData())
view_type::operator*=(rhs);
else
this->reshape(rhs.shape());
return *this; return *this;
} }
/** Divide-assignment from arbitrary MultiArrayView. Fails with /** Divide-assignment from arbitrary MultiArrayView. Fails with
<tt>PreconditionViolation</tt> exception when the shapes do not match. <tt>PreconditionViolation</tt> exception when the shapes do not match.
If the left array has no data (hasData() is false), this functi
on is
equivalent to reshape(rhs.shape()) with zero initialisation (i.
e. an empty
array is interpreted as a zero-array of appropriate size).
*/ */
template <class U, class StrideTag> template <class U, class StrideTag>
MultiArray &operator/= (const MultiArrayView<N, U, StrideTag> &rhs) MultiArray &operator/= (const MultiArrayView<N, U, StrideTag> &rhs)
{ {
view_type::operator/=(rhs); if(this->hasData())
view_type::operator/=(rhs);
else
this->reshape(rhs.shape());
return *this; return *this;
} }
/** Add-assignment of a scalar. /** Add-assignment of a scalar.
*/ */
MultiArray &operator+= (const T &rhs) MultiArray &operator+= (const T &rhs)
{ {
view_type::operator+=(rhs); view_type::operator+=(rhs);
return *this; return *this;
} }
skipping to change at line 2724 skipping to change at line 2801
/** get the allocator. /** get the allocator.
*/ */
allocator_type const & allocator () const allocator_type const & allocator () const
{ {
return m_alloc; return m_alloc;
} }
}; };
template <unsigned int N, class T, class A> template <unsigned int N, class T, class A>
MultiArray <N, T, A>::MultiArray (difference_type_1 length,
allocator_type const & alloc)
: MultiArrayView <N, T> (difference_type(length),
detail::defaultStride <1> (difference_type(length)
),
0),
m_alloc(alloc)
{
allocate (this->m_ptr, this->elementCount (), T());
}
template <unsigned int N, class T, class A>
MultiArray <N, T, A>::MultiArray (const difference_type &shape, MultiArray <N, T, A>::MultiArray (const difference_type &shape,
allocator_type const & alloc) allocator_type const & alloc)
: MultiArrayView <N, T> (shape, : MultiArrayView <N, T> (shape,
detail::defaultStride <MultiArrayView<N,T>::actual _dimension> (shape), detail::defaultStride <MultiArrayView<N,T>::actual _dimension> (shape),
0), 0),
m_alloc(alloc) m_alloc(alloc)
{ {
if (N == 0) if (N == 0)
{ {
this->m_shape [0] = 1; this->m_shape [0] = 1;
skipping to change at line 3259 skipping to change at line 3347
vigra_precondition ( vigra_precondition (
array.shape (0) == 3, "makeRGBImageView(): array.shape(0) must be 3 ."); array.shape (0) == 3, "makeRGBImageView(): array.shape(0) must be 3 .");
return BasicImageView <RGBValue<T> > ( return BasicImageView <RGBValue<T> > (
reinterpret_cast <RGBValue <T> *> (array.data ()), reinterpret_cast <RGBValue <T> *> (array.data ()),
array.shape (1), array.shape (2)); array.shape (1), array.shape (2));
} }
//@} //@}
} // namespace vigra } // namespace vigra
#undef VIGRA_ASSERT_INSIDE #undef VIGRA_ASSERT_INSIDE
#endif // VIGRA_MULTI_ARRAY_HXX #endif // VIGRA_MULTI_ARRAY_HXX
 End of changes. 31 change blocks. 
42 lines changed or deleted 145 lines changed or added


 multi_fft.hxx   multi_fft.hxx 
skipping to change at line 496 skipping to change at line 496
81536, 81648, 81900, 81920, 82320, 82500, 82944, 83160, 83200, 8334 9, 81536, 81648, 81900, 81920, 82320, 82500, 82944, 83160, 83200, 8334 9,
84000, 84035, 84240, 84375, 84480, 84672, 85050, 85293, 85536, 8575 0, 84000, 84035, 84240, 84375, 84480, 84672, 85050, 85293, 85536, 8575 0,
85995, 86016, 86240, 86400, 86436, 86625, 87318, 87360, 87480, 8750 0, 85995, 86016, 86240, 86400, 86436, 86625, 87318, 87360, 87480, 8750 0,
87750, 87808, 88000, 88200, 88452, 88704, 89100, 89180, 89600, 8985 6, 87750, 87808, 88000, 88200, 88452, 88704, 89100, 89180, 89600, 8985 6,
90000, 90112, 90552, 90720, 91000, 91125, 91728, 91854, 91875, 9216 0, 90000, 90112, 90552, 90720, 91000, 91125, 91728, 91854, 91875, 9216 0,
92400, 92610, 93184, 93312, 93555, 93600, 93639, 93750, 94080, 9432 5, 92400, 92610, 93184, 93312, 93555, 93600, 93639, 93750, 94080, 9432 5,
94500, 94770, 95040, 95256, 95550, 96000, 96040, 96228, 96250, 9676 8, 94500, 94770, 95040, 95256, 95550, 96000, 96040, 96228, 96250, 9676 8,
97020, 97200, 97500, 98000, 98280, 98304, 98415, 98560, 98784, 9900 0, 97020, 97200, 97500, 98000, 98280, 98304, 98415, 98560, 98784, 9900 0,
99225, 99792, 99840 }; 99225, 99792, 99840 };
if(s <= 0 || s > goodSizes[size-1]) if(s <= 0 || s >= goodSizes[size-1])
return s; return s;
return *std::upper_bound(goodSizes, goodSizes+size, s, std::less_equal< // find the smallest padding size that is at least as large as 's'
int>()); int * upperBound = std::upper_bound(goodSizes, goodSizes+size, s);
if(upperBound > goodSizes && upperBound[-1] == s)
return s;
else
return *upperBound;
} }
inline inline
int fftwEvenPaddingSize(int s) int fftwEvenPaddingSize(int s)
{ {
// Image sizes where FFTW is fast. The list contains all even // Image sizes where FFTW is fast. The list contains all even
// numbers less than 100000 whose prime decomposition is of the form // numbers less than 100000 whose prime decomposition is of the form
// 2^a*3^b*5^c*7^d*11^e*13^f, where a >= 1, e+f is either 0 or 1, and t he // 2^a*3^b*5^c*7^d*11^e*13^f, where a >= 1, e+f is either 0 or 1, and t he
// other exponents are arbitrary // other exponents are arbitrary
static const int size = 1063; static const int size = 1063;
skipping to change at line 607 skipping to change at line 612
78000, 78400, 78624, 78732, 78750, 78848, 79200, 79380, 79872, 8000 0, 78000, 78400, 78624, 78732, 78750, 78848, 79200, 79380, 79872, 8000 0,
80190, 80262, 80640, 80850, 81000, 81250, 81536, 81648, 81900, 8192 0, 80190, 80262, 80640, 80850, 81000, 81250, 81536, 81648, 81900, 8192 0,
82320, 82500, 82944, 83160, 83200, 84000, 84240, 84480, 84672, 8505 0, 82320, 82500, 82944, 83160, 83200, 84000, 84240, 84480, 84672, 8505 0,
85536, 85750, 86016, 86240, 86400, 86436, 87318, 87360, 87480, 8750 0, 85536, 85750, 86016, 86240, 86400, 86436, 87318, 87360, 87480, 8750 0,
87750, 87808, 88000, 88200, 88452, 88704, 89100, 89180, 89600, 8985 6, 87750, 87808, 88000, 88200, 88452, 88704, 89100, 89180, 89600, 8985 6,
90000, 90112, 90552, 90720, 91000, 91728, 91854, 92160, 92400, 9261 0, 90000, 90112, 90552, 90720, 91000, 91728, 91854, 92160, 92400, 9261 0,
93184, 93312, 93600, 93750, 94080, 94500, 94770, 95040, 95256, 9555 0, 93184, 93312, 93600, 93750, 94080, 94500, 94770, 95040, 95256, 9555 0,
96000, 96040, 96228, 96250, 96768, 97020, 97200, 97500, 98000, 9828 0, 96000, 96040, 96228, 96250, 96768, 97020, 97200, 97500, 98000, 9828 0,
98304, 98560, 98784, 99000, 99792, 99840 }; 98304, 98560, 98784, 99000, 99792, 99840 };
if(s <= 0 || s > goodSizes[size-1]) if(s <= 0 || s >= goodSizes[size-1])
return s;
// find the smallest padding size that is at least as large as 's'
int * upperBound = std::upper_bound(goodSizes, goodSizes+size, s);
if(upperBound > goodSizes && upperBound[-1] == s)
return s; return s;
return *std::upper_bound(goodSizes, goodSizes+size, s, std::less_equal< else
int>()); return *upperBound;
} }
template <int M> template <int M>
struct FFTEmbedKernel struct FFTEmbedKernel
{ {
template <unsigned int N, class Real, class C, class Shape> template <unsigned int N, class Real, class C, class Shape>
static void static void
exec(MultiArrayView<N, Real, C> & out, Shape const & kernelShape, exec(MultiArrayView<N, Real, C> & out, Shape const & kernelShape,
Shape & srcPoint, Shape & destPoint, bool copyIt) Shape & srcPoint, Shape & destPoint, bool copyIt)
{ {
 End of changes. 4 change blocks. 
6 lines changed or deleted 14 lines changed or added


 multi_iterator.hxx   multi_iterator.hxx 
skipping to change at line 65 skipping to change at line 65
<p> <p>
<UL style="list-style-image:url(documents/bullet.gif)"> <UL style="list-style-image:url(documents/bullet.gif)">
<LI> \ref vigra::MultiArrayShape <LI> \ref vigra::MultiArrayShape
<BR>&nbsp;&nbsp;&nbsp;<em>Difference type for \ref vigra::MultiArrayVi ew or \ref vigra::MultiIterator</em> <BR>&nbsp;&nbsp;&nbsp;<em>Difference type for \ref vigra::MultiArrayVi ew or \ref vigra::MultiIterator</em>
<LI> \ref vigra::MultiIterator <LI> \ref vigra::MultiIterator
<BR>&nbsp;&nbsp;&nbsp;<em>Iterator for unstrided \ref vigra::MultiArra yView</em> <BR>&nbsp;&nbsp;&nbsp;<em>Iterator for unstrided \ref vigra::MultiArra yView</em>
<LI> \ref vigra::StridedMultiIterator <LI> \ref vigra::StridedMultiIterator
<BR>&nbsp;&nbsp;&nbsp;<em>Iterator for strided \ref vigra::MultiArrayV iew</em> <BR>&nbsp;&nbsp;&nbsp;<em>Iterator for strided \ref vigra::MultiArrayV iew</em>
<LI> \ref vigra::StridedScanOrderIterator <LI> \ref vigra::StridedScanOrderIterator
<BR>&nbsp;&nbsp;&nbsp;<em>STL-compatible random access iterator for \r ef vigra::MultiArrayView</em> <BR>&nbsp;&nbsp;&nbsp;<em>STL-compatible random access iterator for \r ef vigra::MultiArrayView</em>
<LI> \ref vigra::CoupledScanOrderIterator
<BR>&nbsp;&nbsp;&nbsp;<em>Iterate over multiple images simultaneously
in scan order</em>
</UL> </UL>
</p> </p>
<p> <p>
The Multidimensional Iterator concept allows navigation on arrays The Multidimensional Iterator concept allows navigation on arrays
of arbitrary dimension. It provides two modes of iteration: of arbitrary dimension. It provides two modes of iteration:
<em>direct traversal</em>, and <em>hierarchical traversal</em>. <em>direct traversal</em>, and <em>hierarchical traversal</em>.
In general, hierarchical traversal will be faster, while only In general, hierarchical traversal will be faster, while only
direct traversal allows for true random access in all dimensions. direct traversal allows for true random access in all dimensions.
Via the <tt>dim<K>()</tt> function, operations applying to a particular Via the <tt>dim<K>()</tt> function, operations applying to a particular
skipping to change at line 364 skipping to change at line 366
*/ */
typedef TinyVector<MultiArrayIndex, N> type; typedef TinyVector<MultiArrayIndex, N> type;
}; };
typedef MultiArrayShape<1>::type Shape1; ///< shape type for MultiArray<1, T> typedef MultiArrayShape<1>::type Shape1; ///< shape type for MultiArray<1, T>
typedef MultiArrayShape<2>::type Shape2; ///< shape type for MultiArray<2, T> typedef MultiArrayShape<2>::type Shape2; ///< shape type for MultiArray<2, T>
typedef MultiArrayShape<3>::type Shape3; ///< shape type for MultiArray<3, T> typedef MultiArrayShape<3>::type Shape3; ///< shape type for MultiArray<3, T>
typedef MultiArrayShape<4>::type Shape4; ///< shape type for MultiArray<4, T> typedef MultiArrayShape<4>::type Shape4; ///< shape type for MultiArray<4, T>
typedef MultiArrayShape<5>::type Shape5; ///< shape type for MultiArray<5, T> typedef MultiArrayShape<5>::type Shape5; ///< shape type for MultiArray<5, T>
template <class POINTER>
struct MultiIteratorStrideTraits
{
typedef MultiArrayIndex stride_type;
typedef const stride_type* stride_array_type;
typedef stride_array_type shape_array_type;
static stride_array_type shift(stride_array_type s, unsigned d)
{
return s + d;
}
};
/********************************************************/ /********************************************************/
/* */ /* */
/* MultiIterator */ /* MultiIterator */
/* */ /* */
/********************************************************/ /********************************************************/
template <unsigned int N, class T, class REFERENCE, class POINTER> template <unsigned int N, class T, class REFERENCE, class POINTER>
class MultiIterator; class MultiIterator;
/********************************************************/ /********************************************************/
skipping to change at line 391 skipping to change at line 405
class MultiIterator<1, T, REFERENCE, POINTER> class MultiIterator<1, T, REFERENCE, POINTER>
{ {
public: public:
enum { level = 0 }; enum { level = 0 };
typedef T value_type; typedef T value_type;
typedef REFERENCE reference; typedef REFERENCE reference;
typedef const value_type &const_reference; typedef const value_type &const_reference;
typedef POINTER pointer; typedef POINTER pointer;
typedef const value_type *const_pointer; typedef const value_type *const_pointer;
typedef typename MultiArrayShape<1>::type multi_difference_type; typedef typename MultiArrayShape<1>::type multi_difference_type;
typedef MultiArrayIndex difference_type; typedef MultiIteratorStrideTraits<POINTER> stride_traits;
typedef typename stride_traits::stride_type difference_type;
typedef typename stride_traits::stride_array_type difference_array_type
;
typedef typename stride_traits::shape_array_type shape_array_type;
typedef StridedMultiIterator<1, T, REFERENCE, POINTER> iterator; typedef StridedMultiIterator<1, T, REFERENCE, POINTER> iterator;
typedef std::random_access_iterator_tag iterator_category; typedef std::random_access_iterator_tag iterator_category;
protected: protected:
pointer m_ptr; pointer m_ptr;
public: public:
MultiIterator () MultiIterator ()
: m_ptr (0) : m_ptr (0)
{} {}
MultiIterator (pointer ptr, MultiIterator (pointer ptr,
const difference_type *, const difference_array_type &,
const difference_type *) const shape_array_type &)
: m_ptr (ptr) : m_ptr (ptr)
{} {}
void operator++ () void operator++ ()
{ {
++m_ptr; ++m_ptr;
} }
void operator-- () void operator-- ()
{ {
skipping to change at line 595 skipping to change at line 612
public: public:
typedef MultiIterator<1, T, REFERENCE, POINTER> base_type; typedef MultiIterator<1, T, REFERENCE, POINTER> base_type;
enum { level = 1 }; enum { level = 1 };
typedef T value_type; typedef T value_type;
typedef REFERENCE reference; typedef REFERENCE reference;
typedef const value_type &const_reference; typedef const value_type &const_reference;
typedef POINTER pointer; typedef POINTER pointer;
typedef const value_type *const_pointer; typedef const value_type *const_pointer;
typedef typename MultiArrayShape<2>::type multi_difference_type; typedef typename MultiArrayShape<2>::type multi_difference_type;
typedef MultiArrayIndex difference_type; typedef MultiIteratorStrideTraits<POINTER> stride_traits;
typedef typename stride_traits::stride_type difference_type;
typedef typename stride_traits::stride_array_type difference_array_type
;
typedef typename stride_traits::shape_array_type shape_array_type;
typedef base_type next_type; typedef base_type next_type;
typedef StridedMultiIterator<1, T, REFERENCE, POINTER> iterator; typedef StridedMultiIterator<1, T, REFERENCE, POINTER> iterator;
typedef multi_dimensional_traverser_tag iterator_category; typedef multi_dimensional_traverser_tag iterator_category;
protected: protected:
const difference_type *m_stride; difference_array_type m_stride;
const difference_type *m_shape; shape_array_type m_shape;
public: public:
/* use default copy constructor and assignment operator */ /* use default copy constructor and assignment operator */
MultiIterator () MultiIterator ()
: base_type (), : base_type (),
m_stride (0), m_shape (0) m_stride (0), m_shape (0)
{} {}
MultiIterator (pointer ptr, MultiIterator (pointer ptr,
const difference_type *stride, const difference_array_type & stride,
const difference_type *shape) const shape_array_type & shape)
: base_type (ptr, stride, shape), : base_type (ptr, stride, shape),
m_stride (stride), m_shape (shape) m_stride (stride), m_shape (shape)
{} {}
void operator++ () void operator++ ()
{ {
this->m_ptr += m_stride [level]; this->m_ptr += m_stride [level];
} }
void operator-- () void operator-- ()
skipping to change at line 726 skipping to change at line 746
{ {
next_type ret = *this; next_type ret = *this;
ret += m_shape [level-1]; ret += m_shape [level-1];
return ret; return ret;
} }
iterator iteratorForDimension(unsigned int d) const iterator iteratorForDimension(unsigned int d) const
{ {
vigra_precondition(d <= level, vigra_precondition(d <= level,
"MultiIterator<N>::iteratorForDimension(d): d < N required"); "MultiIterator<N>::iteratorForDimension(d): d < N required");
return iterator(this->m_ptr, &m_stride [d], 0); return iterator(this->m_ptr, stride_traits::shift(m_stride, d), 0);
} }
template <unsigned int K> template <unsigned int K>
MultiIterator<K+1, T, REFERENCE, POINTER> & MultiIterator<K+1, T, REFERENCE, POINTER> &
dim() dim()
{ {
return *this; return *this;
} }
MultiIterator<1, T, REFERENCE, POINTER> & MultiIterator<1, T, REFERENCE, POINTER> &
skipping to change at line 808 skipping to change at line 828
*/ */
typedef const value_type *const_pointer; typedef const value_type *const_pointer;
/** multi difference type /** multi difference type
(used for offsetting along all axes simultaneously) (used for offsetting along all axes simultaneously)
*/ */
typedef typename MultiArrayShape<N>::type multi_difference_type; typedef typename MultiArrayShape<N>::type multi_difference_type;
/** difference type (used for offsetting) /** difference type (used for offsetting)
*/ */
#ifndef DOXYGEN
typedef MultiIteratorStrideTraits<POINTER> stride_traits;
typedef typename stride_traits::stride_type difference_type;
typedef typename stride_traits::stride_array_type difference_array_type
;
typedef typename stride_traits::shape_array_type shape_array_type;
#else
typedef MultiArrayIndex difference_type; typedef MultiArrayIndex difference_type;
#endif
/** the MultiIterator for the next lower dimension. /** the MultiIterator for the next lower dimension.
*/ */
typedef base_type next_type; typedef base_type next_type;
/** the 1-dimensional iterator for this iterator hierarchy /** the 1-dimensional iterator for this iterator hierarchy
(result of iteratorForDimension()). (result of iteratorForDimension()).
*/ */
typedef StridedMultiIterator<1, T, REFERENCE, POINTER> iterator; typedef StridedMultiIterator<1, T, REFERENCE, POINTER> iterator;
skipping to change at line 834 skipping to change at line 861
/** default constructor. /** default constructor.
*/ */
MultiIterator () MultiIterator ()
{} {}
/** construct from pointer, strides (offset of a sample to the /** construct from pointer, strides (offset of a sample to the
next) for every dimension, and the shape. next) for every dimension, and the shape.
*/ */
MultiIterator (pointer ptr, MultiIterator (pointer ptr,
const difference_type *stride, const difference_array_type & stride,
const difference_type *shape) const shape_array_type & shape)
: base_type (ptr, stride, shape) : base_type (ptr, stride, shape)
{} {}
/** prefix-increment the iterator in it's current dimension /** prefix-increment the iterator in its current dimension
*/ */
void operator++ () void operator++ ()
{ {
this->m_ptr += this->m_stride [level]; this->m_ptr += this->m_stride [level];
} }
/** prefix-decrement the iterator in it's current dimension /** prefix-decrement the iterator in its current dimension
*/ */
void operator-- () void operator-- ()
{ {
this->m_ptr -= this->m_stride [level]; this->m_ptr -= this->m_stride [level];
} }
/** postfix-increment the iterator in it's current dimension /** postfix-increment the iterator in its current dimension
*/ */
MultiIterator operator++ (int) MultiIterator operator++ (int)
{ {
MultiIterator ret = *this; MultiIterator ret = *this;
++(*this); ++(*this);
return ret; return ret;
} }
/** postfix-decrement the iterator in it's current dimension /** postfix-decrement the iterator in its current dimension
*/ */
MultiIterator operator-- (int) MultiIterator operator-- (int)
{ {
MultiIterator ret = *this; MultiIterator ret = *this;
--(*this); --(*this);
return ret; return ret;
} }
/** increment the iterator in it's current dimension /** increment the iterator in its current dimension
by the given value. by the given value.
*/ */
MultiIterator & operator+= (difference_type n) MultiIterator & operator+= (difference_type n)
{ {
this->m_ptr += n * this->m_stride [level]; this->m_ptr += n * this->m_stride [level];
return *this; return *this;
} }
/** increment the iterator in all dimensions /** increment the iterator in all dimensions
by the given offset. by the given offset.
*/ */
MultiIterator & operator+= (multi_difference_type const & d) MultiIterator & operator+= (multi_difference_type const & d)
{ {
this->m_ptr += total_stride(d.begin()); this->m_ptr += total_stride(d.begin());
return *this; return *this;
} }
/** decrement the iterator in it's current dimension /** decrement the iterator in its current dimension
by the given value. by the given value.
*/ */
MultiIterator & operator-= (difference_type n) MultiIterator & operator-= (difference_type n)
{ {
this->m_ptr -= n * this->m_stride [level]; this->m_ptr -= n * this->m_stride [level];
return *this; return *this;
} }
/** decrement the iterator in all dimensions /** decrement the iterator in all dimensions
by the given offset. by the given offset.
skipping to change at line 1062 skipping to change at line 1089
for(; i != end; ++i) for(; i != end; ++i)
{ {
// go down the current column starting at the location of ' outer' // go down the current column starting at the location of ' outer'
} }
\endcode \endcode
*/ */
iterator iteratorForDimension(unsigned int d) const iterator iteratorForDimension(unsigned int d) const
{ {
vigra_precondition(d <= level, vigra_precondition(d <= level,
"MultiIterator<N>::iteratorForDimension(d): d < N required"); "MultiIterator<N>::iteratorForDimension(d): d < N required");
return iterator(this->m_ptr, &this->m_stride [d], 0); return iterator(this->m_ptr, stride_traits::shift(this->m_stride, d ),0);
} }
/** Return the multi-iterator that operates on dimension K in order /** Return the multi-iterator that operates on dimension K in order
to manipulate this dimension directly. Usage: to manipulate this dimension directly. Usage:
\code \code
MultiIterator<3, int> i3 = ...; MultiIterator<3, int> i3 = ...;
i3.template dim<2>()++; // increment outer dimension i3.template dim<2>()++; // increment outer dimension
i3.template dim<0>()++; // increment inner dimension i3.template dim<0>()++; // increment inner dimension
skipping to change at line 1141 skipping to change at line 1168
class StridedMultiIterator<1, T, REFERENCE, POINTER> class StridedMultiIterator<1, T, REFERENCE, POINTER>
{ {
public: public:
enum { level = 0 }; enum { level = 0 };
typedef T value_type; typedef T value_type;
typedef REFERENCE reference; typedef REFERENCE reference;
typedef const value_type &const_reference; typedef const value_type &const_reference;
typedef POINTER pointer; typedef POINTER pointer;
typedef const value_type *const_pointer; typedef const value_type *const_pointer;
typedef typename MultiArrayShape<1>::type multi_difference_type; typedef typename MultiArrayShape<1>::type multi_difference_type;
typedef MultiArrayIndex difference_type; typedef MultiIteratorStrideTraits<POINTER> stride_traits;
typedef typename stride_traits::stride_type difference_type;
typedef typename stride_traits::stride_array_type difference_array_type
;
typedef typename stride_traits::shape_array_type shape_array_type;
typedef StridedMultiIterator<1, T, REFERENCE, POINTER> iterator; typedef StridedMultiIterator<1, T, REFERENCE, POINTER> iterator;
typedef std::random_access_iterator_tag iterator_category; typedef std::random_access_iterator_tag iterator_category;
protected: protected:
pointer m_ptr; pointer m_ptr;
difference_type m_stride; difference_type m_stride;
/* use default copy constructor and assignment operator */ /* use default copy constructor and assignment operator */
public: public:
StridedMultiIterator () StridedMultiIterator ()
: m_ptr (0), m_stride (0) : m_ptr (0), m_stride (0)
{} {}
StridedMultiIterator (pointer ptr, StridedMultiIterator (pointer ptr,
const difference_type *stride, const difference_array_type & stride,
const difference_type *) const shape_array_type &)
: m_ptr (ptr), m_stride (stride [level]) : m_ptr (ptr), m_stride (stride [level])
{} {}
void operator++ () void operator++ ()
{ {
m_ptr += m_stride; m_ptr += m_stride;
} }
void operator-- () void operator-- ()
{ {
skipping to change at line 1348 skipping to change at line 1378
public: public:
typedef StridedMultiIterator<1, T, REFERENCE, POINTER> base_type; typedef StridedMultiIterator<1, T, REFERENCE, POINTER> base_type;
enum { level = 1 }; enum { level = 1 };
typedef T value_type; typedef T value_type;
typedef REFERENCE reference; typedef REFERENCE reference;
typedef const value_type &const_reference; typedef const value_type &const_reference;
typedef POINTER pointer; typedef POINTER pointer;
typedef const value_type *const_pointer; typedef const value_type *const_pointer;
typedef typename MultiArrayShape<2>::type multi_difference_type; typedef typename MultiArrayShape<2>::type multi_difference_type;
typedef MultiArrayIndex difference_type; typedef MultiIteratorStrideTraits<POINTER> stride_traits;
typedef typename stride_traits::stride_type difference_type;
typedef typename stride_traits::stride_array_type difference_array_type
;
typedef typename stride_traits::shape_array_type shape_array_type;
typedef base_type next_type; typedef base_type next_type;
typedef StridedMultiIterator<1, T, REFERENCE, POINTER> iterator; typedef StridedMultiIterator<1, T, REFERENCE, POINTER> iterator;
typedef multi_dimensional_traverser_tag iterator_category; typedef multi_dimensional_traverser_tag iterator_category;
protected: protected:
const difference_type *m_stride; difference_array_type m_stride;
const difference_type *m_shape; shape_array_type m_shape;
public: public:
/* use default copy constructor and assignment operator */ /* use default copy constructor and assignment operator */
StridedMultiIterator () StridedMultiIterator ()
: base_type (), : base_type (),
m_stride (0), m_shape (0) m_stride (0), m_shape (0)
{} {}
StridedMultiIterator (pointer ptr, StridedMultiIterator (pointer ptr,
const difference_type *stride, const difference_array_type & stride,
const difference_type *shape) const shape_array_type & shape)
: base_type (ptr, stride, shape), : base_type (ptr, stride, shape),
m_stride (stride), m_shape (shape) m_stride (stride), m_shape (shape)
{} {}
void operator++ () void operator++ ()
{ {
this->m_ptr += m_stride [level]; this->m_ptr += m_stride [level];
} }
void operator-- () void operator-- ()
skipping to change at line 1479 skipping to change at line 1512
{ {
next_type ret = *this; next_type ret = *this;
ret += m_shape [level-1]; ret += m_shape [level-1];
return ret; return ret;
} }
iterator iteratorForDimension(unsigned int d) const iterator iteratorForDimension(unsigned int d) const
{ {
vigra_precondition(d <= level, vigra_precondition(d <= level,
"StridedMultiIterator<N>::iteratorForDimension(d): d < N requir ed"); "StridedMultiIterator<N>::iteratorForDimension(d): d < N requir ed");
return iterator(this->m_ptr, &m_stride [d], 0); return iterator(this->m_ptr, stride_traits::shift(m_stride, d), 0);
} }
template <unsigned int K> template <unsigned int K>
StridedMultiIterator<K+1, T, REFERENCE, POINTER> & StridedMultiIterator<K+1, T, REFERENCE, POINTER> &
dim() dim()
{ {
return *this; return *this;
} }
StridedMultiIterator<1, T, REFERENCE, POINTER> & StridedMultiIterator<1, T, REFERENCE, POINTER> &
skipping to change at line 1561 skipping to change at line 1594
*/ */
typedef const value_type *const_pointer; typedef const value_type *const_pointer;
/** multi difference type /** multi difference type
(used for offsetting along all axes simultaneously) (used for offsetting along all axes simultaneously)
*/ */
typedef typename MultiArrayShape<N>::type multi_difference_type; typedef typename MultiArrayShape<N>::type multi_difference_type;
/** difference type (used for offsetting) /** difference type (used for offsetting)
*/ */
#ifndef DOXYGEN
typedef MultiIteratorStrideTraits<POINTER> stride_traits;
typedef typename stride_traits::stride_type difference_type;
typedef typename stride_traits::stride_array_type difference_array_type
;
#else
typedef MultiArrayIndex difference_type; typedef MultiArrayIndex difference_type;
#endif
/** the StridedMultiIterator for the next lower dimension. /** the StridedMultiIterator for the next lower dimension.
*/ */
typedef base_type next_type; typedef base_type next_type;
/** the 1-dimensional iterator for this iterator hierarchy /** the 1-dimensional iterator for this iterator hierarchy
(result of iteratorForDimension()). (result of iteratorForDimension()).
*/ */
typedef StridedMultiIterator<1, T, REFERENCE, POINTER> iterator; typedef StridedMultiIterator<1, T, REFERENCE, POINTER> iterator;
skipping to change at line 1587 skipping to change at line 1626
/** default constructor. /** default constructor.
*/ */
StridedMultiIterator () StridedMultiIterator ()
{} {}
/** construct from pointer, strides (offset of a sample to the /** construct from pointer, strides (offset of a sample to the
next) for every dimension, and the shape. next) for every dimension, and the shape.
*/ */
StridedMultiIterator (pointer ptr, StridedMultiIterator (pointer ptr,
const difference_type *stride, const difference_array_type & stride,
const difference_type *shape) const difference_array_type & shape)
: base_type (ptr, stride, shape) : base_type (ptr, stride, shape)
{} {}
/** prefix-increment the iterator in it's current dimension /** prefix-increment the iterator in its current dimension
*/ */
void operator++ () void operator++ ()
{ {
this->m_ptr += this->m_stride [level]; this->m_ptr += this->m_stride [level];
} }
/** prefix-decrement the iterator in it's current dimension /** prefix-decrement the iterator in its current dimension
*/ */
void operator-- () void operator-- ()
{ {
this->m_ptr -= this->m_stride [level]; this->m_ptr -= this->m_stride [level];
} }
/** postfix-increment the iterator in it's current dimension /** postfix-increment the iterator in its current dimension
*/ */
StridedMultiIterator operator++ (int) StridedMultiIterator operator++ (int)
{ {
StridedMultiIterator ret = *this; StridedMultiIterator ret = *this;
++(*this); ++(*this);
return ret; return ret;
} }
/** postfix-decrement the iterator in it's current dimension /** postfix-decrement the iterator in its current dimension
*/ */
StridedMultiIterator operator-- (int) StridedMultiIterator operator-- (int)
{ {
StridedMultiIterator ret = *this; StridedMultiIterator ret = *this;
--(*this); --(*this);
return ret; return ret;
} }
/** increment the iterator in it's current dimension /** increment the iterator in its current dimension
by the given value. by the given value.
*/ */
StridedMultiIterator & operator+= (difference_type n) StridedMultiIterator & operator+= (difference_type n)
{ {
this->m_ptr += n * this->m_stride [level]; this->m_ptr += n * this->m_stride [level];
return *this; return *this;
} }
/** increment the iterator in all dimensions /** increment the iterator in all dimensions
by the given offset. by the given offset.
*/ */
StridedMultiIterator & operator+= (multi_difference_type const & d) StridedMultiIterator & operator+= (multi_difference_type const & d)
{ {
this->m_ptr += total_stride(d.begin()); this->m_ptr += total_stride(d.begin());
return *this; return *this;
} }
/** decrement the iterator in it's current dimension /** decrement the iterator in its current dimension
by the given value. by the given value.
*/ */
StridedMultiIterator & operator-= (difference_type n) StridedMultiIterator & operator-= (difference_type n)
{ {
this->m_ptr -= n * this->m_stride [level]; this->m_ptr -= n * this->m_stride [level];
return *this; return *this;
} }
/** decrement the iterator in all dimensions /** decrement the iterator in all dimensions
by the given offset. by the given offset.
skipping to change at line 1815 skipping to change at line 1854
for(; i != end; ++i) for(; i != end; ++i)
{ {
// go down the current column starting at the location of ' outer' // go down the current column starting at the location of ' outer'
} }
\endcode \endcode
*/ */
iterator iteratorForDimension(unsigned int d) const iterator iteratorForDimension(unsigned int d) const
{ {
vigra_precondition(d <= level, vigra_precondition(d <= level,
"StridedMultiIterator<N>::iteratorForDimension(d): d < N requir ed"); "StridedMultiIterator<N>::iteratorForDimension(d): d < N requir ed");
return iterator(this->m_ptr, &this->m_stride [d], 0); return iterator(this->m_ptr, stride_traits::shift(this->m_stride, d ),0);
} }
/** Return the multi-iterator that operates on dimension K in order /** Return the multi-iterator that operates on dimension K in order
to manipulate this dimension directly. Usage: to manipulate this dimension directly. Usage:
\code \code
StridedMultiIterator<3, int> i3 = ...; StridedMultiIterator<3, int> i3 = ...;
i3.template dim<2>()++; // increment outer dimension i3.template dim<2>()++; // increment outer dimension
i3.template dim<0>()++; // increment inner dimension i3.template dim<0>()++; // increment inner dimension
skipping to change at line 1869 skipping to change at line 1908
difference_type difference_type
total_stride(typename multi_difference_type::const_iterator d) const total_stride(typename multi_difference_type::const_iterator d) const
{ {
return d[level]*this->m_stride[level] + base_type::total_stride(d); return d[level]*this->m_stride[level] + base_type::total_stride(d);
} }
}; };
namespace detail { namespace detail {
template <int K>
struct CoordinateToScanOrder
{
template <int N>
static MultiArrayIndex
exec(const TinyVector <MultiArrayIndex, N> &shape,
const TinyVector <MultiArrayIndex, N> & coordinate)
{
return coordinate[N-K] + shape[N-K] * CoordinateToScanOrder<K-1>::e
xec(shape, coordinate);
}
};
template <>
struct CoordinateToScanOrder<1>
{
template <int N>
static MultiArrayIndex
exec(const TinyVector <MultiArrayIndex, N> & /*shape*/,
const TinyVector <MultiArrayIndex, N> & coordinate)
{
return coordinate[N-1];
}
};
template <unsigned int M> template <unsigned int M>
struct MoveToScanOrderIndex struct MoveToScanOrderIndex
{ {
template <class Shape, class Ptr> template <class Shape, class Ptr>
static void static void
exec(MultiArrayIndex newIndex, Shape const & shape, exec(MultiArrayIndex newIndex, Shape const & shape,
Shape & point, Ptr & p, Shape const & strides) Shape & point, Ptr & p, Shape const & strides)
{ {
enum { N = Shape::static_size }; enum { N = Shape::static_size };
MultiArrayIndex newPos = newIndex % shape[N-1-M]; MultiArrayIndex newPos = newIndex % shape[N-1-M];
skipping to change at line 1908 skipping to change at line 1971
template <> template <>
struct MoveToScanOrderIndex<0> struct MoveToScanOrderIndex<0>
{ {
template <class Shape, class Ptr> template <class Shape, class Ptr>
static void static void
exec(MultiArrayIndex newIndex, Shape const & shape, exec(MultiArrayIndex newIndex, Shape const & shape,
Shape & point, Ptr & p, Shape const & strides) Shape & point, Ptr & p, Shape const & strides)
{ {
enum { N = Shape::static_size }; enum { N = Shape::static_size };
MultiArrayIndex newPos = newIndex % shape[N-1]; MultiArrayIndex newPos = std::min(newIndex, shape[N-1]);
p += (newPos - point[N-1]) * strides[N-1]; p += (newPos - point[N-1]) * strides[N-1];
point[N-1] = newPos; point[N-1] = newPos;
} }
template <class Shape, class Ptr1, class Ptr2> template <class Shape, class Ptr1, class Ptr2>
static void static void
exec(MultiArrayIndex newIndex, Shape const & shape, Shape & point, exec(MultiArrayIndex newIndex, Shape const & shape, Shape & point,
Ptr1 & p1, Shape const & strides1, Ptr2 & p2, Shape const & stride s2) Ptr1 & p1, Shape const & strides1, Ptr2 & p2, Shape const & stride s2)
{ {
enum { N = Shape::static_size }; enum { N = Shape::static_size };
MultiArrayIndex newPos = newIndex % shape[N-1]; MultiArrayIndex newPos = std::min(newIndex, shape[N-1]);
p1 += (newPos - point[N-1]) * strides1[N-1]; p1 += (newPos - point[N-1]) * strides1[N-1];
p2 += (newPos - point[N-1]) * strides2[N-1]; p2 += (newPos - point[N-1]) * strides2[N-1];
point[N-1] = newPos; point[N-1] = newPos;
} }
}; };
#if 0 // alternative implementation, may be faster on some machines #if 0 // alternative implementation, may be faster on some machines
template <unsigned int M> template <unsigned int M>
struct MoveToScanOrderIndex struct MoveToScanOrderIndex
{ {
skipping to change at line 2023 skipping to change at line 2086
typedef StridedScanOrderIterator<N, T, REFERENCE, POINTER, M-1> base_ty pe; typedef StridedScanOrderIterator<N, T, REFERENCE, POINTER, M-1> base_ty pe;
enum { level = M-1 }; enum { level = M-1 };
public: public:
typedef typename base_type::value_type value_type; typedef typename base_type::value_type value_type;
typedef typename base_type::pointer pointer; typedef typename base_type::pointer pointer;
typedef typename base_type::reference reference; typedef typename base_type::reference reference;
typedef typename base_type::const_reference const_reference; typedef typename base_type::const_reference const_reference;
typedef typename base_type::shape_type shape_type; typedef typename base_type::shape_type shape_type;
typedef MultiArrayIndex difference_type; typedef MultiIteratorStrideTraits<POINTER> stride_traits;
typedef typename stride_traits::stride_type difference_type;
typedef typename stride_traits::stride_array_type difference_array_type
;
typedef StridedScanOrderIterator iterator; typedef StridedScanOrderIterator iterator;
typedef std::random_access_iterator_tag iterator_category; typedef std::random_access_iterator_tag iterator_category;
StridedScanOrderIterator() StridedScanOrderIterator()
{} {}
StridedScanOrderIterator(pointer i, StridedScanOrderIterator(pointer i,
shape_type const & shape, shape_type const & s trides) shape_type const & shape, shape_type const & s trides)
: base_type(i, shape, strides) : base_type(i, shape, strides)
{} {}
skipping to change at line 2060 skipping to change at line 2125
++*this; ++*this;
return res; return res;
} }
StridedScanOrderIterator & operator+=(MultiArrayIndex i) StridedScanOrderIterator & operator+=(MultiArrayIndex i)
{ {
this->moveToScanOrderIndex(this->index_+i); this->moveToScanOrderIndex(this->index_+i);
return *this; return *this;
} }
//! overload to add a coord-tuple:
// it should be cheaper because the modulo-divisions are avoided
StridedScanOrderIterator & operator+=(const shape_type &coordOffset)
{
this->moveRelative(dot(coordOffset,this->strides_),
detail::CoordinateToScanOrder<N>::exec(this->shape_, coordOf
fset),
coordOffset);
return *this;
}
StridedScanOrderIterator & operator-=(const shape_type &coordOffset)
{
return operator+=(-coordOffset);
}
StridedScanOrderIterator & operator--() StridedScanOrderIterator & operator--()
{ {
base_type::operator--(); base_type::operator--();
if(this->point_[level-1] == -1) if(this->point_[level-1] == -1)
{ {
base_type::inverseReset(); base_type::inverseReset();
this->i_ -= this->strides_[level]; this->i_ -= this->strides_[level];
--this->point_[level]; --this->point_[level];
} }
return *this; return *this;
skipping to change at line 2118 skipping to change at line 2197
StridedScanOrderIterator operator+(MultiArrayIndex d) const StridedScanOrderIterator operator+(MultiArrayIndex d) const
{ {
return StridedScanOrderIterator(*this) += d; return StridedScanOrderIterator(*this) += d;
} }
StridedScanOrderIterator operator-(MultiArrayIndex d) const StridedScanOrderIterator operator-(MultiArrayIndex d) const
{ {
return StridedScanOrderIterator(*this) -= d; return StridedScanOrderIterator(*this) -= d;
} }
StridedScanOrderIterator operator+(const shape_type &coordOffset) const
{
return StridedScanOrderIterator(*this) += coordOffset;
}
StridedScanOrderIterator operator-(const shape_type &coordOffset) const
{
return StridedScanOrderIterator(*this) -= coordOffset;
}
MultiArrayIndex operator-(StridedScanOrderIterator const & r) const MultiArrayIndex operator-(StridedScanOrderIterator const & r) const
{ {
return base_type::operator-(r); return base_type::operator-(r);
} }
bool operator==(StridedScanOrderIterator const & r) bool operator==(StridedScanOrderIterator const & r)
{ {
return base_type::operator==(r); return base_type::operator==(r);
} }
skipping to change at line 2200 skipping to change at line 2289
{ {
base_type::decrement(p2, strides2); base_type::decrement(p2, strides2);
if(this->point_[level-1] == -1) if(this->point_[level-1] == -1)
{ {
base_type::inverseReset(); base_type::inverseReset();
this->i_ -= this->strides_[level]; this->i_ -= this->strides_[level];
p2 -= strides2[level] - this->shape_[level-1]*strides2[level-1] ; p2 -= strides2[level] - this->shape_[level-1]*strides2[level-1] ;
--this->point_[level]; --this->point_[level];
} }
} }
StridedScanOrderIterator & moveRelative(const MultiArrayIndex &pointerO
ffset,
const MultiArrayIndex &indexOff
set,
const shape_type &coordOffset)
{
base_type::moveRelative(pointerOffset, indexOffset, coordOffset);
this->point_[level] += coordOffset[level];
return *this;
}
}; };
template <unsigned int N, class T, class REFERENCE, class POINTER> template <unsigned int N, class T, class REFERENCE, class POINTER>
class StridedScanOrderIterator<N, T, REFERENCE, POINTER, 1> class StridedScanOrderIterator<N, T, REFERENCE, POINTER, 1>
{ {
enum { level = 0 }; enum { level = 0 };
public: public:
typedef T value_type; typedef T value_type;
typedef POINTER pointer; typedef POINTER pointer;
typedef T const * const_pointer; typedef T const * const_pointer;
typedef REFERENCE reference; typedef REFERENCE reference;
typedef T const & const_reference; typedef T const & const_reference;
typedef typename MultiArrayShape<N>::type shape_type; typedef typename MultiArrayShape<N>::type shape_type;
typedef MultiArrayIndex difference_type; typedef MultiIteratorStrideTraits<POINTER> stride_traits;
typedef typename stride_traits::stride_type difference_type;
typedef typename stride_traits::stride_array_type difference_array_type
;
typedef StridedScanOrderIterator iterator; typedef StridedScanOrderIterator iterator;
typedef std::random_access_iterator_tag iterator_category; typedef std::random_access_iterator_tag iterator_category;
StridedScanOrderIterator() StridedScanOrderIterator()
: i_((pointer)0), : i_((pointer)0),
index_(0) index_(0)
{} {}
StridedScanOrderIterator(pointer i, StridedScanOrderIterator(pointer i,
shape_type const & shape, shape_type const & s trides) shape_type const & shape, shape_type const & s trides)
skipping to change at line 2253 skipping to change at line 2352
++*this; ++*this;
return res; return res;
} }
StridedScanOrderIterator & operator+=(MultiArrayIndex i) StridedScanOrderIterator & operator+=(MultiArrayIndex i)
{ {
this->moveToScanOrderIndex(index_+i); this->moveToScanOrderIndex(index_+i);
return *this; return *this;
} }
//! overload to add a coord-tuple:
StridedScanOrderIterator & operator+=(const shape_type &coordOffset)
{
this->moveRelative(dot(coordOffset,strides_),
detail::CoordinateToScanOrder<N>::exec(shape_, coordOffset),
coordOffset);
return *this;
}
StridedScanOrderIterator & operator-=(const shape_type &coordOffset)
{
return operator+=(-coordOffset);
}
StridedScanOrderIterator & operator--() StridedScanOrderIterator & operator--()
{ {
i_ -= strides_[level]; i_ -= strides_[level];
--point_[level]; --point_[level];
--index_; --index_;
return *this; return *this;
} }
StridedScanOrderIterator operator--(int) StridedScanOrderIterator operator--(int)
{ {
skipping to change at line 2329 skipping to change at line 2442
{ {
return StridedScanOrderIterator(*this) += d; return StridedScanOrderIterator(*this) += d;
} }
StridedScanOrderIterator StridedScanOrderIterator
operator-(MultiArrayIndex d) const operator-(MultiArrayIndex d) const
{ {
return StridedScanOrderIterator(*this) -= d; return StridedScanOrderIterator(*this) -= d;
} }
StridedScanOrderIterator operator+(const shape_type &coordOffset) const
{
return StridedScanOrderIterator(*this) += coordOffset;
}
StridedScanOrderIterator operator-(const shape_type &coordOffset) const
{
return StridedScanOrderIterator(*this) -= coordOffset;
}
MultiArrayIndex MultiArrayIndex
operator-(StridedScanOrderIterator const & r) const operator-(StridedScanOrderIterator const & r) const
{ {
return index() - r.index(); return index() - r.index();
} }
bool bool
operator==(StridedScanOrderIterator const & r) operator==(StridedScanOrderIterator const & r)
{ {
return index() == r.index(); return index() == r.index();
skipping to change at line 2453 skipping to change at line 2576
p2 -= strides2[level]; p2 -= strides2[level];
} }
template <class Ptr> template <class Ptr>
void moveToScanOrderIndex(MultiArrayIndex newIndex, Ptr & p2, shape_typ e const & strides2) void moveToScanOrderIndex(MultiArrayIndex newIndex, Ptr & p2, shape_typ e const & strides2)
{ {
index_ = newIndex; index_ = newIndex;
detail::MoveToScanOrderIndex<N-1>::exec(newIndex, shape_, point_, i _, strides_, p2, strides2); detail::MoveToScanOrderIndex<N-1>::exec(newIndex, shape_, point_, i _, strides_, p2, strides2);
} }
StridedScanOrderIterator & moveRelative(const MultiArrayIndex &pointerO
ffset,
const MultiArrayIndex &indexOff
set,
const shape_type &coordOffset)
{
point_[level] += coordOffset[level];
index_+= indexOffset;
i_ += pointerOffset;
return *this;
}
pointer i_; pointer i_;
shape_type point_, shape_, strides_; shape_type point_, shape_, strides_;
MultiArrayIndex index_; MultiArrayIndex index_;
}; };
//@} //@}
} // namespace vigra } // namespace vigra
#endif // VIGRA_MULTI_ITERATOR_HXX #endif // VIGRA_MULTI_ITERATOR_HXX
 End of changes. 45 change blocks. 
40 lines changed or deleted 190 lines changed or added


 multi_math.hxx   multi_math.hxx 
skipping to change at line 661 skipping to change at line 661
VIGRA_MULTIMATH_BINARY_OPERATOR(LessEqual, VIGRA_NOTHING, operator<=, <=, b ool) VIGRA_MULTIMATH_BINARY_OPERATOR(LessEqual, VIGRA_NOTHING, operator<=, <=, b ool)
VIGRA_MULTIMATH_BINARY_OPERATOR(Greater, VIGRA_NOTHING, operator>, >, bool) VIGRA_MULTIMATH_BINARY_OPERATOR(Greater, VIGRA_NOTHING, operator>, >, bool)
VIGRA_MULTIMATH_BINARY_OPERATOR(GreaterEqual, VIGRA_NOTHING, operator>=, >= , bool) VIGRA_MULTIMATH_BINARY_OPERATOR(GreaterEqual, VIGRA_NOTHING, operator>=, >= , bool)
VIGRA_MULTIMATH_BINARY_OPERATOR(Leftshift, VIGRA_NOTHING, operator<<, <<, V IGRA_PROMOTE) VIGRA_MULTIMATH_BINARY_OPERATOR(Leftshift, VIGRA_NOTHING, operator<<, <<, V IGRA_PROMOTE)
VIGRA_MULTIMATH_BINARY_OPERATOR(Rightshift, VIGRA_NOTHING, operator>>, >>, VIGRA_PROMOTE) VIGRA_MULTIMATH_BINARY_OPERATOR(Rightshift, VIGRA_NOTHING, operator>>, >>, VIGRA_PROMOTE)
VIGRA_MULTIMATH_BINARY_OPERATOR(BitwiseAnd, VIGRA_NOTHING, operator&, &, VI GRA_PROMOTE) VIGRA_MULTIMATH_BINARY_OPERATOR(BitwiseAnd, VIGRA_NOTHING, operator&, &, VI GRA_PROMOTE)
VIGRA_MULTIMATH_BINARY_OPERATOR(BitwiseOr, VIGRA_NOTHING, operator|, |, VIG RA_PROMOTE) VIGRA_MULTIMATH_BINARY_OPERATOR(BitwiseOr, VIGRA_NOTHING, operator|, |, VIG RA_PROMOTE)
VIGRA_MULTIMATH_BINARY_OPERATOR(BitwiseXor, VIGRA_NOTHING, operator^, ^, VI GRA_PROMOTE) VIGRA_MULTIMATH_BINARY_OPERATOR(BitwiseXor, VIGRA_NOTHING, operator^, ^, VI GRA_PROMOTE)
VIGRA_MULTIMATH_BINARY_OPERATOR(Atan2, std::atan2, atan2, VIGRA_COMMA, VIGR A_REALPROMOTE) VIGRA_MULTIMATH_BINARY_OPERATOR(Atan2, std::atan2, atan2, VIGRA_COMMA, VIGR A_REALPROMOTE)
VIGRA_MULTIMATH_BINARY_OPERATOR(Pow, std::pow, pow, VIGRA_COMMA, VIGRA_REAL PROMOTE) VIGRA_MULTIMATH_BINARY_OPERATOR(Pow, vigra::pow, pow, VIGRA_COMMA, VIGRA_RE ALPROMOTE)
VIGRA_MULTIMATH_BINARY_OPERATOR(Fmod, std::fmod, fmod, VIGRA_COMMA, VIGRA_R EALPROMOTE) VIGRA_MULTIMATH_BINARY_OPERATOR(Fmod, std::fmod, fmod, VIGRA_COMMA, VIGRA_R EALPROMOTE)
VIGRA_MULTIMATH_BINARY_OPERATOR(Min, std::min, min, VIGRA_COMMA, VIGRA_PROM OTE) VIGRA_MULTIMATH_BINARY_OPERATOR(Min, std::min, min, VIGRA_COMMA, VIGRA_PROM OTE)
VIGRA_MULTIMATH_BINARY_OPERATOR(Max, std::max, max, VIGRA_COMMA, VIGRA_PROM OTE) VIGRA_MULTIMATH_BINARY_OPERATOR(Max, std::max, max, VIGRA_COMMA, VIGRA_PROM OTE)
VIGRA_MULTIMATH_BINARY_OPERATOR(Minimum, std::min, minimum, VIGRA_COMMA, VI GRA_PROMOTE) VIGRA_MULTIMATH_BINARY_OPERATOR(Minimum, std::min, minimum, VIGRA_COMMA, VI GRA_PROMOTE)
VIGRA_MULTIMATH_BINARY_OPERATOR(Maximum, std::max, maximum, VIGRA_COMMA, VI GRA_PROMOTE) VIGRA_MULTIMATH_BINARY_OPERATOR(Maximum, std::max, maximum, VIGRA_COMMA, VI GRA_PROMOTE)
#undef VIGRA_NOTHING #undef VIGRA_NOTHING
#undef VIGRA_COMMA #undef VIGRA_COMMA
#undef VIGRA_PROMOTE #undef VIGRA_PROMOTE
#undef VIGRA_REALPROMOTE #undef VIGRA_REALPROMOTE
skipping to change at line 832 skipping to change at line 832
typename MultiArrayShape<ndim>::type shape; typename MultiArrayShape<ndim>::type shape;
v.checkShape(shape); v.checkShape(shape);
detail::MultiMathReduce<ndim, detail::MultiMathplusAssign>::exec(res, s hape, v); detail::MultiMathReduce<ndim, detail::MultiMathplusAssign>::exec(res, s hape, v);
return res; return res;
} }
template <class U, unsigned int N, class T, class S> template <class U, unsigned int N, class T, class S>
U U
sum(MultiArrayView<N, T, S> const & v, U res = NumericTraits<U>::zero()) sum(MultiArrayView<N, T, S> const & v, U res = NumericTraits<U>::zero())
{ {
return v.sum<U>() + res; return v.template sum<U>() + res;
} }
template <class U, class T> template <class U, class T>
U U
product(MultiMathOperand<T> const & v, U res = NumericTraits<U>::one()) product(MultiMathOperand<T> const & v, U res = NumericTraits<U>::one())
{ {
static const int ndim = MultiMathOperand<T>::ndim; static const int ndim = MultiMathOperand<T>::ndim;
typename MultiArrayShape<ndim>::type shape; typename MultiArrayShape<ndim>::type shape;
v.checkShape(shape); v.checkShape(shape);
detail::MultiMathReduce<ndim, detail::MultiMathmultiplyAssign>::exec(re s, shape, v); detail::MultiMathReduce<ndim, detail::MultiMathmultiplyAssign>::exec(re s, shape, v);
return res; return res;
} }
template <class U, unsigned int N, class T, class S> template <class U, unsigned int N, class T, class S>
U U
product(MultiArrayView<N, T, S> const & v, U res = NumericTraits<U>::one()) product(MultiArrayView<N, T, S> const & v, U res = NumericTraits<U>::one())
{ {
return v.product<U>() * res; return v.template product<U>() * res;
} }
template <class T> template <class T>
bool bool
all(MultiMathOperand<T> const & v) all(MultiMathOperand<T> const & v)
{ {
static const int ndim = MultiMathOperand<T>::ndim; static const int ndim = MultiMathOperand<T>::ndim;
typename MultiArrayShape<ndim>::type shape; typename MultiArrayShape<ndim>::type shape;
v.checkShape(shape); v.checkShape(shape);
bool res = true; bool res = true;
 End of changes. 3 change blocks. 
3 lines changed or deleted 3 lines changed or added


 multi_pointoperators.hxx   multi_pointoperators.hxx 
skipping to change at line 47 skipping to change at line 47
#ifndef VIGRA_MULTI_POINTOPERATORS_H #ifndef VIGRA_MULTI_POINTOPERATORS_H
#define VIGRA_MULTI_POINTOPERATORS_H #define VIGRA_MULTI_POINTOPERATORS_H
#include "initimage.hxx" #include "initimage.hxx"
#include "copyimage.hxx" #include "copyimage.hxx"
#include "transformimage.hxx" #include "transformimage.hxx"
#include "combineimages.hxx" #include "combineimages.hxx"
#include "inspectimage.hxx" #include "inspectimage.hxx"
#include "multi_array.hxx" #include "multi_array.hxx"
#include "metaprogramming.hxx" #include "metaprogramming.hxx"
#include "inspector_passes.hxx"
namespace vigra namespace vigra
{ {
/** \addtogroup MultiPointoperators Point operators for multi-dimensional a rrays. /** \addtogroup MultiPointoperators Point operators for multi-dimensional a rrays.
Copy, transform, and inspect arbitrary dimensional arrays which are rep resented Copy, transform, and inspect arbitrary dimensional arrays which are rep resented
by iterators compatible to \ref MultiIteratorPage. Note that are range is here by iterators compatible to \ref MultiIteratorPage. Note that are range is here
specified by a pair: an iterator referring to the first point of the ar ray specified by a pair: an iterator referring to the first point of the ar ray
and a shape object specifying the size of the (rectangular) ROI. and a shape object specifying the size of the (rectangular) ROI.
skipping to change at line 1495 skipping to change at line 1496
Accessor accessor; Accessor accessor;
Functor functor; Functor functor;
functor(accessor(src_begin)); functor(accessor(src_begin));
\endcode \endcode
*/ */
doxygen_overloaded_function(template <...> void inspectMultiArray) doxygen_overloaded_function(template <...> void inspectMultiArray)
template <class Iterator, class Shape, class Accessor>
struct inspectMultiArray_binder
{
Iterator s;
const Shape & shape;
Accessor a;
inspectMultiArray_binder(Iterator s_, const Shape & shape_, Accessor a_
)
: s(s_), shape(shape_), a(a_) {}
template <class Functor>
void operator()(Functor & f)
{
inspectMultiArrayImpl(s, shape, a, f, MetaInt<Iterator::level>());
}
};
template <class Iterator, class Shape, class Accessor, class Functor> template <class Iterator, class Shape, class Accessor, class Functor>
inline void inline void
inspectMultiArray(Iterator s, Shape const & shape, Accessor a, Functor & f ) inspectMultiArray(Iterator s, Shape const & shape, Accessor a, Functor & f)
{ {
inspectMultiArrayImpl(s, shape, a, f, MetaInt<Iterator::level>()); inspectMultiArray_binder<Iterator, Shape, Accessor> g(s, shape, a);
detail::extra_passes_select(g, f);
} }
template <class Iterator, class Shape, class Accessor, class Functor> template <class Iterator, class Shape, class Accessor, class Functor>
inline void inline void
inspectMultiArray(triple<Iterator, Shape, Accessor> const & s, Functor & f) inspectMultiArray(triple<Iterator, Shape, Accessor> const & s, Functor & f)
{ {
inspectMultiArray(s.first, s.second, s.third, f); inspectMultiArray(s.first, s.second, s.third, f);
} }
/********************************************************/ /********************************************************/
skipping to change at line 1612 skipping to change at line 1629
Accessor a1, a2; Accessor a1, a2;
Functor functor; Functor functor;
functor(a1(src1_begin), a2(src2_begin)); functor(a1(src1_begin), a2(src2_begin));
\endcode \endcode
*/ */
doxygen_overloaded_function(template <...> void inspectTwoMultiArrays) doxygen_overloaded_function(template <...> void inspectTwoMultiArrays)
template <class Iterator1, class Shape, class Accessor1, template <class Iterator1, class Shape, class Accessor1,
class Iterator2, class Accessor2>
struct inspectTwoMultiArrays_binder
{
Iterator1 s1;
const Shape & shape;
Accessor1 a1;
Iterator2 s2;
Accessor2 a2;
inspectTwoMultiArrays_binder(Iterator1 s1_, const Shape & shape_,
Accessor1 a1_, Iterator2 s2_, Accessor2 a2
_)
: s1(s1_), shape(shape_), a1(a1_), s2(s2_), a2(a2_) {}
template <class Functor>
void operator()(Functor & f)
{
inspectTwoMultiArraysImpl(s1, shape, a1, s2, a2, f,
MetaInt<Iterator1::level>());
}
};
template <class Iterator1, class Shape, class Accessor1,
class Iterator2, class Accessor2, class Iterator2, class Accessor2,
class Functor> class Functor>
inline void inline void
inspectTwoMultiArrays(Iterator1 s1, Shape const & shape, Accessor1 a1, inspectTwoMultiArrays(Iterator1 s1, Shape const & shape, Accessor1 a1,
Iterator2 s2, Accessor2 a2, Functor & f) Iterator2 s2, Accessor2 a2, Functor & f)
{ {
inspectTwoMultiArraysImpl(s1, shape, a1, s2, a2, f, MetaInt<Iterator1:: inspectTwoMultiArrays_binder<Iterator1, Shape, Accessor1,
level>()); Iterator2, Accessor2>
g(s1, shape, a1, s2, a2);
detail::extra_passes_select(g, f);
} }
template <class Iterator1, class Shape, class Accessor1, template <class Iterator1, class Shape, class Accessor1,
class Iterator2, class Accessor2, class Iterator2, class Accessor2,
class Functor> class Functor>
inline inline
void void
inspectTwoMultiArrays(triple<Iterator1, Shape, Accessor1> const & s1, inspectTwoMultiArrays(triple<Iterator1, Shape, Accessor1> const & s1,
pair<Iterator2, Accessor2> const & s2, Functor & f) pair<Iterator2, Accessor2> const & s2, Functor & f)
{ {
 End of changes. 6 change blocks. 
4 lines changed or deleted 45 lines changed or added


 nonlineardiffusion.hxx   nonlineardiffusion.hxx 
skipping to change at line 183 skipping to change at line 183
internalNonlinearDiffusionDiagonalSolver(xs, xs+h, as, internalNonlinearDiffusionDiagonalSolver(xs, xs+h, as,
diag.begin(), upper.begin(), lower.begin(), res .begin()); diag.begin(), upper.begin(), lower.begin(), res .begin());
for(y=0; y<h; ++y, ++xd) for(y=0; y<h; ++y, ++xd)
{ {
ad.set(0.5 * (ad(xd) + res[y]), xd); ad.set(0.5 * (ad(xd) + res[y]), xd);
} }
} }
} }
/** \addtogroup NonLinearDiffusion Non-linear Diffusion /** \addtogroup NonLinearDiffusion Non-linear Diffusion and Total Variation
Perform edge-preserving smoothing. Perform edge-preserving smoothing.
*/ */
//@{ //@{
/********************************************************/ /********************************************************/
/* */ /* */
/* nonlinearDiffusion */ /* nonlinearDiffusion */
/* */ /* */
/********************************************************/ /********************************************************/
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 numerictraits.hxx   numerictraits.hxx 
skipping to change at line 472 skipping to change at line 472
</td></tr> </td></tr>
</table> </table>
NormTraits for the built-in types are defined in <b>\#include</b> NormTraits for the built-in types are defined in <b>\#include</b>
\<vigra/numerictraits.hxx\> \<vigra/numerictraits.hxx\>
Namespace: vigra Namespace: vigra
*/ */
namespace vigra { namespace vigra {
namespace detail {
template <typename s, typename t>
inline static t clamp_integer_to_unsigned(s value, t maximum) {
return
value <= s() ?
t() :
(value >= static_cast<s>(maximum) ? maximum : static_cast<t
>(value));
}
template <typename s, typename t>
inline static t clamp_integer_to_signed(s value, t minimum, t maxim
um) {
return
value <= static_cast<s>(minimum) ?
minimum :
(value >= static_cast<s>(maximum) ? maximum : static_cast<t
>(value));
}
template <typename s, typename t>
inline static t clamp_float_to_unsigned(s value, t maximum) {
return
value <= s() ?
t() :
(value >= static_cast<s>(maximum) ? maximum : static_cast<t
>(value + 0.5));
}
template <typename s, typename t>
inline static t clamp_float_to_signed(s value, t minimum, t maximum
) {
if (value >= s()) {
return value >= static_cast<s>(maximum) ? maximum : static_
cast<t>(value + 0.5);
} else {
return value <= static_cast<s>(minimum) ? minimum : static_
cast<t>(value - 0.5);
}
}
} // end namespace detail
struct Error_NumericTraits_not_specialized_for_this_case { }; struct Error_NumericTraits_not_specialized_for_this_case { };
struct Error_NumericTraits_char_is_not_a_numeric_type__use_signed_char_or_u nsigned_char { }; struct Error_NumericTraits_char_is_not_a_numeric_type__use_signed_char_or_u nsigned_char { };
template<class A> template<class A>
struct NumericTraits struct NumericTraits
{ {
typedef Error_NumericTraits_not_specialized_for_this_case Type; typedef Error_NumericTraits_not_specialized_for_this_case Type;
typedef Error_NumericTraits_not_specialized_for_this_case Promote; typedef Error_NumericTraits_not_specialized_for_this_case Promote;
typedef Error_NumericTraits_not_specialized_for_this_case UnsignedPromo te; typedef Error_NumericTraits_not_specialized_for_this_case UnsignedPromo te;
skipping to change at line 583 skipping to change at line 617
#ifdef NO_INLINE_STATIC_CONST_DEFINITION #ifdef NO_INLINE_STATIC_CONST_DEFINITION
enum { minConst = SCHAR_MIN, maxConst = SCHAR_MIN }; enum { minConst = SCHAR_MIN, maxConst = SCHAR_MIN };
#else #else
static const signed char minConst = SCHAR_MIN; static const signed char minConst = SCHAR_MIN;
static const signed char maxConst = SCHAR_MIN; static const signed char maxConst = SCHAR_MIN;
#endif #endif
static Promote toPromote(signed char v) { return v; } static Promote toPromote(signed char v) { return v; }
static RealPromote toRealPromote(signed char v) { return v; } static RealPromote toRealPromote(signed char v) { return v; }
static signed char fromPromote(Promote v) { static signed char fromPromote(Promote v) {
return ((v < SCHAR_MIN) ? SCHAR_MIN : (v > SCHAR_MAX) ? SCHAR_MAX : v); return detail::clamp_integer_to_signed<Promote, signed char>(v, SCH AR_MIN, SCHAR_MAX);
} }
static signed char fromRealPromote(RealPromote v) { static signed char fromRealPromote(RealPromote v) {
return ((v < 0.0) return detail::clamp_float_to_signed<RealPromote, signed char>(v, S
? ((v < (RealPromote)SCHAR_MIN) CHAR_MIN, SCHAR_MAX);
? SCHAR_MIN
: static_cast<signed char>(v - 0.5))
: (v > (RealPromote)SCHAR_MAX)
? SCHAR_MAX
: static_cast<signed char>(v + 0.5));
} }
}; };
template<> template<>
struct NumericTraits<unsigned char> struct NumericTraits<unsigned char>
{ {
typedef unsigned char Type; typedef unsigned char Type;
typedef int Promote; typedef int Promote;
typedef unsigned int UnsignedPromote; typedef unsigned int UnsignedPromote;
typedef double RealPromote; typedef double RealPromote;
skipping to change at line 627 skipping to change at line 655
#ifdef NO_INLINE_STATIC_CONST_DEFINITION #ifdef NO_INLINE_STATIC_CONST_DEFINITION
enum { minConst = 0, maxConst = UCHAR_MAX }; enum { minConst = 0, maxConst = UCHAR_MAX };
#else #else
static const unsigned char minConst = 0; static const unsigned char minConst = 0;
static const unsigned char maxConst = UCHAR_MAX; static const unsigned char maxConst = UCHAR_MAX;
#endif #endif
static Promote toPromote(unsigned char v) { return v; } static Promote toPromote(unsigned char v) { return v; }
static RealPromote toRealPromote(unsigned char v) { return v; } static RealPromote toRealPromote(unsigned char v) { return v; }
static unsigned char fromPromote(Promote const & v) { static unsigned char fromPromote(Promote v) {
return Type((v < 0) return detail::clamp_integer_to_unsigned<Promote, unsigned char>(v,
? 0 UCHAR_MAX);
: (v > (Promote)UCHAR_MAX) }
? UCHAR_MAX static unsigned char fromRealPromote(RealPromote v) {
: v); return detail::clamp_float_to_unsigned<RealPromote, unsigned char>(
} v, UCHAR_MAX);
static unsigned char fromRealPromote(RealPromote const & v) {
return Type((v < 0.0)
? 0
: ((v > (RealPromote)UCHAR_MAX)
? UCHAR_MAX
: v + 0.5));
} }
}; };
template<> template<>
struct NumericTraits<short int> struct NumericTraits<short int>
{ {
typedef short int Type; typedef short int Type;
typedef int Promote; typedef int Promote;
typedef unsigned int UnsignedPromote; typedef unsigned int UnsignedPromote;
typedef double RealPromote; typedef double RealPromote;
skipping to change at line 675 skipping to change at line 695
#ifdef NO_INLINE_STATIC_CONST_DEFINITION #ifdef NO_INLINE_STATIC_CONST_DEFINITION
enum { minConst = SHRT_MIN, maxConst = SHRT_MAX }; enum { minConst = SHRT_MIN, maxConst = SHRT_MAX };
#else #else
static const short int minConst = SHRT_MIN; static const short int minConst = SHRT_MIN;
static const short int maxConst = SHRT_MAX; static const short int maxConst = SHRT_MAX;
#endif #endif
static Promote toPromote(short int v) { return v; } static Promote toPromote(short int v) { return v; }
static RealPromote toRealPromote(short int v) { return v; } static RealPromote toRealPromote(short int v) { return v; }
static short int fromPromote(Promote v) { static short int fromPromote(Promote v) {
return ((v < SHRT_MIN) ? SHRT_MIN : return detail::clamp_integer_to_signed<Promote, short int>(v, SHRT_
(v > SHRT_MAX) ? SHRT_MAX : v); MIN, SHRT_MAX);
} }
static short int fromRealPromote(RealPromote v) { static short int fromRealPromote(RealPromote v) {
return ((v < 0.0) return detail::clamp_float_to_signed<RealPromote, short int>(v, SHR
? ((v < (RealPromote)SHRT_MIN) T_MIN, SHRT_MAX);
? SHRT_MIN
: static_cast<short int>(v - 0.5))
: ((v > (RealPromote)SHRT_MAX)
? SHRT_MAX
: static_cast<short int>(v + 0.5)));
} }
}; };
template<> template<>
struct NumericTraits<short unsigned int> struct NumericTraits<short unsigned int>
{ {
typedef short unsigned int Type; typedef short unsigned int Type;
typedef int Promote; typedef int Promote;
typedef unsigned int UnsignedPromote; typedef unsigned int UnsignedPromote;
typedef double RealPromote; typedef double RealPromote;
skipping to change at line 721 skipping to change at line 734
#ifdef NO_INLINE_STATIC_CONST_DEFINITION #ifdef NO_INLINE_STATIC_CONST_DEFINITION
enum { minConst = 0, maxConst = USHRT_MAX }; enum { minConst = 0, maxConst = USHRT_MAX };
#else #else
static const short unsigned int minConst = 0; static const short unsigned int minConst = 0;
static const short unsigned int maxConst = USHRT_MAX; static const short unsigned int maxConst = USHRT_MAX;
#endif #endif
static Promote toPromote(short unsigned int v) { return v; } static Promote toPromote(short unsigned int v) { return v; }
static RealPromote toRealPromote(short unsigned int v) { return v; } static RealPromote toRealPromote(short unsigned int v) { return v; }
static short unsigned int fromPromote(Promote v) { static short unsigned int fromPromote(Promote v) {
return Type((v < 0) return detail::clamp_integer_to_unsigned<Promote, short unsigned in
? 0 t>(v, USHRT_MAX);
: (v > USHRT_MAX)
? USHRT_MAX
: v);
} }
static short unsigned int fromRealPromote(RealPromote v) { static short unsigned int fromRealPromote(RealPromote v) {
return Type((v < 0.0) return detail::clamp_float_to_unsigned<RealPromote, short unsigned
? 0 int>(v, USHRT_MAX);
: ((v > (RealPromote)USHRT_MAX)
? USHRT_MAX
: v + 0.5));
} }
}; };
template<> template<>
struct NumericTraits<int> struct NumericTraits<int>
{ {
typedef int Type; typedef int Type;
typedef int Promote; typedef int Promote;
typedef unsigned int UnsignedPromote; typedef unsigned int UnsignedPromote;
typedef double RealPromote; typedef double RealPromote;
skipping to change at line 769 skipping to change at line 774
enum { minConst = INT_MIN, maxConst = INT_MAX }; enum { minConst = INT_MIN, maxConst = INT_MAX };
#else #else
static const int minConst = INT_MIN; static const int minConst = INT_MIN;
static const int maxConst = INT_MAX; static const int maxConst = INT_MAX;
#endif #endif
static Promote toPromote(int v) { return v; } static Promote toPromote(int v) { return v; }
static RealPromote toRealPromote(int v) { return v; } static RealPromote toRealPromote(int v) { return v; }
static int fromPromote(Promote v) { return v; } static int fromPromote(Promote v) { return v; }
static int fromRealPromote(RealPromote v) { static int fromRealPromote(RealPromote v) {
return ((v < 0.0) return detail::clamp_float_to_signed<RealPromote, int>(v, INT_MIN,
? ((v < (RealPromote)INT_MIN) INT_MAX);
? INT_MIN
: static_cast<int>(v - 0.5))
: ((v > (RealPromote)INT_MAX)
? INT_MAX
: static_cast<int>(v + 0.5)));
} }
}; };
template<> template<>
struct NumericTraits<unsigned int> struct NumericTraits<unsigned int>
{ {
typedef unsigned int Type; typedef unsigned int Type;
typedef unsigned int Promote; typedef unsigned int Promote;
typedef unsigned int UnsignedPromote; typedef unsigned int UnsignedPromote;
typedef double RealPromote; typedef double RealPromote;
skipping to change at line 812 skipping to change at line 811
enum { minConst = 0, maxConst = UINT_MAX }; enum { minConst = 0, maxConst = UINT_MAX };
#else #else
static const unsigned int minConst = 0; static const unsigned int minConst = 0;
static const unsigned int maxConst = UINT_MAX; static const unsigned int maxConst = UINT_MAX;
#endif #endif
static Promote toPromote(unsigned int v) { return v; } static Promote toPromote(unsigned int v) { return v; }
static RealPromote toRealPromote(unsigned int v) { return v; } static RealPromote toRealPromote(unsigned int v) { return v; }
static unsigned int fromPromote(Promote v) { return v; } static unsigned int fromPromote(Promote v) { return v; }
static unsigned int fromRealPromote(RealPromote v) { static unsigned int fromRealPromote(RealPromote v) {
return ((v < 0.0) return detail::clamp_float_to_unsigned<RealPromote, unsigned int>(v
? 0 , UINT_MAX);
: ((v > (RealPromote)UINT_MAX)
? UINT_MAX
: static_cast<unsigned int>(v + 0.5)));
} }
}; };
template<> template<>
struct NumericTraits<long> struct NumericTraits<long>
{ {
typedef long Type; typedef long Type;
typedef long Promote; typedef long Promote;
typedef unsigned long UnsignedPromote; typedef unsigned long UnsignedPromote;
typedef double RealPromote; typedef double RealPromote;
skipping to change at line 850 skipping to change at line 845
static long max() { return LONG_MAX; } static long max() { return LONG_MAX; }
#ifdef NO_INLINE_STATIC_CONST_DEFINITION #ifdef NO_INLINE_STATIC_CONST_DEFINITION
enum { minConst = LONG_MIN, maxConst = LONG_MAX }; enum { minConst = LONG_MIN, maxConst = LONG_MAX };
#else #else
static const long minConst = LONG_MIN; static const long minConst = LONG_MIN;
static const long maxConst = LONG_MAX; static const long maxConst = LONG_MAX;
#endif #endif
static Promote toPromote(long v) { return v; } static Promote toPromote(long v) { return v; }
static RealPromote toRealPromote(long v) { return v; } static RealPromote toRealPromote(long v) { return static_cast<RealPromo te>(v); }
static long fromPromote(Promote v) { return v; } static long fromPromote(Promote v) { return v; }
static long fromRealPromote(RealPromote v) { static long fromRealPromote(RealPromote v) {
return ((v < 0.0) return detail::clamp_float_to_signed<RealPromote, long>(v, LONG_MIN
? ((v < (RealPromote)LONG_MIN) , LONG_MAX);
? LONG_MIN
: static_cast<long>(v - 0.5))
: ((v > (RealPromote)LONG_MAX)
? LONG_MAX
: static_cast<long>(v + 0.5)));
} }
}; };
template<> template<>
struct NumericTraits<unsigned long> struct NumericTraits<unsigned long>
{ {
typedef unsigned long Type; typedef unsigned long Type;
typedef unsigned long Promote; typedef unsigned long Promote;
typedef unsigned long UnsignedPromote; typedef unsigned long UnsignedPromote;
typedef double RealPromote; typedef double RealPromote;
skipping to change at line 893 skipping to change at line 882
static unsigned long max() { return ULONG_MAX; } static unsigned long max() { return ULONG_MAX; }
#ifdef NO_INLINE_STATIC_CONST_DEFINITION #ifdef NO_INLINE_STATIC_CONST_DEFINITION
enum { minConst = 0, maxConst = ULONG_MAX }; enum { minConst = 0, maxConst = ULONG_MAX };
#else #else
static const unsigned long minConst = 0; static const unsigned long minConst = 0;
static const unsigned long maxConst = ULONG_MAX; static const unsigned long maxConst = ULONG_MAX;
#endif #endif
static Promote toPromote(unsigned long v) { return v; } static Promote toPromote(unsigned long v) { return v; }
static RealPromote toRealPromote(unsigned long v) { return v; } static RealPromote toRealPromote(unsigned long v) { return static_cast< RealPromote>(v); }
static unsigned long fromPromote(Promote v) { return v; } static unsigned long fromPromote(Promote v) { return v; }
static unsigned long fromRealPromote(RealPromote v) { static unsigned long fromRealPromote(RealPromote v) {
return ((v < 0.0) return detail::clamp_float_to_unsigned<RealPromote, unsigned long>(
? 0 v, ULONG_MAX);
: ((v > (RealPromote)ULONG_MAX)
? ULONG_MAX
: static_cast<unsigned long>(v + 0.5)));
} }
}; };
#ifdef LLONG_MAX #ifdef LLONG_MAX
template<> template<>
struct NumericTraits<long long> struct NumericTraits<long long>
{ {
typedef long long Type; typedef long long Type;
typedef long long Promote; typedef long long Promote;
typedef unsigned long long UnsignedPromote; typedef unsigned long long UnsignedPromote;
skipping to change at line 938 skipping to change at line 923
enum { minConst = LLONG_MIN, maxConst = LLONG_MAX }; enum { minConst = LLONG_MIN, maxConst = LLONG_MAX };
#else #else
static const long long minConst = LLONG_MIN; static const long long minConst = LLONG_MIN;
static const long long maxConst = LLONG_MAX; static const long long maxConst = LLONG_MAX;
#endif #endif
static Promote toPromote(long long v) { return v; } static Promote toPromote(long long v) { return v; }
static RealPromote toRealPromote(long long v) { return (RealPromote)v; } static RealPromote toRealPromote(long long v) { return (RealPromote)v; }
static long long fromPromote(Promote v) { return v; } static long long fromPromote(Promote v) { return v; }
static long long fromRealPromote(RealPromote v) { static long long fromRealPromote(RealPromote v) {
return ((v < 0.0) return detail::clamp_float_to_signed<RealPromote, long long>(v, LLO
? ((v < (RealPromote)LLONG_MIN) NG_MIN, LLONG_MAX);
? LLONG_MIN
: static_cast<long long>(v - 0.5))
: ((v > (RealPromote)LLONG_MAX)
? LLONG_MAX
: static_cast<long long>(v + 0.5)));
} }
}; };
template<> template<>
struct NumericTraits<unsigned long long> struct NumericTraits<unsigned long long>
{ {
typedef unsigned long long Type; typedef unsigned long long Type;
typedef unsigned long long Promote; typedef unsigned long long Promote;
typedef unsigned long long UnsignedPromote; typedef unsigned long long UnsignedPromote;
typedef double RealPromote; typedef double RealPromote;
skipping to change at line 981 skipping to change at line 960
enum { minConst = 0, maxConst = ULLONG_MAX }; enum { minConst = 0, maxConst = ULLONG_MAX };
#else #else
static const unsigned long long minConst = 0; static const unsigned long long minConst = 0;
static const unsigned long long maxConst = ULLONG_MAX; static const unsigned long long maxConst = ULLONG_MAX;
#endif #endif
static Promote toPromote(unsigned long long v) { return v; } static Promote toPromote(unsigned long long v) { return v; }
static RealPromote toRealPromote(unsigned long long v) { return (RealPr omote)v; } static RealPromote toRealPromote(unsigned long long v) { return (RealPr omote)v; }
static unsigned long long fromPromote(Promote v) { return v; } static unsigned long long fromPromote(Promote v) { return v; }
static unsigned long long fromRealPromote(RealPromote v) { static unsigned long long fromRealPromote(RealPromote v) {
return ((v < 0.0) return detail::clamp_float_to_unsigned<RealPromote, unsigned long l
? 0 ong>(v, ULLONG_MAX);
: ((v > (RealPromote)ULLONG_MAX)
? ULONG_MAX
: static_cast<unsigned long long>(v + 0.5)));
} }
}; };
#endif // LLONG_MAX #endif // LLONG_MAX
template<> template<>
struct NumericTraits<float> struct NumericTraits<float>
{ {
typedef float Type; typedef float Type;
typedef float Promote; typedef float Promote;
typedef float UnsignedPromote; typedef float UnsignedPromote;
 End of changes. 16 change blocks. 
78 lines changed or deleted 73 lines changed or added


 numpy_array.hxx   numpy_array.hxx 
skipping to change at line 49 skipping to change at line 49
#include <Python.h> #include <Python.h>
#include <string> #include <string>
#include <iostream> #include <iostream>
#include <numpy/arrayobject.h> #include <numpy/arrayobject.h>
#include "multi_array.hxx" #include "multi_array.hxx"
#include "array_vector.hxx" #include "array_vector.hxx"
#include "python_utility.hxx" #include "python_utility.hxx"
#include "numpy_array_traits.hxx" #include "numpy_array_traits.hxx"
#include "numpy_array_taggedshape.hxx" #include "numpy_array_taggedshape.hxx"
// NumPy function called by NumPy’s import_array() macro (and our import_ vigranumpy() below)
int _import_array(); int _import_array();
namespace vigra { namespace vigra {
inline void import_vigranumpy() static inline void import_vigranumpy()
{ {
// roughly equivalent to import_array():
if(_import_array() < 0) if(_import_array() < 0)
pythonToCppException(0); pythonToCppException(0);
// in addition, import vigra.vigranumpycore:
python_ptr module(PyImport_ImportModule("vigra.vigranumpycore"), python _ptr::keep_count); python_ptr module(PyImport_ImportModule("vigra.vigranumpycore"), python _ptr::keep_count);
pythonToCppException(module); pythonToCppException(module);
} }
/********************************************************/ /********************************************************/
/* */ /* */
/* MultibandVectorAccessor */ /* MultibandVectorAccessor */
/* */ /* */
/********************************************************/ /********************************************************/
skipping to change at line 393 skipping to change at line 397
*/ */
int dtype() const int dtype() const
{ {
if(hasData()) if(hasData())
return PyArray_DESCR(pyObject())->type_num; return PyArray_DESCR(pyObject())->type_num;
return -1; return -1;
} }
/** /**
* Return the AxisTags of this array or a NULL pointer when the att ribute * Return the AxisTags of this array or a NULL pointer when the att ribute
'axistags' is missing in the Python object. 'axistags' is missing in the Python object or this array has no data.
*/ */
python_ptr axistags() const python_ptr axistags() const
{ {
static python_ptr key(PyString_FromString("axistags"), python_ptr:: keep_count); static python_ptr key(PyString_FromString("axistags"), python_ptr:: keep_count);
python_ptr axistags(PyObject_GetAttr(pyObject(), key), python_ptr::
keep_count); python_ptr axistags;
if(!axistags) if(pyObject())
PyErr_Clear(); {
axistags.reset(PyObject_GetAttr(pyObject(), key), python_ptr::k
eep_count);
if(!axistags)
PyErr_Clear();
}
return axistags; return axistags;
} }
/** /**
* Return a borrowed reference to the internal PyArrayObject. * Return a borrowed reference to the internal PyArrayObject.
*/ */
PyArrayObject * pyArray() const PyArrayObject * pyArray() const
{ {
return (PyArrayObject *)pyArray_.get(); return (PyArrayObject *)pyArray_.get();
} }
skipping to change at line 635 skipping to change at line 644
/** traverser type /** traverser type
*/ */
typedef typename view_type::traverser traverser; typedef typename view_type::traverser traverser;
/** traverser type to const data /** traverser type to const data
*/ */
typedef typename view_type::const_traverser const_traverser; typedef typename view_type::const_traverser const_traverser;
/** sequential (random access) iterator type /** sequential (random access) iterator type
*/ */
typedef value_type * iterator; typedef typename view_type::iterator iterator;
/** sequential (random access) const iterator type /** sequential (random access) const iterator type
*/ */
typedef value_type * const_iterator; typedef typename view_type::const_iterator const_iterator;
using view_type::shape; // resolve ambiguity of multiple inheritance using view_type::shape; // resolve ambiguity of multiple inheritance
using view_type::hasData; // resolve ambiguity of multiple inheritance using view_type::hasData; // resolve ambiguity of multiple inheritance
using view_type::strideOrdering; // resolve ambiguity of multiple inher itance using view_type::strideOrdering; // resolve ambiguity of multiple inher itance
protected: protected:
// this function assumes that pyArray_ has already been set, and compat ibility been checked // this function assumes that pyArray_ has already been set, and compat ibility been checked
void setupArrayView(); void setupArrayView();
skipping to change at line 710 skipping to change at line 719
return; return;
if(createCopy) if(createCopy)
makeCopy(other.pyObject()); makeCopy(other.pyObject());
else else
makeReferenceUnchecked(other.pyObject()); makeReferenceUnchecked(other.pyObject());
} }
/** /**
* Allocate new memory and copy data from a MultiArrayView. * Allocate new memory and copy data from a MultiArrayView.
*/ */
explicit NumpyArray(const view_type &other) template <class U, class S>
explicit NumpyArray(const MultiArrayView<N, U, S> &other)
{ {
if(!other.hasData()) if(!other.hasData())
return; return;
vigra_postcondition(makeReference(init(other.shape(), false)), vigra_postcondition(makeReference(init(other.shape(), false)),
"NumpyArray(view_type): Python constructor did not produc "NumpyArray(MultiArrayView): Python constructor did not p
e a compatible array."); roduce a compatible array.");
static_cast<view_type &>(*this) = other; view_type::operator=(other);
} }
/** /**
* Construct a new array object, allocating an internal python * Construct a new array object, allocating an internal python
* ndarray of the given shape in the given order (default: VIGRA or der), initialized * ndarray of the given shape in the given order (default: VIGRA or der), initialized
* with zeros. * with zeros.
* *
* An exception is thrown when construction fails. * An exception is thrown when construction fails.
*/ */
explicit NumpyArray(difference_type const & shape, std::string const & order = "") explicit NumpyArray(difference_type const & shape, std::string const & order = "")
skipping to change at line 807 skipping to change at line 817
"NumpyArray::operator=(): reshape failed unexpectedly."); "NumpyArray::operator=(): reshape failed unexpectedly.");
copy = other; copy = other;
makeReferenceUnchecked(copy.pyObject()); makeReferenceUnchecked(copy.pyObject());
} }
return *this; return *this;
} }
/** /**
* Assignment operator. If this is already a view with data * Assignment operator. If this is already a view with data
* (i.e. hasData() is true) and the shapes match, the RHS * (i.e. hasData() is true) and the shapes match, the RHS
* array contents are copied. If this is an empty view,
* a new buffer with the RHS shape is allocated before copying.
*/
template <class U, class S>
NumpyArray &operator=(const MultiArrayView<N, U, S> &other)
{
if(hasData())
{
vigra_precondition(shape() == other.shape(),
"NumpyArray::operator=(): shape mismatch.");
view_type::operator=(other);
}
else if(other.hasData())
{
NumpyArray copy;
copy.reshapeIfEmpty(other.shape(),
"NumpyArray::operator=(): reshape failed unexpectedly.");
copy = other;
makeReferenceUnchecked(copy.pyObject());
}
return *this;
}
/**
* Assignment operator. If this is already a view with data
* (i.e. hasData() is true) and the shapes match, the RHS
* array contents are copied. * array contents are copied.
* If this is an empty view, assignment is identical to * If this is an empty view, assignment is identical to
* makeReference(other.pyObject()). * makeReference(other.pyObject()).
* Otherwise, an exception is thrown. * Otherwise, an exception is thrown.
*/ */
NumpyArray &operator=(const NumpyAnyArray &other) NumpyArray &operator=(const NumpyAnyArray &other)
{ {
if(hasData()) if(hasData())
{ {
NumpyAnyArray::operator=(other); NumpyAnyArray::operator=(other);
skipping to change at line 834 skipping to change at line 870
vigra_precondition(false, vigra_precondition(false,
"NumpyArray::operator=(): Cannot assign from incompatible a rray."); "NumpyArray::operator=(): Cannot assign from incompatible a rray.");
} }
return *this; return *this;
} }
/** /**
Permute the entries of the given array \a data exactly like the ax es of this NumpyArray Permute the entries of the given array \a data exactly like the ax es of this NumpyArray
were permuted upon conversion from numpy. were permuted upon conversion from numpy.
*/ */
template<class U> template <class U>
ArrayVector<U> ArrayVector<U>
permuteLikewise(ArrayVector<U> const & data) const permuteLikewise(ArrayVector<U> const & data) const
{ {
vigra_precondition(hasData(), vigra_precondition(hasData(),
"NumpyArray::permuteLikewise(): array has no data."); "NumpyArray::permuteLikewise(): array has no data.");
ArrayVector<U> res(data.size()); ArrayVector<U> res(data.size());
ArrayTraits::permuteLikewise(this->pyArray_, data, res); ArrayTraits::permuteLikewise(this->pyArray_, data, res);
return res; return res;
} }
/** /**
Permute the entries of the given array \a data exactly like the ax es of this NumpyArray Permute the entries of the given array \a data exactly like the ax es of this NumpyArray
were permuted upon conversion from numpy. were permuted upon conversion from numpy.
*/ */
template<class U, int K> template <class U, int K>
TinyVector<U, K> TinyVector<U, K>
permuteLikewise(TinyVector<U, K> const & data) const permuteLikewise(TinyVector<U, K> const & data) const
{ {
vigra_precondition(hasData(), vigra_precondition(hasData(),
"NumpyArray::permuteLikewise(): array has no data."); "NumpyArray::permuteLikewise(): array has no data.");
TinyVector<U, K> res; TinyVector<U, K> res;
ArrayTraits::permuteLikewise(this->pyArray_, data, res); ArrayTraits::permuteLikewise(this->pyArray_, data, res);
return res; return res;
} }
/** /**
Get the permutation of the axes of this NumpyArray
that was performed upon conversion from numpy.
*/
template <int K>
TinyVector<npy_intp, K>
permuteLikewise() const
{
vigra_precondition(hasData(),
"NumpyArray::permuteLikewise(): array has no data.");
TinyVector<npy_intp, K> data, res;
linearSequence(data.begin(), data.end());
ArrayTraits::permuteLikewise(this->pyArray_, data, res);
return res;
}
/**
* Test whether a given python object is a numpy array that can be * Test whether a given python object is a numpy array that can be
* converted (copied) into an array compatible to this NumpyArray t ype. * converted (copied) into an array compatible to this NumpyArray t ype.
* This means that the array's shape conforms to the requirements o f * This means that the array's shape conforms to the requirements o f
* makeCopy(). * makeCopy().
*/ */
static bool isCopyCompatible(PyObject *obj) static bool isCopyCompatible(PyObject *obj)
{ {
#if VIGRA_CONVERTER_DEBUG #if VIGRA_CONVERTER_DEBUG
std::cerr << "class " << typeid(NumpyArray).name() << " got " << ob j->ob_type->tp_name << "\n"; std::cerr << "class " << typeid(NumpyArray).name() << " got " << ob j->ob_type->tp_name << "\n";
std::cerr << "using traits " << typeid(ArrayTraits).name() << "\n"; std::cerr << "using traits " << typeid(ArrayTraits).name() << "\n";
skipping to change at line 930 skipping to change at line 983
{ {
NumpyAnyArray::makeReference(obj); NumpyAnyArray::makeReference(obj);
setupArrayView(); setupArrayView();
} }
/** /**
* Try to set up a view referencing the given PyObject. * Try to set up a view referencing the given PyObject.
* Returns false if the python object is not a compatible * Returns false if the python object is not a compatible
* numpy array (see isReferenceCompatible()). * numpy array (see isReferenceCompatible()).
* *
* The parameter \a strict is deprecated and will be ignored * The second parameter ('strict') is deprecated and will be ignore d.
*/ */
bool makeReference(PyObject *obj, bool strict = false) bool makeReference(PyObject *obj, bool /* strict */ = false)
{ {
if(!isReferenceCompatible(obj)) if(!isReferenceCompatible(obj))
return false; return false;
makeReferenceUnchecked(obj); makeReferenceUnchecked(obj);
return true; return true;
} }
/** /**
* Try to set up a view referencing the same data as the given * Try to set up a view referencing the same data as the given
* NumpyAnyArray. This overloaded variant simply calls * NumpyAnyArray. This overloaded variant simply calls
skipping to change at line 1076 skipping to change at line 1129
pyArray()->strides, this->m_stride.begin()); pyArray()->strides, this->m_stride.begin());
if((int)permute.size() == actual_dimension - 1) if((int)permute.size() == actual_dimension - 1)
{ {
this->m_shape[actual_dimension-1] = 1; this->m_shape[actual_dimension-1] = 1;
this->m_stride[actual_dimension-1] = sizeof(value_type); this->m_stride[actual_dimension-1] = sizeof(value_type);
} }
this->m_stride /= sizeof(value_type); this->m_stride /= sizeof(value_type);
this->m_ptr = reinterpret_cast<pointer>(pyArray()->data); this->m_ptr = reinterpret_cast<pointer>(pyArray()->data);
vigra_precondition(checkInnerStride(Stride()), vigra_precondition(this->checkInnerStride(Stride()),
"NumpyArray<..., UnstridedArrayTag>::setupArrayView(): First di mension of given array is not unstrided (should never happen)."); "NumpyArray<..., UnstridedArrayTag>::setupArrayView(): First di mension of given array is not unstrided (should never happen).");
} }
else else
{ {
this->m_ptr = 0; this->m_ptr = 0;
} }
} }
typedef NumpyArray<2, float > NumpyFArray2; typedef NumpyArray<2, float > NumpyFArray2;
 End of changes. 17 change blocks. 
17 lines changed or deleted 70 lines changed or added


 numpy_array_traits.hxx   numpy_array_traits.hxx 
skipping to change at line 289 skipping to change at line 289
template <class U> template <class U>
static TaggedShape taggedShape(TinyVector<U, N> const & shape, PyAxisTa gs axistags) static TaggedShape taggedShape(TinyVector<U, N> const & shape, PyAxisTa gs axistags)
{ {
return TaggedShape(shape, axistags); return TaggedShape(shape, axistags);
} }
// Construct a tagged shape from a 'shape - order' pair by creating // Construct a tagged shape from a 'shape - order' pair by creating
// the appropriate axistags object for that order and NumpyArray type. // the appropriate axistags object for that order and NumpyArray type.
// (called in NumpyArray constructors via NumpyArray::init()) // (called in NumpyArray constructors via NumpyArray::init())
template <class U> template <class U>
static TaggedShape taggedShape(TinyVector<U, N> const & shape, std::str static TaggedShape taggedShape(TinyVector<U, N> const & shape,
ing const & order = "") std::string const & /* order */ = "")
{ {
// we ignore the 'order' parameter, because we don't know the axis // We ignore the 'order' parameter, because we don't know the axis
meaning meaning
// in a plain array (use Singleband, Multiband, TinyVector etc. ins // in a plain array (use Singleband, Multiband, TinyVector etc. ins
tead) tead).
return TaggedShape(shape, PyAxisTags(detail::emptyAxistags(shape.si // Since we also have no useful axistags in this case, we enforce
ze()))); // the result array to be a plain numpy.ndarray by passing empty ax
istags.
return TaggedShape(shape, PyAxisTags());
} }
// Adjust a TaggedShape that was created by another array to the proper ties of // Adjust a TaggedShape that was created by another array to the proper ties of
// the present NumpyArray type (called in NumpyArray::reshapeIfEmpty()) . // the present NumpyArray type (called in NumpyArray::reshapeIfEmpty()) .
static void finalizeTaggedShape(TaggedShape & tagged_shape) static void finalizeTaggedShape(TaggedShape & tagged_shape)
{ {
vigra_precondition(tagged_shape.size() == N, vigra_precondition(tagged_shape.size() == N,
"reshapeIfEmpty(): tagged_shape has wrong size."); "reshapeIfEmpty(): tagged_shape has wrong size.");
} }
skipping to change at line 581 skipping to change at line 584
template <class U> template <class U>
static TaggedShape taggedShape(TinyVector<U, N> const & shape, std::str ing const & order = "") static TaggedShape taggedShape(TinyVector<U, N> const & shape, std::str ing const & order = "")
{ {
return TaggedShape(shape, return TaggedShape(shape,
PyAxisTags(detail::defaultAxistags(shape.size(), order) )).setChannelIndexLast(); PyAxisTags(detail::defaultAxistags(shape.size(), order) )).setChannelIndexLast();
} }
static void finalizeTaggedShape(TaggedShape & tagged_shape) static void finalizeTaggedShape(TaggedShape & tagged_shape)
{ {
if(tagged_shape.axistags && // When there is only one channel, and the axistags don't enforce a
!tagged_shape.axistags.hasChannelAxis() && tagged_shape.channelC n
ount() == 1) // explicit channel axis, we return an array without explicit chann
el axis.
if(tagged_shape.channelCount() == 1 && !tagged_shape.axistags.hasCh
annelAxis())
{ {
tagged_shape.setChannelCount(0); tagged_shape.setChannelCount(0);
vigra_precondition(tagged_shape.size() == N-1, vigra_precondition(tagged_shape.size() == N-1,
"reshapeIfEmpty(): tagged_shape has wrong size."); "reshapeIfEmpty(): tagged_shape has wrong size.");
} }
else else
{ {
vigra_precondition(tagged_shape.size() == N, vigra_precondition(tagged_shape.size() == N,
"reshapeIfEmpty(): tagged_shape has wrong size."); "reshapeIfEmpty(): tagged_shape has wrong size.");
} }
 End of changes. 3 change blocks. 
11 lines changed or deleted 16 lines changed or added


 random.hxx   random.hxx 
skipping to change at line 41 skipping to change at line 41
/* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */ /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */
/* OTHER DEALINGS IN THE SOFTWARE. */ /* OTHER DEALINGS IN THE SOFTWARE. */
/* */ /* */
/************************************************************************/ /************************************************************************/
#ifndef VIGRA_RANDOM_HXX #ifndef VIGRA_RANDOM_HXX
#define VIGRA_RANDOM_HXX #define VIGRA_RANDOM_HXX
#include "mathutil.hxx" #include "mathutil.hxx"
#include "functortraits.hxx" #include "functortraits.hxx"
#include "array_vector.hxx"
#include <ctime> #include <ctime>
// includes to get the current process and thread IDs
// to be used for automated seeding
#ifdef _MSC_VER
#include <vigra/windows.h> // for GetCurrentProcessId() and GetCurrentTh
readId()
#endif
#if __linux__
#include <unistd.h> // for getpid()
#include <sys/syscall.h> // for SYS_gettid
#endif
#if __APPLE__
#include <unistd.h> // for getpid()
#include <sys/syscall.h> // SYS_thread_selfid
#include <AvailabilityMacros.h> // to check if we are on MacOS 10.6 or
later
#endif
namespace vigra { namespace vigra {
enum RandomSeedTag { RandomSeed }; enum RandomSeedTag { RandomSeed };
namespace detail { namespace detail {
enum RandomEngineTag { TT800, MT19937 }; enum RandomEngineTag { TT800, MT19937 };
template<RandomEngineTag EngineTag> template<RandomEngineTag EngineTag>
struct RandomState; struct RandomState;
skipping to change at line 109 skipping to change at line 127
} }
} }
engine.state_[0] = 0x80000000U; /* MSB is 1; assuring non-zero initial array */ engine.state_[0] = 0x80000000U; /* MSB is 1; assuring non-zero initial array */
} }
template <RandomEngineTag EngineTag> template <RandomEngineTag EngineTag>
void seed(RandomSeedTag, RandomState<EngineTag> & engine) void seed(RandomSeedTag, RandomState<EngineTag> & engine)
{ {
static UInt32 globalCount = 0; static UInt32 globalCount = 0;
UInt32 init[3] = { (UInt32)time(0), (UInt32)clock(), ++globalCount }; ArrayVector<UInt32> seedData;
seed(init, 3, engine);
seedData.push_back((UInt32)time(0));
seedData.push_back((UInt32)clock());
seedData.push_back(++globalCount);
std::size_t ptr((char*)&engine - (char*)0);
seedData.push_back((UInt32)(ptr & 0xffffffff));
seedData.push_back((UInt32)(ptr >> 32));
#ifdef _MSC_VER
seedData.push_back((UInt32)GetCurrentProcessId());
seedData.push_back((UInt32)GetCurrentThreadId());
#endif
#ifdef __linux__
seedData.push_back((UInt32)getpid());
# ifdef SYS_gettid
seedData.push_back((UInt32)syscall(SYS_gettid));
# endif
#endif
#ifdef __APPLE__
seedData.push_back((UInt32)getpid());
#if defined(SYS_thread_selfid) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_O
S_X_VERSION_10_6)
// SYS_thread_selfid was introduced in MacOS 10.6
seedData.push_back((UInt32)syscall(SYS_thread_selfid));
#endif
#endif
seed(seedData.begin(), seedData.size(), engine);
} }
/* Tempered twister TT800 by M. Matsumoto */ /* Tempered twister TT800 by M. Matsumoto */
template<> template<>
struct RandomState<TT800> struct RandomState<TT800>
{ {
static const UInt32 N = 25, M = 7; static const UInt32 N = 25, M = 7;
mutable UInt32 state_[N]; mutable UInt32 state_[N];
mutable UInt32 current_; mutable UInt32 current_;
skipping to change at line 455 skipping to change at line 502
create this number). create this number).
*/ */
double uniform53() const double uniform53() const
{ {
// make full use of the entire 53-bit mantissa of a double, by Isak u Wada // make full use of the entire 53-bit mantissa of a double, by Isak u Wada
return ( (this->get() >> 5) * 67108864.0 + (this->get() >> 6)) * (1 .0/9007199254740992.0); return ( (this->get() >> 5) * 67108864.0 + (this->get() >> 6)) * (1 .0/9007199254740992.0);
} }
/** Return a uniformly distributed double-precision random number i n [0.0, 1.0]. /** Return a uniformly distributed double-precision random number i n [0.0, 1.0].
That is, 0.0 &lt;= i &lt;= 1.0. This number is computed by <tt> uniformInt()</tt> / 2<sup>32</sup>, That is, 0.0 &lt;= i &lt;= 1.0. This number is computed by <tt> uniformInt()</tt> / (2<sup>32</sup> - 1),
so it has effectively only 32 random bits. so it has effectively only 32 random bits.
*/ */
double uniform() const double uniform() const
{ {
return (double)this->get() / 4294967295.0; return (double)this->get() / 4294967295.0;
} }
/** Return a uniformly distributed double-precision random number i n [lower, upper]. /** Return a uniformly distributed double-precision random number i n [lower, upper].
That is, <tt>lower</tt> &lt;= i &lt;= <tt>upper</tt>. This numb er is computed That is, <tt>lower</tt> &lt;= i &lt;= <tt>upper</tt>. This numb er is computed
 End of changes. 4 change blocks. 
3 lines changed or deleted 53 lines changed or added


 recursiveconvolution.hxx   recursiveconvolution.hxx 
skipping to change at line 219 skipping to change at line 219
for(x = 0; x < kernelw; ++x, --is) for(x = 0; x < kernelw; ++x, --is)
old = TempType(as(is) + b * old); old = TempType(as(is) + b * old);
} }
else if(border == BORDER_TREATMENT_WRAP) else if(border == BORDER_TREATMENT_WRAP)
{ {
is = isend - kernelw; is = isend - kernelw;
old = TempType((1.0 / (1.0 - b)) * as(is)); old = TempType((1.0 / (1.0 - b)) * as(is));
for(x = 0; x < kernelw; ++x, ++is) for(x = 0; x < kernelw; ++x, ++is)
old = TempType(as(is) + b * old); old = TempType(as(is) + b * old);
} }
else if(border == BORDER_TREATMENT_CLIP) else if(border == BORDER_TREATMENT_CLIP ||
border == BORDER_TREATMENT_ZEROPAD)
{ {
old = NumericTraits<TempType>::zero(); old = NumericTraits<TempType>::zero();
} }
else else
{ {
vigra_fail("recursiveFilterLine(): Unknown border treatment mode.\n "); vigra_fail("recursiveFilterLine(): Unknown border treatment mode.\n ");
old = NumericTraits<TempType>::zero(); // fix a stupid warning old = NumericTraits<TempType>::zero(); // fix a stupid warning
} }
// left side of filter // left side of filter
skipping to change at line 254 skipping to change at line 255
{ {
old = line[w-2]; old = line[w-2];
} }
else if(border == BORDER_TREATMENT_WRAP) else if(border == BORDER_TREATMENT_WRAP)
{ {
is = istart + kernelw - 1; is = istart + kernelw - 1;
old = TempType((1.0 / (1.0 - b)) * as(is)); old = TempType((1.0 / (1.0 - b)) * as(is));
for(x = 0; x < kernelw; ++x, --is) for(x = 0; x < kernelw; ++x, --is)
old = TempType(as(is) + b * old); old = TempType(as(is) + b * old);
} }
else if(border == BORDER_TREATMENT_CLIP) else if(border == BORDER_TREATMENT_CLIP ||
border == BORDER_TREATMENT_ZEROPAD)
{ {
old = NumericTraits<TempType>::zero(); old = NumericTraits<TempType>::zero();
} }
is = isend - 1; is = isend - 1;
id += w - 1; id += w - 1;
if(border == BORDER_TREATMENT_CLIP) if(border == BORDER_TREATMENT_CLIP)
{ {
// correction factors for b // correction factors for b
double bright = b; double bright = b;
skipping to change at line 310 skipping to change at line 312
/* recursiveFilterLine (2nd order) */ /* recursiveFilterLine (2nd order) */
/* */ /* */
/********************************************************/ /********************************************************/
template <class SrcIterator, class SrcAccessor, template <class SrcIterator, class SrcAccessor,
class DestIterator, class DestAccessor> class DestIterator, class DestAccessor>
void recursiveFilterLine(SrcIterator is, SrcIterator isend, SrcAccessor as, void recursiveFilterLine(SrcIterator is, SrcIterator isend, SrcAccessor as,
DestIterator id, DestAccessor ad, double b1, doubl e b2) DestIterator id, DestAccessor ad, double b1, doubl e b2)
{ {
int w = isend - is; int w = isend - is;
SrcIterator istart = is;
int x; int x;
typedef typename typedef typename
NumericTraits<typename SrcAccessor::value_type>::RealPromote TempTy pe; NumericTraits<typename SrcAccessor::value_type>::RealPromote TempTy pe;
typedef NumericTraits<typename DestAccessor::value_type> DestTraits; typedef NumericTraits<typename DestAccessor::value_type> DestTraits;
// speichert den Ergebnis der linkseitigen Filterung. // speichert den Ergebnis der linkseitigen Filterung.
std::vector<TempType> vline(w+1); std::vector<TempType> vline(w+1);
typename std::vector<TempType>::iterator line = vline.begin(); typename std::vector<TempType>::iterator line = vline.begin();
 End of changes. 3 change blocks. 
4 lines changed or deleted 4 lines changed or added


 regression.hxx   regression.hxx 
skipping to change at line 385 skipping to change at line 385
/** Set the mode of the algorithm. /** Set the mode of the algorithm.
Mode must be one of "lars", "lasso", "nnlasso". The function ju st calls Mode must be one of "lars", "lasso", "nnlasso". The function ju st calls
the member function of the corresponding name to set the mode. the member function of the corresponding name to set the mode.
Default: "lasso" Default: "lasso"
*/ */
LeastAngleRegressionOptions & setMode(std::string mode) LeastAngleRegressionOptions & setMode(std::string mode)
{ {
for(unsigned int k=0; k<mode.size(); ++k) mode = tolower(mode);
mode[k] = (std::string::value_type)tolower(mode[k]);
if(mode == "lars") if(mode == "lars")
this->lars(); this->lars();
else if(mode == "lasso") else if(mode == "lasso")
this->lasso(); this->lasso();
else if(mode == "nnlasso") else if(mode == "nnlasso")
this->nnlasso(); this->nnlasso();
else else
vigra_fail("LeastAngleRegressionOptions.setMode(): Invalid mode ."); vigra_fail("LeastAngleRegressionOptions.setMode(): Invalid mode .");
return *this; return *this;
} }
skipping to change at line 487 skipping to change at line 486
lars_solution(d.lars_solution.subarray(Shape(0,0), Shape(activeSetSiz e, 1))), lars_prediction(d.lars_prediction), lars_solution(d.lars_solution.subarray(Shape(0,0), Shape(activeSetSiz e, 1))), lars_prediction(d.lars_prediction),
next_lsq_solution(d.next_lsq_solution.subarray(Shape(0,0), Shape(acti veSetSize, 1))), next_lsq_solution(d.next_lsq_solution.subarray(Shape(0,0), Shape(acti veSetSize, 1))),
next_lsq_prediction(d.next_lsq_prediction), searchVector(d.searchVect or), next_lsq_prediction(d.next_lsq_prediction), searchVector(d.searchVect or),
columnPermutation(A.shape(1)) columnPermutation(A.shape(1))
{ {
for(unsigned int k=0; k<columnPermutation.size(); ++k) for(unsigned int k=0; k<columnPermutation.size(); ++k)
columnPermutation[k] = k; columnPermutation[k] = k;
} }
}; };
template <class T, class C1, class C2, class Array1, class Array2> template <class T, class C1, class C2, class Array1, class Array2, class Ar
unsigned int leastAngleRegressionMainLoop(LarsData<T, C1, C2> & d, ray3>
Array1 & activeSets, Array2 * lars_solutions, Array2 * ls unsigned int
q_solutions, leastAngleRegressionMainLoop(LarsData<T, C1, C2> & d,
LeastAngleRegressionOptions const & options) Array1 & activeSets,
Array2 * lars_solutions, Array3 * lsq_solution
s,
LeastAngleRegressionOptions const & options)
{ {
using namespace vigra::functor; using namespace vigra::functor;
typedef typename MultiArrayShape<2>::type Shape; typedef typename MultiArrayShape<2>::type Shape;
typedef typename Matrix<T>::view_type Subarray; typedef typename Matrix<T>::view_type Subarray;
typedef ArrayVector<MultiArrayIndex> Permutation; typedef ArrayVector<MultiArrayIndex> Permutation;
typedef typename Permutation::view_type ColumnSet; typedef typename Permutation::view_type ColumnSet;
vigra_precondition(d.activeSetSize > 0, vigra_precondition(d.activeSetSize > 0,
"leastAngleRegressionMainLoop() must not be called with empty active set."); "leastAngleRegressionMainLoop() must not be called with empty active set.");
skipping to change at line 520 skipping to change at line 521
if(maxSolutionCount == 0) if(maxSolutionCount == 0)
maxSolutionCount = lasso_modification maxSolutionCount = lasso_modification
? 10*maxRank ? 10*maxRank
: maxRank; : maxRank;
bool needToRemoveColumn = false; bool needToRemoveColumn = false;
MultiArrayIndex columnToBeAdded = 0, columnToBeRemoved = 0; MultiArrayIndex columnToBeAdded = 0, columnToBeRemoved = 0;
MultiArrayIndex currentSolutionCount = 0; MultiArrayIndex currentSolutionCount = 0;
while(currentSolutionCount < maxSolutionCount) while(currentSolutionCount < maxSolutionCount)
{ {
ColumnSet activeSet = d.columnPermutation.subarray(0, (unsigned int )d.activeSetSize); //ColumnSet activeSet = d.columnPermutation.subarray(0, (unsigned i nt)d.activeSetSize);
ColumnSet inactiveSet = d.columnPermutation.subarray((unsigned int) d.activeSetSize, (unsigned int)cols); ColumnSet inactiveSet = d.columnPermutation.subarray((unsigned int) d.activeSetSize, (unsigned int)cols);
// find next dimension to be activated // find next dimension to be activated
Matrix<T> cLARS = transpose(d.A) * (d.b - d.lars_prediction), // correlation with LARS residual Matrix<T> cLARS = transpose(d.A) * (d.b - d.lars_prediction), // correlation with LARS residual
cLSQ = transpose(d.A) * (d.b - d.next_lsq_prediction); // correlation with LSQ residual cLSQ = transpose(d.A) * (d.b - d.next_lsq_prediction); // correlation with LSQ residual
// In theory, all vectors in the active set should have the same co rrelation C, and // In theory, all vectors in the active set should have the same co rrelation C, and
// the correlation of all others should not exceed this. In practic e, we may find the // the correlation of all others should not exceed this. In practic e, we may find the
// maximum correlation in any variable due to tiny numerical inaccu racies. Therefore, we // maximum correlation in any variable due to tiny numerical inaccu racies. Therefore, we
// determine C from the entire set of variables. // determine C from the entire set of variables.
skipping to change at line 610 skipping to change at line 611
activeSets.push_back(typename Array1::value_type(d.columnPermutatio n.begin(), d.columnPermutation.begin()+d.activeSetSize)); activeSets.push_back(typename Array1::value_type(d.columnPermutatio n.begin(), d.columnPermutation.begin()+d.activeSetSize));
if(lsq_solutions != 0) if(lsq_solutions != 0)
{ {
if(enforce_positive) if(enforce_positive)
{ {
ArrayVector<Matrix<T> > nnresults; ArrayVector<Matrix<T> > nnresults;
ArrayVector<ArrayVector<MultiArrayIndex> > nnactiveSets; ArrayVector<ArrayVector<MultiArrayIndex> > nnactiveSets;
LarsData<T, C1, C2> nnd(d, d.activeSetSize); LarsData<T, C1, C2> nnd(d, d.activeSetSize);
leastAngleRegressionMainLoop(nnd, nnactiveSets, &nnresults, (Array2*)0, leastAngleRegressionMainLoop(nnd, nnactiveSets, &nnresults, (Array3*)0,
LeastAngleRegressionOptions(). leastSquaresSolutions(false).nnlasso()); LeastAngleRegressionOptions(). leastSquaresSolutions(false).nnlasso());
Matrix<T> nnlsq_solution(d.activeSetSize, 1); //Matrix<T> nnlsq_solution(d.activeSetSize, 1);
typename Array2::value_type nnlsq_solution(Shape(d.activeSe
tSize, 1));
for(unsigned int k=0; k<nnactiveSets.back().size(); ++k) for(unsigned int k=0; k<nnactiveSets.back().size(); ++k)
{ {
nnlsq_solution(nnactiveSets.back()[k],0) = nnresults.ba ck()[k]; nnlsq_solution(nnactiveSets.back()[k],0) = nnresults.ba ck()[k];
} }
lsq_solutions->push_back(nnlsq_solution); //lsq_solutions->push_back(nnlsq_solution);
lsq_solutions->push_back(typename Array3::value_type());
lsq_solutions->back() = nnlsq_solution;
} }
else else
{ {
lsq_solutions->push_back(d.next_lsq_solution.subarray(Shape //lsq_solutions->push_back(d.next_lsq_solution.subarray(Sha
(0,0), Shape(d.activeSetSize, 1))); pe(0,0), Shape(d.activeSetSize, 1)));
lsq_solutions->push_back(typename Array3::value_type());
lsq_solutions->back() = d.next_lsq_solution.subarray(Shape(
0,0), Shape(d.activeSetSize, 1));
} }
} }
if(lars_solutions != 0) if(lars_solutions != 0)
{ {
lars_solutions->push_back(d.lars_solution.subarray(Shape(0,0), //lars_solutions->push_back(d.lars_solution.subarray(Shape(0,0)
Shape(d.activeSetSize, 1))); , Shape(d.activeSetSize, 1)));
lars_solutions->push_back(typename Array2::value_type());
lars_solutions->back() = d.lars_solution.subarray(Shape(0,0), S
hape(d.activeSetSize, 1));
} }
// no further solutions possible // no further solutions possible
if(gamma == 1.0) if(gamma == 1.0)
break; break;
if(needToRemoveColumn) if(needToRemoveColumn)
{ {
--d.activeSetSize; --d.activeSetSize;
if(columnToBeRemoved != d.activeSetSize) if(columnToBeRemoved != d.activeSetSize)
skipping to change at line 755 skipping to change at line 763
Array1 & activeSets, Array2 & lasso_solutions, Array2 & lsq_solutions, Array1 & activeSets, Array2 & lasso_solutions, Array2 & lsq_solutions,
LeastAngleRegressionOptions const & options = LeastAngleRegressionOptions()); LeastAngleRegressionOptions const & options = LeastAngleRegressionOptions());
} }
using linalg::leastAngleRegression; using linalg::leastAngleRegression;
} }
\endcode \endcode
This function implements Least Angle Regression (LARS) as described in This function implements Least Angle Regression (LARS) as described in
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
B.Efron, T.Hastie, I.Johnstone, and R.Tibshirani: <em>"Least Angle R egression"</em>, B.Efron, T.Hastie, I.Johnstone, and R.Tibshirani: <i>"Least Angle Re gression"</i>,
Annals of Statistics 32(2):407-499, 2004. Annals of Statistics 32(2):407-499, 2004.
It is an efficient algorithm to solve the L1-regularized least squar es (LASSO) problem It is an efficient algorithm to solve the L1-regularized least squar es (LASSO) problem
\f[ \tilde \textrm{\bf x} = \textrm{argmin} \f[ \tilde \textrm{\bf x} = \textrm{argmin}
\left|\left|\textrm{\bf A} \textrm{\bf x} - \textrm{\bf b}\rig ht|\right|_2^2 \left|\left|\textrm{\bf A} \textrm{\bf x} - \textrm{\bf b}\rig ht|\right|_2^2
\textrm{ subject to } \left|\left|\textrm{\bf x}\right|\right|_1 \le s \textrm{ subject to } \left|\left|\textrm{\bf x}\right|\right|_1 \le s
\f] \f]
and the L1-regularized non-negative least squares (NN-LASSO) problem and the L1-regularized non-negative least squares (NN-LASSO) problem
 End of changes. 9 change blocks. 
16 lines changed or deleted 28 lines changed or added


 resizeimage.hxx   resizeimage.hxx 
skipping to change at line 761 skipping to change at line 761
line_tmp, line.accessor(), (double)height_old/height_n ew/scale); line_tmp, line.accessor(), (double)height_old/height_n ew/scale);
} }
resamplingConvolveLine(line_tmp, line_tmp + height_old, line.ac cessor(), resamplingConvolveLine(line_tmp, line_tmp + height_old, line.ac cessor(),
c_tmp, c_tmp + height_new, tmp_acc, c_tmp, c_tmp + height_new, tmp_acc,
kernels, ymapCoordinate); kernels, ymapCoordinate);
} }
} }
y_tmp = tmp.upperLeft(); y_tmp = tmp.upperLeft();
DestIterator dest = dest_iter;
kernels.resize(xperiod); kernels.resize(xperiod);
createResamplingKernels(spline, xmapCoordinate, kernels); createResamplingKernels(spline, xmapCoordinate, kernels);
for(y=0; y < height_new; ++y, ++y_tmp.y, ++dest_iter.y) for(y=0; y < height_new; ++y, ++y_tmp.y, ++dest_iter.y)
{ {
typename DestIterator::row_iterator r_dest = dest_iter.rowIterator( ); typename DestIterator::row_iterator r_dest = dest_iter.rowIterator( );
typename TmpImageIterator::row_iterator r_tmp = y_tmp.rowIterator() ; typename TmpImageIterator::row_iterator r_tmp = y_tmp.rowIterator() ;
if(prefilterCoeffs.size() == 0) if(prefilterCoeffs.size() == 0)
{ {
 End of changes. 1 change blocks. 
2 lines changed or deleted 0 lines changed or added


 rf_algorithm.hxx   rf_algorithm.hxx 
skipping to change at line 792 skipping to change at line 792
ClusterNode secondChild(topology_, ClusterNode secondChild(topology_,
parameters_, parameters_,
(addr.begin() +jj_min)->first); (addr.begin() +jj_min)->first);
parent.parameters_begin()[0] = min_dist; parent.parameters_begin()[0] = min_dist;
parent.set_index(index); parent.set_index(index);
++index; ++index;
std::merge(firstChild.columns_begin(), firstChild.columns_end() , std::merge(firstChild.columns_begin(), firstChild.columns_end() ,
secondChild.columns_begin(),secondChild.columns_end( ), secondChild.columns_begin(),secondChild.columns_end( ),
parent.columns_begin()); parent.columns_begin());
//merge nodes in addr //merge nodes in addr
int to_keep;
int to_desc; int to_desc;
int ii_keep; int ii_keep;
if(*parent.columns_begin() == *firstChild.columns_begin()) if(*parent.columns_begin() == *firstChild.columns_begin())
{ {
parent.child(0) = (addr.begin()+ii_min)->first; parent.child(0) = (addr.begin()+ii_min)->first;
parent.child(1) = (addr.begin()+jj_min)->first; parent.child(1) = (addr.begin()+jj_min)->first;
(addr.begin()+ii_min)->first = cur_addr; (addr.begin()+ii_min)->first = cur_addr;
ii_keep = ii_min; ii_keep = ii_min;
to_keep = (addr.begin()+ii_min)->second;
to_desc = (addr.begin()+jj_min)->second; to_desc = (addr.begin()+jj_min)->second;
addr.erase(addr.begin()+jj_min); addr.erase(addr.begin()+jj_min);
} }
else else
{ {
parent.child(1) = (addr.begin()+ii_min)->first; parent.child(1) = (addr.begin()+ii_min)->first;
parent.child(0) = (addr.begin()+jj_min)->first; parent.child(0) = (addr.begin()+jj_min)->first;
(addr.begin()+jj_min)->first = cur_addr; (addr.begin()+jj_min)->first = cur_addr;
ii_keep = jj_min; ii_keep = jj_min;
to_keep = (addr.begin()+jj_min)->second;
to_desc = (addr.begin()+ii_min)->second; to_desc = (addr.begin()+ii_min)->second;
addr.erase(addr.begin()+ii_min); addr.erase(addr.begin()+ii_min);
} }
//update distances; //update distances;
for(int jj = 0 ; jj < (int)addr.size(); ++jj) for(int jj = 0 ; jj < (int)addr.size(); ++jj)
{ {
if(jj == ii_keep) if(jj == ii_keep)
continue; continue;
double bla = dist_func( double bla = dist_func(
 End of changes. 3 change blocks. 
3 lines changed or deleted 0 lines changed or added


 rf_decisionTree.hxx   rf_decisionTree.hxx 
skipping to change at line 444 skipping to change at line 444
child_stack_entry[0].leftParent = topology_.size(); child_stack_entry[0].leftParent = topology_.size();
child_stack_entry[1].rightParent = topology_.size(); child_stack_entry[1].rightParent = topology_.size();
child_stack_entry[0].rightParent = -1; child_stack_entry[0].rightParent = -1;
child_stack_entry[1].leftParent = -1; child_stack_entry[1].leftParent = -1;
stack.push_back(child_stack_entry[0]); stack.push_back(child_stack_entry[0]);
stack.push_back(child_stack_entry[1]); stack.push_back(child_stack_entry[1]);
} }
//copy the newly created node form the split functor to the //copy the newly created node form the split functor to the
//decision tree. //decision tree.
NodeBase(split.createNode(), topology_, parameters_ ); NodeBase node(split.createNode(), topology_, parameters_ );
} }
if(garbaged_child!=-1) if(garbaged_child!=-1)
{ {
Node<e_ConstProbNode>(topology_,parameters_,garbaged_child).copy(No de<e_ConstProbNode>(topology_,parameters_,last_node_pos)); Node<e_ConstProbNode>(topology_,parameters_,garbaged_child).copy(No de<e_ConstProbNode>(topology_,parameters_,last_node_pos));
int last_parameter_size = Node<e_ConstProbNode>(topology_,parameter s_,garbaged_child).parameters_size(); int last_parameter_size = Node<e_ConstProbNode>(topology_,parameter s_,garbaged_child).parameters_size();
topology_.resize(last_node_pos); topology_.resize(last_node_pos);
parameters_.resize(parameters_.size() - last_parameter_size); parameters_.resize(parameters_.size() - last_parameter_size);
if(top.leftParent != StackEntry_t::DecisionTreeNoParent) if(top.leftParent != StackEntry_t::DecisionTreeNoParent)
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 rgbvalue.hxx   rgbvalue.hxx 
skipping to change at line 467 skipping to change at line 467
{ {
typedef RGBValue<T, R, G, B> Type; typedef RGBValue<T, R, G, B> Type;
typedef RGBValue<typename NumericTraits<T>::Promote, R, G, B> Promote; typedef RGBValue<typename NumericTraits<T>::Promote, R, G, B> Promote;
typedef RGBValue<typename NumericTraits<T>::RealPromote, R, G, B> RealP romote; typedef RGBValue<typename NumericTraits<T>::RealPromote, R, G, B> RealP romote;
typedef RGBValue<typename NumericTraits<T>::ComplexPromote, R, G, B> Co mplexPromote; typedef RGBValue<typename NumericTraits<T>::ComplexPromote, R, G, B> Co mplexPromote;
typedef T ValueType; typedef T ValueType;
typedef typename NumericTraits<T>::isIntegral isIntegral; typedef typename NumericTraits<T>::isIntegral isIntegral;
typedef VigraFalseType isScalar; typedef VigraFalseType isScalar;
typedef typename NumericTraits<T>::isSigned isSigned; typedef typename NumericTraits<T>::isSigned isSigned;
typedef VigraFalseType isOrdered; typedef VigraTrueType isOrdered;
typedef VigraFalseType isComplex; typedef VigraFalseType isComplex;
static Type zero() { static Type zero()
{
return Type(NumericTraits<T>::zero()); return Type(NumericTraits<T>::zero());
} }
static Type one() { static Type one()
{
return Type(NumericTraits<T>::one()); return Type(NumericTraits<T>::one());
} }
static Type nonZero() { static Type nonZero()
{
return Type(NumericTraits<T>::nonZero()); return Type(NumericTraits<T>::nonZero());
} }
static Promote toPromote(Type const & v) { static Type min()
{
return Type(NumericTraits<T>::min());
}
static Type max()
{
return Type(NumericTraits<T>::max());
}
static Promote toPromote(Type const & v)
{
return Promote(v); return Promote(v);
} }
static RealPromote toRealPromote(Type const & v) { static RealPromote toRealPromote(Type const & v)
{
return RealPromote(v); return RealPromote(v);
} }
static Type fromPromote(Promote const & v) { static Type fromPromote(Promote const & v)
{
return Type(NumericTraits<T>::fromPromote(v.red()), return Type(NumericTraits<T>::fromPromote(v.red()),
NumericTraits<T>::fromPromote(v.green()), NumericTraits<T>::fromPromote(v.green()),
NumericTraits<T>::fromPromote(v.blue())); NumericTraits<T>::fromPromote(v.blue()));
} }
static Type fromRealPromote(RealPromote const & v) { static Type fromRealPromote(RealPromote const & v)
{
return Type(NumericTraits<T>::fromRealPromote(v.red()), return Type(NumericTraits<T>::fromRealPromote(v.red()),
NumericTraits<T>::fromRealPromote(v.green()), NumericTraits<T>::fromRealPromote(v.green()),
NumericTraits<T>::fromRealPromote(v.blue())); NumericTraits<T>::fromRealPromote(v.blue()));
} }
}; };
template <class T, unsigned int R, unsigned int G, unsigned int B> template <class T, unsigned int R, unsigned int G, unsigned int B>
struct NormTraits<RGBValue<T, R, G, B> > struct NormTraits<RGBValue<T, R, G, B> >
{ {
typedef RGBValue<T, R, G, B> Type; typedef RGBValue<T, R, G, B> Type;
skipping to change at line 906 skipping to change at line 922
template <class V, unsigned int RIDX, unsigned int GIDX, unsigned int BIDX> template <class V, unsigned int RIDX, unsigned int GIDX, unsigned int BIDX>
inline inline
RGBValue<V, RIDX, GIDX, BIDX> RGBValue<V, RIDX, GIDX, BIDX>
floor(RGBValue<V, RIDX, GIDX, BIDX> const & r) floor(RGBValue<V, RIDX, GIDX, BIDX> const & r)
{ {
return RGBValue<V, RIDX, GIDX, BIDX>(floor(r.red()), return RGBValue<V, RIDX, GIDX, BIDX>(floor(r.red()),
floor(r.green()), floor(r.green()),
floor(r.blue())); floor(r.blue()));
} }
// overload min and max to avoid that std:min() and std::max() match
template <class V, unsigned int RIDX, unsigned int GIDX, unsigned int BIDX>
inline
RGBValue<V, RIDX, GIDX, BIDX>
min(RGBValue<V, RIDX, GIDX, BIDX> const & l,
RGBValue<V, RIDX, GIDX, BIDX> const & r)
{
typedef typename detail::LoopType<3>::type ltype;
RGBValue<V, RIDX, GIDX, BIDX> res(l);
ltype::min(res.begin(), r.begin());
return res;
}
template <class V, unsigned int RIDX, unsigned int GIDX, unsigned int BIDX>
inline
RGBValue<V, RIDX, GIDX, BIDX>
max(RGBValue<V, RIDX, GIDX, BIDX> const & l,
RGBValue<V, RIDX, GIDX, BIDX> const & r)
{
typedef typename detail::LoopType<3>::type ltype;
RGBValue<V, RIDX, GIDX, BIDX> res(l);
ltype::max(res.begin(), r.begin());
return res;
}
//@} //@}
/********************************************************/ /********************************************************/
/* */ /* */
/* RGBValue-Accessors */ /* RGBValue-Accessors */
/* */ /* */
/********************************************************/ /********************************************************/
/** \addtogroup DataAccessors /** \addtogroup DataAccessors
*/ */
 End of changes. 9 change blocks. 
8 lines changed or deleted 49 lines changed or added


 sampling.hxx   sampling.hxx 
skipping to change at line 214 skipping to change at line 214
ArrayVerctor<int> strata(totalCount); ArrayVerctor<int> strata(totalCount);
for(int i=0; i<stratumSize1; ++i) for(int i=0; i<stratumSize1; ++i)
strata[i] = 1; strata[i] = 1;
for(int i=stratumSize1; i<stratumSize2; ++i) for(int i=stratumSize1; i<stratumSize2; ++i)
strata[i] = 2; strata[i] = 2;
int sampleSize = 200; // i.e. sample 100 elements from each of the two strata int sampleSize = 200; // i.e. sample 100 elements from each of the two strata
int numberOfSamples = 20; // repeat experiment 20 times int numberOfSamples = 20; // repeat experiment 20 times
Sampler<> stratifiedSampler(strata.begin(), strata.end(), Sampler<> stratifiedSampler(strata.begin(), strata.end(),
SamplerOptions().withoutReplacement().stratified().sam pleSize(sampleSize)); SamplerOptions().withoutReplacement().stratified().sam pleSize(sampleSize));
// create first sample
sampler.sample();
for(int k=0; k<numberOfSamples; ++k) for(int k=0; k<numberOfSamples; ++k)
{ {
// process current sample // process current sample
for(int i=0; i<sampler.sampleSize(); ++i) for(int i=0; i<sampler.sampleSize(); ++i)
{ {
int currentIndex = sampler[i]; int currentIndex = sampler[i];
processData(data[currentIndex]); processData(data[currentIndex]);
} }
// create next sample // create next sample
 End of changes. 1 change blocks. 
0 lines changed or deleted 2 lines changed or added


 seededregiongrowing3d.hxx   seededregiongrowing3d.hxx 
skipping to change at line 305 skipping to change at line 305
class RegionStatisticsArray, class Neighborhood> class RegionStatisticsArray, class Neighborhood>
void void
seededRegionGrowing3D(SrcImageIterator srcul, Diff_type shape, SrcAccessor as, seededRegionGrowing3D(SrcImageIterator srcul, Diff_type shape, SrcAccessor as,
SeedImageIterator seedsul, SeedAccessor aseeds, SeedImageIterator seedsul, SeedAccessor aseeds,
DestImageIterator destul, DestAccessor ad, DestImageIterator destul, DestAccessor ad,
RegionStatisticsArray & stats, RegionStatisticsArray & stats,
SRGType srgType, SRGType srgType,
Neighborhood, Neighborhood,
double max_cost) double max_cost)
{ {
SrcImageIterator srclr = srcul + shape; //SrcImageIterator srclr = srcul + shape;
//int w = srclr.x - srcul.x; //int w = srclr.x - srcul.x;
int w = shape[0]; int w = shape[0];
//int h = srclr.y - srcul.y; //int h = srclr.y - srcul.y;
int h = shape[1]; int h = shape[1];
//int d = srclr.z - srcul.z; //int d = srclr.z - srcul.z;
int d = shape[2]; int d = shape[2];
int count = 0; int count = 0;
SrcImageIterator isy = srcul, isx = srcul, isz = srcul; // iterators f or the src image SrcImageIterator isy = srcul, isx = srcul, isz = srcul; // iterators f or the src image
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 separableconvolution.hxx   separableconvolution.hxx 
skipping to change at line 51 skipping to change at line 51
#include "numerictraits.hxx" #include "numerictraits.hxx"
#include "imageiteratoradapter.hxx" #include "imageiteratoradapter.hxx"
#include "bordertreatment.hxx" #include "bordertreatment.hxx"
#include "gaussians.hxx" #include "gaussians.hxx"
#include "array_vector.hxx" #include "array_vector.hxx"
namespace vigra { namespace vigra {
/********************************************************/ /********************************************************/
/* */ /* */
/* internalConvolveLineOptimistic */
/* */
/********************************************************/
// This function assumes that the input array is actually larger than
// the range [is, iend), so that it can safely access values outside
// this range. This is useful if (1) we work on a small ROI, or
// (2) we enlarge the input by copying with border treatment.
template <class SrcIterator, class SrcAccessor,
class DestIterator, class DestAccessor,
class KernelIterator, class KernelAccessor>
void internalConvolveLineOptimistic(SrcIterator is, SrcIterator iend, SrcAc
cessor sa,
DestIterator id, DestAccessor da,
KernelIterator kernel, KernelAccessor k
a,
int kleft, int kright)
{
typedef typename PromoteTraits<
typename SrcAccessor::value_type,
typename KernelAccessor::value_type>::Promote SumType;
int w = std::distance( is, iend );
int kw = kright - kleft + 1;
for(int x=0; x<w; ++x, ++is, ++id)
{
SrcIterator iss = is + (-kright);
KernelIterator ik = kernel + kright;
SumType sum = NumericTraits<SumType>::zero();
for(int k = 0; k < kw; ++k, --ik, ++iss)
{
sum += ka(ik) * sa(iss);
}
da.set(detail::RequiresExplicitCast<typename
DestAccessor::value_type>::cast(sum), id);
}
}
namespace detail {
// dest array must have size = stop - start + kright - kleft
template <class SrcIterator, class SrcAccessor,
class DestIterator, class DestAccessor>
void
copyLineWithBorderTreatment(SrcIterator is, SrcIterator iend, SrcAccessor s
a,
DestIterator id, DestAccessor da,
int start, int stop,
int kleft, int kright,
BorderTreatmentMode borderTreatment)
{
int w = std::distance( is, iend );
int leftBorder = start - kright;
int rightBorder = stop - kleft;
int copyEnd = std::min(w, rightBorder);
if(leftBorder < 0)
{
switch(borderTreatment)
{
case BORDER_TREATMENT_WRAP:
{
for(; leftBorder<0; ++leftBorder, ++id)
da.set(sa(iend, leftBorder), id);
break;
}
case BORDER_TREATMENT_AVOID:
{
// nothing to do
break;
}
case BORDER_TREATMENT_REFLECT:
{
for(; leftBorder<0; ++leftBorder, ++id)
da.set(sa(is, -leftBorder), id);
break;
}
case BORDER_TREATMENT_REPEAT:
{
for(; leftBorder<0; ++leftBorder, ++id)
da.set(sa(is), id);
break;
}
case BORDER_TREATMENT_CLIP:
{
vigra_precondition(false,
"copyLineWithBorderTreatment() internal error:
not applicable to BORDER_TREATMENT_CLIP.");
break;
}
case BORDER_TREATMENT_ZEROPAD:
{
for(; leftBorder<0; ++leftBorder, ++id)
da.set(NumericTraits<typename DestAccessor::value_type>
::zero(), id);
break;
}
default:
{
vigra_precondition(false,
"copyLineWithBorderTreatment(): Unknown border
treatment mode.");
}
}
}
SrcIterator iss = is + leftBorder;
vigra_invariant( leftBorder < copyEnd,
"copyLineWithBorderTreatment(): assertion failed.");
for(; leftBorder<copyEnd; ++leftBorder, ++id, ++iss)
da.set(sa(iss), id);
if(copyEnd < rightBorder)
{
switch(borderTreatment)
{
case BORDER_TREATMENT_WRAP:
{
for(; copyEnd<rightBorder; ++copyEnd, ++id, ++is)
da.set(sa(is), id);
break;
}
case BORDER_TREATMENT_AVOID:
{
// nothing to do
break;
}
case BORDER_TREATMENT_REFLECT:
{
iss -= 2;
for(; copyEnd<rightBorder; ++copyEnd, ++id, --iss)
da.set(sa(iss), id);
break;
}
case BORDER_TREATMENT_REPEAT:
{
--iss;
for(; copyEnd<rightBorder; ++copyEnd, ++id)
da.set(sa(iss), id);
break;
}
case BORDER_TREATMENT_CLIP:
{
vigra_precondition(false,
"copyLineWithBorderTreatment() internal error:
not applicable to BORDER_TREATMENT_CLIP.");
break;
}
case BORDER_TREATMENT_ZEROPAD:
{
for(; copyEnd<rightBorder; ++copyEnd, ++id)
da.set(NumericTraits<typename DestAccessor::value_type>
::zero(), id);
break;
}
default:
{
vigra_precondition(false,
"copyLineWithBorderTreatment(): Unknown border
treatment mode.");
}
}
}
}
} // namespace detail
/********************************************************/
/* */
/* internalConvolveLineWrap */ /* internalConvolveLineWrap */
/* */ /* */
/********************************************************/ /********************************************************/
template <class SrcIterator, class SrcAccessor, template <class SrcIterator, class SrcAccessor,
class DestIterator, class DestAccessor, class DestIterator, class DestAccessor,
class KernelIterator, class KernelAccessor> class KernelIterator, class KernelAccessor>
void internalConvolveLineWrap(SrcIterator is, SrcIterator iend, SrcAccessor sa, void internalConvolveLineWrap(SrcIterator is, SrcIterator iend, SrcAccessor sa,
DestIterator id, DestAccessor da, DestIterator id, DestAccessor da,
KernelIterator kernel, KernelAccessor ka, KernelIterator kernel, KernelAccessor ka,
skipping to change at line 92 skipping to change at line 254
{ {
int x0 = x - kright; int x0 = x - kright;
SrcIterator iss = iend + x0; SrcIterator iss = iend + x0;
for(; x0; ++x0, --ik, ++iss) for(; x0; ++x0, --ik, ++iss)
{ {
sum += ka(ik) * sa(iss); sum += ka(ik) * sa(iss);
} }
iss = ibegin; iss = ibegin;
SrcIterator isend = is + (1 - kleft); if(w-x <= -kleft)
for(; iss != isend ; --ik, ++iss)
{ {
sum += ka(ik) * sa(iss); SrcIterator isend = iend;
for(; iss != isend ; --ik, ++iss)
{
sum += ka(ik) * sa(iss);
}
int x0 = -kleft - w + x + 1;
iss = ibegin;
for(; x0; --x0, --ik, ++iss)
{
sum += ka(ik) * sa(iss);
}
}
else
{
SrcIterator isend = is + (1 - kleft);
for(; iss != isend ; --ik, ++iss)
{
sum += ka(ik) * sa(iss);
}
} }
} }
else if(w-x <= -kleft) else if(w-x <= -kleft)
{ {
SrcIterator iss = is + (-kright); SrcIterator iss = is + (-kright);
SrcIterator isend = iend; SrcIterator isend = iend;
for(; iss != isend ; --ik, ++iss) for(; iss != isend ; --ik, ++iss)
{ {
sum += ka(ik) * sa(iss); sum += ka(ik) * sa(iss);
} }
skipping to change at line 174 skipping to change at line 355
{ {
int x0 = x - kright; int x0 = x - kright;
Norm clipped = NumericTraits<Norm>::zero(); Norm clipped = NumericTraits<Norm>::zero();
for(; x0; ++x0, --ik) for(; x0; ++x0, --ik)
{ {
clipped += ka(ik); clipped += ka(ik);
} }
SrcIterator iss = ibegin; SrcIterator iss = ibegin;
SrcIterator isend = is + (1 - kleft); if(w-x <= -kleft)
for(; iss != isend ; --ik, ++iss)
{ {
sum += ka(ik) * sa(iss); SrcIterator isend = iend;
for(; iss != isend ; --ik, ++iss)
{
sum += ka(ik) * sa(iss);
}
int x0 = -kleft - w + x + 1;
for(; x0; --x0, --ik)
{
clipped += ka(ik);
}
}
else
{
SrcIterator isend = is + (1 - kleft);
for(; iss != isend ; --ik, ++iss)
{
sum += ka(ik) * sa(iss);
}
} }
sum = norm / (norm - clipped) * sum; sum = norm / (norm - clipped) * sum;
} }
else if(w-x <= -kleft) else if(w-x <= -kleft)
{ {
SrcIterator iss = is + (-kright); SrcIterator iss = is + (-kright);
SrcIterator isend = iend; SrcIterator isend = iend;
for(; iss != isend ; --ik, ++iss) for(; iss != isend ; --ik, ++iss)
{ {
skipping to change at line 219 skipping to change at line 418
} }
} }
da.set(detail::RequiresExplicitCast<typename da.set(detail::RequiresExplicitCast<typename
DestAccessor::value_type>::cast(sum), id); DestAccessor::value_type>::cast(sum), id);
} }
} }
/********************************************************/ /********************************************************/
/* */ /* */
/* internalConvolveLineZeropad */
/* */
/********************************************************/
template <class SrcIterator, class SrcAccessor,
class DestIterator, class DestAccessor,
class KernelIterator, class KernelAccessor>
void internalConvolveLineZeropad(SrcIterator is, SrcIterator iend, SrcAcces
sor sa,
DestIterator id, DestAccessor da,
KernelIterator kernel, KernelAccessor ka,
int kleft, int kright,
int start = 0, int stop = 0)
{
int w = std::distance( is, iend );
typedef typename PromoteTraits<
typename SrcAccessor::value_type,
typename KernelAccessor::value_type>::Promote SumType;
SrcIterator ibegin = is;
if(stop == 0)
stop = w;
is += start;
for(int x=start; x<stop; ++x, ++is, ++id)
{
SumType sum = NumericTraits<SumType>::zero();
if(x < kright)
{
KernelIterator ik = kernel + x;
SrcIterator iss = ibegin;
if(w-x <= -kleft)
{
SrcIterator isend = iend;
for(; iss != isend ; --ik, ++iss)
{
sum += ka(ik) * sa(iss);
}
}
else
{
SrcIterator isend = is + (1 - kleft);
for(; iss != isend ; --ik, ++iss)
{
sum += ka(ik) * sa(iss);
}
}
}
else if(w-x <= -kleft)
{
KernelIterator ik = kernel + kright;
SrcIterator iss = is + (-kright);
SrcIterator isend = iend;
for(; iss != isend ; --ik, ++iss)
{
sum += ka(ik) * sa(iss);
}
}
else
{
KernelIterator ik = kernel + kright;
SrcIterator iss = is + (-kright);
SrcIterator isend = is + (1 - kleft);
for(; iss != isend ; --ik, ++iss)
{
sum += ka(ik) * sa(iss);
}
}
da.set(detail::RequiresExplicitCast<typename
DestAccessor::value_type>::cast(sum), id);
}
}
/********************************************************/
/* */
/* internalConvolveLineReflect */ /* internalConvolveLineReflect */
/* */ /* */
/********************************************************/ /********************************************************/
template <class SrcIterator, class SrcAccessor, template <class SrcIterator, class SrcAccessor,
class DestIterator, class DestAccessor, class DestIterator, class DestAccessor,
class KernelIterator, class KernelAccessor> class KernelIterator, class KernelAccessor>
void internalConvolveLineReflect(SrcIterator is, SrcIterator iend, SrcAcces sor sa, void internalConvolveLineReflect(SrcIterator is, SrcIterator iend, SrcAcces sor sa,
DestIterator id, DestAccessor da, DestIterator id, DestAccessor da,
KernelIterator kernel, KernelAccessor ka, KernelIterator kernel, KernelAccessor ka,
skipping to change at line 259 skipping to change at line 537
if(x < kright) if(x < kright)
{ {
int x0 = x - kright; int x0 = x - kright;
SrcIterator iss = ibegin - x0; SrcIterator iss = ibegin - x0;
for(; x0; ++x0, --ik, --iss) for(; x0; ++x0, --ik, --iss)
{ {
sum += ka(ik) * sa(iss); sum += ka(ik) * sa(iss);
} }
SrcIterator isend = is + (1 - kleft); if(w-x <= -kleft)
for(; iss != isend ; --ik, ++iss)
{ {
sum += ka(ik) * sa(iss); SrcIterator isend = iend;
for(; iss != isend ; --ik, ++iss)
{
sum += ka(ik) * sa(iss);
}
int x0 = -kleft - w + x + 1;
iss = iend - 2;
for(; x0; --x0, --ik, --iss)
{
sum += ka(ik) * sa(iss);
}
}
else
{
SrcIterator isend = is + (1 - kleft);
for(; iss != isend ; --ik, ++iss)
{
sum += ka(ik) * sa(iss);
}
} }
} }
else if(w-x <= -kleft) else if(w-x <= -kleft)
{ {
SrcIterator iss = is + (-kright); SrcIterator iss = is + (-kright);
SrcIterator isend = iend; SrcIterator isend = iend;
for(; iss != isend ; --ik, ++iss) for(; iss != isend ; --ik, ++iss)
{ {
sum += ka(ik) * sa(iss); sum += ka(ik) * sa(iss);
} }
skipping to change at line 339 skipping to change at line 636
if(x < kright) if(x < kright)
{ {
int x0 = x - kright; int x0 = x - kright;
SrcIterator iss = ibegin; SrcIterator iss = ibegin;
for(; x0; ++x0, --ik) for(; x0; ++x0, --ik)
{ {
sum += ka(ik) * sa(iss); sum += ka(ik) * sa(iss);
} }
SrcIterator isend = is + (1 - kleft); if(w-x <= -kleft)
for(; iss != isend ; --ik, ++iss)
{ {
sum += ka(ik) * sa(iss); SrcIterator isend = iend;
for(; iss != isend ; --ik, ++iss)
{
sum += ka(ik) * sa(iss);
}
int x0 = -kleft - w + x + 1;
iss = iend - 1;
for(; x0; --x0, --ik)
{
sum += ka(ik) * sa(iss);
}
}
else
{
SrcIterator isend = is + (1 - kleft);
for(; iss != isend ; --ik, ++iss)
{
sum += ka(ik) * sa(iss);
}
} }
} }
else if(w-x <= -kleft) else if(w-x <= -kleft)
{ {
SrcIterator iss = is + (-kright); SrcIterator iss = is + (-kright);
SrcIterator isend = iend; SrcIterator isend = iend;
for(; iss != isend ; --ik, ++iss) for(; iss != isend ; --ik, ++iss)
{ {
sum += ka(ik) * sa(iss); sum += ka(ik) * sa(iss);
} }
skipping to change at line 600 skipping to change at line 916
// int w = iend - is; // int w = iend - is;
int w = std::distance( is, iend ); int w = std::distance( is, iend );
vigra_precondition(w >= std::max(kright, -kleft) + 1, vigra_precondition(w >= std::max(kright, -kleft) + 1,
"convolveLine(): kernel longer than line.\n"); "convolveLine(): kernel longer than line.\n");
if(stop != 0) if(stop != 0)
vigra_precondition(0 <= start && start < stop && stop <= w, vigra_precondition(0 <= start && start < stop && stop <= w,
"convolveLine(): invalid subrange (start, stop).\n" ); "convolveLine(): invalid subrange (start, stop).\n" );
typedef typename PromoteTraits<
typename SrcAccessor::value_type,
typename KernelAccessor::value_type>::Promote SumType;
ArrayVector<SumType> a(iend - is);
switch(border) switch(border)
{ {
case BORDER_TREATMENT_WRAP: case BORDER_TREATMENT_WRAP:
{ {
internalConvolveLineWrap(is, iend, sa, id, da, ik, ka, kleft, krigh t, start, stop); internalConvolveLineWrap(is, iend, sa, id, da, ik, ka, kleft, krigh t, start, stop);
break; break;
} }
case BORDER_TREATMENT_AVOID: case BORDER_TREATMENT_AVOID:
{ {
internalConvolveLineAvoid(is, iend, sa, id, da, ik, ka, kleft, krig ht, start, stop); internalConvolveLineAvoid(is, iend, sa, id, da, ik, ka, kleft, krig ht, start, stop);
skipping to change at line 638 skipping to change at line 958
for(int i=kleft; i<=kright; ++i, ++iik) for(int i=kleft; i<=kright; ++i, ++iik)
norm += ka(iik); norm += ka(iik);
vigra_precondition(norm != NumericTraits<KT>::zero(), vigra_precondition(norm != NumericTraits<KT>::zero(),
"convolveLine(): Norm of kernel must be != 0" "convolveLine(): Norm of kernel must be != 0"
" in mode BORDER_TREATMENT_CLIP.\n"); " in mode BORDER_TREATMENT_CLIP.\n");
internalConvolveLineClip(is, iend, sa, id, da, ik, ka, kleft, krigh t, norm, start, stop); internalConvolveLineClip(is, iend, sa, id, da, ik, ka, kleft, krigh t, norm, start, stop);
break; break;
} }
case BORDER_TREATMENT_ZEROPAD:
{
internalConvolveLineZeropad(is, iend, sa, id, da, ik, ka, kleft, kr
ight, start, stop);
break;
}
default: default:
{ {
vigra_precondition(0, vigra_precondition(0,
"convolveLine(): Unknown border treatment mode.\n"); "convolveLine(): Unknown border treatment mode.\n");
} }
} }
} }
template <class SrcIterator, class SrcAccessor, template <class SrcIterator, class SrcAccessor,
class DestIterator, class DestAccessor, class DestIterator, class DestAccessor,
skipping to change at line 977 skipping to change at line 1302
struct InitProxy struct InitProxy
{ {
InitProxy(Iterator i, int count, value_type & norm) InitProxy(Iterator i, int count, value_type & norm)
: iter_(i), base_(i), : iter_(i), base_(i),
count_(count), sum_(count), count_(count), sum_(count),
norm_(norm) norm_(norm)
{} {}
~InitProxy() ~InitProxy()
#ifndef _MSC_VER
throw(PreconditionViolation)
#endif
{ {
vigra_precondition(count_ == 1 || count_ == sum_, vigra_precondition(count_ == 1 || count_ == sum_,
"Kernel1D::initExplicitly(): " "Kernel1D::initExplicitly(): "
"Wrong number of init values."); "Wrong number of init values.");
} }
InitProxy & operator,(value_type const & v) InitProxy & operator,(value_type const & v)
{ {
if(sum_ == count_) if(sum_ == count_)
norm_ = *iter_; norm_ = *iter_;
norm_ += v; norm_ += v;
--count_; --count_;
if(count_ > 0) if(count_ > 0)
{ {
++iter_; ++iter_;
*iter_ = v; *iter_ = v;
} }
return *this; return *this;
} }
Iterator iter_, base_; Iterator iter_, base_;
int count_, sum_; int count_, sum_;
value_type & norm_; value_type & norm_;
}; };
static value_type one() { return NumericTraits<value_type>::one(); } static value_type one() { return NumericTraits<value_type>::one(); }
skipping to change at line 1474 skipping to change at line 1801
/** Init as a symmetric gradient filter with norm 1. /** Init as a symmetric gradient filter with norm 1.
<b>Deprecated</b>. Use initSymmetricDifference() instead. <b>Deprecated</b>. Use initSymmetricDifference() instead.
*/ */
void initSymmetricGradient() void initSymmetricGradient()
{ {
initSymmetricGradient(one()); initSymmetricGradient(one());
} }
/** Init as the 2-tap forward difference filter.
The filter values are
\code
[1.0, -1.0]
\endcode
(note that filters are reflected by the convolution algorithm,
and we get a forward difference after reflection).
Postconditions:
\code
1. left() == -1
2. right() == 0
3. borderTreatment() == BORDER_TREATMENT_REFLECT
4. norm() == 1.0
\endcode
*/
void initForwardDifference()
{
this->initExplicitly(-1, 0) = 1.0, -1.0;
this->setBorderTreatment(BORDER_TREATMENT_REFLECT);
}
/** Init as the 2-tap backward difference filter.
The filter values are
\code
[1.0, -1.0]
\endcode
(note that filters are reflected by the convolution algorithm,
and we get a forward difference after reflection).
Postconditions:
\code
1. left() == 0
2. right() == 1
3. borderTreatment() == BORDER_TREATMENT_REFLECT
4. norm() == 1.0
\endcode
*/
void initBackwardDifference()
{
this->initExplicitly(0, 1) = 1.0, -1.0;
this->setBorderTreatment(BORDER_TREATMENT_REFLECT);
}
void void
initSymmetricDifference(value_type norm ); initSymmetricDifference(value_type norm );
/** Init as the 3-tap symmetric difference filter /** Init as the 3-tap symmetric difference filter
The filter values are The filter values are
\code \code
[0.5, 0, -0.5] [0.5, 0, -0.5]
\endcode \endcode
Postconditions: Postconditions:
\code \code
1. left() == -1 1. left() == -1
2. right() == 1 2. right() == 1
3. borderTreatment() == BORDER_TREATMENT_REFLECT 3. borderTreatment() == BORDER_TREATMENT_REFLECT
4. norm() == 1.0 4. norm() == 1.0
\endcode \endcode
*/ */
void initSymmetricDifference() void initSymmetricDifference()
{ {
initSymmetricDifference(one()); initSymmetricDifference(one());
} }
/** /**
Init the 3-tap second difference filter. Init the 3-tap second difference filter.
The filter values are The filter values are
\code \code
[1, -2, 1] [1, -2, 1]
\endcode \endcode
Postconditions: Postconditions:
\code \code
1. left() == -1 1. left() == -1
2. right() == 1 2. right() == 1
3. borderTreatment() == BORDER_TREATMENT_REFLECT 3. borderTreatment() == BORDER_TREATMENT_REFLECT
4. norm() == 1 4. norm() == 1
\endcode \endcode
*/ */
void void
 End of changes. 18 change blocks. 
20 lines changed or deleted 406 lines changed or added


 sized_int.hxx   sized_int.hxx 
skipping to change at line 125 skipping to change at line 125
template<int SIZE> template<int SIZE>
struct SelectIntegerType<SIZE, Int_type_not_supported_on_this_platform> struct SelectIntegerType<SIZE, Int_type_not_supported_on_this_platform>
{ {
typedef Int_type_not_supported_on_this_platform type; typedef Int_type_not_supported_on_this_platform type;
}; };
template<class LIST> template<class LIST>
struct SelectBiggestIntegerType struct SelectBiggestIntegerType
{ {
enum { cursize = LIST::size, enum { cursize = static_cast<int>(LIST::size),
nextsize = SelectBiggestIntegerType<typename LIST::next>::size, nextsize = static_cast<int>(SelectBiggestIntegerType<typename LI
ST::next>::size),
size = (cursize < nextsize) ? nextsize : cursize }; size = (cursize < nextsize) ? nextsize : cursize };
typedef typename typedef typename
IfBool<(cursize < nextsize), IfBool<(cursize < nextsize),
typename SelectBiggestIntegerType<typename LIST::next>::type, typename SelectBiggestIntegerType<typename LIST::next>::type,
typename LIST::type>::type typename LIST::type>::type
type; type;
}; };
template<> template<>
struct SelectBiggestIntegerType<Int_type_not_supported_on_this_platform> struct SelectBiggestIntegerType<Int_type_not_supported_on_this_platform>
 End of changes. 1 change blocks. 
2 lines changed or deleted 3 lines changed or added


 splineimageview.hxx   splineimageview.hxx 
skipping to change at line 109 skipping to change at line 109
class SplineImageView class SplineImageView
{ {
typedef typename NumericTraits<VALUETYPE>::RealPromote InternalValue; typedef typename NumericTraits<VALUETYPE>::RealPromote InternalValue;
public: public:
/** The view's value type (return type of access and derivative fun ctions). /** The view's value type (return type of access and derivative fun ctions).
*/ */
typedef VALUETYPE value_type; typedef VALUETYPE value_type;
/** The view's squared norm type (return type of g2() etc.).
*/
typedef typename NormTraits<VALUETYPE>::SquaredNormType SquaredNormType
;
/** The view's size type. /** The view's size type.
*/ */
typedef Size2D size_type; typedef Size2D size_type;
/** The view's difference type. /** The view's difference type.
*/ */
typedef TinyVector<double, 2> difference_type; typedef TinyVector<double, 2> difference_type;
/** The order of the spline used. /** The order of the spline used.
*/ */
skipping to change at line 310 skipping to change at line 314
{ return dxxy(d[0], d[1]); } { return dxxy(d[0], d[1]); }
/** Access mixed 3rd derivative dxyy at real-valued coordinate <tt> d</tt>. /** Access mixed 3rd derivative dxyy at real-valued coordinate <tt> d</tt>.
Equivalent to <tt>splineView.dxyy(d[0], d[1])</tt>. Equivalent to <tt>splineView.dxyy(d[0], d[1])</tt>.
*/ */
value_type dxyy(difference_type const & d) const value_type dxyy(difference_type const & d) const
{ return dxyy(d[0], d[1]); } { return dxyy(d[0], d[1]); }
/** Access gradient squared magnitude at real-valued coordinate <tt >(x, y)</tt>. /** Access gradient squared magnitude at real-valued coordinate <tt >(x, y)</tt>.
*/ */
value_type g2(double x, double y) const; SquaredNormType g2(double x, double y) const;
/** Access 1st derivative in x-direction of gradient squared magnit ude /** Access 1st derivative in x-direction of gradient squared magnit ude
at real-valued coordinate <tt>(x, y)</tt>. at real-valued coordinate <tt>(x, y)</tt>.
*/ */
value_type g2x(double x, double y) const; SquaredNormType g2x(double x, double y) const;
/** Access 1st derivative in y-direction of gradient squared magnit ude /** Access 1st derivative in y-direction of gradient squared magnit ude
at real-valued coordinate <tt>(x, y)</tt>. at real-valued coordinate <tt>(x, y)</tt>.
*/ */
value_type g2y(double x, double y) const; SquaredNormType g2y(double x, double y) const;
/** Access 2nd derivative in x-direction of gradient squared magnit ude /** Access 2nd derivative in x-direction of gradient squared magnit ude
at real-valued coordinate <tt>(x, y)</tt>. at real-valued coordinate <tt>(x, y)</tt>.
*/ */
value_type g2xx(double x, double y) const; SquaredNormType g2xx(double x, double y) const;
/** Access mixed 2nd derivative of gradient squared magnitude /** Access mixed 2nd derivative of gradient squared magnitude
at real-valued coordinate <tt>(x, y)</tt>. at real-valued coordinate <tt>(x, y)</tt>.
*/ */
value_type g2xy(double x, double y) const; SquaredNormType g2xy(double x, double y) const;
/** Access 2nd derivative in y-direction of gradient squared magnit ude /** Access 2nd derivative in y-direction of gradient squared magnit ude
at real-valued coordinate <tt>(x, y)</tt>. at real-valued coordinate <tt>(x, y)</tt>.
*/ */
value_type g2yy(double x, double y) const; SquaredNormType g2yy(double x, double y) const;
/** Access gradient squared magnitude at real-valued coordinate <tt >d</tt>. /** Access gradient squared magnitude at real-valued coordinate <tt >d</tt>.
*/ */
value_type g2(difference_type const & d) const SquaredNormType g2(difference_type const & d) const
{ return g2(d[0], d[1]); } { return g2(d[0], d[1]); }
/** Access 1st derivative in x-direction of gradient squared magnit ude /** Access 1st derivative in x-direction of gradient squared magnit ude
at real-valued coordinate <tt>d</tt>. at real-valued coordinate <tt>d</tt>.
*/ */
value_type g2x(difference_type const & d) const SquaredNormType g2x(difference_type const & d) const
{ return g2x(d[0], d[1]); } { return g2x(d[0], d[1]); }
/** Access 1st derivative in y-direction of gradient squared magnit ude /** Access 1st derivative in y-direction of gradient squared magnit ude
at real-valued coordinate <tt>d</tt>. at real-valued coordinate <tt>d</tt>.
*/ */
value_type g2y(difference_type const & d) const SquaredNormType g2y(difference_type const & d) const
{ return g2y(d[0], d[1]); } { return g2y(d[0], d[1]); }
/** Access 2nd derivative in x-direction of gradient squared magnit ude /** Access 2nd derivative in x-direction of gradient squared magnit ude
at real-valued coordinate <tt>d</tt>. at real-valued coordinate <tt>d</tt>.
*/ */
value_type g2xx(difference_type const & d) const SquaredNormType g2xx(difference_type const & d) const
{ return g2xx(d[0], d[1]); } { return g2xx(d[0], d[1]); }
/** Access mixed 2nd derivative of gradient squared magnitude /** Access mixed 2nd derivative of gradient squared magnitude
at real-valued coordinate <tt>d</tt>. at real-valued coordinate <tt>d</tt>.
*/ */
value_type g2xy(difference_type const & d) const SquaredNormType g2xy(difference_type const & d) const
{ return g2xy(d[0], d[1]); } { return g2xy(d[0], d[1]); }
/** Access 2nd derivative in y-direction of gradient squared magnit ude /** Access 2nd derivative in y-direction of gradient squared magnit ude
at real-valued coordinate <tt>d</tt>. at real-valued coordinate <tt>d</tt>.
*/ */
value_type g2yy(difference_type const & d) const SquaredNormType g2yy(difference_type const & d) const
{ return g2yy(d[0], d[1]); } { return g2yy(d[0], d[1]); }
/** The width of the image. /** The width of the image.
<tt>0 <= x <= width()-1</tt> is required for all access functio ns. <tt>0 <= x <= width()-1</tt> is required for all access functio ns.
*/ */
unsigned int width() const unsigned int width() const
{ return w_; } { return w_; }
/** The height of the image. /** The height of the image.
<tt>0 <= y <= height()-1</tt> is required for all access functi ons. <tt>0 <= y <= height()-1</tt> is required for all access functi ons.
skipping to change at line 405 skipping to change at line 409
{ return TinyVector<unsigned int, 2>(w_, h_); } { return TinyVector<unsigned int, 2>(w_, h_); }
/** The internal image holding the spline coefficients. /** The internal image holding the spline coefficients.
*/ */
InternalImage const & image() const InternalImage const & image() const
{ {
return image_; return image_;
} }
/** Get the array of polynomial coefficients for the facet containi ng /** Get the array of polynomial coefficients for the facet containi ng
the point <tt>(x, y)</tt>. The array <tt>res</tt> will be resiz ed to the point <tt>(x, y)</tt>. The array <tt>res</tt> must have
dimension <tt>(ORDER+1)x(ORDER+1)</tt>. From these coefficients , the dimension <tt>(ORDER+1)x(ORDER+1)</tt>. From these coefficients , the
value of the interpolated function can be calculated by the fol lowing value of the interpolated function can be calculated by the fol lowing
algorithm algorithm
\code \code
SplineImageView<ORDER, float> view(...); SplineImageView<ORDER, float> view(...);
double x = ..., y = ...; double x = ..., y = ...;
double dx, dy; double dx, dy;
// calculate the local facet coordinates of x and y // calculate the local facet coordinates of x and y
skipping to change at line 664 skipping to change at line 668
ky_[j]*detail::SplineImageViewUnrollLoop2<ORDER, RealPromote>::ex ec(kx_, image_.rowBegin(iy_[j]), ix_)); ky_[j]*detail::SplineImageViewUnrollLoop2<ORDER, RealPromote>::ex ec(kx_, image_.rowBegin(iy_[j]), ix_));
} }
return detail::RequiresExplicitCast<VALUETYPE>::cast(sum); return detail::RequiresExplicitCast<VALUETYPE>::cast(sum);
} }
template <int ORDER, class VALUETYPE> template <int ORDER, class VALUETYPE>
template <class Array> template <class Array>
void void
SplineImageView<ORDER, VALUETYPE>::coefficientArray(double x, double y, Arr ay & res) const SplineImageView<ORDER, VALUETYPE>::coefficientArray(double x, double y, Arr ay & res) const
{ {
typedef typename Array::value_type ResType;
typename Spline::WeightMatrix & weights = Spline::weights(); typename Spline::WeightMatrix & weights = Spline::weights();
double tmp[ksize_][ksize_]; ResType tmp[ksize_][ksize_];
calculateIndices(x, y); calculateIndices(x, y);
for(int j=0; j<ksize_; ++j) for(int j=0; j<ksize_; ++j)
{ {
for(int i=0; i<ksize_; ++i) for(int i=0; i<ksize_; ++i)
{ {
tmp[i][j] = 0.0; tmp[i][j] = ResType();
for(int k=0; k<ksize_; ++k) for(int k=0; k<ksize_; ++k)
{ {
tmp[i][j] += weights[i][k]*image_(ix_[k], iy_[j]); tmp[i][j] += weights[i][k]*image_(ix_[k], iy_[j]);
} }
} }
} }
res.resize(ksize_, ksize_);
for(int j=0; j<ksize_; ++j) for(int j=0; j<ksize_; ++j)
{ {
for(int i=0; i<ksize_; ++i) for(int i=0; i<ksize_; ++i)
{ {
res(i,j) = 0.0; res(i,j) = ResType();
for(int k=0; k<ksize_; ++k) for(int k=0; k<ksize_; ++k)
{ {
res(i,j) += weights[j][k]*tmp[i][k]; res(i,j) += weights[j][k]*tmp[i][k];
} }
} }
} }
} }
template <int ORDER, class VALUETYPE> template <int ORDER, class VALUETYPE>
VALUETYPE SplineImageView<ORDER, VALUETYPE>::operator()(double x, double y) const VALUETYPE SplineImageView<ORDER, VALUETYPE>::operator()(double x, double y) const
skipping to change at line 713 skipping to change at line 717
VALUETYPE SplineImageView<ORDER, VALUETYPE>::operator()(double x, double y, VALUETYPE SplineImageView<ORDER, VALUETYPE>::operator()(double x, double y,
unsigned int dx, unsigned int dy) const unsigned int dx, unsigned int dy) const
{ {
calculateIndices(x, y); calculateIndices(x, y);
derivCoefficients(u_, dx, kx_); derivCoefficients(u_, dx, kx_);
derivCoefficients(v_, dy, ky_); derivCoefficients(v_, dy, ky_);
return convolve(); return convolve();
} }
template <int ORDER, class VALUETYPE> template <int ORDER, class VALUETYPE>
VALUETYPE SplineImageView<ORDER, VALUETYPE>::g2(double x, double y) const typename SplineImageView<ORDER, VALUETYPE>::SquaredNormType
SplineImageView<ORDER, VALUETYPE>::g2(double x, double y) const
{ {
return sq(dx(x,y)) + sq(dy(x,y)); return squaredNorm(dx(x,y)) + squaredNorm(dy(x,y));
} }
template <int ORDER, class VALUETYPE> template <int ORDER, class VALUETYPE>
VALUETYPE SplineImageView<ORDER, VALUETYPE>::g2x(double x, double y) const typename SplineImageView<ORDER, VALUETYPE>::SquaredNormType
SplineImageView<ORDER, VALUETYPE>::g2x(double x, double y) const
{ {
return VALUETYPE(2.0)*(dx(x,y) * dxx(x,y) + dy(x,y) * dxy(x,y)); return SquaredNormType(2.0)*(dot(dx(x,y), dxx(x,y)) + dot(dy(x,y), dxy( x,y)));
} }
template <int ORDER, class VALUETYPE> template <int ORDER, class VALUETYPE>
VALUETYPE SplineImageView<ORDER, VALUETYPE>::g2y(double x, double y) const typename SplineImageView<ORDER, VALUETYPE>::SquaredNormType
SplineImageView<ORDER, VALUETYPE>::g2y(double x, double y) const
{ {
return VALUETYPE(2.0)*(dx(x,y) * dxy(x,y) + dy(x,y) * dyy(x,y)); return SquaredNormType(2.0)*(dot(dx(x,y), dxy(x,y)) + dot(dy(x,y), dyy( x,y)));
} }
template <int ORDER, class VALUETYPE> template <int ORDER, class VALUETYPE>
VALUETYPE SplineImageView<ORDER, VALUETYPE>::g2xx(double x, double y) const typename SplineImageView<ORDER, VALUETYPE>::SquaredNormType
SplineImageView<ORDER, VALUETYPE>::g2xx(double x, double y) const
{ {
return VALUETYPE(2.0)*(sq(dxx(x,y)) + dx(x,y) * dx3(x,y) + sq(dxy(x,y)) return SquaredNormType(2.0)*(squaredNorm(dxx(x,y)) + dot(dx(x,y), dx3(x
+ dy(x,y) * dxxy(x,y)); ,y)) +
squaredNorm(dxy(x,y)) + dot(dy(x,y), dxxy(
x,y)));
} }
template <int ORDER, class VALUETYPE> template <int ORDER, class VALUETYPE>
VALUETYPE SplineImageView<ORDER, VALUETYPE>::g2yy(double x, double y) const typename SplineImageView<ORDER, VALUETYPE>::SquaredNormType
SplineImageView<ORDER, VALUETYPE>::g2yy(double x, double y) const
{ {
return VALUETYPE(2.0)*(sq(dxy(x,y)) + dx(x,y) * dxyy(x,y) + sq(dyy(x,y) return SquaredNormType(2.0)*(squaredNorm(dxy(x,y)) + dot(dx(x,y), dxyy(
) + dy(x,y) * dy3(x,y)); x,y)) +
squaredNorm(dyy(x,y)) + dot(dy(x,y), dy3(x
,y)));
} }
template <int ORDER, class VALUETYPE> template <int ORDER, class VALUETYPE>
VALUETYPE SplineImageView<ORDER, VALUETYPE>::g2xy(double x, double y) const typename SplineImageView<ORDER, VALUETYPE>::SquaredNormType
SplineImageView<ORDER, VALUETYPE>::g2xy(double x, double y) const
{ {
return VALUETYPE(2.0)*(dx(x,y) * dxxy(x,y) + dy(x,y) * dxyy(x,y) + dxy( return SquaredNormType(2.0)*(dot(dx(x,y), dxxy(x,y)) + dot(dy(x,y), dxy
x,y) * (dxx(x,y) + dyy(x,y))); y(x,y)) +
dot(dxy(x,y), dxx(x,y) + dyy(x,y)));
} }
/********************************************************/ /********************************************************/
/* */ /* */
/* SplineImageView0 */ /* SplineImageView0 */
/* */ /* */
/********************************************************/ /********************************************************/
template <class VALUETYPE, class INTERNAL_INDEXER> template <class VALUETYPE, class INTERNAL_INDEXER>
class SplineImageView0Base class SplineImageView0Base
{ {
typedef typename INTERNAL_INDEXER::value_type InternalValue; typedef typename INTERNAL_INDEXER::value_type InternalValue;
public: public:
typedef VALUETYPE value_type; typedef VALUETYPE value_type;
typedef typename NormTraits<VALUETYPE>::SquaredNormType SquaredNormType ;
typedef Size2D size_type; typedef Size2D size_type;
typedef TinyVector<double, 2> difference_type; typedef TinyVector<double, 2> difference_type;
enum StaticOrder { order = 0 }; enum StaticOrder { order = 0 };
public: public:
SplineImageView0Base(unsigned int w, unsigned int h) SplineImageView0Base(unsigned int w, unsigned int h)
: w_(w), h_(h) : w_(w), h_(h)
{} {}
skipping to change at line 909 skipping to change at line 923
value_type dy3(difference_type const & d) const value_type dy3(difference_type const & d) const
{ return NumericTraits<VALUETYPE>::zero(); } { return NumericTraits<VALUETYPE>::zero(); }
value_type dxxy(difference_type const & d) const value_type dxxy(difference_type const & d) const
{ return NumericTraits<VALUETYPE>::zero(); } { return NumericTraits<VALUETYPE>::zero(); }
value_type dxyy(difference_type const & d) const value_type dxyy(difference_type const & d) const
{ return NumericTraits<VALUETYPE>::zero(); } { return NumericTraits<VALUETYPE>::zero(); }
value_type g2(double x, double y) const SquaredNormType g2(double x, double y) const
{ return NumericTraits<VALUETYPE>::zero(); } { return NumericTraits<SquaredNormType>::zero(); }
value_type g2x(double x, double y) const SquaredNormType g2x(double x, double y) const
{ return NumericTraits<VALUETYPE>::zero(); } { return NumericTraits<SquaredNormType>::zero(); }
value_type g2y(double x, double y) const SquaredNormType g2y(double x, double y) const
{ return NumericTraits<VALUETYPE>::zero(); } { return NumericTraits<SquaredNormType>::zero(); }
value_type g2xx(double x, double y) const SquaredNormType g2xx(double x, double y) const
{ return NumericTraits<VALUETYPE>::zero(); } { return NumericTraits<SquaredNormType>::zero(); }
value_type g2xy(double x, double y) const SquaredNormType g2xy(double x, double y) const
{ return NumericTraits<VALUETYPE>::zero(); } { return NumericTraits<SquaredNormType>::zero(); }
value_type g2yy(double x, double y) const SquaredNormType g2yy(double x, double y) const
{ return NumericTraits<VALUETYPE>::zero(); } { return NumericTraits<SquaredNormType>::zero(); }
value_type g2(difference_type const & d) const SquaredNormType g2(difference_type const & d) const
{ return NumericTraits<VALUETYPE>::zero(); } { return NumericTraits<SquaredNormType>::zero(); }
value_type g2x(difference_type const & d) const SquaredNormType g2x(difference_type const & d) const
{ return NumericTraits<VALUETYPE>::zero(); } { return NumericTraits<SquaredNormType>::zero(); }
value_type g2y(difference_type const & d) const SquaredNormType g2y(difference_type const & d) const
{ return NumericTraits<VALUETYPE>::zero(); } { return NumericTraits<SquaredNormType>::zero(); }
value_type g2xx(difference_type const & d) const SquaredNormType g2xx(difference_type const & d) const
{ return NumericTraits<VALUETYPE>::zero(); } { return NumericTraits<SquaredNormType>::zero(); }
value_type g2xy(difference_type const & d) const SquaredNormType g2xy(difference_type const & d) const
{ return NumericTraits<VALUETYPE>::zero(); } { return NumericTraits<SquaredNormType>::zero(); }
value_type g2yy(difference_type const & d) const SquaredNormType g2yy(difference_type const & d) const
{ return NumericTraits<VALUETYPE>::zero(); } { return NumericTraits<SquaredNormType>::zero(); }
unsigned int width() const unsigned int width() const
{ return w_; } { return w_; }
unsigned int height() const unsigned int height() const
{ return h_; } { return h_; }
size_type size() const size_type size() const
{ return size_type(w_, h_); } { return size_type(w_, h_); }
TinyVector<unsigned int, 2> shape() const TinyVector<unsigned int, 2> shape() const
{ return TinyVector<unsigned int, 2>(w_, h_); } { return TinyVector<unsigned int, 2>(w_, h_); }
template <class Array> template <class Array>
void coefficientArray(double x, double y, Array & res) const void coefficientArray(double x, double y, Array & res) const
{ {
res.resize(1, 1);
res(0, 0) = operator()(x,y); res(0, 0) = operator()(x,y);
} }
bool isInsideX(double x) const bool isInsideX(double x) const
{ {
return x >= 0.0 && x <= width() - 1.0; return x >= 0.0 && x <= width() - 1.0;
} }
bool isInsideY(double y) const bool isInsideY(double y) const
{ {
skipping to change at line 1014 skipping to change at line 1027
\ref vigra::MultiArray&lt;2, ...&gt;, and \ref vigra::MultiArrayView&lt ;2, ...&gt;. \ref vigra::MultiArray&lt;2, ...&gt;, and \ref vigra::MultiArrayView&lt ;2, ...&gt;.
*/ */
template <class VALUETYPE, class INTERNAL_TRAVERSER = typename BasicImage<V ALUETYPE>::const_traverser> template <class VALUETYPE, class INTERNAL_TRAVERSER = typename BasicImage<V ALUETYPE>::const_traverser>
class SplineImageView0 class SplineImageView0
: public SplineImageView0Base<VALUETYPE, INTERNAL_TRAVERSER> : public SplineImageView0Base<VALUETYPE, INTERNAL_TRAVERSER>
{ {
typedef SplineImageView0Base<VALUETYPE, INTERNAL_TRAVERSER> Base; typedef SplineImageView0Base<VALUETYPE, INTERNAL_TRAVERSER> Base;
public: public:
typedef typename Base::value_type value_type; typedef typename Base::value_type value_type;
typedef typename Base::SquaredNormType SquaredNormType;
typedef typename Base::size_type size_type; typedef typename Base::size_type size_type;
typedef typename Base::difference_type difference_type; typedef typename Base::difference_type difference_type;
enum StaticOrder { order = Base::order }; enum StaticOrder { order = Base::order };
typedef BasicImage<VALUETYPE> InternalImage; typedef BasicImage<VALUETYPE> InternalImage;
protected: protected:
typedef typename IteratorTraits<INTERNAL_TRAVERSER>::mutable_iterator I nternalTraverser; typedef typename IteratorTraits<INTERNAL_TRAVERSER>::mutable_iterator I nternalTraverser;
typedef typename IteratorTraits<InternalTraverser>::DefaultAccessor Int ernalAccessor; typedef typename IteratorTraits<InternalTraverser>::DefaultAccessor Int ernalAccessor;
typedef typename IteratorTraits<INTERNAL_TRAVERSER>::const_iterator Int ernalConstTraverser; typedef typename IteratorTraits<INTERNAL_TRAVERSER>::const_iterator Int ernalConstTraverser;
typedef typename IteratorTraits<InternalConstTraverser>::DefaultAccesso r InternalConstAccessor; typedef typename IteratorTraits<InternalConstTraverser>::DefaultAccesso r InternalConstAccessor;
skipping to change at line 1089 skipping to change at line 1103
InternalImage image_; InternalImage image_;
}; };
template <class VALUETYPE, class StridedOrUnstrided> template <class VALUETYPE, class StridedOrUnstrided>
class SplineImageView0<VALUETYPE, MultiArrayView<2, VALUETYPE, StridedOrUns trided> > class SplineImageView0<VALUETYPE, MultiArrayView<2, VALUETYPE, StridedOrUns trided> >
: public SplineImageView0Base<VALUETYPE, MultiArrayView<2, VALUETYPE, Strid edOrUnstrided> > : public SplineImageView0Base<VALUETYPE, MultiArrayView<2, VALUETYPE, Strid edOrUnstrided> >
{ {
typedef SplineImageView0Base<VALUETYPE, MultiArrayView<2, VALUETYPE, St ridedOrUnstrided> > Base; typedef SplineImageView0Base<VALUETYPE, MultiArrayView<2, VALUETYPE, St ridedOrUnstrided> > Base;
public: public:
typedef typename Base::value_type value_type; typedef typename Base::value_type value_type;
typedef typename Base::SquaredNormType SquaredNormType;
typedef typename Base::size_type size_type; typedef typename Base::size_type size_type;
typedef typename Base::difference_type difference_type; typedef typename Base::difference_type difference_type;
enum StaticOrder { order = Base::order }; enum StaticOrder { order = Base::order };
typedef BasicImage<VALUETYPE> InternalImage; typedef BasicImage<VALUETYPE> InternalImage;
protected: protected:
typedef MultiArrayView<2, VALUETYPE, StridedOrUnstrided> InternalIndexe r; typedef MultiArrayView<2, VALUETYPE, StridedOrUnstrided> InternalIndexe r;
public: public:
skipping to change at line 1152 skipping to change at line 1167
InternalImage image_; InternalImage image_;
}; };
template <class VALUETYPE> template <class VALUETYPE>
class SplineImageView<0, VALUETYPE> class SplineImageView<0, VALUETYPE>
: public SplineImageView0<VALUETYPE> : public SplineImageView0<VALUETYPE>
{ {
typedef SplineImageView0<VALUETYPE> Base; typedef SplineImageView0<VALUETYPE> Base;
public: public:
typedef typename Base::value_type value_type; typedef typename Base::value_type value_type;
typedef typename Base::SquaredNormType SquaredNormType;
typedef typename Base::size_type size_type; typedef typename Base::size_type size_type;
typedef typename Base::difference_type difference_type; typedef typename Base::difference_type difference_type;
enum StaticOrder { order = Base::order }; enum StaticOrder { order = Base::order };
typedef typename Base::InternalImage InternalImage; typedef typename Base::InternalImage InternalImage;
protected: protected:
typedef typename Base::InternalTraverser InternalTraverser; typedef typename Base::InternalTraverser InternalTraverser;
typedef typename Base::InternalAccessor InternalAccessor; typedef typename Base::InternalAccessor InternalAccessor;
typedef typename Base::InternalConstTraverser InternalConstTraverser; typedef typename Base::InternalConstTraverser InternalConstTraverser;
typedef typename Base::InternalConstAccessor InternalConstAccessor; typedef typename Base::InternalConstAccessor InternalConstAccessor;
skipping to change at line 1211 skipping to change at line 1227
/* SplineImageView1 */ /* SplineImageView1 */
/* */ /* */
/********************************************************/ /********************************************************/
template <class VALUETYPE, class INTERNAL_INDEXER> template <class VALUETYPE, class INTERNAL_INDEXER>
class SplineImageView1Base class SplineImageView1Base
{ {
typedef typename INTERNAL_INDEXER::value_type InternalValue; typedef typename INTERNAL_INDEXER::value_type InternalValue;
public: public:
typedef VALUETYPE value_type; typedef VALUETYPE value_type;
typedef Size2D size_type; typedef Size2D size_type;
typedef typename NormTraits<VALUETYPE>::SquaredNormType SquaredNormType ;
typedef TinyVector<double, 2> difference_type; typedef TinyVector<double, 2> difference_type;
enum StaticOrder { order = 1 }; enum StaticOrder { order = 1 };
public: public:
SplineImageView1Base(unsigned int w, unsigned int h) SplineImageView1Base(unsigned int w, unsigned int h)
: w_(w), h_(h) : w_(w), h_(h)
{} {}
SplineImageView1Base(int w, int h, INTERNAL_INDEXER i) SplineImageView1Base(int w, int h, INTERNAL_INDEXER i)
skipping to change at line 1478 skipping to change at line 1495
value_type dy3(difference_type const & d) const value_type dy3(difference_type const & d) const
{ return NumericTraits<VALUETYPE>::zero(); } { return NumericTraits<VALUETYPE>::zero(); }
value_type dxxy(difference_type const & d) const value_type dxxy(difference_type const & d) const
{ return NumericTraits<VALUETYPE>::zero(); } { return NumericTraits<VALUETYPE>::zero(); }
value_type dxyy(difference_type const & d) const value_type dxyy(difference_type const & d) const
{ return NumericTraits<VALUETYPE>::zero(); } { return NumericTraits<VALUETYPE>::zero(); }
value_type g2(double x, double y) const SquaredNormType g2(double x, double y) const
{ return sq(dx(x,y)) + sq(dy(x,y)); } { return squaredNorm(dx(x,y)) + squaredNorm(dy(x,y)); }
value_type g2x(double x, double y) const SquaredNormType g2x(double x, double y) const
{ return NumericTraits<VALUETYPE>::zero(); } { return NumericTraits<SquaredNormType>::zero(); }
value_type g2y(double x, double y) const SquaredNormType g2y(double x, double y) const
{ return NumericTraits<VALUETYPE>::zero(); } { return NumericTraits<SquaredNormType>::zero(); }
value_type g2xx(double x, double y) const SquaredNormType g2xx(double x, double y) const
{ return NumericTraits<VALUETYPE>::zero(); } { return NumericTraits<SquaredNormType>::zero(); }
value_type g2xy(double x, double y) const SquaredNormType g2xy(double x, double y) const
{ return NumericTraits<VALUETYPE>::zero(); } { return NumericTraits<SquaredNormType>::zero(); }
value_type g2yy(double x, double y) const SquaredNormType g2yy(double x, double y) const
{ return NumericTraits<VALUETYPE>::zero(); } { return NumericTraits<SquaredNormType>::zero(); }
value_type g2(difference_type const & d) const SquaredNormType g2(difference_type const & d) const
{ return g2(d[0], d[1]); } { return g2(d[0], d[1]); }
value_type g2x(difference_type const & d) const SquaredNormType g2x(difference_type const & d) const
{ return NumericTraits<VALUETYPE>::zero(); } { return NumericTraits<SquaredNormType>::zero(); }
value_type g2y(difference_type const & d) const SquaredNormType g2y(difference_type const & d) const
{ return NumericTraits<VALUETYPE>::zero(); } { return NumericTraits<SquaredNormType>::zero(); }
value_type g2xx(difference_type const & d) const SquaredNormType g2xx(difference_type const & d) const
{ return NumericTraits<VALUETYPE>::zero(); } { return NumericTraits<SquaredNormType>::zero(); }
value_type g2xy(difference_type const & d) const SquaredNormType g2xy(difference_type const & d) const
{ return NumericTraits<VALUETYPE>::zero(); } { return NumericTraits<SquaredNormType>::zero(); }
value_type g2yy(difference_type const & d) const SquaredNormType g2yy(difference_type const & d) const
{ return NumericTraits<VALUETYPE>::zero(); } { return NumericTraits<SquaredNormType>::zero(); }
unsigned int width() const unsigned int width() const
{ return w_; } { return w_; }
unsigned int height() const unsigned int height() const
{ return h_; } { return h_; }
size_type size() const size_type size() const
{ return size_type(w_, h_); } { return size_type(w_, h_); }
skipping to change at line 1571 skipping to change at line 1588
unsigned int w_, h_; unsigned int w_, h_;
INTERNAL_INDEXER internalIndexer_; INTERNAL_INDEXER internalIndexer_;
}; };
template <class VALUETYPE, class INTERNAL_INDEXER> template <class VALUETYPE, class INTERNAL_INDEXER>
template <class Array> template <class Array>
void SplineImageView1Base<VALUETYPE, INTERNAL_INDEXER>::coefficientArray(do uble x, double y, Array & res) const void SplineImageView1Base<VALUETYPE, INTERNAL_INDEXER>::coefficientArray(do uble x, double y, Array & res) const
{ {
int ix, iy, ix1, iy1; int ix, iy, ix1, iy1;
calculateIndices(x, y, ix, iy, ix1, iy1); calculateIndices(x, y, ix, iy, ix1, iy1);
res.resize(2, 2);
res(0,0) = internalIndexer_(ix,iy); res(0,0) = internalIndexer_(ix,iy);
res(1,0) = internalIndexer_(ix1,iy) - internalIndexer_(ix,iy); res(1,0) = internalIndexer_(ix1,iy) - internalIndexer_(ix,iy);
res(0,1) = internalIndexer_(ix,iy1) - internalIndexer_(ix,iy); res(0,1) = internalIndexer_(ix,iy1) - internalIndexer_(ix,iy);
res(1,1) = internalIndexer_(ix,iy) - internalIndexer_(ix1,iy) - res(1,1) = internalIndexer_(ix,iy) - internalIndexer_(ix1,iy) -
internalIndexer_(ix,iy1) + internalIndexer_(ix1,iy1); internalIndexer_(ix,iy1) + internalIndexer_(ix1,iy1);
} }
template <class VALUETYPE, class INTERNAL_INDEXER> template <class VALUETYPE, class INTERNAL_INDEXER>
void SplineImageView1Base<VALUETYPE, INTERNAL_INDEXER>::calculateIndices(do uble x, double y, int & ix, int & iy, int & ix1, int & iy1) const void SplineImageView1Base<VALUETYPE, INTERNAL_INDEXER>::calculateIndices(do uble x, double y, int & ix, int & iy, int & ix1, int & iy1) const
{ {
skipping to change at line 1648 skipping to change at line 1664
In addition, <tt>x</tt> and <tt>y</tt> can have type \ref vigra::FixedP oint instead of In addition, <tt>x</tt> and <tt>y</tt> can have type \ref vigra::FixedP oint instead of
<tt>double</tt>. <tt>double</tt>.
*/ */
template <class VALUETYPE, class INTERNAL_TRAVERSER = typename BasicImage<V ALUETYPE>::const_traverser> template <class VALUETYPE, class INTERNAL_TRAVERSER = typename BasicImage<V ALUETYPE>::const_traverser>
class SplineImageView1 class SplineImageView1
: public SplineImageView1Base<VALUETYPE, INTERNAL_TRAVERSER> : public SplineImageView1Base<VALUETYPE, INTERNAL_TRAVERSER>
{ {
typedef SplineImageView1Base<VALUETYPE, INTERNAL_TRAVERSER> Base; typedef SplineImageView1Base<VALUETYPE, INTERNAL_TRAVERSER> Base;
public: public:
typedef typename Base::value_type value_type; typedef typename Base::value_type value_type;
typedef typename Base::SquaredNormType SquaredNormType;
typedef typename Base::size_type size_type; typedef typename Base::size_type size_type;
typedef typename Base::difference_type difference_type; typedef typename Base::difference_type difference_type;
enum StaticOrder { order = Base::order }; enum StaticOrder { order = Base::order };
typedef BasicImage<VALUETYPE> InternalImage; typedef BasicImage<VALUETYPE> InternalImage;
protected: protected:
typedef typename IteratorTraits<INTERNAL_TRAVERSER>::mutable_iterator I nternalTraverser; typedef typename IteratorTraits<INTERNAL_TRAVERSER>::mutable_iterator I nternalTraverser;
typedef typename IteratorTraits<InternalTraverser>::DefaultAccessor Int ernalAccessor; typedef typename IteratorTraits<InternalTraverser>::DefaultAccessor Int ernalAccessor;
typedef typename IteratorTraits<INTERNAL_TRAVERSER>::const_iterator Int ernalConstTraverser; typedef typename IteratorTraits<INTERNAL_TRAVERSER>::const_iterator Int ernalConstTraverser;
typedef typename IteratorTraits<InternalConstTraverser>::DefaultAccesso r InternalConstAccessor; typedef typename IteratorTraits<InternalConstTraverser>::DefaultAccesso r InternalConstAccessor;
skipping to change at line 1723 skipping to change at line 1740
InternalImage image_; InternalImage image_;
}; };
template <class VALUETYPE, class StridedOrUnstrided> template <class VALUETYPE, class StridedOrUnstrided>
class SplineImageView1<VALUETYPE, MultiArrayView<2, VALUETYPE, StridedOrUns trided> > class SplineImageView1<VALUETYPE, MultiArrayView<2, VALUETYPE, StridedOrUns trided> >
: public SplineImageView1Base<VALUETYPE, MultiArrayView<2, VALUETYPE, Strid edOrUnstrided> > : public SplineImageView1Base<VALUETYPE, MultiArrayView<2, VALUETYPE, Strid edOrUnstrided> >
{ {
typedef SplineImageView1Base<VALUETYPE, MultiArrayView<2, VALUETYPE, St ridedOrUnstrided> > Base; typedef SplineImageView1Base<VALUETYPE, MultiArrayView<2, VALUETYPE, St ridedOrUnstrided> > Base;
public: public:
typedef typename Base::value_type value_type; typedef typename Base::value_type value_type;
typedef typename Base::SquaredNormType SquaredNormType;
typedef typename Base::size_type size_type; typedef typename Base::size_type size_type;
typedef typename Base::difference_type difference_type; typedef typename Base::difference_type difference_type;
enum StaticOrder { order = Base::order }; enum StaticOrder { order = Base::order };
typedef BasicImage<VALUETYPE> InternalImage; typedef BasicImage<VALUETYPE> InternalImage;
protected: protected:
typedef MultiArrayView<2, VALUETYPE, StridedOrUnstrided> InternalIndexe r; typedef MultiArrayView<2, VALUETYPE, StridedOrUnstrided> InternalIndexe r;
public: public:
skipping to change at line 1786 skipping to change at line 1804
InternalImage image_; InternalImage image_;
}; };
template <class VALUETYPE> template <class VALUETYPE>
class SplineImageView<1, VALUETYPE> class SplineImageView<1, VALUETYPE>
: public SplineImageView1<VALUETYPE> : public SplineImageView1<VALUETYPE>
{ {
typedef SplineImageView1<VALUETYPE> Base; typedef SplineImageView1<VALUETYPE> Base;
public: public:
typedef typename Base::value_type value_type; typedef typename Base::value_type value_type;
typedef typename Base::SquaredNormType SquaredNormType;
typedef typename Base::size_type size_type; typedef typename Base::size_type size_type;
typedef typename Base::difference_type difference_type; typedef typename Base::difference_type difference_type;
enum StaticOrder { order = Base::order }; enum StaticOrder { order = Base::order };
typedef typename Base::InternalImage InternalImage; typedef typename Base::InternalImage InternalImage;
protected: protected:
typedef typename Base::InternalTraverser InternalTraverser; typedef typename Base::InternalTraverser InternalTraverser;
typedef typename Base::InternalAccessor InternalAccessor; typedef typename Base::InternalAccessor InternalAccessor;
typedef typename Base::InternalConstTraverser InternalConstTraverser; typedef typename Base::InternalConstTraverser InternalConstTraverser;
typedef typename Base::InternalConstAccessor InternalConstAccessor; typedef typename Base::InternalConstAccessor InternalConstAccessor;
 End of changes. 65 change blocks. 
81 lines changed or deleted 103 lines changed or added


 stdconvolution.hxx   stdconvolution.hxx 
skipping to change at line 188 skipping to change at line 188
class KernelIterator, class KernelAccessor> class KernelIterator, class KernelAccessor>
void convolveImage(SrcIterator src_ul, SrcIterator src_lr, SrcAccessor src_ acc, void convolveImage(SrcIterator src_ul, SrcIterator src_lr, SrcAccessor src_ acc,
DestIterator dest_ul, DestAccessor dest_acc, DestIterator dest_ul, DestAccessor dest_acc,
KernelIterator ki, KernelAccessor ak, KernelIterator ki, KernelAccessor ak,
Diff2D kul, Diff2D klr, BorderTreatmentMode border) Diff2D kul, Diff2D klr, BorderTreatmentMode border)
{ {
vigra_precondition((border == BORDER_TREATMENT_CLIP || vigra_precondition((border == BORDER_TREATMENT_CLIP ||
border == BORDER_TREATMENT_AVOID || border == BORDER_TREATMENT_AVOID ||
border == BORDER_TREATMENT_REFLECT || border == BORDER_TREATMENT_REFLECT ||
border == BORDER_TREATMENT_REPEAT || border == BORDER_TREATMENT_REPEAT ||
border == BORDER_TREATMENT_WRAP), border == BORDER_TREATMENT_WRAP ||
border == BORDER_TREATMENT_ZEROPAD),
"convolveImage():\n" "convolveImage():\n"
" Border treatment must be one of follow treatments :\n" " Border treatment must be one of follow treatments :\n"
" - BORDER_TREATMENT_CLIP\n" " - BORDER_TREATMENT_CLIP\n"
" - BORDER_TREATMENT_AVOID\n" " - BORDER_TREATMENT_AVOID\n"
" - BORDER_TREATMENT_REFLECT\n" " - BORDER_TREATMENT_REFLECT\n"
" - BORDER_TREATMENT_REPEAT\n" " - BORDER_TREATMENT_REPEAT\n"
" - BORDER_TREATMENT_WRAP\n"); " - BORDER_TREATMENT_WRAP\n"
" - BORDER_TREATMENT_ZEROPAD\n");
vigra_precondition(kul.x <= 0 && kul.y <= 0, vigra_precondition(kul.x <= 0 && kul.y <= 0,
"convolveImage(): coordinates of " "convolveImage(): coordinates of "
"kernel's upper left must be <= 0."); "kernel's upper left must be <= 0.");
vigra_precondition(klr.x >= 0 && klr.y >= 0, vigra_precondition(klr.x >= 0 && klr.y >= 0,
"convolveImage(): coordinates of " "convolveImage(): coordinates of "
"kernel's lower right must be >= 0."); "kernel's lower right must be >= 0.");
// use traits to determine SumType as to prevent possible overflow // use traits to determine SumType as to prevent possible overflow
typedef typename typedef typename
skipping to change at line 223 skipping to change at line 225
int w = src_lr.x - src_ul.x; int w = src_lr.x - src_ul.x;
int h = src_lr.y - src_ul.y; int h = src_lr.y - src_ul.y;
// calculate width and height of the kernel // calculate width and height of the kernel
int kernel_width = klr.x - kul.x + 1; int kernel_width = klr.x - kul.x + 1;
int kernel_height = klr.y - kul.y + 1; int kernel_height = klr.y - kul.y + 1;
vigra_precondition(w >= std::max(klr.x, -kul.x) + 1 && h >= std::max(kl r.y, -kul.y) + 1, vigra_precondition(w >= std::max(klr.x, -kul.x) + 1 && h >= std::max(kl r.y, -kul.y) + 1,
"convolveImage(): kernel larger than image."); "convolveImage(): kernel larger than image.");
KernelSumType norm = NumericTraits<KernelSumType>::zero(); KernelSumType norm = KernelSumType();
if(border == BORDER_TREATMENT_CLIP) if(border == BORDER_TREATMENT_CLIP)
{ {
// calculate the sum of the kernel elements for renormalization // calculate the sum of the kernel elements for renormalization
KernelIterator yk = ki + klr; KernelIterator yk = ki + klr;
// determine sum within kernel (= norm) // determine sum within kernel (= norm)
for(int y = 0; y < kernel_height; ++y, --yk.y) for(int y = 0; y < kernel_height; ++y, --yk.y)
{ {
KernelIterator xk = yk; KernelIterator xk = yk;
for(int x = 0; x < kernel_width; ++x, --xk.x) for(int x = 0; x < kernel_width; ++x, --xk.x)
{ {
norm += ak(xk); norm += ak(xk);
} }
} }
vigra_precondition(norm != NumericTraits<KernelSumType>::zero(), vigra_precondition(norm != NumericTraits<KernelSumType>::zero(),
"convolveImage(): Cannot use BORDER_TREATMENT_CLIP with a DC-fr ee kernel"); "convolveImage(): Cannot use BORDER_TREATMENT_CLIP with a DC-fr ee kernel");
} }
DestIterator yd = dest_ul; DestIterator yd = dest_ul;
SrcIterator ys = src_ul; SrcIterator ys = src_ul;
SrcIterator send = src_lr;
// iterate over the interior part // iterate over the interior part
for(int y=0; y<h; ++y, ++ys.y, ++yd.y) for(int y=0; y<h; ++y, ++ys.y, ++yd.y)
{ {
// create x iterators // create x iterators
DestIterator xd(yd); DestIterator xd(yd);
SrcIterator xs(ys); SrcIterator xs(ys);
for(int x=0; x < w; ++x, ++xs.x, ++xd.x) for(int x=0; x < w; ++x, ++xs.x, ++xd.x)
{ {
skipping to change at line 349 skipping to change at line 350
diff.x = x - xk; diff.x = x - xk;
if(diff.x < 0 || diff.x >= w) if(diff.x < 0 || diff.x >= w)
continue; continue;
ksum += ak(xkernel); ksum += ak(xkernel);
sum += ak(xkernel) * src_acc(src_ul, diff); sum += ak(xkernel) * src_acc(src_ul, diff);
} }
} }
sum *= norm / ksum; sum *= norm / ksum;
} }
else if(border == BORDER_TREATMENT_ZEROPAD)
{
Diff2D diff;
for(int yk = klr.y; yk >= kul.y; --yk, --ykernel.y)
{
diff.y = y - yk;
if(diff.y < 0 || diff.y >= h)
continue;
typename KernelIterator::row_iterator xkernel = ykerne
l.rowIterator();
for(int xk = klr.x; xk >= kul.x; --xk, --xkernel)
{
diff.x = x - xk;
if(diff.x < 0 || diff.x >= w)
continue;
sum += ak(xkernel) * src_acc(src_ul, diff);
}
}
}
else if(border == BORDER_TREATMENT_AVOID) else if(border == BORDER_TREATMENT_AVOID)
{ {
continue; continue;
} }
// store convolution result in destination pixel // store convolution result in destination pixel
dest_acc.set(detail::RequiresExplicitCast<DestType>::cast(sum), xd); dest_acc.set(detail::RequiresExplicitCast<DestType>::cast(sum), xd);
} }
} }
} }
skipping to change at line 601 skipping to change at line 621
bool first = true; bool first = true;
// init the sum // init the sum
SumType sum = NumericTraits<SumType>::zero(); SumType sum = NumericTraits<SumType>::zero();
KSumType ksum = NumericTraits<KSumType>::zero(); KSumType ksum = NumericTraits<KSumType>::zero();
SrcIterator yys = xs + Diff2D(x0, y0); SrcIterator yys = xs + Diff2D(x0, y0);
MaskIterator yym = xm + Diff2D(x0, y0); MaskIterator yym = xm + Diff2D(x0, y0);
KernelIterator yk = ki - Diff2D(x0, y0); KernelIterator yk = ki - Diff2D(x0, y0);
int xx, kernel_width, kernel_height; int kernel_width, kernel_height;
kernel_width = x1 - x0 + 1; kernel_width = x1 - x0 + 1;
kernel_height = y1 - y0 + 1; kernel_height = y1 - y0 + 1;
for(yy=0; yy<kernel_height; ++yy, ++yys.y, --yk.y, ++yym.y) for(yy=0; yy<kernel_height; ++yy, ++yys.y, --yk.y, ++yym.y)
{ {
typename SrcIterator::row_iterator xxs = yys.rowIterator(); typename SrcIterator::row_iterator xxs = yys.rowIterator();
typename SrcIterator::row_iterator xxend = xxs + kernel_wid th; typename SrcIterator::row_iterator xxend = xxs + kernel_wid th;
typename MaskIterator::row_iterator xxm = yym.rowIterator() ; typename MaskIterator::row_iterator xxm = yym.rowIterator() ;
typename KernelIterator::row_iterator xk = yk.rowIterator( ); typename KernelIterator::row_iterator xk = yk.rowIterator( );
for(xx=0; xxs < xxend; ++xxs, --xk, ++xxm) for(xx=0; xxs < xxend; ++xxs, --xk, ++xxm)
 End of changes. 6 change blocks. 
5 lines changed or deleted 26 lines changed or added


 timing.hxx   timing.hxx 
skipping to change at line 142 skipping to change at line 142
inner_repetitions, and the best result of the outer_repetitions is inner_repetitions, and the best result of the outer_repetitions is
reported to std::cerr. reported to std::cerr.
\hideinitializer \hideinitializer
\def TICTOCLOOP_END \def TICTOCLOOP_END
Ends the timing loop started with the TICTOCLOOP_BEGIN macro Ends the timing loop started with the TICTOCLOOP_BEGIN macro
and outputs the result. and outputs the result.
\hideinitializer \hideinitializer
*/ */
#ifdef WIN32 #ifdef _WIN32
#include "windows.h" #include "windows.h"
namespace { namespace {
inline double queryTimerUnit() inline double queryTimerUnit()
{ {
LARGE_INTEGER frequency; LARGE_INTEGER frequency;
QueryPerformanceFrequency(&frequency); QueryPerformanceFrequency(&frequency);
return 1000.0 / frequency.QuadPart; return 1000.0 / frequency.QuadPart;
skipping to change at line 173 skipping to change at line 173
inline std::string tic_toc_diff_string(LARGE_INTEGER const & tic) inline std::string tic_toc_diff_string(LARGE_INTEGER const & tic)
{ {
double diff = tic_toc_diff_num(tic); double diff = tic_toc_diff_num(tic);
std::stringstream s; std::stringstream s;
s << diff << " msec"; s << diff << " msec";
return s.str(); return s.str();
} }
inline void tic_toc_diff(LARGE_INTEGER const & tic) inline void tic_toc_diff(LARGE_INTEGER const & tic)
{ {
std::cerr << tic_toc_diff_string(tic) <<std::endl; double diff = tic_toc_diff_num(tic);
std::cerr << diff << " msec" << std::endl;
} }
inline double tic_toc_diff_num(std::vector<LARGE_INTEGER> & tic) inline double tic_toc_diff_num(std::vector<LARGE_INTEGER> & tic)
{ {
double res = tic_toc_diff_num(tic.back()); double res = tic_toc_diff_num(tic.back());
tic.pop_back(); tic.pop_back();
return res; return res;
} }
inline std::string tic_toc_diff_string(std::vector<LARGE_INTEGER> & tic ) inline std::string tic_toc_diff_string(std::vector<LARGE_INTEGER> & tic )
skipping to change at line 328 skipping to change at line 329
#define TIC gettimeofday (&tic_timer, NULL); #define TIC gettimeofday (&tic_timer, NULL);
#define TOC tic_toc_diff (tic_timer); #define TOC tic_toc_diff (tic_timer);
#define TOCN tic_toc_diff_num (tic_timer) #define TOCN tic_toc_diff_num (tic_timer)
#define TOCS tic_toc_diff_string(tic_timer) #define TOCS tic_toc_diff_string(tic_timer)
#define USE_NESTED_TICTOC std::vector<timeval> tic_timer; #define USE_NESTED_TICTOC std::vector<timeval> tic_timer;
#define TICPUSH tic_timer.push_back(timeval());\ #define TICPUSH tic_timer.push_back(timeval());\
gettimeofday(&(tic_timer.back()), NULL); gettimeofday(&(tic_timer.back()), NULL);
#endif // VIGRA_HIRES_TIMING #endif // VIGRA_HIRES_TIMING
#endif // WIN32 #endif // _WIN32
// TICTOCLOOP runs the body inner_repetitions times, and minimizes the resu lt over a number of outer_repetitions runs, // TICTOCLOOP runs the body inner_repetitions times, and minimizes the resu lt over a number of outer_repetitions runs,
// outputting the final minimal average to std::cerr // outputting the final minimal average to std::cerr
// We enclose the loop in a dummy do { ... } while(false) in order to make
this a true single statement
// (instead of just a scope).
#define TICTOCLOOP_BEGIN(inner_repetitions,outer_repetitions) \ #define TICTOCLOOP_BEGIN(inner_repetitions,outer_repetitions) \
{ \ do { \
USETICTOC \ USETICTOC \
double tictoc_best_, tictoc_inner_repetitions_=inner_repetitions; s ize_t tictoc_outer_repetitions_=outer_repetitions; \ double tictoc_best_, tictoc_inner_repetitions_=inner_repetitions; s ize_t tictoc_outer_repetitions_=outer_repetitions; \
for (size_t tictoccounter_=0; tictoccounter_<tictoc_outer_repetitio ns_; ++tictoccounter_) { \ for (size_t tictoccounter_=0; tictoccounter_<tictoc_outer_repetitio ns_; ++tictoccounter_) { \
TIC \ TIC \
for (size_t tictocinnercounter_=0; tictocinnercounter_<inner_repeti tions; ++tictocinnercounter_) { \ for (size_t tictocinnercounter_=0; tictocinnercounter_<inner_repeti tions; ++tictocinnercounter_) { \
#define TICTOCLOOP_END \ #define TICTOCLOOP_END \
} \ } \
const double tictoc_cur_ = TOCN; \ const double tictoc_cur_ = TOCN; \
if ((tictoccounter_==0) || (tictoc_cur_ < tictoc_best_)) \ if ((tictoccounter_==0) || (tictoc_cur_ < tictoc_best_)) \
tictoc_best_ = tictoc_cur_; \ tictoc_best_ = tictoc_cur_; \
} \ } \
std::cerr << tictoc_best_/tictoc_inner_repetitions_ \ std::cerr << tictoc_best_/tictoc_inner_repetitions_ \
<< " msec (best-of-" << tictoc_outer_repetitions_ << ")" << st d::endl; \ << " msec (best-of-" << tictoc_outer_repetitions_ << ")" << st d::endl; \
}\ } while(false);
#else // NDEBUG #else // NDEBUG
#define USETICTOC #define USETICTOC
#define TIC #define TIC
#define TOC #define TOC
#define TOCN 0.0 #define TOCN 0.0
#define TICS "" #define TICS ""
#define USE_NESTED_TICTOC #define USE_NESTED_TICTOC
#define TICPUSH #define TICPUSH
#define TICTOCLOOP_BEGIN { #define TICTOCLOOP_BEGIN(inner_repetitions,outer_repetitions) do {
#define TICTOCLOOP_END } #define TICTOCLOOP_END } while(false);
#endif // NDEBUG #endif // NDEBUG
#endif // VIGRA_TIMING_HXX #endif // VIGRA_TIMING_HXX
 End of changes. 7 change blocks. 
7 lines changed or deleted 11 lines changed or added


 tinyvector.hxx   tinyvector.hxx 
skipping to change at line 42 skipping to change at line 42
/* OTHER DEALINGS IN THE SOFTWARE. */ /* OTHER DEALINGS IN THE SOFTWARE. */
/* */ /* */
/************************************************************************/ /************************************************************************/
#ifndef VIGRA_TINYVECTOR_HXX #ifndef VIGRA_TINYVECTOR_HXX
#define VIGRA_TINYVECTOR_HXX #define VIGRA_TINYVECTOR_HXX
#include <cmath> // abs(double) #include <cmath> // abs(double)
#include <cstdlib> // abs(int) #include <cstdlib> // abs(int)
#include <iosfwd> // ostream #include <iosfwd> // ostream
#include <algorithm>
#include "config.hxx" #include "config.hxx"
#include "error.hxx" #include "error.hxx"
#include "metaprogramming.hxx" #include "metaprogramming.hxx"
#include "numerictraits.hxx" #include "numerictraits.hxx"
#include "memory.hxx" #include "memory.hxx"
#include "mathutil.hxx" #include "mathutil.hxx"
#include "diff2d.hxx" #include "diff2d.hxx"
#ifdef VIGRA_CHECK_BOUNDS #ifdef VIGRA_CHECK_BOUNDS
#define VIGRA_ASSERT_INSIDE(diff) \ #define VIGRA_ASSERT_INSIDE(diff) \
vigra_precondition(diff >= 0, "Index out of bounds");\ vigra_precondition(diff >= 0, "Index out of bounds");\
vigra_precondition(diff < SIZE, "Index out of bounds"); vigra_precondition(diff < SIZE, "Index out of bounds");
#else #else
#define VIGRA_ASSERT_INSIDE(diff) #define VIGRA_ASSERT_INSIDE(diff)
#endif #endif
namespace vigra { namespace vigra {
// mask cl.exe shortcomings [begin]
#if defined(_MSC_VER)
#pragma warning( push )
#pragma warning( disable : 4503 )
#endif
using VIGRA_CSTD::abs; using VIGRA_CSTD::abs;
using VIGRA_CSTD::ceil; using VIGRA_CSTD::ceil;
using VIGRA_CSTD::floor; using VIGRA_CSTD::floor;
using VIGRA_CSTD::sqrt;
template <class V1, int SIZE, class D1, class D2> template <class V1, int SIZE, class D1, class D2>
class TinyVectorBase; class TinyVectorBase;
template <class V1, int SIZE, class D1, class D2> template <class V1, int SIZE, class D1, class D2>
inline inline
typename TinyVectorBase<V1, SIZE, D1, D2>::SquaredNormType typename TinyVectorBase<V1, SIZE, D1, D2>::SquaredNormType
squaredNorm(TinyVectorBase<V1, SIZE, D1, D2> const & t); squaredNorm(TinyVectorBase<V1, SIZE, D1, D2> const & t);
namespace detail { namespace detail {
#define VIGRA_EXEC_LOOP(NAME, OPER) \ #define VIGRA_EXEC_LOOP(NAME, OPER) \
template <class T1, class T2> \ template <class T1, class T2> \
static void NAME(T1 * left, T2 const * right) \ static void NAME(T1 * left, T2 const * right) \
{ \ { \
for(int i=0; i<LEVEL; ++i) \ for(int i=0; i<LEVEL; ++i) \
(left[i]) OPER (right[i]); \ (left[i]) OPER (right[i]); \
} }
#define VIGRA_EXEC_LOOP_MINMAX(NAME, OPER) \
template <class T1, class T2> \
static void NAME(T1 * left, T2 const * right) \
{ \
for(int i=0; i<LEVEL; ++i) \
if(left[i] OPER right[i]) \
left[i] = right[i]; \
}
#define VIGRA_EXEC_LOOP_SCALAR(NAME, OPER) \ #define VIGRA_EXEC_LOOP_SCALAR(NAME, OPER) \
template <class T1, class T2> \ template <class T1, class T2> \
static void NAME(T1 * left, T2 right) \ static void NAME(T1 * left, T2 right) \
{ \ { \
for(int i=0; i<LEVEL; ++i) \ for(int i=0; i<LEVEL; ++i) \
(left[i]) = detail::RequiresExplicitCast<T1>::cast((left[i]) OP ER (right)); \ (left[i]) = detail::RequiresExplicitCast<T1>::cast((left[i]) OP ER (right)); \
} }
template <int LEVEL> template <int LEVEL>
struct ExecLoop struct ExecLoop
skipping to change at line 114 skipping to change at line 131
left[i] = right[-i]; left[i] = right[-i];
} }
template <class T1, class T2> template <class T1, class T2>
static void assignScalar(T1 * left, T2 right) static void assignScalar(T1 * left, T2 right)
{ {
for(int i=0; i<LEVEL; ++i) for(int i=0; i<LEVEL; ++i)
left[i] = detail::RequiresExplicitCast<T1>::cast(right); left[i] = detail::RequiresExplicitCast<T1>::cast(right);
} }
template <class T1, class T2>
static void power(T1 * left, T2 right)
{
for(int i=0; i<LEVEL; ++i)
left[i] = detail::RequiresExplicitCast<T1>::cast(pow(left, righ
t));
}
VIGRA_EXEC_LOOP(assign, =) VIGRA_EXEC_LOOP(assign, =)
VIGRA_EXEC_LOOP(add, +=) VIGRA_EXEC_LOOP(add, +=)
VIGRA_EXEC_LOOP(sub, -=) VIGRA_EXEC_LOOP(sub, -=)
VIGRA_EXEC_LOOP(mul, *=) VIGRA_EXEC_LOOP(mul, *=)
VIGRA_EXEC_LOOP(div, /=) VIGRA_EXEC_LOOP(div, /=)
VIGRA_EXEC_LOOP(neg, = -) VIGRA_EXEC_LOOP(neg, = -)
VIGRA_EXEC_LOOP(abs, = vigra::abs) VIGRA_EXEC_LOOP(abs, = vigra::abs)
VIGRA_EXEC_LOOP(floor, = vigra::floor) VIGRA_EXEC_LOOP(floor, = vigra::floor)
VIGRA_EXEC_LOOP(ceil, = vigra::ceil) VIGRA_EXEC_LOOP(ceil, = vigra::ceil)
VIGRA_EXEC_LOOP(sqrt, = vigra::sqrt)
VIGRA_EXEC_LOOP(fromPromote, = NumericTraits<T1>::fromPromote) VIGRA_EXEC_LOOP(fromPromote, = NumericTraits<T1>::fromPromote)
VIGRA_EXEC_LOOP(fromRealPromote, = NumericTraits<T1>::fromRealPromote) VIGRA_EXEC_LOOP(fromRealPromote, = NumericTraits<T1>::fromRealPromote)
VIGRA_EXEC_LOOP_SCALAR(mulScalar, *) VIGRA_EXEC_LOOP_SCALAR(mulScalar, *)
VIGRA_EXEC_LOOP_SCALAR(divScalar, /) VIGRA_EXEC_LOOP_SCALAR(divScalar, /)
VIGRA_EXEC_LOOP_MINMAX(min, >)
VIGRA_EXEC_LOOP_MINMAX(max, <)
template <class T>
static T const & minimum(T const * p)
{
return *std::min_element(p, p+LEVEL);
}
template <class T>
static T const & maximum(T const * p)
{
return *std::max_element(p, p+LEVEL);
}
template <class T1, class T2> template <class T1, class T2>
static bool notEqual(T1 const * left, T2 const * right) static bool notEqual(T1 const * left, T2 const * right)
{ {
for(int i=0; i<LEVEL; ++i) for(int i=0; i<LEVEL; ++i)
if(left[i] != right[i]) if(left[i] != right[i])
return true; return true;
return false; return false;
} }
template <class T1, class T2>
static bool less(T1 const * left, T2 const * right)
{
for(int i=0; i<LEVEL; ++i)
{
if(left[i] < right[i])
return true;
if(right[i] < left[i])
return false;
}
return false;
}
template <class T> template <class T>
static typename NumericTraits<T>::Promote static typename NumericTraits<T>::Promote
dot(T const * d) dot(T const * d)
{ {
typename NumericTraits<T>::Promote res(*d * *d); typename NumericTraits<T>::Promote res(*d * *d);
for(int i=1; i<LEVEL; ++i) for(int i=1; i<LEVEL; ++i)
res += d[i] * d[i]; res += d[i] * d[i];
return res; return res;
} }
skipping to change at line 169 skipping to change at line 221
squaredNorm(T const * d) squaredNorm(T const * d)
{ {
typename NormTraits<T>::SquaredNormType res = vigra::squaredNorm(* d); typename NormTraits<T>::SquaredNormType res = vigra::squaredNorm(* d);
for(int i=1; i<LEVEL; ++i) for(int i=1; i<LEVEL; ++i)
res += vigra::squaredNorm(d[i]); res += vigra::squaredNorm(d[i]);
return res; return res;
} }
}; };
template <int LEVEL> template <int LEVEL>
struct UnrollDot struct UnrollScalarResult
{ {
template <class T> template <class T>
static typename NumericTraits<T>::Promote static typename NumericTraits<T>::Promote
dot(T const * d) dot(T const * d)
{ {
return *d * *d + UnrollDot<LEVEL-1>::dot(d+1); return *d * *d + UnrollScalarResult<LEVEL-1>::dot(d+1);
} }
template <class T1, class T2> template <class T1, class T2>
static typename PromoteTraits<T1, T2>::Promote static typename PromoteTraits<T1, T2>::Promote
dot(T1 const * left, T2 const * right) dot(T1 const * left, T2 const * right)
{ {
return *left * *right + UnrollDot<LEVEL-1>::dot(left+1, right+1); return *left * *right + UnrollScalarResult<LEVEL-1>::dot(left+1, ri
ght+1);
}
template <class T>
static typename NormTraits<T>::SquaredNormType
squaredNorm(T const * d)
{
return vigra::squaredNorm(*d) + UnrollScalarResult<LEVEL-1>::square
dNorm(d+1);
}
static std::ptrdiff_t
squaredNorm(std::ptrdiff_t const * d)
{
return (*d)*(*d) + UnrollScalarResult<LEVEL-1>::squaredNorm(d+1);
}
template <class T>
static T const & minimum(T const * p)
{
T const & m = UnrollScalarResult<LEVEL - 1>::minimum(p+1);
return *p < m
? *p
: m;
}
template <class T>
static T const & maximum(T const * p)
{
T const & m = UnrollScalarResult<LEVEL - 1>::maximum(p+1);
return *p > m
? *p
: m;
} }
}; };
template <> template <>
struct UnrollDot<1> struct UnrollScalarResult<1>
{ {
template <class T> template <class T>
static typename NumericTraits<T>::Promote static typename NumericTraits<T>::Promote
dot(T const * d) dot(T const * d)
{ {
return *d * *d ; return *d * *d ;
} }
template <class T1, class T2> template <class T1, class T2>
static typename PromoteTraits<T1, T2>::Promote static typename PromoteTraits<T1, T2>::Promote
dot(T1 const * left, T2 const * right) dot(T1 const * left, T2 const * right)
{ {
return *left * *right; return *left * *right;
} }
};
template <int LEVEL>
struct UnrollSquaredNorm
{
template <class T> template <class T>
static typename NormTraits<T>::SquaredNormType static typename NormTraits<T>::SquaredNormType
squaredNorm(T const * d) squaredNorm(T const * d)
{ {
return vigra::squaredNorm(*d) + UnrollSquaredNorm<LEVEL-1>::squared Norm(d+1); return vigra::squaredNorm(*d);
} }
static std::ptrdiff_t static std::ptrdiff_t
squaredNorm(std::ptrdiff_t const * d) squaredNorm(std::ptrdiff_t const * d)
{ {
return (*d)*(*d) + UnrollSquaredNorm<LEVEL-1>::squaredNorm(d+1); return (*d)*(*d);
} }
};
template <>
struct UnrollSquaredNorm<1>
{
template <class T> template <class T>
static typename NormTraits<T>::SquaredNormType static T const & minimum(T const * p)
squaredNorm(T const * d)
{ {
return vigra::squaredNorm(*d); return *p;
} }
static std::ptrdiff_t template <class T>
squaredNorm(std::ptrdiff_t const * d) static T const & maximum(T const * p)
{ {
return (*d)*(*d); return *p;
} }
}; };
#undef VIGRA_EXEC_LOOP #undef VIGRA_EXEC_LOOP
#undef VIGRA_EXEC_LOOP_MINMAX
#undef VIGRA_EXEC_LOOP_SCALAR #undef VIGRA_EXEC_LOOP_SCALAR
#define VIGRA_UNROLL_LOOP(NAME, OPER) \ #define VIGRA_UNROLL_LOOP(NAME, OPER) \
template <class T1, class T2> \ template <class T1, class T2> \
static void NAME(T1 * left, T2 const * right) \ static void NAME(T1 * left, T2 const * right) \
{ \ { \
(*left) OPER (*right); \ (*left) OPER (*right); \
UnrollLoop<LEVEL-1>::NAME(left+1, right+1); \ UnrollLoop<LEVEL-1>::NAME(left+1, right+1); \
} }
#define VIGRA_UNROLL_LOOP_MINMAX(NAME, OPER) \
template <class T1, class T2> \
static void NAME(T1 * left, T2 const * right) \
{ \
if(*left OPER *right) \
*left = *right; \
UnrollLoop<LEVEL-1>::NAME(left+1, right+1); \
}
#define VIGRA_UNROLL_LOOP_SCALAR(NAME, OPER) \ #define VIGRA_UNROLL_LOOP_SCALAR(NAME, OPER) \
template <class T1, class T2> \ template <class T1, class T2> \
static void NAME(T1 * left, T2 right) \ static void NAME(T1 * left, T2 right) \
{ \ { \
(*left) = detail::RequiresExplicitCast<T1>::cast((*left) OPER (righ t)); \ (*left) = detail::RequiresExplicitCast<T1>::cast((*left) OPER (righ t)); \
UnrollLoop<LEVEL-1>::NAME(left+1, right); \ UnrollLoop<LEVEL-1>::NAME(left+1, right); \
} }
template <int LEVEL> template <int LEVEL>
struct UnrollLoop struct UnrollLoop
skipping to change at line 281 skipping to change at line 365
UnrollLoop<LEVEL-1>::assignCast(left+1, right+1); UnrollLoop<LEVEL-1>::assignCast(left+1, right+1);
} }
template <class T1, class T2> template <class T1, class T2>
static void assignScalar(T1 * left, T2 right) static void assignScalar(T1 * left, T2 right)
{ {
*left = detail::RequiresExplicitCast<T1>::cast(right); *left = detail::RequiresExplicitCast<T1>::cast(right);
UnrollLoop<LEVEL-1>::assignScalar(left+1, right); UnrollLoop<LEVEL-1>::assignScalar(left+1, right);
} }
template <class T1, class T2>
static void power(T1 * left, T2 right)
{
*left = detail::RequiresExplicitCast<T1>::cast(pow(*left, right));
UnrollLoop<LEVEL-1>::power(left+1, right);
}
VIGRA_UNROLL_LOOP(assign, =) VIGRA_UNROLL_LOOP(assign, =)
VIGRA_UNROLL_LOOP(add, +=) VIGRA_UNROLL_LOOP(add, +=)
VIGRA_UNROLL_LOOP(sub, -=) VIGRA_UNROLL_LOOP(sub, -=)
VIGRA_UNROLL_LOOP(mul, *=) VIGRA_UNROLL_LOOP(mul, *=)
VIGRA_UNROLL_LOOP(div, /=) VIGRA_UNROLL_LOOP(div, /=)
VIGRA_UNROLL_LOOP(neg, = -) VIGRA_UNROLL_LOOP(neg, = -)
VIGRA_UNROLL_LOOP(abs, = vigra::abs) VIGRA_UNROLL_LOOP(abs, = vigra::abs)
VIGRA_UNROLL_LOOP(floor, = vigra::floor) VIGRA_UNROLL_LOOP(floor, = vigra::floor)
VIGRA_UNROLL_LOOP(ceil, = vigra::ceil) VIGRA_UNROLL_LOOP(ceil, = vigra::ceil)
VIGRA_UNROLL_LOOP(sqrt, = vigra::sqrt)
VIGRA_UNROLL_LOOP(fromPromote, = NumericTraits<T1>::fromPromote) VIGRA_UNROLL_LOOP(fromPromote, = NumericTraits<T1>::fromPromote)
VIGRA_UNROLL_LOOP(fromRealPromote, = NumericTraits<T1>::fromRealPromote ) VIGRA_UNROLL_LOOP(fromRealPromote, = NumericTraits<T1>::fromRealPromote )
VIGRA_UNROLL_LOOP_SCALAR(mulScalar, *) VIGRA_UNROLL_LOOP_SCALAR(mulScalar, *)
VIGRA_UNROLL_LOOP_SCALAR(divScalar, /) VIGRA_UNROLL_LOOP_SCALAR(divScalar, /)
VIGRA_UNROLL_LOOP_MINMAX(min, >)
VIGRA_UNROLL_LOOP_MINMAX(max, <)
template <class T>
static T const & minimum(T const * p)
{
return UnrollScalarResult<LEVEL>::minimum(p);
}
template <class T>
static T const & maximum(T const * p)
{
return UnrollScalarResult<LEVEL>::maximum(p);
}
template <class T1, class T2> template <class T1, class T2>
static bool notEqual(T1 const * left, T2 const * right) static bool notEqual(T1 const * left, T2 const * right)
{ {
return (*left != *right) || UnrollLoop<LEVEL - 1>::notEqual(left+1, right+1); return (*left != *right) || UnrollLoop<LEVEL - 1>::notEqual(left+1, right+1);
} }
template <class T1, class T2>
static bool less(T1 const * left, T2 const * right)
{
if(*left < *right)
return true;
if(*right < *left)
return false;
return UnrollLoop<LEVEL - 1>::less(left+1, right+1);
}
template <class T> template <class T>
static typename NumericTraits<T>::Promote static typename NumericTraits<T>::Promote
dot(T const * d) dot(T const * d)
{ {
return UnrollDot<LEVEL>::dot(d); return UnrollScalarResult<LEVEL>::dot(d);
} }
template <class T1, class T2> template <class T1, class T2>
static typename PromoteTraits<T1, T2>::Promote static typename PromoteTraits<T1, T2>::Promote
dot(T1 const * left, T2 const * right) dot(T1 const * left, T2 const * right)
{ {
return UnrollDot<LEVEL>::dot(left, right); return UnrollScalarResult<LEVEL>::dot(left, right);
} }
template <class T> template <class T>
static typename NormTraits<T>::SquaredNormType static typename NormTraits<T>::SquaredNormType
squaredNorm(T const * d) squaredNorm(T const * d)
{ {
return UnrollSquaredNorm<LEVEL>::squaredNorm(d); return UnrollScalarResult<LEVEL>::squaredNorm(d);
} }
}; };
#undef VIGRA_UNROLL_LOOP #undef VIGRA_UNROLL_LOOP
#undef VIGRA_UNROLL_LOOP_MINMAX
#undef VIGRA_UNROLL_LOOP_SCALAR #undef VIGRA_UNROLL_LOOP_SCALAR
template <> template <>
struct UnrollLoop<0> struct UnrollLoop<0>
{ {
template <class T1, class T2> template <class T1, class T2>
static void reverseAssign(T1, T2) {} static void reverseAssign(T1, T2) {}
template <class T1, class T2> template <class T1, class T2>
static void assignCast(T1, T2) {} static void assignCast(T1, T2) {}
template <class T1, class T2> template <class T1, class T2>
static void assign(T1, T2) {} static void assign(T1, T2) {}
template <class T1, class T2> template <class T1, class T2>
static void assignScalar(T1, T2) {} static void assignScalar(T1, T2) {}
template <class T1, class T2> template <class T1, class T2>
static void power(T1, T2) {}
template <class T1, class T2>
static void add(T1, T2) {} static void add(T1, T2) {}
template <class T1, class T2> template <class T1, class T2>
static void sub(T1, T2) {} static void sub(T1, T2) {}
template <class T1, class T2> template <class T1, class T2>
static void mul(T1, T2) {} static void mul(T1, T2) {}
template <class T1, class T2> template <class T1, class T2>
static void mulScalar(T1, T2) {} static void mulScalar(T1, T2) {}
template <class T1, class T2> template <class T1, class T2>
static void div(T1, T2) {} static void div(T1, T2) {}
template <class T1, class T2> template <class T1, class T2>
skipping to change at line 362 skipping to change at line 482
static void fromRealPromote(T1, T2) {} static void fromRealPromote(T1, T2) {}
template <class T1, class T2> template <class T1, class T2>
static void neg(T1, T2) {} static void neg(T1, T2) {}
template <class T1, class T2> template <class T1, class T2>
static void abs(T1, T2) {} static void abs(T1, T2) {}
template <class T1, class T2> template <class T1, class T2>
static void floor(T1, T2) {} static void floor(T1, T2) {}
template <class T1, class T2> template <class T1, class T2>
static void ceil(T1, T2) {} static void ceil(T1, T2) {}
template <class T1, class T2> template <class T1, class T2>
static void sqrt(T1, T2) {}
template <class T1, class T2>
static bool notEqual(T1, T2) { return false; } static bool notEqual(T1, T2) { return false; }
template <class T1, class T2>
static bool less(T1, T2) { return false; }
template <class T1, class T2>
static void min(T1, T2) {}
template <class T1, class T2>
static void max(T1, T2) {}
template <class T>
static T minimum(T const * p)
{
return NumericTraits<T>::max();
}
template <class T>
static T maximum(T const * p)
{
return NumericTraits<T>::min();
}
}; };
template <int SIZE> template <int SIZE>
struct LoopType struct LoopType
{ {
typedef typename IfBool<(SIZE < 5), UnrollLoop<SIZE>, ExecLoop<SIZE> >: :type type; typedef typename IfBool<(SIZE <= 5), UnrollLoop<SIZE>, ExecLoop<SIZE> > ::type type;
}; };
struct DontInit {}; struct DontInit {};
inline DontInit dontInit() {return DontInit(); } inline DontInit dontInit() {return DontInit(); }
} // namespace detail } // namespace detail
template <class T, int SIZE> template <class T, int SIZE>
skipping to change at line 448 skipping to change at line 586
/** STL-compatible definition of const iterator /** STL-compatible definition of const iterator
*/ */
typedef value_type const * const_iterator; typedef value_type const * const_iterator;
/** STL-compatible definition of size_type /** STL-compatible definition of size_type
*/ */
typedef unsigned int size_type; typedef unsigned int size_type;
/** STL-compatible definition of difference_type /** STL-compatible definition of difference_type
*/ */
typedef int difference_type; typedef std::ptrdiff_t difference_type;
/** the scalar type for the outer product /** the scalar type for the outer product
*/ */
typedef double scalar_multiplier; typedef double scalar_multiplier;
/** the vector's squared norm type /** the vector's squared norm type
*/ */
typedef typename NormTraits<VALUETYPE>::SquaredNormType SquaredNormType ; typedef typename NormTraits<VALUETYPE>::SquaredNormType SquaredNormType ;
/** the vector's norm type /** the vector's norm type
skipping to change at line 550 skipping to change at line 688
SquareRootTraits<SquaredNormType>::SquareRootArgument>(square dMagnitude())); SquareRootTraits<SquaredNormType>::SquareRootArgument>(square dMagnitude()));
} }
/** Calculate squared magnitude. /** Calculate squared magnitude.
*/ */
SquaredNormType squaredMagnitude() const SquaredNormType squaredMagnitude() const
{ {
return Loop::squaredNorm(data_); return Loop::squaredNorm(data_);
} }
/** Return the minimal element.
*/
VALUETYPE const & minimum() const
{
return Loop::minimum(data_);
}
/** Return the maximal element.
*/
VALUETYPE const & maximum() const
{
return Loop::maximum(data_);
}
/** Access component by index. /** Access component by index.
*/ */
reference operator[](difference_type i) reference operator[](difference_type i)
{ {
VIGRA_ASSERT_INSIDE(i); VIGRA_ASSERT_INSIDE(i);
return data_[i]; return data_[i];
} }
/** Get component by index. /** Get component by index.
*/ */
skipping to change at line 646 skipping to change at line 798
typedef typename BaseType::iterator iterator; typedef typename BaseType::iterator iterator;
typedef typename BaseType::const_iterator const_iterator; typedef typename BaseType::const_iterator const_iterator;
typedef typename BaseType::size_type size_type; typedef typename BaseType::size_type size_type;
typedef typename BaseType::difference_type difference_type; typedef typename BaseType::difference_type difference_type;
typedef typename BaseType::scalar_multiplier scalar_multiplier; typedef typename BaseType::scalar_multiplier scalar_multiplier;
typedef typename BaseType::SquaredNormType SquaredNormType; typedef typename BaseType::SquaredNormType SquaredNormType;
typedef typename BaseType::NormType NormType; typedef typename BaseType::NormType NormType;
enum ReverseCopyTag { ReverseCopy }; enum ReverseCopyTag { ReverseCopy };
/** Construction with constant value /** Construction with constant value.
Initializes all vector elements with the given value.
*/ */
explicit TinyVector(value_type const & initial) explicit TinyVector(value_type const & initial)
: BaseType() : BaseType()
{ {
Loop::assignScalar(BaseType::begin(), initial); Loop::assignScalar(BaseType::begin(), initial);
} }
/** Construction with Diff2D (only implemented for 2D TinyVector) /** Construction with Diff2D.
Use only when <tt>SIZE == 2</tt>.
*/ */
explicit TinyVector(Diff2D const & initial) explicit TinyVector(Diff2D const & initial)
: BaseType() : BaseType()
{ {
BaseType::data_[0] = detail::RequiresExplicitCast<T>::cast(initial. x); BaseType::data_[0] = detail::RequiresExplicitCast<T>::cast(initial. x);
BaseType::data_[1] = detail::RequiresExplicitCast<T>::cast(initial. y); BaseType::data_[1] = detail::RequiresExplicitCast<T>::cast(initial. y);
} }
/** Construction with explicit values. /** Construction with explicit values.
Call only if SIZE == 2 Call only if SIZE == 2
skipping to change at line 711 skipping to change at line 867
value_type const & i3, value_type const & i4, value_type const & i3, value_type const & i4,
value_type const & i5) value_type const & i5)
: BaseType() : BaseType()
{ {
BaseType::data_[0] = i1; BaseType::data_[0] = i1;
BaseType::data_[1] = i2; BaseType::data_[1] = i2;
BaseType::data_[2] = i3; BaseType::data_[2] = i3;
BaseType::data_[3] = i4; BaseType::data_[3] = i4;
BaseType::data_[4] = i5; BaseType::data_[4] = i5;
} }
/** Default constructor (initializes all components with zero)
/** Default constructor (initializes all elements with zero).
*/ */
TinyVector() TinyVector()
: BaseType() : BaseType()
{ {
Loop::assignScalar(BaseType::data_, NumericTraits<value_type>::zero ()); Loop::assignScalar(BaseType::data_, NumericTraits<value_type>::zero ());
} }
/** Construct without initializing the vector elements.
*/
explicit TinyVector(SkipInitializationTag)
: BaseType()
{}
explicit TinyVector(detail::DontInit)
: BaseType()
{}
/** Copy constructor. /** Copy constructor.
*/ */
TinyVector(TinyVector const & r) TinyVector(TinyVector const & r)
: BaseType() : BaseType()
{ {
Loop::assign(BaseType::data_, r.data_); Loop::assign(BaseType::data_, r.data_);
} }
/** Constructor from C array. /** Constructor from C array.
*/ */
skipping to change at line 749 skipping to change at line 916
TinyVector<int, 3> v(1,2,3); TinyVector<int, 3> v(1,2,3);
TinyVector<int, 3> reverse(v.begin(), TinyVector<int, 3>::Rever seCopy); TinyVector<int, 3> reverse(v.begin(), TinyVector<int, 3>::Rever seCopy);
\endcode \endcode
*/ */
explicit TinyVector(const_pointer data, ReverseCopyTag) explicit TinyVector(const_pointer data, ReverseCopyTag)
: BaseType() : BaseType()
{ {
Loop::reverseAssign(BaseType::data_, data+SIZE-1); Loop::reverseAssign(BaseType::data_, data+SIZE-1);
} }
/** Copy with type conversion.
*/
template <class U, class DATA, class DERIVED>
TinyVector(TinyVectorBase<U, SIZE, DATA, DERIVED> const & r)
: BaseType()
{
Loop::assignCast(BaseType::data_, r.begin());
}
/** Copy assignment. /** Copy assignment.
*/ */
TinyVector & operator=(TinyVector const & r) TinyVector & operator=(TinyVector const & r)
{ {
Loop::assign(BaseType::data_, r.data_); Loop::assign(BaseType::data_, r.data_);
return *this; return *this;
} }
/** Copy assignment with type conversion.
*/
template <class U, class DATA, class DERIVED>
TinyVector & operator=(TinyVectorBase<U, SIZE, DATA, DERIVED> const & r
)
{
Loop::assignCast(BaseType::data_, r.begin());
return *this;
}
/** Assignment from Diff2D. /** Assignment from Diff2D.
Use only when <tt>SIZE == 2</tt>.
*/ */
TinyVector & operator=(Diff2D const & r) TinyVector & operator=(Diff2D const & r)
{ {
BaseType::data_[0] = detail::RequiresExplicitCast<T>::cast(r.x); BaseType::data_[0] = detail::RequiresExplicitCast<T>::cast(r.x);
BaseType::data_[1] = detail::RequiresExplicitCast<T>::cast(r.y); BaseType::data_[1] = detail::RequiresExplicitCast<T>::cast(r.y);
return *this; return *this;
} }
/** Copy with type conversion. /** Assignment from scalar. Will set all entries to the given value .
*/ */
template <class U> TinyVector & operator=(value_type const & v)
TinyVector(TinyVector<U, SIZE> const & r)
: BaseType()
{ {
Loop::assignCast(BaseType::data_, r.begin()); Loop::assignScalar(BaseType::begin(), v);
return *this;
} }
/** Copy with type conversion. /** Copy from a TinyVector with a different number of elements.
*/
template <class U, class DATA, class DERIVED>
TinyVector(TinyVectorBase<U, SIZE, DATA, DERIVED> const & r)
: BaseType()
{
Loop::assignCast(BaseType::data_, r.begin());
}
/** Copy assignment with type conversion. Only the first <tt>min(SIZE, USIZE)</tt> elements are copied.
*/ */
template <class U, class DATA, class DERIVED> template <class U, int USIZE, class DATA, class DERIVED>
TinyVector & operator=(TinyVectorBase<U, SIZE, DATA, DERIVED> const & r TinyVector & copy(TinyVectorBase<U, USIZE, DATA, DERIVED> const & r)
)
{ {
Loop::assignCast(BaseType::data_, r.begin()); static const int minSize = USIZE < SIZE
? USIZE
: SIZE;
typedef typename detail::LoopType<minSize>::type MinLoop;
MinLoop::assignCast(BaseType::data_, r.begin());
return *this; return *this;
} }
explicit TinyVector(SkipInitializationTag)
: BaseType()
{}
explicit TinyVector(detail::DontInit)
: BaseType()
{}
}; };
/** \brief Wrapper for fixed size vectors. /** \brief Wrapper for fixed size vectors.
This class wraps an array of size SIZE of the specified VALUETYPE. This class wraps an array of size SIZE of the specified VALUETYPE.
Thus, the array can be accessed with an interface similar to Thus, the array can be accessed with an interface similar to
that of std::vector (except that there are no functions that of std::vector (except that there are no functions
that change the size of a TinyVectorView). The TinyVectorView that change the size of a TinyVectorView). The TinyVectorView
does <em>not</em> assume ownership of the given memory. does <em>not</em> assume ownership of the given memory.
skipping to change at line 941 skipping to change at line 1117
/// component-wise not equal /// component-wise not equal
template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4> template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4>
inline bool inline bool
operator!=(TinyVectorBase<V1, SIZE, D1, D2> const & l, operator!=(TinyVectorBase<V1, SIZE, D1, D2> const & l,
TinyVectorBase<V2, SIZE, D3, D4> const & r) TinyVectorBase<V2, SIZE, D3, D4> const & r)
{ {
typedef typename detail::LoopType<SIZE>::type ltype; typedef typename detail::LoopType<SIZE>::type ltype;
return ltype::notEqual(l.begin(), r.begin()); return ltype::notEqual(l.begin(), r.begin());
} }
/// component-wise lexicographical comparison
template <class V1, int SIZE, class D1, class D2, class V2, class D3, class
D4>
inline bool
operator<(TinyVectorBase<V1, SIZE, D1, D2> const & l,
TinyVectorBase<V2, SIZE, D3, D4> const & r)
{
typedef typename detail::LoopType<SIZE>::type ltype;
return ltype::less(l.begin(), r.begin());
}
/********************************************************/ /********************************************************/
/* */ /* */
/* TinyVector Output */ /* TinyVector Output */
/* */ /* */
/********************************************************/ /********************************************************/
/// stream output /// stream output
template <class V1, int SIZE, class DATA, class DERIVED> template <class V1, int SIZE, class DATA, class DERIVED>
std::ostream & std::ostream &
operator<<(std::ostream & out, TinyVectorBase<V1, SIZE, DATA, DERIVED> cons t & l) operator<<(std::ostream & out, TinyVectorBase<V1, SIZE, DATA, DERIVED> cons t & l)
skipping to change at line 1027 skipping to change at line 1213
{ {
typedef TinyVector<T, SIZE> Type; typedef TinyVector<T, SIZE> Type;
typedef TinyVector<typename NumericTraits<T>::Promote, SIZE> Promote; typedef TinyVector<typename NumericTraits<T>::Promote, SIZE> Promote;
typedef TinyVector<typename NumericTraits<T>::RealPromote, SIZE> RealPr omote; typedef TinyVector<typename NumericTraits<T>::RealPromote, SIZE> RealPr omote;
typedef TinyVector<typename NumericTraits<T>::ComplexPromote, SIZE> Com plexPromote; typedef TinyVector<typename NumericTraits<T>::ComplexPromote, SIZE> Com plexPromote;
typedef T ValueType; typedef T ValueType;
typedef typename NumericTraits<T>::isIntegral isIntegral; typedef typename NumericTraits<T>::isIntegral isIntegral;
typedef VigraFalseType isScalar; typedef VigraFalseType isScalar;
typedef typename NumericTraits<T>::isSigned isSigned; typedef typename NumericTraits<T>::isSigned isSigned;
typedef VigraFalseType isOrdered; typedef VigraTrueType isOrdered;
typedef VigraFalseType isComplex; typedef VigraFalseType isComplex;
static TinyVector<T, SIZE> zero() { static TinyVector<T, SIZE> zero()
{
return TinyVector<T, SIZE>(NumericTraits<T>::zero()); return TinyVector<T, SIZE>(NumericTraits<T>::zero());
} }
static TinyVector<T, SIZE> one() { static TinyVector<T, SIZE> one()
{
return TinyVector<T, SIZE>(NumericTraits<T>::one()); return TinyVector<T, SIZE>(NumericTraits<T>::one());
} }
static TinyVector<T, SIZE> nonZero() { static TinyVector<T, SIZE> nonZero()
{
return TinyVector<T, SIZE>(NumericTraits<T>::nonZero()); return TinyVector<T, SIZE>(NumericTraits<T>::nonZero());
} }
static TinyVector<T, SIZE> min()
{
return TinyVector<T, SIZE>(NumericTraits<T>::min());
}
static TinyVector<T, SIZE> max()
{
return TinyVector<T, SIZE>(NumericTraits<T>::max());
}
template <class D1, class D2> template <class D1, class D2>
static Promote toPromote(TinyVectorBase<T, SIZE, D1, D2> const & v) static Promote toPromote(TinyVectorBase<T, SIZE, D1, D2> const & v)
{ {
return Promote(v); return Promote(v);
} }
template <class D1, class D2> template <class D1, class D2>
static RealPromote toRealPromote(TinyVectorBase<T, SIZE, D1, D2> const & v) static RealPromote toRealPromote(TinyVectorBase<T, SIZE, D1, D2> const & v)
{ {
return RealPromote(v); return RealPromote(v);
skipping to change at line 1419 skipping to change at line 1617
inline inline
TinyVector<V, SIZE> TinyVector<V, SIZE>
floor(TinyVectorBase<V, SIZE, D1, D2> const & v) floor(TinyVectorBase<V, SIZE, D1, D2> const & v)
{ {
TinyVector<V, SIZE> res(detail::dontInit()); TinyVector<V, SIZE> res(detail::dontInit());
typedef typename detail::LoopType<SIZE>::type ltype; typedef typename detail::LoopType<SIZE>::type ltype;
ltype::floor(res.begin(), v.begin()); ltype::floor(res.begin(), v.begin());
return res; return res;
} }
/** Apply sqrt() function to each vector component.
*/
template <class V, int SIZE, class D1, class D2>
inline
TinyVector<V, SIZE>
sqrt(TinyVectorBase<V, SIZE, D1, D2> const & v)
{
TinyVector<V, SIZE> res(detail::dontInit());
typedef typename detail::LoopType<SIZE>::type ltype;
ltype::sqrt(res.begin(), v.begin());
return res;
}
using std::pow;
/** Apply pow() function to each vector component.
*/
template <class V, int SIZE, class D1, class D2, class E>
inline
TinyVector<V, SIZE>
pow(TinyVectorBase<V, SIZE, D1, D2> const & v, E exponent)
{
TinyVector<V, SIZE> res(v);
typedef typename detail::LoopType<SIZE>::type ltype;
ltype::power(res.begin(), exponent);
return res;
}
/// cross product /// cross product
template <class V1, class D1, class D2, class V2, class D3, class D4> template <class V1, class D1, class D2, class V2, class D3, class D4>
inline inline
TinyVector<typename PromoteTraits<V1, V2>::Promote, 3> TinyVector<typename PromoteTraits<V1, V2>::Promote, 3>
cross(TinyVectorBase<V1, 3, D1, D2> const & r1, cross(TinyVectorBase<V1, 3, D1, D2> const & r1,
TinyVectorBase<V2, 3, D3, D4> const & r2) TinyVectorBase<V2, 3, D3, D4> const & r2)
{ {
typedef TinyVector<typename PromoteTraits<V1, V2>::Promote, 3> typedef TinyVector<typename PromoteTraits<V1, V2>::Promote, 3>
Res; Res;
return Res(r1[1]*r2[2] - r1[2]*r2[1], return Res(r1[1]*r2[2] - r1[2]*r2[1],
skipping to change at line 1480 skipping to change at line 1706
inline inline
typename NumericTraits<V>::Promote typename NumericTraits<V>::Promote
prod(TinyVectorBase<V, SIZE, D1, D2> const & l) prod(TinyVectorBase<V, SIZE, D1, D2> const & l)
{ {
typename NumericTraits<V>::Promote res = l[0]; typename NumericTraits<V>::Promote res = l[0];
for(int k=1; k<SIZE; ++k) for(int k=1; k<SIZE; ++k)
res *= l[k]; res *= l[k];
return res; return res;
} }
/// cumulative sum of the vector's elements /// cumulative product of the vector's elements
template <class V, int SIZE, class D1, class D2> template <class V, int SIZE, class D1, class D2>
inline inline
TinyVector<typename NumericTraits<V>::Promote, SIZE> TinyVector<typename NumericTraits<V>::Promote, SIZE>
cumprod(TinyVectorBase<V, SIZE, D1, D2> const & l) cumprod(TinyVectorBase<V, SIZE, D1, D2> const & l)
{ {
TinyVector<typename NumericTraits<V>::Promote, SIZE> res(l); TinyVector<typename NumericTraits<V>::Promote, SIZE> res(l);
for(int k=1; k<SIZE; ++k) for(int k=1; k<SIZE; ++k)
res[k] *= res[k-1]; res[k] *= res[k-1];
return res; return res;
} }
using std::min;
/// element-wise minimum /// element-wise minimum
template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4> template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4>
inline inline
TinyVector<typename PromoteTraits<V1, V2>::Promote, SIZE> TinyVector<typename PromoteTraits<V1, V2>::Promote, SIZE>
min(TinyVectorBase<V1, SIZE, D1, D2> const & l, min(TinyVectorBase<V1, SIZE, D1, D2> const & l,
TinyVectorBase<V2, SIZE, D3, D4> const & r) TinyVectorBase<V2, SIZE, D3, D4> const & r)
{ {
typedef typename detail::LoopType<SIZE>::type ltype;
TinyVector<typename PromoteTraits<V1, V2>::Promote, SIZE> res(l); TinyVector<typename PromoteTraits<V1, V2>::Promote, SIZE> res(l);
for(int k=0; k<SIZE; ++k) ltype::min(res.begin(), r.begin());
if(r[k] < res[k]) return res;
res[k] = r[k]; }
// we also have to overload min for like-typed argument to prevent match of
std::min()
template <class V1, int SIZE, class D1, class D2>
inline
TinyVector<V1, SIZE>
min(TinyVectorBase<V1, SIZE, D1, D2> const & l,
TinyVectorBase<V1, SIZE, D1, D2> const & r)
{
typedef typename detail::LoopType<SIZE>::type ltype;
TinyVector<V1, SIZE> res(l);
ltype::min(res.begin(), r.begin());
return res;
}
template <class V1, int SIZE>
inline
TinyVector<V1, SIZE>
min(TinyVector<V1, SIZE> const & l,
TinyVector<V1, SIZE> const & r)
{
typedef typename detail::LoopType<SIZE>::type ltype;
TinyVector<V1, SIZE> res(l);
ltype::min(res.begin(), r.begin());
return res; return res;
} }
/// minimum element
template <class V, int SIZE, class D1, class D2>
inline
V const &
min(TinyVectorBase<V, SIZE, D1, D2> const & l)
{
return l.minimum();
}
using std::max;
/// element-wise maximum /// element-wise maximum
template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4> template <class V1, int SIZE, class D1, class D2, class V2, class D3, class D4>
inline inline
TinyVector<typename PromoteTraits<V1, V2>::Promote, SIZE> TinyVector<typename PromoteTraits<V1, V2>::Promote, SIZE>
max(TinyVectorBase<V1, SIZE, D1, D2> const & l, max(TinyVectorBase<V1, SIZE, D1, D2> const & l,
TinyVectorBase<V2, SIZE, D3, D4> const & r) TinyVectorBase<V2, SIZE, D3, D4> const & r)
{ {
typedef typename detail::LoopType<SIZE>::type ltype;
TinyVector<typename PromoteTraits<V1, V2>::Promote, SIZE> res(l); TinyVector<typename PromoteTraits<V1, V2>::Promote, SIZE> res(l);
for(int k=0; k<SIZE; ++k) ltype::max(res.begin(), r.begin());
if(res[k] < r[k]) return res;
res[k] = r[k]; }
// we also have to overload max for like-typed argument to prevent match of
std::max()
template <class V1, int SIZE, class D1, class D2>
inline
TinyVector<V1, SIZE>
max(TinyVectorBase<V1, SIZE, D1, D2> const & l,
TinyVectorBase<V1, SIZE, D1, D2> const & r)
{
typedef typename detail::LoopType<SIZE>::type ltype;
TinyVector<V1, SIZE> res(l);
ltype::max(res.begin(), r.begin());
return res;
}
template <class V1, int SIZE>
inline
TinyVector<V1, SIZE>
max(TinyVector<V1, SIZE> const & l,
TinyVector<V1, SIZE> const & r)
{
typedef typename detail::LoopType<SIZE>::type ltype;
TinyVector<V1, SIZE> res(l);
ltype::max(res.begin(), r.begin());
return res; return res;
} }
/// maximum element
template <class V, int SIZE, class D1, class D2>
inline
V const &
max(TinyVectorBase<V, SIZE, D1, D2> const & l)
{
return l.maximum();
}
/// squared norm /// squared norm
template <class V1, int SIZE, class D1, class D2> template <class V1, int SIZE, class D1, class D2>
inline inline
typename TinyVectorBase<V1, SIZE, D1, D2>::SquaredNormType typename TinyVectorBase<V1, SIZE, D1, D2>::SquaredNormType
squaredNorm(TinyVectorBase<V1, SIZE, D1, D2> const & t) squaredNorm(TinyVectorBase<V1, SIZE, D1, D2> const & t)
{ {
return t.squaredMagnitude(); return t.squaredMagnitude();
} }
/// squared norm /// squared norm
template <class V, int SIZE> template <class V, int SIZE>
inline inline
typename TinyVector<V, SIZE>::SquaredNormType typename TinyVector<V, SIZE>::SquaredNormType
squaredNorm(TinyVector<V, SIZE> const & t) squaredNorm(TinyVector<V, SIZE> const & t)
{ {
return t.squaredMagnitude(); return t.squaredMagnitude();
} }
//@} //@}
// mask cl.exe shortcomings [end]
#if defined(_MSC_VER)
#pragma warning( pop )
#endif
} // namespace vigra } // namespace vigra
#undef VIGRA_ASSERT_INSIDE #undef VIGRA_ASSERT_INSIDE
#endif // VIGRA_TINYVECTOR_HXX #endif // VIGRA_TINYVECTOR_HXX
 End of changes. 69 change blocks. 
65 lines changed or deleted 372 lines changed or added


 unsupervised_decomposition.hxx   unsupervised_decomposition.hxx 
skipping to change at line 220 skipping to change at line 220
/** \brief Decompose a matrix according to the pLSA algorithm. /** \brief Decompose a matrix according to the pLSA algorithm.
This function implements the pLSA algorithm (probabilistic latent s emantic analysis) This function implements the pLSA algorithm (probabilistic latent s emantic analysis)
proposed in proposed in
T. Hofmann: <a href="http://www.cs.brown.edu/people/th/papers/Hofma nn-UAI99.pdf"> T. Hofmann: <a href="http://www.cs.brown.edu/people/th/papers/Hofma nn-UAI99.pdf">
<i>"Probabilistic Latent Semantic Analysis"</i></a>, <i>"Probabilistic Latent Semantic Analysis"</i></a>,
in: UAI'99, Proc. 15th Conf. on Uncertainty in Artificial Intellige nce, in: UAI'99, Proc. 15th Conf. on Uncertainty in Artificial Intellige nce,
pp. 289-296, Morgan Kaufmann, 1999 pp. 289-296, Morgan Kaufmann, 1999
\arg features must be a matrix with shape <tt>(numFeatures * numSam \arg features must be a matrix with shape <tt>(numFeatures * numSam
ples)</tt>, which is ples)</tt> and
decomposed into the matrices non-negative entries, which is decomposed into the matrices
\arg fz with shape <tt>(numFeatures * numComponents)</tt> and \arg fz with shape <tt>(numFeatures * numComponents)</tt> and
\arg zv with shape <tt>(numComponents * numSamples)</tt> \arg zv with shape <tt>(numComponents * numSamples)</tt>
such that such that
\f[ \f[
\mathrm{features} \approx \mathrm{fz} * \mathrm{zv} \mathrm{features} \approx \mathrm{fz} * \mathrm{zv}
\f] \f]
(this formula applies when pLSA is called with (this formula applies when pLSA is called with
<tt>PLSAOptions.normalizedComponentWeights(false)</tt>. Otherwise, you must <tt>PLSAOptions.normalizedComponentWeights(false)</tt>. Otherwise, you must
normalize the features by calling <tt>\ref linalg::prepareColumns&n bsp;(features, features, UnitSum)</tt> normalize the features by calling <tt>\ref linalg::prepareColumns&n bsp;(features, features, UnitSum)</tt>
 End of changes. 1 change blocks. 
3 lines changed or deleted 3 lines changed or added


 utilities.hxx   utilities.hxx 
skipping to change at line 47 skipping to change at line 47
#define VIGRA_BASICS_HXX #define VIGRA_BASICS_HXX
#include "config.hxx" #include "config.hxx"
#include "error.hxx" #include "error.hxx"
#include "metaprogramming.hxx" #include "metaprogramming.hxx"
#include "tuple.hxx" #include "tuple.hxx"
#include "diff2d.hxx" #include "diff2d.hxx"
#include "mathutil.hxx" #include "mathutil.hxx"
#include <string> #include <string>
#include <sstream> #include <sstream>
#include <cctype>
namespace vigra { namespace vigra {
/** Convert a value to a string. Available for integral and floating point types /** Convert a value to a string. Available for integral and floating point types
and void *. and void *.
*/ */
doxygen_overloaded_function(template <class T> std::string asString(T t)) doxygen_overloaded_function(template <class T> std::string asString(T t))
#define VIGRA_AS_STRING(T) \ #define VIGRA_AS_STRING(T) \
inline std::string asString(T t) \ inline std::string asString(T t) \
skipping to change at line 89 skipping to change at line 90
#undef VIGRA_AS_STRING #undef VIGRA_AS_STRING
template <class T> template <class T>
std::string & operator<<(std::string & s, T const & t) std::string & operator<<(std::string & s, T const & t)
{ {
std::stringstream ss; std::stringstream ss;
ss << t; ss << t;
return s += ss.str(); return s += ss.str();
} }
/** Convert string to lower case.
*/
inline std::string tolower(std::string s)
{
for(unsigned int k=0; k<s.size(); ++k)
s[k] = (std::string::value_type)std::tolower(s[k]);
return s;
}
inline std::string tolower(const char * s)
{
return tolower(std::string(s));
}
/** Convert string to lower case and remove any white space characters.
*/
inline std::string normalizeString(std::string const & s)
{
std::string res;
for(unsigned int k=0; k<s.size(); ++k)
{
if(std::isspace(s[k]))
continue;
res += (std::string::value_type)std::tolower(s[k]);
}
return res;
}
inline std::string normalizeString(const char * s)
{
return normalizeString(std::string(s));
}
} // namespace vigra } // namespace vigra
namespace std {
template <class T1, class T2>
ostream & operator<<(ostream & s, std::pair<T1, T2> const & p)
{
s << "(" << p.first << ", " << p.second << ")";
return s;
}
}
/*! \page Utilities Utilities /*! \page Utilities Utilities
Basic helper functionality needed throughout. Basic helper functionality needed throughout.
<UL style="list-style-image:url(documents/bullet.gif)"> <UL style="list-style-image:url(documents/bullet.gif)">
<LI> \ref vigra::ArrayVector <LI> \ref vigra::ArrayVector
<BR>&nbsp;&nbsp;&nbsp;<em>replacement for std::vector (always uses consecutive memory)</em> <BR>&nbsp;&nbsp;&nbsp;<em>replacement for std::vector (always uses consecutive memory)</em>
<LI> \ref vigra::BucketQueue and \ref vigra::MappedBucketQueue <LI> \ref vigra::BucketQueue and \ref vigra::MappedBucketQueue
<BR>&nbsp;&nbsp;&nbsp;<em>efficient priority queues for integer pr iorities</em> <BR>&nbsp;&nbsp;&nbsp;<em>efficient priority queues for integer pr iorities</em>
<LI> \ref RangesAndPoints <LI> \ref RangesAndPoints
<BR>&nbsp;&nbsp;&nbsp;<em>2-D and N-D positions, extents, and boxe s</em> <BR>&nbsp;&nbsp;&nbsp;<em>2-D and N-D positions, extents, and boxe s</em>
 End of changes. 3 change blocks. 
0 lines changed or deleted 46 lines changed or added


 watersheds.hxx   watersheds.hxx 
skipping to change at line 503 skipping to change at line 503
BImage seeds(shape); BImage seeds(shape);
if(options.mini == SeedOptions::LevelSets) if(options.mini == SeedOptions::LevelSets)
{ {
transformImage(srcIterRange(upperlefts, lowerrights, sa), transformImage(srcIterRange(upperlefts, lowerrights, sa),
destImage(seeds), destImage(seeds),
ifThenElse(Arg1() <= Param(options.thresh), Param(1) , Param(0))); ifThenElse(Arg1() <= Param(options.thresh), Param(1) , Param(0)));
} }
else else
{ {
LocalMinmaxOptions lm_options;
lm_options.neighborhood(Neighborhood::DirectionCount)
.markWith(1.0)
.allowAtBorder()
.allowPlateaus(options.mini == SeedOptions::ExtendedMinim
a);
if(options.thresholdIsValid<SrcType>())
lm_options.threshold(options.thresh);
localMinima(srcIterRange(upperlefts, lowerrights, sa), destImage(se eds), localMinima(srcIterRange(upperlefts, lowerrights, sa), destImage(se eds),
LocalMinmaxOptions().neighborhood(Neighborhood::DirectionCount) lm_options);
.markWith(1.0)
.threshold(options.thresh)
.allowAtBorder()
.allowPlateaus(options.mini == SeedOptions:
:ExtendedMinima));
} }
return labelImageWithBackground(srcImageRange(seeds), destIter(upperlef td, da), return labelImageWithBackground(srcImageRange(seeds), destIter(upperlef td, da),
Neighborhood::DirectionCount == 8, 0); Neighborhood::DirectionCount == 8, 0);
} }
template <class SrcIterator, class SrcAccessor, template <class SrcIterator, class SrcAccessor,
class DestIterator, class DestAccessor> class DestIterator, class DestAccessor>
inline unsigned int inline unsigned int
generateWatershedSeeds(SrcIterator upperlefts, SrcIterator lowerrights, Src Accessor sa, generateWatershedSeeds(SrcIterator upperlefts, SrcIterator lowerrights, Src Accessor sa,
skipping to change at line 655 skipping to change at line 659
template <class SrcIterator, class SrcAccessor, template <class SrcIterator, class SrcAccessor,
class DestIterator, class DestAccessor, class DestIterator, class DestAccessor,
class Neighborhood> class Neighborhood>
unsigned int unsigned int
watershedsUnionFind(SrcIterator upperlefts, SrcIterator lowerrights, SrcAcc essor sa, watershedsUnionFind(SrcIterator upperlefts, SrcIterator lowerrights, SrcAcc essor sa,
DestIterator upperleftd, DestAccessor da, DestIterator upperleftd, DestAccessor da,
Neighborhood neighborhood) Neighborhood neighborhood)
{ {
SImage orientationImage(lowerrights - upperlefts); SImage orientationImage(lowerrights - upperlefts);
SImage::traverser yo = orientationImage.upperLeft();
prepareWatersheds(upperlefts, lowerrights, sa, prepareWatersheds(upperlefts, lowerrights, sa,
orientationImage.upperLeft(), orientationImage.accesso r(), neighborhood); orientationImage.upperLeft(), orientationImage.accesso r(), neighborhood);
return watershedLabeling(orientationImage.upperLeft(), orientationImage .lowerRight(), orientationImage.accessor(), return watershedLabeling(orientationImage.upperLeft(), orientationImage .lowerRight(), orientationImage.accessor(),
upperleftd, da, neighborhood); upperleftd, da, neighborhood);
} }
template <class SrcIterator, class SrcAccessor, template <class SrcIterator, class SrcAccessor,
class DestIterator, class DestAccessor> class DestIterator, class DestAccessor>
inline unsigned int inline unsigned int
 End of changes. 3 change blocks. 
7 lines changed or deleted 10 lines changed or added

This html diff was produced by rfcdiff 1.41. The latest version is available from http://tools.ietf.org/tools/rfcdiff/