ivl 679
ivl/details/array_nd/impl/specialization/array_nd_image_class.hpp
00001 /* This file is part of the ivl C++ library <http://image.ntua.gr/ivl>.
00002    A C++ template library extending syntax towards mathematical notation.
00003 
00004    Copyright (C) 2012 Yannis Avrithis <iavr@image.ntua.gr>
00005    Copyright (C) 2012 Kimon Kontosis <kimonas@image.ntua.gr>
00006 
00007    ivl is free software; you can redistribute it and/or modify
00008    it under the terms of the GNU Lesser General Public License 
00009    version 3 as published by the Free Software Foundation.
00010 
00011    Alternatively, you can redistribute it and/or modify it under the terms 
00012    of the GNU General Public License version 2 as published by the Free 
00013    Software Foundation.
00014 
00015    ivl is distributed in the hope that it will be useful,
00016    but WITHOUT ANY WARRANTY; without even the implied warranty of
00017    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
00018    See the GNU General Public License for more details.
00019 
00020    You should have received a copy of the GNU General Public License 
00021    and a copy of the GNU Lesser General Public License along 
00022    with ivl. If not, see <http://www.gnu.org/licenses/>. */
00023 
00024 
00025 namespace data {
00026 
00027 template<int N>
00028 struct get_channels
00029 {
00030         template<class A>
00031         inline static size_t from (const A& a) { return N; }
00032 };
00033 
00034 template<>
00035 struct get_channels<0>
00036 {
00037         template<class A>
00038         inline static size_t from (const A& a) { return a[2]; }
00039 };
00040 
00041 template<int N>
00042 struct image_stride_2
00043 {
00044         size_t s;
00045         image_stride_2(size_t sz0, size_t sz1) : s(sz0 * sz1) { }
00046         inline const size_t& get() const { return s; }
00047 };
00048 
00049 template<>
00050 struct image_stride_2<1>
00051 {
00052         image_stride_2(size_t sz0, size_t sz1) { }
00053         inline size_t get() const { return 0; }
00054 };
00055 
00056 
00057 }; //namespace data
00058 
00059 
00078 template <class T,
00079                  int N,
00080                  class DERIVED_INFO
00081              >
00082 
00083 class array_nd<T, data::normal_image<N, DERIVED_INFO> >
00084         :
00085         public
00086         array_common_base<array_nd<T,
00087                 data::normal_image<N, DERIVED_INFO> > >,
00088 
00089         public
00090         array_nd_details::basic_iterator_nd_interface<array_nd<T,
00091                 data::normal_image<N, DERIVED_INFO> > >
00092 {
00093 private:
00094         typedef array_nd prv_this_type;
00095         typedef typename prv_this_type::common_base_class common_base_class;
00096         typedef typename prv_this_type::iter_nd_interface_class iter_nd_interface;
00097 
00099         size_dims<3> sizes;
00100 
00101         data::image_stride_2<N> stride_2;
00102 
00103         // disable 1-dim resize functions for this type of array
00104 
00106         void resize(const size_t newsize, const T& s);
00107 
00109         void resize(const size_t newsize);
00110 
00111 protected:
00112 
00113         // faster access to specific members
00114         inline size_t get_channels() const { return data::get_channels<N>(sizes); }
00115 
00116         inline size_t get_stride2() const { return stride_2.get(); }
00117 
00118 public:
00119         typedef array_nd this_type;
00120 
00121         typedef this_type this_array_nd_type;
00122 
00123         typedef typename common_base_class::derived_type derived_type;
00124 
00125         typedef typename common_base_class::base_class base_class;
00126 
00127         typedef this_type array_type;
00128 
00130         typedef array<size_t, tiny> size_type;
00131 
00133         typedef const size_dims<3>& size_nd_ref_type;
00134 
00136         typedef array<size_t, tiny> stride_ref_type;
00137 
00139         typedef types::t_false has_1d_parenthesis;
00140         typedef types::t_false has_2d_parenthesis;
00141         typedef types::t_true has_3d_parenthesis;
00142         typedef types::t_false has_nd_parenthesis;
00143 
00144         using base_class::derived;
00145 
00147         base_class& base() { return *this; }
00148         const base_class& base() const { return *this; }
00149 
00156         using base_class::operator[];
00157         using base_class::length;
00158         using base_class::numel;
00159 
00160         using common_base_class::operator();
00161 
00168         T& operator()(size_t s1, size_t s2, size_t s3 = 0)
00169         {
00170                 CHECK(s3 < data::get_channels<N>::from(sizes), erange);
00171                 CHECK(s2 < sizes[1], erange);
00172                 CHECK(s1 < sizes[0], erange);
00173                 return derived()[s1 + sizes[0] * s2 + get_stride2() * s3];
00174         }
00175 
00178         template<class S>
00179         T& operator()(const array<size_t, S>& indx)
00180         {
00181                 CHECK(indx.length() == 2 + (N != 1) || indx.length() == 3, edims);
00182                 CHECK(indx.length() == 2 ||
00183                         indx[2] < data::get_channels<N>::from(sizes), erange);
00184                 CHECK(indx[1] < sizes[1], erange);
00185                 CHECK(indx[0] < sizes[0], erange);
00186 
00187                 return derived()[indx[0] + sizes[0] * indx[1] +
00188                         get_stride2() * indx[2]];
00189         }
00190 
00191         const T& operator()(size_t s1, size_t s2, size_t s3 = 0) const
00192         {
00193                 CHECK(s3 < data::get_channels<N>::from(sizes), erange);
00194                 CHECK(s2 < sizes[1], erange);
00195                 CHECK(s1 < sizes[0], erange);
00196                 return derived()[s1 + sizes[0] * s2 + get_stride2() * s3];
00197         }
00198 
00201         template<class S>
00202         const T& operator()(const array<size_t, S>& indx) const
00203         {
00204                 CHECK(indx.length() == 2 + (N != 1) || indx.length() == 3, edims);
00205                 CHECK(indx.length() == 2 ||
00206                         indx[2] < data::get_channels<N>::from(sizes), erange);
00207                 CHECK(indx[1] < sizes[1], erange);
00208                 CHECK(indx[0] < sizes[0], erange);
00209 
00210                 return derived()[indx[0] + sizes[0] * indx[1] +
00211                         get_stride2() * indx[2]];
00212         }
00214 
00215 
00219 
00220         array_nd() : sizes(0, 0, 0), stride_2(0, 0) {};
00221 
00224 
00225         template<class S>
00226         array_nd(const array<size_t, S>& sz) :
00227                 common_base_class(sz[0] * sz[1] * data::get_channels<N>::from(sz)),
00228                 sizes(sz[0], sz[1], data::get_channels<N>::from(sz)),
00229                 stride_2(sz[0], sz[1])
00230                 { CHECK((sz.length() == 2 + (N != 1)) ||
00231                         ((N == 1) && sz.length() == 3 && sz[2] == 1), edims); }
00232 
00235         template<class S>
00236         array_nd(const array<size_t, S>& sz, const T& s) :
00237                 common_base_class(sz[0] * sz[1] * data::get_channels<N>::from(sz), s),
00238                 sizes(sz[0], sz[1], data::get_channels<N>::from(sz)),
00239                 stride_2(sz[0], sz[1])
00240                 { CHECK((sz.length() == 2 + (N != 1)) ||
00241                         ((N == 1) && sz.length() == 3 && sz[2] == 1), edims); }
00242 
00245         template<class S>
00246         array_nd(const array<size_t, S>& sz, const T* ptr) :
00247                 common_base_class(sz[0] * sz[1] * data::get_channels<N>::from(sz), ptr),
00248                 sizes(sz[0], sz[1], data::get_channels<N>::from(sz)),
00249                 stride_2(sz[0], sz[1])
00250                 { CHECK((sz.length() == 2 + (N != 1)) ||
00251                         ((N == 1) && sz.length() == 3 && sz[2] == 1), edims); }
00252 
00255         template<class S, class J, class D>
00256         array_nd(const array<size_t, S>& sz, const array<J, D>& a) :
00257                 common_base_class(sz[0] * sz[1] * data::get_channels<N>::from(sz), a),
00258                 sizes(sz[0], sz[1], data::get_channels<N>::from(sz)),
00259                 stride_2(sz[0], sz[1])
00260                 { CHECK((sz.length() == 2 + (N != 1)) ||
00261                         ((N == 1) && sz.length() == 3 && sz[2] == 1), edims); }
00262 
00264         array_nd(const this_type& a) :
00265                 common_base_class(a), sizes(a.sizes), stride_2(a.stride_2) {};
00266 
00268         template<class J, class S>
00269         array_nd(const array_nd<J, S>& a) :
00270                 common_base_class(a),
00271                 sizes(a.size_nd()[0], a.size_nd()[1],
00272                         data::get_channels<N>::from(a.size_nd())),
00273                 stride_2(a.size_nd()[0], a.size_nd()[1])
00274                 { CHECK((a.size_nd().length() == 2 + (N != 1)) || ((N == 1)
00275                         && a.size_nd().length() == 3 && a.size_nd()[2] == 1), edims); }
00276 
00277 #ifdef IVL_MATLAB
00278 
00287         array_nd(const mxArray* mx);
00288 #endif
00289 
00290 
00298 
00299         size_nd_ref_type size_nd() const
00300         {
00301                 return sizes;
00302         }
00303 
00305         size_t size_nd(size_t d) const
00306         {
00307                 return sizes[d];
00308         }
00309 
00311         stride_ref_type stride() const
00312         {
00313                 return size_dims<3>(1, sizes[0], get_stride2());
00314         }
00315 
00317         size_t stride(size_t dim) const
00318         {
00319                 return (dim == 0 ? 1 : (dim == 1 ? sizes[0] : get_stride2()));
00320         }
00321 
00323         size_type size() const { return size_nd(); }
00325         size_t size(size_t d) const { return sizes[d]; }
00326 
00328         size_t ndims() const { return 3; }
00335 
00336         template <class S>
00337         void resize(const array<size_t, S>& newsize, const T& s);
00338 
00340         template <class S>
00341         void resize(const array<size_t, S>& newsize);
00342 
00344         template <class S>
00345         void reshape(const array<size_t, S>& newsize, const T& s);
00346 
00348         template <class S>
00349         void reshape(const array<size_t, S>& newsize);
00352         // Operators
00353 
00358         using common_base_class::operator=;
00360         this_type& operator=(const this_type& in)
00361         { common_base_class::operator=(in); return *this; }
00362 
00367 };
00368 
00369 
00370 template <class T, int N, class P>
00371 template <class S>
00372 void array_nd<T, data::normal_image<N, P> >
00373 ::resize(const array<size_t, S>& sz)
00374 {
00375         CHECK((sz.length() == 2 + (N != 1)) ||
00376                 ((N == 1) && sz.length() == 3 && sz[2] == 1), edims);
00377         // call array data class resize first
00378         base_class::resize(sz[0] * sz[1] * data::get_channels<N>::from(sz));
00379 
00380         sizes[0] = sz[0];
00381         sizes[1] = sz[1];
00382         sizes[2] = data::get_channels<N>::from(sz);
00383         stride_2 = data::image_stride_2<N>(sizes[0], sizes[1]);
00384 }
00385 
00386 template <class T, int N, class P>
00387 template <class S>
00388 void array_nd<T, data::normal_image<N, P> >
00389 ::resize(const array<size_t, S>& sz, const T& s)
00390 {
00391         CHECK((sz.length() == 2 + (N != 1)) ||
00392                 ((N == 1) && sz.length() == 3 && sz[2] == 1), edims);
00393         // call array data class resize first
00394         base_class::resize(sz[0] * sz[1] * data::get_channels<N>::from(sz), s);
00395 
00396         sizes[0] = sz[0];
00397         sizes[1] = sz[1];
00398         sizes[2] = data::get_channels<N>::from(sz);
00399         stride_2 = data::image_stride_2<N>(sizes[0], sizes[1]);
00400 }
00401 
00402 
00403 template <class T, int N, class P>
00404 template <class S>
00405 void array_nd<T, data::normal_image<N, P> >
00406 ::reshape(const array<size_t, S>& sz)
00407 {
00408         CHECK((sz.length() == 2 + (N != 1)) ||
00409                 ((N == 1) && sz.length() == 3 && sz[2] == 1), edims);
00410         // call array data class resize first
00411         base_class::reshape(sz[0] * sz[1] * data::get_channels<N>::from(sz));
00412 
00413         sizes[0] = sz[0];
00414         sizes[1] = sz[1];
00415         sizes[2] = data::get_channels<N>::from(sz);
00416         stride_2 = data::image_stride_2<N>(sizes[0], sizes[1]);
00417 }
00418 
00419 template <class T, int N, class P>
00420 template <class S>
00421 void array_nd<T, data::normal_image<N, P> >
00422 ::reshape(const array<size_t, S>& sz, const T& s)
00423 {
00424         CHECK((sz.length() == 2 + (N != 1)) ||
00425                 ((N == 1) && sz.length() == 3 && sz[2] == 1), edims);
00426         // call array data class resize first
00427         base_class::reshape(sz[0] * sz[1] * data::get_channels<N>::from(sz), s);
00428 
00429         sizes[0] = sz[0];
00430         sizes[1] = sz[1];
00431         sizes[2] = data::get_channels<N>::from(sz);
00432         stride_2 = data::image_stride_2<N>(sizes[0], sizes[1]);
00433 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations