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