image_array3d.hh

00001 // Copyright (C) 2001, 2003, 2004  EPITA Research and Development Laboratory
00002 //
00003 // This file is part of the Olena Library.  This library is free
00004 // software; you can redistribute it and/or modify it under the terms
00005 // of the GNU General Public License version 2 as published by the
00006 // Free Software Foundation.
00007 //
00008 // This library is distributed in the hope that it will be useful,
00009 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00010 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00011 // General Public License for more details.
00012 //
00013 // You should have received a copy of the GNU General Public License
00014 // along with this library; see the file COPYING.  If not, write to
00015 // the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
00016 // MA 02111-1307, USA.
00017 //
00018 // As a special exception, you may use this file as part of a free
00019 // software library without restriction.  Specifically, if other files
00020 // instantiate templates or use macros or inline functions from this
00021 // file, or you compile this file and link it with other files to
00022 // produce an executable, this file does not by itself cause the
00023 // resulting executable to be covered by the GNU General Public
00024 // License.  This exception does not however invalidate any other
00025 // reasons why the executable file might be covered by the GNU General
00026 // Public License.
00027 
00028 #ifndef OLENA_CORE_IMPL_IMAGE_ARRAY3D_HH
00029 # define OLENA_CORE_IMPL_IMAGE_ARRAY3D_HH
00030 
00031 # include <oln/core/impl/image_array.hh>
00032 # include <oln/core/image3d_size.hh>
00033 # include <oln/core/point3d.hh>
00034 
00035 namespace oln {
00036 
00038 
00039   template<class T>
00040   void
00041   pretreat_3d_data_(T*& buffer, T**& array2, T***& array,
00042                     const image3d_size& s)
00043   {
00044     precondition(s.nslices() > 0
00045                  && s.nrows() > 0
00046                  && s.ncols() > 0
00047                  && s.border() >= 0);
00048     coord nslices_eff = s.nslices() + 2 * s.border();
00049     coord nrows_eff = s.nrows() + 2 * s.border();
00050     coord ncols_eff = s.ncols() + 2 * s.border();
00051     array = new T**[size_t(nslices_eff)];
00052     array2 = new T*[size_t(nslices_eff)
00053                         * size_t(nrows_eff)];
00054     T* buf = buffer + s.border();
00055 
00056     for (coord slice = 0; slice < nslices_eff; ++slice)
00057       {
00058         T** a2 = array2 + slice * nrows_eff;
00059         array[slice] = a2 + s.border();
00060         for (coord row = 0; row < nrows_eff; ++row)
00061           {
00062             a2[row] = buf;
00063             buf += ncols_eff;
00064           }
00065       }
00066     array += s.border();
00067   }
00068 
00070 
00071   template<class T>
00072   void
00073   desallocate_3d_data_(T**& array2, T***& array, const
00074                        image3d_size& s)
00075   {
00076     delete[] array2;
00077     array2 = 0;  // security
00078     array -= s.border();
00079     delete[] array;
00080     array = 0;  // security
00081   }
00082 
00083 
00084   namespace impl {
00085     template<class T>
00086     class image_array3d;
00087   } // end of impl
00088 
00095   template<class T>
00096   struct impl_traits<impl::image_array3d<T> >: public impl_traits<impl::image_array<T, impl::image_array3d<T> > >
00097   {
00098     enum { dim = 3 };
00099     typedef point3d point_type;
00100     typedef image3d_size size_type;
00101     typedef T value_type;
00102   };
00103 
00104   namespace impl
00105   {
00106 
00112     template<class T>
00113     class image_array3d :
00114       public image_array<T, image_array3d<T> >
00115     {
00116 
00117     public:
00118 
00119       typedef image_array3d<T> self_type;
00120       typedef image_array3d<T> exact_type;
00121 
00122       typedef typename impl_traits<exact_type>::point_type point_type;
00123       typedef typename impl_traits<exact_type>::value_type value_type;
00124       typedef typename impl_traits<exact_type>::size_type size_type;
00125 
00126       typedef image_array<T, image_array3d<T> > super_type;
00127 
00128 
00129       friend class image_impl<image_array3d<T> >;
00130       friend class image_array<T, image_array3d<T> >;
00131 
00132       image_array3d(const size_type& s): super_type(s)
00133       {
00134         pretreat_3d_data_(this->buffer_, array2_, array_, s);
00135       }
00136 
00137       image_array3d() : array_(0) {}
00138 
00139       ~image_array3d()
00140       {
00141         if (array_)
00142           desallocate_3d_data_(array2_, array_, this->size_);
00143       }
00144 
00145     protected:
00146 
00148 
00149       bool
00150       hold_(const point_type& p) const
00151       {
00152         return (p.slice() >= 0
00153                 && p.slice() < this->size_.nslices()
00154                 && p.row() >= 0
00155                 && p.row() < this->size_.nrows()
00156                 && p.col() >= 0
00157                 && p.col() < this->size_.ncols());
00158       }
00159 
00161 
00162       bool
00163       hold_large_(const point_type& p) const
00164       {
00165         return (p.slice() >= -this->size_.border()
00166                 && p.slice() < this->size_.nslices() + this->size_.border()
00167                 && p.row() >= - this->size_.border()
00168                 && p.row() < this->size_.nrows() + this->size_.border()
00169                 && p.col() >= - this->size_.border()
00170                 && p.col() < this->size_.ncols() + this->size_.border());
00171       }
00172 
00174 
00175       value_type&
00176       at_(const point_type& p)
00177       {
00178 
00179         return at_(p.slice(), p.row(), p.col());
00180       }
00181 
00183 
00184       value_type&
00185       at_(coord slice, coord row, coord col)
00186       {
00187         invariant(this->buffer_ != 0);
00188         precondition_hold_large(point_type(slice, row, col));
00189         return array_[slice][row][col];
00190       }
00191 
00193 
00194       size_t
00195       len_(const size_type& s) const
00196       {
00197         coord nslices_eff = s.nslices() + 2 * s.border();
00198         coord ncols_eff = s.ncols() + 2 * s.border();
00199         coord nrows_eff = s.nrows() + 2 * s.border();
00200         return size_t(nslices_eff * nrows_eff * ncols_eff);
00201       }
00202 
00203       // borders
00204 
00209       void
00210       border_reallocate_and_copy_(coord new_border, bool
00211                                   copy_border)
00212       {
00213         T* buffer = 0;
00214         T** array2 = 0;
00215         T*** array = 0;
00216         // first allocate
00217 
00218         allocate_data_(buffer, len_(size_type(this->size_.nslices(), this->size_.nrows(),
00219                                               this->size_.ncols(), new_border)));
00220         pretreat_3d_data_(buffer, array2, array, size_type(this->size_.nslices(), this->size_.nrows(),
00221                                                              this->size_.ncols(), new_border));
00222         // move data
00223         coord border = this->size_.border();
00224         if (border > new_border)
00225           border = new_border;
00226         coord src_min_slice = copy_border ? -border : 0;
00227         coord src_max_slice = this->size_.nslices() + (copy_border ? border : 0);
00228         coord src_min_row = copy_border ? -border : 0;
00229         coord src_max_row = this->size_.nrows() + (copy_border ? border : 0);
00230         coord src_min_col = copy_border ? -border : 0;
00231         coord src_ncols = this->size_.ncols() + (copy_border ? (border * 2) : 0);
00232         for (coord slice = src_min_slice; slice < src_max_slice; ++slice)
00233           for (coord row = src_min_row; row < src_max_row; ++row)
00234             memcpy(array[slice][row],
00235                    &at_(slice, row, src_min_col),
00236                    src_ncols * sizeof(T));
00237 
00238         // then replace
00239         desallocate_data_(this->buffer_);
00240         desallocate_3d_data_(array2_, array_, this->size_);
00241         this->size_.border() = new_border;
00242         this->buffer_ = buffer;
00243         array2_ = array2;
00244         array_ = array;
00245       }
00246 
00251       void
00252       border_replicate_(void)
00253       {
00254         const coord imax = this->size_.nslices() - 1;
00255         const coord jmax = this->size_.nrows() - 1;
00256         const coord kmax = this->size_.ncols() - 1;
00257         // front & rear
00258         for (coord i = - this->size_.border(); i; ++i)
00259           for (coord j = 0; j <= jmax; ++j)
00260             for (coord k = 0; k <= kmax; ++k)
00261               {
00262                 at_(i, j, k)        = at_(0, j, k);
00263                 at_(imax - i, j, k) = at_(imax, j, k);
00264               }
00265         // top & bottom
00266         for (coord i = - this->size_.border(); i <= imax + this->size_.border(); ++i)
00267           for (coord j = - this->size_.border(); j; ++j)
00268             for (coord k = 0; k <= kmax; ++k)
00269               {
00270                 at_(i, j, k)        = at_(i, 0, k);
00271                 at_(i, jmax - j, k) = at_(i, jmax, k);
00272               }
00273         // left & right
00274         for (coord i = - this->size_.border(); i <= imax + this->size_.border(); ++i)
00275           for (coord j = - this->size_.border(); j <= jmax + this->size_.border(); ++j)
00276             for (coord k = - this->size_.border(); k; ++k)
00277               {
00278                 at_(i, j, k)        = at_(i, j, 0);
00279                 at_(i, j, kmax - k) = at_(i, j, kmax);
00280               }
00281       }
00282 
00287       void
00288       border_mirror_(void)
00289       {
00290         const coord imax = this->size_.nslices() - 1;
00291         const coord jmax = this->size_.nrows() - 1;
00292         const coord kmax = this->size_.ncols() - 1;
00293         // front & rear
00294         for (coord i = - this->size_.border(); i; ++i)
00295           for (coord j = 0; j <= jmax; ++j)
00296             for (coord k = 0; k <= kmax; ++k)
00297               {
00298                 at_(i, j, k)        = at_(- i, j, k);
00299                 at_(imax - i, j, k) = at_(imax + i, j, k);
00300               }
00301         // top & bottom
00302         for (coord i = - this->size_.border(); i <= imax + this->size_.border(); ++i)
00303           for (coord j = - this->size_.border(); j; ++j)
00304             for (coord k = 0; k <= kmax; ++k)
00305               {
00306                 at_(i, j, k)        = at_(i, - j, k);
00307                 at_(i, jmax - j, k) = at_(i, jmax + j, k);
00308               }
00309         // left & right
00310         for (coord i = - this->size_.border(); i <= imax + this->size_.border(); ++i)
00311           for (coord j = - this->size_.border(); j <= jmax + this->size_.border(); ++j)
00312             for (coord k = - this->size_.border(); k; ++k)
00313               {
00314                 at_(i, j, k)        = at_(i, j, - k);
00315                 at_(i, j, kmax - k) = at_(i, j, kmax + k);
00316               }
00317       }
00318 
00320 
00321       void
00322       border_assign_(value_type val)
00323       {
00324         const coord imax = this->size_.nslices() - 1;
00325         const coord jmax = this->size_.nrows() - 1;
00326         const coord kmax = this->size_.ncols() - 1;
00327         // front & rear
00328         for (coord i = - this->size_.border(); i; ++i)
00329           for (coord j = 0; j <= jmax; ++j)
00330             for (coord k = 0; k <= kmax; ++k)
00331               {
00332                 at_(i, j, k)        = val;
00333                 at_(imax - i, j, k) = val;
00334               }
00335         // top & bottom
00336         for (coord i = - this->size_.border(); i <= imax + this->size_.border(); ++i)
00337           for (coord j = - this->size_.border(); j; ++j)
00338             for (coord k = 0; k <= kmax; ++k)
00339               {
00340                 at_(i, j, k)        = val;
00341                 at_(i, jmax - j, k) = val;
00342               }
00343         // left & right
00344         for (coord i = - this->size_.border(); i <= imax + this->size_.border(); ++i)
00345           for (coord j = - this->size_.border(); j <= jmax + this->size_.border(); ++j)
00346             for (coord k = - this->size_.border(); k; ++k)
00347               {
00348                 at_(i, j, k)        = val;
00349                 at_(i, j, kmax - k) = val;
00350               }
00351       }
00352 
00353     private:
00354 
00355       T** array2_;
00356       T*** array_;
00357 
00358     };
00359 
00360   } // end of namespace impl
00361 
00362 } // end of namespace oln
00363 
00364 #endif // ! OLENA_CORE_IMPL_IMAGE_ARRAY3D_HH

Generated on Thu Apr 15 20:13:12 2004 for Olena by doxygen 1.3.6-20040222