[ VIGRA Homepage | Class Index | Function Index | File Index | Main Page ]

details vigra/multi_array.hxx VIGRA

00001 /************************************************************************/
00002 /*                                                                      */
00003 /*               Copyright 2003 by Gunnar Kedenburg                     */
00004 /*       Cognitive Systems Group, University of Hamburg, Germany        */
00005 /*                                                                      */
00006 /*    This file is part of the VIGRA computer vision library.           */
00007 /*    ( Version 1.3.3, Aug 18 2005 )                                    */
00008 /*    ( Version 1.3.0, Sep 10 2004 )                                    */
00009 /*    You may use, modify, and distribute this software according       */
00010 /*    to the terms stated in the LICENSE file included in               */
00011 /*    the VIGRA distribution.                                           */
00012 /*                                                                      */
00013 /*    The VIGRA Website is                                              */
00014 /*        http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/      */
00015 /*    Please direct questions, bug reports, and contributions to        */
00016 /*        koethe@informatik.uni-hamburg.de                              */
00017 /*                                                                      */
00018 /*  THIS SOFTWARE IS PROVIDED AS IS AND WITHOUT ANY EXPRESS OR          */
00019 /*  IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED      */
00020 /*  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */
00021 /*                                                                      */
00022 /************************************************************************/
00023 
00024 
00025 #ifndef VIGRA_MULTI_ARRAY_HXX
00026 #define VIGRA_MULTI_ARRAY_HXX
00027 
00028 #include <memory>
00029 #include <algorithm>
00030 #include "vigra/accessor.hxx"
00031 #include "vigra/tinyvector.hxx"
00032 #include "vigra/rgbvalue.hxx"
00033 #include "vigra/basicimageview.hxx"
00034 #include "vigra/imageiterator.hxx"
00035 #include "vigra/numerictraits.hxx"
00036 #include "vigra/multi_iterator.hxx"
00037 #include "vigra/metaprogramming.hxx"
00038 
00039 namespace vigra
00040 {
00041 
00042 namespace detail
00043 {
00044 /********************************************************/
00045 /*                                                      */
00046 /*                    defaultStride                     */
00047 /*                                                      */
00048 /********************************************************/
00049 
00050 /* generates the stride for a gapless shape.
00051 
00052     Namespace: vigra::detail
00053 */
00054 template <unsigned int N>
00055 TinyVector <int, N> defaultStride(const TinyVector <int, N> &shape)
00056 {
00057     TinyVector <int, N> ret;
00058     ret [0] = 1;
00059     for (unsigned int i = 1; i < N; ++i)
00060         ret [i] = ret [i-1] * shape [i-1];
00061     return ret;
00062 }
00063 
00064 /********************************************************/
00065 /*                                                      */
00066 /*                     MaybeStrided                     */
00067 /*                                                      */
00068 /********************************************************/
00069 
00070 /* metatag implementing a test for marking MultiArrays that were
00071     indexed at the zero'th dimension as strided, and all others as
00072     unstrided.
00073 
00074 <b>\#include</b>
00075 "<a href="multi__array_8hxx-source.html">vigra/multi_array.hxx</a>"
00076 
00077 Namespace: vigra::detail
00078 */
00079 template <unsigned int N>
00080 struct MaybeStrided
00081 {
00082     typedef UnstridedArrayTag type;
00083 };
00084 
00085 template <>
00086 struct MaybeStrided <0>
00087 {
00088     typedef StridedArrayTag type;
00089 };
00090 
00091 /********************************************************/
00092 /*                                                      */
00093 /*                MultiIteratorChooser                  */
00094 /*                                                      */
00095 /********************************************************/
00096 
00097 /* metatag implementing a test (by pattern matching) for marking
00098     MultiArrays that were indexed at the zero'th dimension as strided.
00099 
00100 <b>\#include</b>
00101 "<a href="multi__array_8hxx-source.html">vigra/multi_array.hxx</a>"
00102 
00103 Namespace: vigra::detail
00104 */
00105 template <class O>
00106 struct MultiIteratorChooser
00107 {
00108     struct Nil {};
00109 
00110     template <unsigned int N, class T, class REFERENCE, class POINTER>
00111     struct Traverser
00112     {
00113         typedef Nil type;
00114     };
00115 };
00116 
00117 /********************************************************/
00118 /*                                                      */
00119 /*       MultiIteratorChooser <StridedArrayTag>         */
00120 /*                                                      */
00121 /********************************************************/
00122 
00123 /* specialization of the MultiIteratorChooser for strided arrays.
00124 
00125 <b>\#include</b>
00126 "<a href="multi__array_8hxx-source.html">vigra/multi_array.hxx</a>"
00127 
00128 Namespace: vigra::detail
00129 */
00130 template <>
00131 struct MultiIteratorChooser <StridedArrayTag>
00132 {
00133     template <unsigned int N, class T, class REFERENCE, class POINTER>
00134     struct Traverser
00135     {
00136         typedef StridedMultiIterator <N, T, REFERENCE, POINTER> type;
00137     };
00138 };
00139 
00140 /********************************************************/
00141 /*                                                      */
00142 /*      MultiIteratorChooser <UnstridedArrayTag>        */
00143 /*                                                      */
00144 /********************************************************/
00145 
00146 /* specialization of the MultiIteratorChooser for unstrided arrays.
00147 
00148 <b>\#include</b>
00149 "<a href="multi__array_8hxx-source.html">vigra/multi_array.hxx</a>"
00150 
00151 Namespace: vigra::detail
00152 */
00153 template <>
00154 struct MultiIteratorChooser <UnstridedArrayTag>
00155 {
00156     template <unsigned int N, class T, class REFERENCE, class POINTER>
00157     struct Traverser
00158     {
00159         typedef MultiIterator <N, T, REFERENCE, POINTER> type;
00160     };
00161 };
00162 
00163 /********************************************************/
00164 /*                                                      */
00165 /*                   helper functions                   */
00166 /*                                                      */
00167 /********************************************************/
00168 
00169 template <class DestIterator, class Shape, class T, int N>
00170 void
00171 initMultiArrayData(DestIterator d, Shape const & shape, T const & init, MetaInt<N>)
00172 {    
00173     DestIterator dend = d + shape[N];
00174     for(; d != dend; ++d)
00175     {
00176         initMultiArrayData(d.begin(), shape, init, MetaInt<N-1>());
00177     }
00178 }
00179 
00180 template <class DestIterator, class Shape, class T>
00181 void
00182 initMultiArrayData(DestIterator d, Shape const & shape, T const & init, MetaInt<0>)
00183 {    
00184     DestIterator dend = d + shape[0];
00185     for(; d != dend; ++d)
00186     {
00187         *d = init;
00188     }
00189 }
00190 
00191 template <class SrcIterator, class Shape, class DestIterator, int N>
00192 void
00193 copyMultiArrayData(SrcIterator s, Shape const & shape, DestIterator d, MetaInt<N>)
00194 {    
00195     SrcIterator send = s + shape[N];
00196     for(; s != send; ++s, ++d)
00197     {
00198         copyMultiArrayData(s.begin(), shape, d.begin(), MetaInt<N-1>());
00199     }
00200 }
00201 
00202 template <class SrcIterator, class Shape, class DestIterator>
00203 void
00204 copyMultiArrayData(SrcIterator s, Shape const & shape, DestIterator d, MetaInt<0>)
00205 {    
00206     SrcIterator send = s + shape[0];
00207     for(; s != send; ++s, ++d)
00208     {
00209         *d = *s;
00210     }
00211 }
00212 
00213 template <class SrcIterator, class Shape, class T, class ALLOC, int N>
00214 void
00215 uninitializedCopyMultiArrayData(SrcIterator s, Shape const & shape, T * & d, ALLOC & a, MetaInt<N>)
00216 {    
00217     SrcIterator send = s + shape[N];
00218     for(; s != send; ++s)
00219     {
00220         uninitializedCopyMultiArrayData(s.begin(), shape, d, a, MetaInt<N-1>());
00221     }
00222 }
00223 
00224 template <class SrcIterator, class Shape, class T, class ALLOC>
00225 void
00226 uninitializedCopyMultiArrayData(SrcIterator s, Shape const & shape, T * & d, ALLOC & a, MetaInt<0>)
00227 {    
00228     SrcIterator send = s + shape[0];
00229     for(; s != send; ++s, ++d)
00230     {
00231         a.construct(d, *s);
00232     }
00233 }
00234 
00235 template <class SrcIterator, class Shape, class T, int N>
00236 void
00237 squaredNormOfMultiArray(SrcIterator s, Shape const & shape, T & result, MetaInt<N>)
00238 {    
00239     SrcIterator send = s + shape[N];
00240     for(; s != send; ++s)
00241     {
00242         squaredNormOfMultiArray(s.begin(), shape, result, MetaInt<N-1>());
00243     }
00244 }
00245 
00246 template <class SrcIterator, class Shape, class T>
00247 void
00248 squaredNormOfMultiArray(SrcIterator s, Shape const & shape, T & result, MetaInt<0>)
00249 {    
00250     SrcIterator send = s + shape[0];
00251     for(; s != send; ++s)
00252     {
00253         result += *s * *s;
00254     }
00255 }
00256 
00257 
00258 } // namespace detail
00259 
00260 /********************************************************/
00261 /*                                                      */
00262 /*                     MultiArrayView                   */
00263 /*                                                      */
00264 /********************************************************/
00265 
00266 // forward declaration
00267 template <unsigned int N, class T, class C = UnstridedArrayTag>
00268 class MultiArrayView;
00269 template <unsigned int N, class T, class A = std::allocator<T> >
00270 class MultiArray;
00271 
00272 /** \brief Base class for, and view to, \ref vigra::MultiArray.
00273 
00274 This class implements the interface of both MultiArray and
00275 MultiArrayView.  By default, MultiArrayViews are tagged as
00276 unstrided. If necessary, strided arrays are constructed automatically
00277 by calls to a variant of the bind...() function.
00278 
00279 If you want to apply an algorithm requiring an image to a
00280 <tt>MultiArrayView</tt> of appropriate (2-dimensional) shape, you can
00281 create a \ref vigra::BasicImageView that acts as a wrapper with the
00282 necessary interface -- see \ref MultiArrayToImage.
00283 
00284 The template parameter are as follows
00285 \code
00286     N: the array dimension
00287 
00288     T: the type of the array elements
00289 
00290     C: a tag determining whether the array's inner dimension is strided
00291        or not. An array is unstrided if the array elements occupy consecutive
00292        memory location, strided if there is an offset in between (e.g.
00293        when a view is created that skips every other array element).
00294        The compiler can generate faster code for unstrided arrays.
00295        Possible values: UnstridedArrayTag (default), StridedArrayTag
00296 \endcode
00297 
00298 <b>\#include</b>
00299 "<a href="multi__array_8hxx-source.html">vigra/multi_array.hxx</a>"
00300 
00301 Namespace: vigra
00302 */
00303 template <unsigned int N, class T, class C>
00304 class MultiArrayView
00305 {
00306 public:
00307 
00308         /** the array's actual dimensionality.
00309             This ensures that MultiArrayView can also be used for
00310             scalars (that is, when <tt>N == 0</tt>). Calculated as:<br>
00311             \code
00312             actual_dimension = (N==0) ? 1 : N
00313             \endcode
00314          */
00315     enum ActualDimension { actual_dimension = (N==0) ? 1 : N };
00316 
00317         /** the array's value type
00318          */
00319     typedef T value_type;
00320 
00321         /** reference type (result of operator[])
00322          */
00323     typedef value_type &reference;
00324 
00325         /** const reference type (result of operator[] const)
00326          */
00327     typedef const value_type &const_reference;
00328 
00329         /** pointer type
00330          */
00331     typedef value_type *pointer;
00332 
00333         /** const pointer type
00334          */
00335     typedef const value_type *const_pointer;
00336 
00337         /** size type
00338          */
00339     typedef TinyVector <int, actual_dimension> size_type;
00340 
00341         /** difference type (used for offsetting)
00342          */
00343     typedef TinyVector <int, actual_dimension> difference_type;
00344 
00345         /** traverser (MultiIterator) type
00346          */
00347     typedef typename detail::MultiIteratorChooser <
00348         C>::template Traverser <actual_dimension, T, T &, T *>::type traverser;
00349 
00350         /** const traverser (MultiIterator) type
00351          */
00352     typedef typename detail::MultiIteratorChooser <
00353         C>::template Traverser <actual_dimension, T, T const &, T const *>::type const_traverser;
00354 
00355         /** the view type associated with this array.
00356          */
00357     typedef MultiArrayView <N, T, C> view_type;
00358 
00359         /** the matrix type associated with this array.
00360          */
00361     typedef MultiArray <N, T> matrix_type;
00362 
00363         /** the squared norm type (return type of array.squaredNorm()).
00364          */
00365     typedef typename NormTraits<T>::SquaredNormType SquaredNormType;
00366 
00367         /** the norm type (return type of array.norm()).
00368          */
00369     typedef typename NumericTraits<SquaredNormType>::RealPromote NormType;
00370 
00371 protected:
00372 
00373         /** the shape of the image pointed to is stored here.
00374      */
00375     difference_type m_shape;
00376 
00377         /** the strides (offset of a sample to the next) for every dimension
00378             are stored here.
00379         */
00380     difference_type m_stride;
00381 
00382         /** pointer to the image.
00383          */
00384     pointer m_ptr;
00385 
00386 public:
00387 
00388         /** default constructor: create an empty image of size 0.
00389          */
00390     MultiArrayView ()
00391         : m_shape (0), m_stride (0), m_ptr (0)
00392     {}
00393 
00394 
00395         /** construct from shape and pointer
00396          */
00397     MultiArrayView (const difference_type &shape, pointer ptr);
00398 
00399         /** construct from shape, strides (offset of a sample to the next)
00400             for every dimension) and pointer
00401          */
00402     MultiArrayView (const difference_type &shape,
00403                     const difference_type &stride,
00404                     pointer ptr);
00405 
00406         /** array access.
00407          */
00408     reference operator[] (const difference_type &d)
00409     {
00410         return m_ptr [dot (d, m_stride)];
00411     }
00412 
00413         /** array access.
00414          */
00415     const_reference operator[] (const difference_type &d) const
00416     {
00417         return m_ptr [dot (d, m_stride)];
00418     }
00419 
00420         /** 1D array access. Use only if N == 1.
00421          */
00422     reference operator() (int x)
00423     {
00424         return m_ptr [m_stride[0]*x];
00425     }
00426 
00427         /** 2D array access. Use only if N == 2.
00428          */
00429     reference operator() (int x, int y)
00430     {
00431         return m_ptr [m_stride[0]*x + m_stride[1]*y];
00432     }
00433 
00434         /** 3D array access. Use only if N == 3.
00435          */
00436     reference operator() (int x, int y, int z)
00437     {
00438         return m_ptr [m_stride[0]*x + m_stride[1]*y + m_stride[2]*z];
00439     }
00440 
00441         /** 4D array access. Use only if N == 4.
00442          */
00443     reference operator() (int x, int y, int z, int u)
00444     {
00445         return m_ptr [m_stride[0]*x + m_stride[1]*y + m_stride[2]*z + m_stride[3]*u];
00446     }
00447 
00448         /** 5D array access. Use only if N == 5.
00449          */
00450     reference operator() (int x, int y, int z, int u, int v)
00451     {
00452         return m_ptr [m_stride[0]*x + m_stride[1]*y + m_stride[2]*z + m_stride[3]*u + m_stride[4]*v];
00453     }
00454 
00455         /** 1D const array access. Use only if N == 1.
00456          */
00457     const_reference operator() (int x) const
00458     {
00459         return m_ptr [m_stride[0]*x];
00460     }
00461 
00462         /** 2D const array access. Use only if N == 2.
00463          */
00464     const_reference operator() (int x, int y) const
00465     {
00466         return m_ptr [m_stride[0]*x + m_stride[1]*y];
00467     }
00468 
00469         /** 3D const array access. Use only if N == 3.
00470          */
00471     const_reference operator() (int x, int y, int z) const
00472     {
00473         return m_ptr [m_stride[0]*x + m_stride[1]*y + m_stride[2]*z];
00474     }
00475 
00476         /** 4D const array access. Use only if N == 4.
00477          */
00478     const_reference operator() (int x, int y, int z, int u) const
00479     {
00480         return m_ptr [m_stride[0]*x + m_stride[1]*y + m_stride[2]*z + m_stride[3]*u];
00481     }
00482 
00483         /** 5D const array access. Use only if N == 5.
00484          */
00485     const_reference operator() (int x, int y, int z, int u, int v) const
00486     {
00487         return m_ptr [m_stride[0]*x + m_stride[1]*y + m_stride[2]*z + m_stride[3]*u + m_stride[4]*v];
00488     }
00489 
00490         /** Init with a constant.
00491          */
00492     template <class U>
00493     void init(const U & init);
00494 
00495         /** Copy the data of the right-hand array (array shapes must match).
00496          */
00497     template <class U, class CN>
00498     void copy(const MultiArrayView <N, U, CN>& rhs);
00499 
00500         /** bind the M outmost dimensions to certain indices.
00501             this reduces the dimensionality of the image to
00502             max { 1, N-M }
00503         */
00504     template <unsigned int M>
00505     MultiArrayView <N-M, T, C> bindOuter (const TinyVector <int, M> &d) const;
00506 
00507         /** bind the M innermost dimensions to certain indices.
00508             this reduces the dimensionality of the image to
00509             max { 1, N-M }
00510         */
00511     template <unsigned int M>
00512     MultiArrayView <N-M, T, StridedArrayTag>
00513     bindInner (const TinyVector <int, M> &d) const;
00514 
00515         /** bind dimension M to index d.
00516             this reduces the dimensionality of the image to
00517             max { 1, N-1 }
00518          */
00519     template <unsigned int M>
00520     MultiArrayView <N-1, T, typename detail::MaybeStrided <M>::type >
00521     bind (int d) const;
00522 
00523         /** bind the outmost dimension to a certain index.
00524             this reduces the dimensionality of the image to
00525             max { 1, N-1 }
00526         */
00527     MultiArrayView <N-1, T, C> bindOuter (int d) const;
00528 
00529         /** bind the innermost dimension to a certain index.
00530             this reduces the dimensionality of the image to
00531             max { 1, N-1 }
00532         */
00533     MultiArrayView <N-1, T, StridedArrayTag> bindInner (int d) const;
00534 
00535         /** bind dimension m to index d.
00536             this reduces the dimensionality of the image to
00537             max { 1, N-1 }
00538          */
00539     MultiArrayView <N-1, T, StridedArrayTag>
00540     bindAt (int m, int d) const;
00541 
00542         /** create a rectangular subarray that spans between the
00543             points p and q, where p is in the subarray, q not.
00544         */
00545     MultiArrayView subarray (const difference_type &p,
00546                              const difference_type &q) const
00547     {
00548         const int offset = dot (m_stride, p);
00549         return MultiArrayView (q - p, m_stride, m_ptr + offset);
00550     }
00551 
00552         /** apply an additional striding to the image, thereby reducing
00553             the shape of the array.
00554             for example, multiplying the stride of dimension one by three
00555             turns an appropriately layed out (interleaved) rgb image into
00556             a single band image.
00557         */
00558     MultiArrayView <N, T, StridedArrayTag>
00559     stridearray (const difference_type &s) const
00560     {
00561         difference_type shape = m_shape;
00562         for (unsigned int i = 0; i < actual_dimension; ++i)
00563             shape [i] /= s [i];
00564         return MultiArrayView <N, T, StridedArrayTag>
00565             (shape, m_stride * s, m_ptr);
00566     }
00567 
00568         /** number of the elements in the array.
00569          */
00570     std::size_t elementCount () const
00571     {
00572         std::size_t ret = m_shape[0];
00573         for(unsigned int i = 1; i < actual_dimension; ++i)
00574             ret *= m_shape[i];
00575         return ret;
00576     }
00577 
00578         /** return the array's size.
00579          */
00580     const size_type & size () const
00581     {
00582         return m_shape;
00583     }
00584 
00585         /** return the array's shape (same as the <tt>size()</tt>).
00586          */
00587     const difference_type & shape () const
00588     {
00589         return m_shape;
00590     }
00591 
00592         /** return the array's size at a certain dimension.
00593          */
00594     int size (int n) const
00595     {
00596         return m_shape [n];
00597     }
00598 
00599         /** return the array's shape at a certain dimension 
00600             (same as <tt>size(n)</tt>).
00601          */
00602     int shape (int n) const
00603     {
00604         return m_shape [n];
00605     }
00606 
00607         /** return the array's stride for every dimension.
00608          */
00609     const difference_type & stride () const
00610     {
00611         return m_stride;
00612     }
00613 
00614         /** return the array's stride at a certain dimension.
00615          */
00616     int stride (int n) const
00617     {
00618         return m_stride [n];
00619     }
00620 
00621         /** return the squared norm of the array (sum of squares of the array elements).
00622          */
00623     SquaredNormType squaredNorm() const
00624     {
00625         SquaredNormType res = NumericTraits<SquaredNormType>::zero();  
00626         detail::squaredNormOfMultiArray(traverser_begin(), shape(), res, MetaInt<actual_dimension-1>());
00627         return res;
00628     }
00629 
00630         /** return the norm of the array (equals <tt>sqrt(array.squaredNorm())</tt>).
00631          */
00632     NormType norm() const
00633     {
00634         return VIGRA_CSTD::sqrt(static_cast<NormType>(this->squaredNorm()));
00635     }
00636 
00637         /** return the pointer to the image data
00638          */
00639     pointer data () const
00640     {
00641         return m_ptr;
00642     }
00643 
00644         /** returns the N-dimensional MultiIterator pointing
00645             to the first element in every dimension.
00646         */
00647     traverser traverser_begin ()
00648     {
00649         traverser ret (m_ptr, m_stride.begin (), m_shape.begin ());
00650         return ret;
00651     }
00652 
00653         /** returns the N-dimensional MultiIterator pointing
00654             to the const first element in every dimension.
00655         */
00656     const_traverser traverser_begin () const
00657     {
00658         const_traverser ret (m_ptr, m_stride.begin (), m_shape.begin ());
00659         return ret;
00660     }
00661 
00662         /** returns the N-dimensional MultiIterator pointing
00663             beyond the last element in dimension N, and to the
00664             first element in every other dimension.
00665         */
00666     traverser traverser_end ()
00667     {
00668         traverser ret (m_ptr, m_stride.begin (), m_shape.begin ());
00669         ret += m_shape [actual_dimension-1];
00670         return ret;
00671     }
00672 
00673         /** returns the N-dimensional const MultiIterator pointing
00674             beyond the last element in dimension N, and to the
00675             first element in every other dimension.
00676         */
00677     const_traverser traverser_end () const
00678     {
00679         const_traverser ret (m_ptr, m_stride.begin (), m_shape.begin ());
00680         ret += m_shape [actual_dimension-1];
00681         return ret;
00682     }
00683 
00684     view_type view ()
00685     {
00686         return *this;
00687     }
00688 };
00689 
00690 template <unsigned int N, class T, class C>
00691 MultiArrayView <N, T, C>::MultiArrayView (const difference_type &shape,
00692                                           pointer ptr)
00693     : m_shape (shape), m_stride (detail::defaultStride <MultiArrayView<N,T>::actual_dimension> (shape)), m_ptr (ptr)
00694 {}
00695 
00696 template <unsigned int N, class T, class C>
00697 MultiArrayView <N, T, C>::MultiArrayView
00698 (const difference_type &shape, const difference_type &stride, pointer ptr)
00699     : m_shape (shape), m_stride (stride), m_ptr (ptr)
00700 {}
00701 
00702 template <unsigned int N, class T, class C>
00703 template <class U>
00704 void 
00705 MultiArrayView <N, T, C>::init(const U & init)
00706 {
00707     detail::initMultiArrayData(traverser_begin(), shape(), init, MetaInt<actual_dimension-1>());
00708 }
00709 
00710 template <unsigned int N, class T, class C>
00711 template <class U, class CN>
00712 void 
00713 MultiArrayView <N, T, C>::copy(const MultiArrayView <N, U, CN>& rhs)
00714 {
00715     if(this == &rhs)
00716         return;
00717     vigra_precondition (shape () == rhs.shape (),
00718         "MultiArrayView::copy(): shape mismatch.");
00719     detail::copyMultiArrayData(rhs.traverser_begin(), shape(), traverser_begin(), MetaInt<actual_dimension-1>());
00720 }
00721 
00722 template <unsigned int N, class T, class C>
00723 template <unsigned int M>
00724 MultiArrayView <N-M, T, C>
00725 MultiArrayView <N, T, C>::bindOuter (const TinyVector <int, M> &d) const
00726 {
00727     TinyVector <int, M> stride;
00728     stride.init (m_stride.begin () + N-M, m_stride.end ());
00729     pointer ptr = m_ptr + dot (d, stride);
00730     static const int NNew = (N-M == 0) ? 1 : N-M;
00731     TinyVector <int, NNew> inner_shape, inner_stride;
00732     if (N-M == 0)
00733     {
00734         inner_shape [0] = 1;
00735         inner_stride [0] = 0;
00736     }
00737     else
00738     {
00739         inner_shape.init (m_shape.begin (), m_shape.end () - M);
00740         inner_stride.init (m_stride.begin (), m_stride.end () - M);
00741     }
00742     return MultiArrayView <N-M, T, C> (inner_shape, inner_stride, ptr);
00743 }
00744 
00745 template <unsigned int N, class T, class C>
00746 template <unsigned int M>
00747 MultiArrayView <N - M, T, StridedArrayTag>
00748 MultiArrayView <N, T, C>::bindInner (const TinyVector <int, M> &d) const
00749 {
00750     TinyVector <int, M> stride;
00751     stride.init (m_stride.begin (), m_stride.end () - N + M);
00752     pointer ptr = m_ptr + dot (d, stride);
00753     static const int NNew = (N-M == 0) ? 1 : N-M;
00754     TinyVector <int, NNew> outer_shape, outer_stride;
00755     if (N-M == 0)
00756     {
00757         outer_shape [0] = 1;
00758         outer_stride [0] = 0;
00759     }
00760     else
00761     {
00762         outer_shape.init (m_shape.begin () + M, m_shape.end ());
00763         outer_stride.init (m_stride.begin () + M, m_stride.end ());
00764     }
00765     return MultiArrayView <N-M, T, StridedArrayTag>
00766         (outer_shape, outer_stride, ptr);
00767 }
00768 
00769 template <unsigned int N, class T, class C>
00770 template <unsigned int M>
00771 MultiArrayView <N-1, T, typename detail::MaybeStrided <M>::type >
00772 MultiArrayView <N, T, C>::bind (int d) const
00773 {
00774     static const int NNew = (N-1 == 0) ? 1 : N-1;
00775     TinyVector <int, NNew> shape, stride;
00776     // the remaining dimensions are 0..n-1,n+1..N-1
00777     if (N-1 == 0)
00778     {
00779         shape[0] = 1;
00780         stride[0] = 0;
00781     }
00782     else
00783     {
00784         std::copy (m_shape.begin (), m_shape.begin () + M, shape.begin ());
00785         std::copy (m_shape.begin () + M+1, m_shape.end (),
00786                    shape.begin () + M);
00787         std::copy (m_stride.begin (), m_stride.begin () + M, stride.begin ());
00788         std::copy (m_stride.begin () + M+1, m_stride.end (),
00789                    stride.begin () + M);
00790     }
00791     return MultiArrayView <N-1, T, typename detail::MaybeStrided <M>::type>
00792         (shape, stride, m_ptr + d * m_stride[M]);
00793 }
00794 
00795 template <unsigned int N, class T, class C>
00796 MultiArrayView <N - 1, T, C>
00797 MultiArrayView <N, T, C>::bindOuter (int d) const
00798 {
00799     static const int NNew = (N-1 == 0) ? 1 : N-1;
00800     TinyVector <int, NNew> inner_shape, inner_stride;
00801     if (N-1 == 0)
00802     {
00803         inner_shape [0] = 1;
00804         inner_stride [0] = 0;
00805     }
00806     else
00807     {
00808         inner_shape.init (m_shape.begin (), m_shape.end () - 1);
00809         inner_stride.init (m_stride.begin (), m_stride.end () - 1);
00810     }
00811     return MultiArrayView <N-1, T, C> (inner_shape, inner_stride,
00812                                        m_ptr + d * m_stride [N-1]);
00813 }
00814 
00815 template <unsigned int N, class T, class C>
00816 MultiArrayView <N - 1, T, StridedArrayTag>
00817 MultiArrayView <N, T, C>::bindInner (int d) const
00818 {
00819     static const int NNew = (N-1 == 0) ? 1 : N-1;
00820     TinyVector <int, NNew> outer_shape, outer_stride;
00821     if (N-1 == 0)
00822     {
00823         outer_shape [0] = 1;
00824         outer_stride [0] = 0;
00825     }
00826     else
00827     {
00828         outer_shape.init (m_shape.begin () + 1, m_shape.end ());
00829         outer_stride.init (m_stride.begin () + 1, m_stride.end ());
00830     }
00831     return MultiArrayView <N-1, T, StridedArrayTag>
00832         (outer_shape, outer_stride, m_ptr + d * m_stride [0]);
00833 }
00834 
00835 template <unsigned int N, class T, class C>
00836 MultiArrayView <N - 1, T, StridedArrayTag>
00837 MultiArrayView <N, T, C>::bindAt (int n, int d) const
00838 {
00839     vigra_precondition (
00840         n < static_cast <int> (N),
00841         "MultiArrayView <N, T, C>::bindAt(): dimension out of range.");
00842     static const int NNew = (N-1 == 0) ? 1 : N-1;
00843     TinyVector <int, NNew> shape, stride;
00844     // the remaining dimensions are 0..n-1,n+1..N-1
00845     if (N-1 == 0)
00846     {
00847         shape [0] = 1;
00848         stride [0] = 0;
00849     }
00850     else
00851     {
00852         std::copy (m_shape.begin (), m_shape.begin () + n, shape.begin ());
00853         std::copy (m_shape.begin () + n+1, m_shape.end (),
00854                    shape.begin () + n);
00855         std::copy (m_stride.begin (), m_stride.begin () + n, stride.begin ());
00856         std::copy (m_stride.begin () + n+1, m_stride.end (),
00857                    stride.begin () + n);
00858     }
00859     return MultiArrayView <N-1, T, StridedArrayTag>
00860         (shape, stride, m_ptr + d * m_stride[n]);
00861 }
00862 
00863 /********************************************************/
00864 /*                                                      */
00865 /*                          norm                        */
00866 /*                                                      */
00867 /********************************************************/
00868 
00869 template <unsigned int N, class T, class C>
00870 struct NormTraits<MultiArrayView <N, T, C> >
00871 {
00872     typedef MultiArrayView <N, T, C> Type;
00873     typedef typename Type::SquaredNormType SquaredNormType;
00874     typedef typename Type::NormType NormType;
00875 };
00876 
00877 template <unsigned int N, class T, class C>
00878 inline typename MultiArrayView <N, T, C>::SquaredNormType
00879 squaredNorm(MultiArrayView <N, T, C> const & a)
00880 {
00881     return a.squaredNorm();
00882 }
00883 
00884 template <unsigned int N, class T, class C>
00885 inline typename MultiArrayView <N, T, C>::NormType
00886 norm(MultiArrayView <N, T, C> const & a)
00887 {
00888     return a.norm();
00889 }
00890 
00891 /********************************************************/
00892 /*                                                      */
00893 /*                       MultiArray                     */
00894 /*                                                      */
00895 /********************************************************/
00896 
00897 /** \brief Main <TT>MultiArray</TT> class containing the memory
00898     management.
00899 
00900 This class inherits the interface of MultiArrayView, and implements
00901 the memory ownership.
00902 MultiArray's are always unstrided, striding them creates a MultiArrayView.
00903 
00904 
00905 The template parameters are as follows
00906 \code
00907     N: the array dimension
00908 
00909     T: the type of the array elements
00910 
00911     A: the allocator used for internal storage management
00912        (default: std::allocator<T>)
00913 \endcode
00914 
00915 <b>\#include</b>
00916 "<a href="multi__array_8hxx-source.html">vigra/multi_array.hxx</a>"
00917 
00918 Namespace: vigra
00919 */
00920 template <unsigned int N, class T, class A /* default already declared above */>
00921 class MultiArray : public MultiArrayView <N, T>
00922 {
00923 
00924 public:
00925     using MultiArrayView <N, T>::actual_dimension;
00926 
00927         /** the allocator type used to allocate the memory
00928          */
00929     typedef A allocator_type;
00930 
00931         /** the view type associated with this array.
00932          */
00933     typedef MultiArrayView <N, T> view_type;
00934 
00935         /** the matrix type associated with this array.
00936          */
00937     typedef MultiArray <N, T, A> matrix_type;
00938 
00939         /** the array's value type
00940          */
00941     typedef typename view_type::value_type value_type;
00942 
00943         /** pointer type
00944          */
00945     typedef typename view_type::pointer pointer;
00946 
00947         /** const pointer type
00948          */
00949     typedef typename view_type::const_pointer const_pointer;
00950 
00951         /** reference type (result of operator[])
00952          */
00953     typedef typename view_type::reference reference;
00954 
00955         /** const reference type (result of operator[] const)
00956          */
00957     typedef typename view_type::const_reference const_reference;
00958 
00959         /** size type
00960          */
00961     typedef typename view_type::size_type size_type;
00962 
00963         /** difference type (used for offsetting)
00964          */
00965     typedef typename view_type::difference_type difference_type;
00966 
00967         /** traverser type
00968          */
00969     typedef typename detail::MultiIteratorChooser <
00970         UnstridedArrayTag>::template Traverser <N, T, T &, T *>::type
00971     traverser;
00972 
00973         /** traverser type to const data
00974          */
00975     typedef typename detail::MultiIteratorChooser <
00976         UnstridedArrayTag>::template Traverser <N, T, T const &, T const *>::type
00977     const_traverser;
00978 
00979         /** sequential (random access) iterator type
00980          */
00981     typedef T * iterator;
00982 
00983         /** sequential (random access) const iterator type
00984          */
00985     typedef T * const_iterator;
00986 
00987         /** the squared norm type (return type of squaredNorm(array)).
00988          */
00989     typedef typename view_type::SquaredNormType SquaredNormType;
00990 
00991         /** the norm type (return type of norm(array)).
00992          */
00993     typedef typename view_type::NormType NormType;
00994 
00995 protected:
00996 
00997         /** the allocator used to allocate the memory
00998          */
00999     allocator_type m_alloc;
01000 
01001         /** allocate memory for s pixels, write its address into the given
01002             pointer and initialize the pixels with init.
01003         */
01004     void allocate (pointer &ptr, std::size_t s, const_reference init);
01005 
01006         /** allocate memory for s pixels, write its address into the given
01007             pointer and initialize the linearized pixels to the values of init.
01008         */
01009     template <class U>
01010     void allocate (pointer &ptr, std::size_t s, U const * init);
01011 
01012         /** allocate memory, write its address into the given
01013             pointer and initialize it by copying the data from the given MultiArrayView.
01014         */
01015     template <class U, class C>
01016     void allocate (pointer &ptr, MultiArrayView<N, U, C> const & init);
01017 
01018         /** deallocate the memory (of length s) starting at the given address.
01019          */
01020     void deallocate (pointer &ptr, std::size_t s);
01021 
01022 public:
01023 
01024         /** default constructor
01025          */
01026     MultiArray ();
01027 
01028         /** construct with given allocator
01029          */
01030     MultiArray (allocator_type const & alloc);
01031 
01032         /** construct with given shape
01033          */
01034     explicit MultiArray (const difference_type &shape,
01035                          allocator_type const & alloc = allocator_type());
01036 
01037         /** construct from shape with an initial value
01038          */
01039     MultiArray (const difference_type &shape, const_reference init,
01040                          allocator_type const & alloc = allocator_type());
01041 
01042         /** construct from shape and copy values from the given array
01043          */
01044     MultiArray (const difference_type &shape, const_pointer init,
01045                          allocator_type const & alloc = allocator_type());
01046 
01047         /** copy constructor
01048          */
01049     MultiArray (const MultiArray &rhs);
01050 
01051         /** construct by copying from a MultiArrayView
01052          */
01053     template <class U, class C>
01054     MultiArray (const MultiArrayView<N, U, C>  &rhs,
01055                 allocator_type const & alloc = allocator_type());
01056 
01057         /** assignment.<br>
01058             If the size of \a rhs is the same as the left-hand side arrays's old size, only 
01059             the data are copied. Otherwise, new storage is allocated, which invalidates all 
01060             objects (array views, iterators) depending on the lhs array.
01061          */
01062     MultiArray &operator= (const MultiArray &rhs)
01063     {
01064         return this->operator=(static_cast<view_type const &>(rhs));
01065     }
01066 
01067         /** assignment from arbitrary MultiArrayView.<br>
01068             If the size of \a rhs is the same as the left-hand side arrays's old size, only 
01069             the data are copied. Otherwise, new storage is allocated, which invalidates all 
01070             objects (array views, iterators) depending on the lhs array.
01071          */
01072     template <class U, class C>
01073     MultiArray &operator= (const MultiArrayView<N, U, C> &rhs);
01074 
01075         /** destructor
01076          */
01077    ~MultiArray ();
01078 
01079 
01080         /** change the shape and allocate new memory.<br>
01081             <em>Note:</em> this operation invalidates all dependent objects
01082             (array views and iterators)
01083          */
01084     void reshape (const difference_type &shape)
01085     {
01086         reshape (shape, NumericTraits <T>::zero ());
01087     }
01088 
01089         /** change the shape, allocate new memory and initialize it
01090             with the given value.<br>
01091             <em>Note:</em> this operation invalidates all dependent objects
01092             (array views and iterators)
01093          */
01094     void reshape (const difference_type &shape, const_reference init);
01095 
01096         /** Swap the contents with another MultiArray. This is fast,
01097             because no data are copied, but only pointers and shapes swapped.
01098             <em>Note:</em> this operation invalidates all dependent objects
01099             (array views and iterators)
01100          */
01101     void swap (MultiArray & other);
01102 
01103         /** sequential iterator pointing to the first array element.
01104          */
01105     iterator begin ()
01106     {
01107         return this->data();
01108     }
01109 
01110         /** sequential iterator pointing beyond the last array element.
01111          */
01112     iterator end ()
01113     {
01114         return this->data() + this->elementCount();
01115     }
01116 
01117         /** sequential const iterator pointing to the first array element.
01118          */
01119     const_iterator begin () const
01120     {
01121         return this->data();
01122     }
01123 
01124         /** sequential const iterator pointing beyond the last array element.
01125          */
01126     const_iterator end () const
01127     {
01128         return this->data() + this->elementCount();
01129     }
01130 
01131         /** get the allocator.
01132          */
01133     allocator_type const & allocator () const
01134     {
01135         return m_alloc;
01136     }
01137 };
01138 
01139 template <unsigned int N, class T, class A>
01140 MultiArray <N, T, A>::MultiArray ()
01141     : MultiArrayView <N, T> (difference_type (0), difference_type (0), 0)
01142 {}
01143 
01144 template <unsigned int N, class T, class A>
01145 MultiArray <N, T, A>::MultiArray (allocator_type const & alloc)
01146     : MultiArrayView <N, T> (difference_type (0), difference_type (0), 0),
01147       m_alloc(alloc)
01148 {}
01149 
01150 template <unsigned int N, class T, class A>
01151 MultiArray <N, T, A>::MultiArray (const difference_type &shape,
01152                                   allocator_type const & alloc)
01153     : MultiArrayView <N, T> (shape, detail::defaultStride <MultiArrayView<N,T>::actual_dimension> (shape), 0),
01154       m_alloc(alloc)
01155 {
01156     if (N == 0)
01157     {
01158         this->m_shape [0] = 1;
01159         this->m_stride [0] = 0;
01160     }
01161     allocate (this->m_ptr, this->elementCount (), NumericTraits<T>::zero ());
01162 }
01163 
01164 template <unsigned int N, class T, class A>
01165 MultiArray <N, T, A>::MultiArray (const difference_type &shape,
01166                                   const_reference init,
01167                                   allocator_type const & alloc)
01168     : MultiArrayView <N, T> (shape, detail::defaultStride <MultiArrayView<N,T>::actual_dimension> (shape), 0),
01169       m_alloc(alloc)
01170 {
01171     if (N == 0)
01172     {
01173         this->m_shape [0] = 1;
01174         this->m_stride [0] = 0;
01175     }
01176     allocate (this->m_ptr, this->elementCount (), init);
01177 }
01178 
01179 template <unsigned int N, class T, class A>
01180 MultiArray <N, T, A>::MultiArray (const difference_type &shape,
01181                                   const_pointer init,
01182                                   allocator_type const & alloc)
01183     : MultiArrayView <N, T> (shape, detail::defaultStride <MultiArrayView<N,T>::actual_dimension> (shape), 0),
01184       m_alloc(alloc)
01185 {
01186     if (N == 0)
01187     {
01188         this->m_shape [0] = 1;
01189         this->m_stride [0] = 0;
01190     }
01191     allocate (this->m_ptr, this->elementCount (), init);
01192 }
01193 
01194 template <unsigned int N, class T, class A>
01195 MultiArray <N, T, A>::MultiArray (const MultiArray &rhs)
01196     : MultiArrayView <N, T> (rhs.m_shape, rhs.m_stride, 0),
01197     m_alloc (rhs.m_alloc)
01198 {
01199     allocate (this->m_ptr, this->elementCount (), rhs.data ());
01200 }
01201 
01202 template <unsigned int N, class T, class A>
01203 template <class U, class C>
01204 MultiArray <N, T, A>::MultiArray (const MultiArrayView<N, U, C> &rhs,
01205                                   allocator_type const & alloc)
01206     : MultiArrayView <N, T> (rhs.shape(), 
01207                              detail::defaultStride <MultiArrayView<N,T>::actual_dimension> (rhs.shape()), 0),
01208     m_alloc (alloc)
01209 {
01210     allocate (this->m_ptr, rhs); 
01211 }
01212 
01213 template <unsigned int N, class T, class A>
01214 MultiArray <N, T, A>::~MultiArray ()
01215 {
01216     deallocate (this->m_ptr, this->elementCount ());
01217 }
01218 
01219 template <unsigned int N, class T, class A>
01220 template <class U, class C>
01221 MultiArray <N, T, A> &
01222 MultiArray <N, T, A>::operator= (const MultiArrayView<N, U, C> &rhs)
01223 {
01224     if (this == &rhs)
01225         return *this;
01226     if (this->shape() == rhs.shape())
01227         this->copy(rhs);
01228     else
01229     {
01230         pointer new_ptr;
01231         allocate (new_ptr, rhs);
01232         deallocate (this->m_ptr, this->elementCount ());
01233         this->m_shape = rhs.shape();
01234         this->m_stride = rhs.stride();
01235         this->m_ptr = new_ptr;
01236     }
01237     return *this;
01238 }
01239 
01240 template <unsigned int N, class T, class A>
01241 void MultiArray <N, T, A>::reshape (const difference_type & new_shape,
01242                                     const_reference init)
01243 {
01244     if (N== 0)
01245         return;
01246 
01247     difference_type new_stride = detail::defaultStride <MultiArrayView<N,T>::actual_dimension> (new_shape);
01248     std::size_t new_size = new_shape [MultiArrayView<N,T>::actual_dimension-1] * new_stride [MultiArrayView<N,T>::actual_dimension-1];
01249     T *new_ptr;
01250     allocate (new_ptr, new_size, init);
01251     deallocate (this->m_ptr, this->elementCount ());
01252     this->m_ptr = new_ptr;
01253     this->m_shape = new_shape;
01254     this->m_stride = new_stride;
01255 }
01256 
01257 
01258 template <unsigned int N, class T, class A>
01259 void MultiArray <N, T, A>::swap (MultiArray <N, T, A> & other)
01260 {
01261     if (this == &other)
01262         return;
01263     std::swap(this->m_shape,  other.m_shape);
01264     std::swap(this->m_stride, other.m_stride);
01265     std::swap(this->m_ptr,    other.m_ptr);
01266     std::swap(this->m_alloc,  other.m_alloc);
01267 }
01268 
01269 template <unsigned int N, class T, class A>
01270 void MultiArray <N, T, A>::allocate (pointer & ptr, std::size_t s,
01271                                      const_reference init)
01272 {
01273     ptr = m_alloc.allocate (s);
01274     std::size_t i;
01275     try {
01276         for (i = 0; i < s; ++i)
01277             m_alloc.construct (ptr + i, init);
01278     }
01279     catch (...) {
01280         for (std::size_t j = 0; j < i; ++j)
01281             m_alloc.destroy (ptr + j);
01282         m_alloc.deallocate (ptr, s);
01283         throw;
01284     }
01285 }
01286 
01287 template <unsigned int N, class T, class A>
01288 template <class U>
01289 void MultiArray <N, T, A>::allocate (pointer & ptr, std::size_t s,
01290                                      U const * init)
01291 {
01292     ptr = m_alloc.allocate (s);
01293     std::size_t i;
01294     try {
01295         for (i = 0; i < s; ++i, ++init)
01296             m_alloc.construct (ptr + i, *init);
01297     }
01298     catch (...) {
01299         for (std::size_t j = 0; j < i; ++j)
01300             m_alloc.destroy (ptr + j);
01301         m_alloc.deallocate (ptr, s);
01302         throw;
01303     }
01304 }
01305 
01306 template <unsigned int N, class T, class A>
01307 template <class U, class C>
01308 void MultiArray <N, T, A>::allocate (pointer & ptr, MultiArrayView<N, U, C> const & init)
01309 {
01310     std::size_t s = init.elementCount();
01311     ptr = m_alloc.allocate (s);
01312     pointer p = ptr;
01313     try {
01314         detail::uninitializedCopyMultiArrayData(init.traverser_begin(), init.shape(), 
01315                                                 p, m_alloc, MetaInt<actual_dimension-1>());
01316     }
01317     catch (...) {
01318         for (pointer pp = ptr; pp < p; ++pp)
01319             m_alloc.destroy (pp);
01320         m_alloc.deallocate (ptr, s);
01321         throw;
01322     }
01323 }
01324 
01325 template <unsigned int N, class T, class A>
01326 void MultiArray <N, T, A>::deallocate (pointer & ptr, std::size_t s)
01327 {
01328     if (ptr == 0)
01329         return;
01330     for (std::size_t i = 0; i < s; ++i)
01331         m_alloc.destroy (ptr + i);
01332     m_alloc.deallocate (ptr, s);
01333     ptr = 0;
01334 }
01335 
01336 /********************************************************/
01337 /*                                                      */
01338 /*                       NormTraits                     */
01339 /*                                                      */
01340 /********************************************************/
01341 
01342 template <unsigned int N, class T, class A>
01343 struct NormTraits<MultiArray <N, T, A> >
01344 {
01345     typedef MultiArray <N, T, A> Type;
01346     typedef typename Type::SquaredNormType SquaredNormType;
01347     typedef typename Type::NormType NormType;
01348 };
01349 
01350 /********************************************************/
01351 /*                                                      */
01352 /*              argument object factories               */
01353 /*                                                      */
01354 /********************************************************/
01355 
01356 template <unsigned int N, class T, class C>
01357 inline triple<typename MultiArrayView<N,T,C>::const_traverser,
01358               typename MultiArrayView<N,T,C>::difference_type,
01359               typename AccessorTraits<T>::default_const_accessor >
01360 srcMultiArrayRange( MultiArrayView<N,T,C> const & array )
01361 {
01362     return triple<typename MultiArrayView<N,T,C>::const_traverser,
01363                   typename MultiArrayView<N,T,C>::difference_type,
01364                   typename AccessorTraits<T>::default_const_accessor >
01365       ( array.traverser_begin(),
01366         array.shape(),
01367         typename AccessorTraits<T>::default_const_accessor() );
01368 }
01369 
01370 template <unsigned int N, class T, class C, class Accessor>
01371 inline triple<typename MultiArrayView<N,T,C>::const_traverser,
01372               typename MultiArrayView<N,T,C>::difference_type,
01373               Accessor >
01374 srcMultiArrayRange( MultiArrayView<N,T,C> const & array, Accessor a )
01375 {
01376     return triple<typename MultiArrayView<N,T,C>::const_traverser,
01377                   typename MultiArrayView<N,T,C>::difference_type,
01378                   Accessor >
01379       ( array.traverser_begin(),
01380         array.shape(),
01381         a);
01382 }
01383 
01384 template <unsigned int N, class T, class C>
01385 inline pair<typename MultiArrayView<N,T,C>::const_traverser,
01386             typename AccessorTraits<T>::default_const_accessor >
01387 srcMultiArray( MultiArrayView<N,T,C> const & array )
01388 {
01389     return pair<typename MultiArrayView<N,T,C>::const_traverser,
01390                 typename AccessorTraits<T>::default_const_accessor >
01391       ( array.traverser_begin(),
01392         typename AccessorTraits<T>::default_const_accessor() );
01393 }
01394 
01395 template <unsigned int N, class T, class C, class Accessor>
01396 inline pair<typename MultiArrayView<N,T,C>::const_traverser,
01397             Accessor >
01398 srcMultiArray( MultiArrayView<N,T,C> const & array, Accessor a )
01399 {
01400     return pair<typename MultiArrayView<N,T,C>::const_traverser,
01401                 Accessor >
01402       ( array.traverser_begin(), a );
01403 }
01404 
01405 template <unsigned int N, class T, class C>
01406 inline triple<typename MultiArrayView<N,T,C>::traverser,
01407               typename MultiArrayView<N,T,C>::difference_type,
01408               typename AccessorTraits<T>::default_accessor >
01409 destMultiArrayRange( MultiArrayView<N,T,C> & array )
01410 {
01411     return triple<typename MultiArrayView<N,T,C>::traverser,
01412                   typename MultiArrayView<N,T,C>::difference_type,
01413                   typename AccessorTraits<T>::default_accessor >
01414       ( array.traverser_begin(),
01415         array.shape(),
01416         typename AccessorTraits<T>::default_accessor() );
01417 }
01418 
01419 template <unsigned int N, class T, class C, class Accessor>
01420 inline triple<typename MultiArrayView<N,T,C>::traverser,
01421               typename MultiArrayView<N,T,C>::difference_type,
01422               Accessor >
01423 destMultiArrayRange( MultiArrayView<N,T,C> & array, Accessor a )
01424 {
01425     return triple<typename MultiArrayView<N,T,C>::traverser,
01426                   typename MultiArrayView<N,T,C>::difference_type,
01427                   Accessor >
01428       ( array.traverser_begin(),
01429         array.shape(),
01430         a );
01431 }
01432 
01433 template <unsigned int N, class T, class C>
01434 inline pair<typename MultiArrayView<N,T,C>::traverser,
01435             typename AccessorTraits<T>::default_accessor >
01436 destMultiArray( MultiArrayView<N,T,C> & array )
01437 {
01438     return pair<typename MultiArrayView<N,T,C>::traverser,
01439                 typename AccessorTraits<T>::default_accessor >
01440         ( array.traverser_begin(),
01441           typename AccessorTraits<T>::default_accessor() );
01442 }
01443 
01444 template <unsigned int N, class T, class C, class Accessor>
01445 inline pair<typename MultiArrayView<N,T,C>::traverser,
01446             Accessor >
01447 destMultiArray( MultiArrayView<N,T,C> & array, Accessor a )
01448 {
01449     return pair<typename MultiArrayView<N,T,C>::traverser,
01450                 Accessor >
01451         ( array.traverser_begin(), a );
01452 }
01453 
01454 /********************************************************/
01455 /*                                                      */
01456 /*                  makeBasicImageView                  */
01457 /*                                                      */
01458 /********************************************************/
01459 
01460 /** \addtogroup MultiArrayToImage Wrap a \ref vigra::MultiArrayView in
01461                                   a \ref vigra::BasicImageView
01462 */
01463 //@{
01464 /** Create a \ref vigra::BasicImageView from an unstrided 2-dimensional
01465     \ref vigra::MultiArrayView.
01466 
01467     The \ref vigra::BasicImageView will have the same <tt>value_type </tt>
01468     as the original \ref vigra::MultiArrayView.
01469 */
01470 template <class T>
01471 BasicImageView <T>
01472 makeBasicImageView (MultiArrayView <2, T, UnstridedArrayTag> const &array)
01473 {
01474     return BasicImageView <T> (array.data (), array.shape (0),
01475                                array.shape (1));
01476 }
01477 
01478 /** Create a \ref vigra::BasicImageView from a 3-dimensional
01479     \ref vigra::MultiArray.
01480 
01481     This wrapper flattens the two innermost dimensions of the array
01482     into single rows of the resulting image.
01483     The \ref vigra::BasicImageView will have the same <tt>value_type </tt>
01484     as the original \ref vigra::MultiArray.
01485 */
01486 template <class T>
01487 BasicImageView <T>
01488 makeBasicImageView (MultiArray <3, T> const &array)
01489 {
01490     return BasicImageView <T> (array.data (),
01491                                array.shape (0)*array.shape (1), array.shape (2));
01492 }
01493 
01494 /** Create a \ref vigra::BasicImageView from a 3-dimensional
01495     \ref vigra::MultiArray.
01496 
01497     This wrapper only works if <tt>T</tt> is a scalar type and the
01498     array's innermost dimension has size 3. It then re-interprets
01499     the data array as a 2-dimensional array with value_type
01500     <tt>RGBValue&lt; T &gt;</tt>.
01501 */
01502 template <class T>
01503 BasicImageView <RGBValue<T> >
01504 makeRGBImageView (MultiArray<3, T> const &array)
01505 {
01506     vigra_precondition (
01507         array.shape (0) == 3, "makeRGBImageView(): array.shape(0) must be 3.");
01508     return BasicImageView <RGBValue<T> > (
01509         reinterpret_cast <RGBValue <T> *> (array.data ()),
01510         array.shape (1), array.shape (2));
01511 }
01512 
01513 //@}
01514 
01515 } // namespace vigra
01516 
01517 #endif // VIGRA_MULTI_ARRAY_HXX

© Ullrich Köthe (koethe@informatik.uni-hamburg.de)
Cognitive Systems Group, University of Hamburg, Germany

html generated using doxygen and Python
VIGRA 1.3.3 (18 Aug 2005)