cartodata  5.0.5
volumeutil_d.h
Go to the documentation of this file.
1 /* This software and supporting documentation are distributed by
2  * Institut Federatif de Recherche 49
3  * CEA/NeuroSpin, Batiment 145,
4  * 91191 Gif-sur-Yvette cedex
5  * France
6  *
7  * This software is governed by the CeCILL-B license under
8  * French law and abiding by the rules of distribution of free software.
9  * You can use, modify and/or redistribute the software under the
10  * terms of the CeCILL-B license as circulated by CEA, CNRS
11  * and INRIA at the following URL "http://www.cecill.info".
12  *
13  * As a counterpart to the access to the source code and rights to copy,
14  * modify and redistribute granted by the license, users are provided only
15  * with a limited warranty and the software's author, the holder of the
16  * economic rights, and the successive licensors have only limited
17  * liability.
18  *
19  * In this respect, the user's attention is drawn to the risks associated
20  * with loading, using, modifying and/or developing or reproducing the
21  * software by the user in light of its specific status of free software,
22  * that may mean that it is complicated to manipulate, and that also
23  * therefore means that it is reserved for developers and experienced
24  * professionals having in-depth computer knowledge. Users are therefore
25  * encouraged to load and test the software's suitability as regards their
26  * requirements in conditions enabling the security of their systems and/or
27  * data to be ensured and, more generally, to use and operate it in the
28  * same conditions as regards security.
29  *
30  * The fact that you are presently reading this means that you have had
31  * knowledge of the CeCILL-B license and that you accept its terms.
32  */
33 
34 #ifndef CARTODATA_VOLUME_VOLUMEUTIL_D_H
35 #define CARTODATA_VOLUME_VOLUMEUTIL_D_H
36 
46 #include <cartobase/type/converter.h> // carto::min_limit<T>()
47 #include <limits>
48 
49 /* bug in gcc 4.2, accumulate doesn't accept std::max<T> or std::min<T> as
50  argument, but accepts a function without a namespace */
51 /* in C++11 (g++ --std=c++11) std::min and std::max<T> cannot be passed to a
52  function also - because there are other variants, like
53  max( std::initializer_list<T> ilist ). */
54 
55 namespace
56 {
57  template <typename T>
58  inline
59  T internal_max( const T x, const T y )
60  { return std::max<T>( x, y ); }
61 
62  template <typename T>
63  inline
64  T internal_min( const T x, const T y )
65  { return std::min<T>( x, y ); }
66 }
67 
68 
69 namespace carto
70 {
71 
72  template <typename T> template <class UnaryFunction>
73  VolumeRef<T> VolumeUtil<T>::apply( UnaryFunction f, const VolumeRef<T> & o )
74  {
75  VolumeRef<T> res
76  ( new Volume<T>( o->getSizeX(), o->getSizeY(), o->getSizeZ(),
77  o->getSizeT() ) );
78  res->header() = o->header();
79 
80  unsigned x, nx = o->getSizeX(), y, ny = o->getSizeY(),
81  z, nz = o->getSizeZ(), t, nt = o->getSizeT();
82  T *op, *rp;
83  for( t=0; t<nt; ++t )
84  for( z=0; z<nz; ++z )
85  for( y=0; y<ny; ++y )
86  {
87  op = &o->at( 0, y, z, t );
88  rp = &res->at( 0, y, z, t );
89  for( x=0; x<nx; ++x )
90  *rp++ = f( *op++ );
91  }
92  return res;
93  }
94 
95 
96  namespace internal
97  {
98 
99  template <typename T> inline T _neutral()
100  {
101  return T();
102  }
103 
104  template<> inline int8_t _neutral<int8_t>()
105  {
106  return 0;
107  }
108 
109  template<> inline uint8_t _neutral<uint8_t>()
110  {
111  return 0;
112  }
113 
114  template<> inline int16_t _neutral<int16_t>()
115  {
116  return 0;
117  }
118 
119  template<> inline uint16_t _neutral<uint16_t>()
120  {
121  return 0;
122  }
123 
124  template<> inline int32_t _neutral<int32_t>()
125  {
126  return 0;
127  }
128 
129  template<> inline uint32_t _neutral<uint32_t>()
130  {
131  return 0;
132  }
133 
134  template<> inline float _neutral<float>()
135  {
136  return 0;
137  }
138 
139  template<> inline double _neutral<double>()
140  {
141  return 0;
142  }
143 
144  }
145 
146 
147  template <typename T> template <class BinaryFunction>
149  const VolumeRef<T> & o1,
150  const VolumeRef<T> & o2 )
151  {
152  int x, nx = o1->getSizeX(), y, ny = o1->getSizeY(),
153  z, nz = o1->getSizeZ(), t, nt = o1->getSizeT(), nx2, ny2, nz2, nt2, nx3;
154  if( o2->getSizeX() < nx )
155  {
156  nx2 = nx;
157  nx = o2->getSizeX();
158  }
159  else
160  nx2 = o2->getSizeX();
161  if( o2->getSizeY() < ny )
162  {
163  ny2 = ny;
164  ny = o2->getSizeY();
165  }
166  else
167  ny2 = o2->getSizeY();
168  if( o2->getSizeZ() < nz )
169  {
170  nz2 = nz;
171  nz = o2->getSizeZ();
172  }
173  else
174  nz2 = o2->getSizeZ();
175  if( o2->getSizeT() < nt )
176  {
177  nt2 = nt;
178  nt = o2->getSizeT();
179  }
180  else
181  nt2 = o2->getSizeT();
182 
183  VolumeRef<T> res( new Volume<T>( nx2, ny2, nz2, nt2 ) );
184  res->header() = o1->header();
185 
186  bool x1, y1, z1, x2, y2, z2;
187  T *o1p, *o2p, *rp;
188  for( t=0; t<nt2; ++t )
189  {
190  if( t >= nt )
191  if( nt == o1->getSizeT() )
192  {
193  z1 = false;
194  z2 = true;
195  }
196  else
197  {
198  z1 = true;
199  z2 = false;
200  }
201  else
202  {
203  z1 = true;
204  z2 = true;
205  }
206 
207  for( z=0; z<nz2; ++z )
208  {
209  y1 = z1;
210  y2 = z2;
211  if( z >= nz )
212  {
213  if( nz == o1->getSizeZ() )
214  y1 = false;
215  else
216  y2 = false;
217  }
218 
219  for( y=0; y<ny2; ++y )
220  {
221  x1 = y1;
222  x2 = y2;
223  if( y >= ny )
224  {
225  if( ny == o1->getSizeY() )
226  x1 = false;
227  else
228  x2 = false;
229  }
230  if( x1 )
231  o1p = &o1->at( 0, y, z, t );
232  else
233  o1p = 0;
234  if( x2 )
235  o2p = &o2->at( 0, y, z, t );
236  else
237  o2p = 0;
238  rp = &res->at( 0, y, z, t );
239 
240  /*
241  std::cout << "pos: " << t << ", " << z << ", " << y
242  << ", x1: " << x1 << ", " << y1 << ", " << z1
243  << ", x2: " << x2 << ", " << y2 << ", " << z2
244  << std::endl;
245  */
246 
247  x = 0;
248  if( x1 && x2 )
249  {
250  for( ; x<nx; ++x )
251  *rp++ = f( *o1p++, *o2p++ );
252  nx3 = nx2;
253  if( nx == o1->getSizeX() )
254  x1 = false;
255  else
256  x2 = false;
257  }
258  else if( x1 )
259  nx3 = o1->getSizeX();
260  else if( x2 )
261  nx3 = o2->getSizeX();
262  else
263  nx3 = 0;
264  if( !x1 && x2 )
265  for( ; x<nx3; ++x )
266  *rp++ = f( internal::_neutral<T>(), *o2p++ );
267  else if( x1 && !x2 )
268  for( ; x<nx3; ++x )
269  *rp++ = f( *o1p++, internal::_neutral<T>() );
270  for( ; x<nx2; ++x )
271  *rp++ = f( internal::_neutral<T>(),
272  internal::_neutral<T>() );
273  }
274  }
275  }
276  return res;
277  }
278 
279 
280  template <typename T> template <class UnaryFunction>
281  void VolumeUtil<T>::selfApply( UnaryFunction f, VolumeRef<T> & o )
282  {
283  int x, nx = o->getSizeX(), y, ny = o->getSizeY(),
284  z, nz = o->getSizeZ(), t, nt = o->getSizeT();
285  T *op;
286  for( t=0; t<nt; ++t )
287  for( z=0; z<nz; ++z )
288  for( y=0; y<ny; ++y )
289  {
290  op = &o->at( 0, y, z, t );
291  for( x=0; x<nx; ++x, ++op )
292  *op = f( *op );
293  }
294  }
295 
296 
297  template <typename T> template <class BinaryFunction>
298  void VolumeUtil<T>::selfApply( BinaryFunction f, VolumeRef<T> & o1,
299  const VolumeRef<T> & o2 )
300  {
301  int x, nx = o1->getSizeX(), y, ny = o1->getSizeY(),
302  z, nz = o1->getSizeZ(), t, nt = o1->getSizeT();
303 
304  if( o2->getSizeX() < nx )
305  nx = o2->getSizeX();
306  if( o2->getSizeY() < ny )
307  ny = o2->getSizeY();
308  if( o2->getSizeZ() < nz )
309  nz = o2->getSizeZ();
310  if( o2->getSizeT() < nt )
311  nt = o2->getSizeT();
312 
313  T *o1p, *o2p;
314  for( t=0; t<nt; ++t )
315  for( z=0; z<nz; ++z )
316  for( y=0; y<ny; ++y )
317  {
318  o1p = &o1->at( 0, y, z, t );
319  o2p = &o2->at( 0, y, z, t );
320  for( x=0; x<nx; ++x, ++o1p )
321  *o1p = f( *o1p, *o2p++ );
322  }
323  }
324 
325 
326  template <typename T> template <class BinaryFunction>
327  T VolumeUtil<T>::accumulate( BinaryFunction f,
328  const Volume<T> & o, T initial )
329  {
330  T res = initial;
331 
332  unsigned x, nx = o.getSizeX(), y, ny = o.getSizeY(),
333  z, nz = o.getSizeZ(), t, nt = o.getSizeT();
334  const T *op;
335  for( t=0; t<nt; ++t )
336  for( z=0; z<nz; ++z )
337  for( y=0; y<ny; ++y )
338  {
339  op = &o.at( 0, y, z, t );
340  for( x=0; x<nx; ++x )
341  res = f( *op++, res );
342  }
343  return res;
344  }
345 
346 
347  template <typename T>
349  {
351  internal_min<T>, o, std::numeric_limits<T>::max() );
352  }
353 
354  template <typename T>
356  {
358  internal_max<T>, o, min_limit<T>() );
359  }
360 
361 #if 0
362  // VolumeUtil declarations (needed on Mac)
363  extern template VolumeRef<VoxelRGB>
365  const VolumeRef<VoxelRGB> & );
366  extern template void
369  extern template VolumeRef<VoxelRGB>
370  VolumeUtil<VoxelRGB>::apply( std::plus<VoxelRGB>, const VolumeRef<VoxelRGB> &,
371  const VolumeRef<VoxelRGB> & );
372  extern template void
374  const VolumeRef<VoxelRGB> & );
375  extern template VolumeRef<VoxelRGB>
377  std::plus<VoxelRGB> >,
378  const VolumeRef<VoxelRGB> & );
379  extern template void
381  std::plus<VoxelRGB> >, VolumeRef<VoxelRGB> & );
382  extern template VolumeRef<VoxelRGB>
384  std::plus<VoxelRGB> >,
385  const VolumeRef<VoxelRGB> & );
386  extern template VolumeRef<VoxelRGB>
387  VolumeUtil<VoxelRGB>::apply( std::minus<VoxelRGB>, const VolumeRef<VoxelRGB> &,
388  const VolumeRef<VoxelRGB> & );
389  extern template void
390  VolumeUtil<VoxelRGB>::selfApply( std::minus<VoxelRGB>, VolumeRef<VoxelRGB> &,
391  const VolumeRef<VoxelRGB> & );
392  extern template VolumeRef<VoxelRGB>
394  std::minus<VoxelRGB> >,
395  const VolumeRef<VoxelRGB> & );
396  extern template void
398  std::minus<VoxelRGB> >,
400  extern template VolumeRef<VoxelRGB>
402  std::minus<VoxelRGB> >,
403  const VolumeRef<VoxelRGB> & );
404 
405  extern template VolumeRef<VoxelRGBA>
407  const VolumeRef<VoxelRGBA> & );
408  extern template void
411  extern template VolumeRef<VoxelRGBA>
412  VolumeUtil<VoxelRGBA>::apply( std::plus<VoxelRGBA>,
413  const VolumeRef<VoxelRGBA> &,
414  const VolumeRef<VoxelRGBA> & );
415  extern template void
417  const VolumeRef<VoxelRGBA> & );
418  extern template VolumeRef<VoxelRGBA>
420  std::plus<VoxelRGBA> >,
421  const VolumeRef<VoxelRGBA> & );
422  extern template void
424  std::plus<VoxelRGBA> >,
426  extern template VolumeRef<VoxelRGBA>
428  std::plus<VoxelRGBA> >,
429  const VolumeRef<VoxelRGBA> & );
430  extern template VolumeRef<VoxelRGBA>
431  VolumeUtil<VoxelRGBA>::apply( std::minus<VoxelRGBA>,
432  const VolumeRef<VoxelRGBA> &,
433  const VolumeRef<VoxelRGBA> & );
434  extern template void
435  VolumeUtil<VoxelRGBA>::selfApply( std::minus<VoxelRGBA>,
437  const VolumeRef<VoxelRGBA> & );
438  extern template VolumeRef<VoxelRGBA>
440  std::minus<VoxelRGBA> >,
441  const VolumeRef<VoxelRGBA> & );
442  extern template void
444  std::minus<VoxelRGBA> >,
446  extern template VolumeRef<VoxelRGBA>
448  std::minus<VoxelRGBA> >,
449  const VolumeRef<VoxelRGBA> & );
450 #endif
451 
452 }
453 
454 #endif
455 
N-D Volume main class.
uint32_t _neutral< uint32_t >()
Definition: volumeutil_d.h:129
float _neutral< float >()
Definition: volumeutil_d.h:134
int getSizeZ() const
Definition: volumeproxy.h:107
const T & at(long x, long y=0, long z=0, long t=0) const
static VolumeRef< T > apply(UnaryFunction f, const VolumeRef< T > &o)
applies a unary function to each voxel of a volume
Definition: volumeutil_d.h:73
double _neutral< double >()
Definition: volumeutil_d.h:139
int32_t _neutral< int32_t >()
Definition: volumeutil_d.h:124
int8_t _neutral< int8_t >()
Definition: volumeutil_d.h:104
T max(const Volume< T > &vol)
Returns the maximum value of the volume.
Definition: volumeutil.h:762
Convenient handle for a Volume - this is normally the entry point for all volumes handling...
uint8_t _neutral< uint8_t >()
Definition: volumeutil_d.h:109
Scaler functor.
Definition: volumeutil.h:1141
int getSizeX() const
Definition: volumeproxy.h:87
T min(const Volume< T > &vol)
Returns the minimum value of the volume.
Definition: volumeutil.h:744
const T & at(long x, long y=0, long z=0, long t=0) const
const PropertySet & header() const
uint16_t _neutral< uint16_t >()
Definition: volumeutil_d.h:119
int16_t _neutral< int16_t >()
Definition: volumeutil_d.h:114
int getSizeY() const
Definition: volumeproxy.h:97
static T accumulate(BinaryFunction f, const VolumeRef< T > &o2, T initial)
Apply a binary function to each voxel of the volume, with a "current" value as second argument...
Definition: volumeutil.h:1272
int getSizeT() const
Definition: volumeproxy.h:117
static void selfApply(UnaryFunction f, VolumeRef< T > &o)
same as apply() except that the input volume is used to store the result
Definition: volumeutil_d.h:281