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