ivl 679
ivl/details/mfunc/padarray.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 #ifndef IVL_MFUNC_PADARRAY
00026 #define IVL_MFUNC_PADARRAY
00027 
00028 namespace ivl {
00029 
00030 //------ padarray function stuff
00031 
00033 enum padarray_direction
00034 {
00035         pre,   // pad before the array elements
00036         post,  // pad after the
00037         both   // pad both sides
00038 };
00039 
00040 enum padarray_method {
00041         circular,
00042         replicate,
00043         symmetric
00044 };
00045 
00047 template<class T, class D>
00048 typename array_nd<T, D>::NewDerived padarray(const array_nd<T, D>& in, size_array sz,
00049                  T padval = 0, padarray_direction dir = both)
00050 {
00051         // Constant pad
00052         size_t ndims = in.ndims();
00053         if(sz.length() < ndims) // \todo fix this. resize does not keep contents...
00054                 sz.resize(ndims, 0);
00055 
00056         array<index_array> indx(ndims);
00057         size_array size_b(ndims);
00058 
00059         for(size_t k = 0; k < ndims; k++) {
00060 
00061                 size_t m = in.size()[k];
00062 
00063                 switch(dir) {
00064 
00065                 case pre:
00066                         indx[k] = size_range(sz[k], sz[k] + m - 1);
00067                         size_b[k] = m + sz[k];
00068                         break;
00069 
00070                 case post:
00071                         indx[k] = size_range(0, m - 1);
00072                         size_b[k] = m + sz[k];
00073                         break;
00074 
00075                 case both:
00076                         indx[k] = size_range(sz[k], sz[k] + m - 1);
00077                         size_b[k] = m + 2 * sz[k];
00078 
00079                 } // switch(dir)
00080         } //for
00081 
00082         typename array_nd<T, D>::NewDerived b(size_b, padval);
00083         b(indx) = in;
00084         return b;
00085 }
00086 
00087 //---- padarray helper functions
00088 
00089 namespace array_nd_details {
00090 
00091 template <class T, class D>
00092 typename array_nd<T, D>::create_new circular_pad(
00093                         const array_nd<T, D>& in, size_array sz,
00094                         padarray_direction dir = both)
00095 {
00096         size_t ndims = in.ndims();
00097         if(sz.length() < ndims)
00098                 sz.resize(ndims, 0);
00099 
00100         array<index_array> indx(ndims);
00101         size_t k;
00102 
00103         for(k = 0; k < ndims; k++) {
00104 
00105                 size_t m = in.size()[k];
00106                 size_t p = sz[k];
00107 
00108                 switch(dir) {
00109 
00110                 case pre:
00111                         indx[k] = ivl::cast<size_t>(mod(array<int>(
00112                                 range<int>(-int(p), int(m) - 1)), int(m)));
00113                         break;
00114 
00115                 case post:
00116                         indx[k] = mod(size_array(ivl::rng(0, m + p - 1)), m);
00117                         break;
00118 
00119                 case both:
00120                         indx[k] = ivl::cast<size_t>(mod(array<int>(
00121                                 range<int>(-int(p), int(m) + int(p) - 1)),
00122                                 int(m)));
00123 
00124                 } //switch
00125         } //for
00126 
00127         return typename array_nd<T, D>::create_new(in(indx));
00128 }
00129 
00130 // Does symmetric pad for padarray
00131 template <class T, class D>
00132 typename array_nd<T, D>::create_new symmetric_pad(
00133         const array_nd<T, D>& in, size_array sz,
00134         padarray_direction dir = both)
00135 {
00136         size_t ndims = in.ndims();
00137         if(sz.length() < ndims)
00138                 sz.resize(ndims, 0);
00139 
00140         array<index_array> indx(ndims);
00141         size_t k;
00142 
00143         for(k = 0; k < ndims; k++) {
00144 
00145                 size_t m = in.size()[k];
00146                 size_t p = sz[k];
00147 
00148                 switch(dir) {
00149 
00150                 case pre:
00151                         indx[k] = ivl::cast<size_t>(mod(array<int>(
00152                                 range<int>(-int(p), int(m) - 1)), 2 * int(m)));
00153                         break;
00154 
00155                 case post:
00156                         indx[k] = mod(size_array(rng(0, m + p - 1)), 2 * m);
00157                         break;
00158 
00159                 case both:
00160                         indx[k] = ivl::cast<size_t>(mod(array<int>(
00161                                 range<int>(-int(p), int(m) + int(p) - 1)),
00162                                 2 * int(m)));
00163 
00164                 } //switch
00165 
00166                 size_t idx_len = indx[k].length();
00167                 index_array& ia(indx[k]);
00168 
00169                 for(size_t j = 0; j < idx_len; j++) {
00170                         if(ia[j] >= m)
00171                                 ia[j] = 2 * m - ia[j] - 1;
00172                 }
00173         } //for
00174 
00175         return typename array_nd<T, D>::create_new(in(indx));
00176 }
00177 
00178 template <class T, class D>
00179 typename array_nd<T, D>::create_new replicate_pad(
00180                         const array_nd<T, D>& in, size_array sz,
00181                       padarray_direction dir = both)
00182 {
00183         size_t ndims = in.ndims();
00184         if(sz.length() < ndims)
00185                 sz.resize(ndims, 0);
00186 
00187         array<index_array> indx(ndims);
00188         size_t k;
00189 
00190         for(k = 0; k < ndims; k++) {
00191 
00192                 size_t m = in.size()[k];
00193                 size_t p = sz[k];
00194                 index_array& ia(indx[k]);
00195 
00196                 switch(dir) {
00197 
00198                 case pre:
00199                         indx[k] = size_array(p + m, size_t(0));
00200                         for(size_t j = 0; j < m; j++)
00201                                 ia[j + p] = j;
00202                         break;
00203 
00204                 case post:
00205                         indx[k] = size_array(p + m, m - 1);
00206                         for(size_t j = 0; j < m; j++)
00207                                 ia[j] = j;
00208                         break;
00209 
00210                 case both:
00211                         indx[k] = size_array(2 * p + m, m - 1);
00212                         for(size_t j = 0; j < p; j++)
00213                                 ia[j] = 0;
00214                         for(size_t j = 0; j < m; j++)
00215                                 ia[j + p] = j;
00216                 } //switch
00217         } //for
00218 
00219         return typename array_nd<T, D>::create_new(in(indx));
00220 }
00221 
00222 }; //namespace array_nd_details
00223 
00225 template <class T, class D>
00226 typename array_nd<T, D>::create_new padarray(
00227         const array_nd<T, D>& in, size_array sz,
00228         padarray_method mthd, padarray_direction dir = both)
00229 {
00230         using namespace array_nd_details;
00231 
00232         switch(mthd)
00233         {
00234         case circular:
00235                 return circular_pad(in, sz, dir);
00236                 break;
00237 
00238         case replicate:
00239                 return replicate_pad(in, sz, dir);
00240                 break;
00241 
00242         case symmetric:
00243                 return symmetric_pad(in, sz, dir);
00244         } //switch
00245 
00246         CHECK(1, etype);
00247         return typename array_nd<T, D>::create_new(in);// used only for compiler
00248 }
00249 
00250 } // namespace ivl
00251 
00252 #endif // IVL_MFUNC_PADARRAY
 All Classes Namespaces Files Functions Variables Typedefs Enumerations