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