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

| vigra/multi_array.hxx |
--- | --- | ---

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