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