[ 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.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)