aimstil  5.0.5
ImageCPT.h
Go to the documentation of this file.
1 #ifndef TIL_IMAGERLE_H
2 #define TIL_IMAGERLE_H
3 
4 // includes from STL
5 #include <cassert>
6 //#include <float.h>
7 #include <limits>
8 #include <list>
9 #include <cstring>
10 #include <vector>
11 #include <iostream>
12 
13 
14 // includes from TIL library
15 #include "til/til_common.h"
16 #include "til/Box.h"
17 #include "til/ImageBase.h"
18 #include "til/image_common.h"
19 #include "til/numeric_array.h"
20 #include "til/templateTools.h"
21 
24 //#include "til/ConstImageRLEVolumetricIterator.h"
25 //#include "til/ImageRLEVolumetricIterator.h"
26 
27 
28 // Namespace
29 namespace til {
30 
31 
33 template < typename T >
34 //class ImageRLE : public SmartObject, public ImageBase
35 class ImageRLE : public ImageBase
36 {
37 private: // typedefs
38 
39  class RepeatedValue;
40  typedef typename std::list<RepeatedValue> Line;
41  typedef typename std::vector<Line> Data;
42 
43 
44 public: // typedefs
45 
46  typedef T value_type;
47  typedef ImageRLE<T> Self;
48 
49 public: // constructors & destructor
50 
51  ImageRLE();
52  ImageRLE(int x, int y, int z, t_voxsize vx, t_voxsize vy, t_voxsize vz);
54  ImageRLE(const ImageRLE<T> *);
55  //template < typename TImage >
56  //ImageRLE(const TImage *im, typename enable_if<is_Image<TImage> >::type);
58 
59  /*
63  static Self* New() { return new Self(); }
65  static Self* New(int x, int y, int z, t_voxsize vx, t_voxsize vy, t_voxsize vz) { return new Self(x,y,z,vx,vy,vz); }
67  static Self* New(const numeric_array<int,3> &dim, const numeric_array<t_voxsize,3> &vDim) { return new Self(dim, vDim); }
69  static Self* New(const ImageParameter &param) {return new Self(param); }
70  */
71 
72 public: // initialization
73 
74  // Initialization functions
75  // Basically similar to constructors
76 
77  void init();
78  void init(int x, int y, int z, t_voxsize vx, t_voxsize vy, t_voxsize vz);
79  void init(const numeric_array<int,3> &dim, const numeric_array<t_voxsize,3> &vDim);
80  void init(const ImageRLE<T> *);
81  void init(const ImageParameter &param);
82  //template < typename TImage >
83  //void init(const TImage *im, typename enable_if<is_Image<TImage> >::type);
84 
85 public: // functions
86 
87  // Get value
88 
89  // Access (read-write) the value at point (i,j,k)
90  // Range checking is done
91 
92  INLINE T operator()(int i, int j, int k);
93  T operator()(const numeric_array<int,3> &v) { return this->operator()(EXPAND_VECTOR(v)); }
94 
96  // If point lies outside image, an exception is thrown
97  INLINE const T getValue(int i, int j, int k) const;
98  const T getValue(const numeric_array<int,3> &v) const { return this->getValue(EXPAND_VECTOR(v)); }
99 
100  INLINE void setValue(T value, int i, int j, int k);
101  void setValue(T value, const numeric_array<int,3> &v) { this->setValue(value, EXPAND_VECTOR(v)); }
102  INLINE void setUnsafeValue(T value, int i, int j, int k);
103 
105  // WARNING: No range checking!
106  T getUnsafeValue(int i, int j, int k) const;
107  T getUnsafeValue(const numeric_array<int,3> &v) const { return this->getUnsafeValue(EXPAND_VECTOR(v)); }
108 
110  bool isAllocated() const { return (!m_data.empty());}
111 
113  void reset();
114 
115  void debugLine(const Line & line) const
116  {
117  for (typename Line::const_iterator iRepValue = line.begin(); iRepValue != line.end(); ++iRepValue)
118  {
119  std::cout << "Value : " << iRepValue->getValue() << " ";
120  std::cout << "Repeat : " << iRepValue->getRepeat() << ", ";
121  }
122  std::cout << std::endl;
123  }
124 
126  void debug() const
127  {
128  for (typename Data::const_iterator iLine = m_data.begin(); iLine != m_data.end(); ++iLine)
129  {
130  this->debugLine(*iLine);
131  }
132  }
133 
134  void copy(const Self & im)
135  {
136  if (!((this->dim()[0] == im.dim()[0]) &&
137  (this->dim()[1] == im.dim()[1]) &&
138  (this->dim()[2] == im.dim()[2]) &&
139  (this->vdim()[0] == im.vdim()[0]) &&
140  (this->vdim()[1] == im.vdim()[1]) &&
141  (this->vdim()[2] == im.vdim()[2])))
142  {
143  throw std::invalid_argument("Incompatible images");
144  }
145 
146  // TODO: check wheter a simple call to std::copy on the vector would not do, i.e.
147  // get rid of the loop. Or carremently using operator=??
148  typename Data::iterator myData = m_data.begin();
149  typename Data::const_iterator imData = im.m_data.begin();
150  for(; myData != m_data.end(); ++myData, ++imData)
151  {
152  //std::copy(imData->begin(), imData->end(), myData->begin());
153  myData->assign(imData->begin(), imData->end());
154  }
155  //this->debugLine(this->getLine(this->dim()[0]-1, this->dim()[1]-1));
156  //im.debugLine(this->getLine(this->dim()[0]-1, this->dim()[1]-1));
157  }
158 
159 public: // friends
160 
161  friend class ConstLinearIterator<ImageRLE<T> >;
162  friend class LinearIterator<ImageRLE<T> >;
163 // friend class ImageRLELinearIterator<T>::m_RLEPixel;
164 
165 private: // constructors
166 
167 
168 private: // classes
169 
170  // The basic atom of run-length encoding: a structure that comprises
171  // a value, and the number of time this value is repeated.
172  // TODO: should repeat be coded on int, unsigned short,...?
173  class RepeatedValue
174  {
175  public: // typedef
176  typedef int t_repeat;
177  public: // constructors & destructor
178  RepeatedValue() : m_value(), m_repeat(0) {};
179  RepeatedValue(const T &v, t_repeat r) : m_value(v), m_repeat(r) {};
180 
181  // I think a good reason not to return a t_repeat for const is that if we
182  // do ++(x.getRepeat()) we can't be sure if the const has not actually been called!
183  const t_repeat & getRepeat() const { return m_repeat; }
184  t_repeat & getRepeat() { return m_repeat; }
185  const T & getValue() const { return m_value; }
186  T & getValue() { return m_value; }
187  private: // data
188  T m_value;
189  t_repeat m_repeat;
190  };
191 
192 private: // methods
193 
194  void allocateData()
195  {
196  // Not good: should not allocate that much!
197  /*
198  if ( this->dim()[0]<0 || this->dim()[1]<0 || this->dim()[2]<0)
199  {
200  throw std::invalid_argument("Image size < 0");
201  }
202  */
203  int nLine = this->dim()[1] * this->dim()[2];
204  m_data.resize(nLine);
205  }
206 
207  // Return a repeated value corresponding to an entire line filled with default value
208  // (zeros being an abusive shorthand).
209  RepeatedValue zeroLine()
210  {
211  RepeatedValue zeros;
212  zeros.getValue() = T();
213  zeros.getRepeat() = this->dim()[0];
214  return zeros;
215  }
216 
217  // Common operations done in init methods
218  void _init(int x, int y, int z, t_voxsize vx, t_voxsize vy, t_voxsize vz);
219 
220  void setUnsafeValue(
221  T value,
222  Line & line,
223  typename Line::iterator & iLine,
224  int & remaining // I used const just to check I didn't screw up
225  );
226 /*
227  void _setUnsafeValue(
228  T value, Line line, typename Line::iterator &iLine,
229 // typename std::list<RepeatedValue> line,
230 // typename std::list<RepeatedValue>::iterator & iLine,
231  int &remaining);
232 */
233  // Copy constructor is intentionally left undefined
234  // Non-explicit image copying is unwanted!
235  // use copy instead
236  ImageRLE(const ImageRLE<T> &);
237 
238 
239  Line & getLine(int y, int z)
240  {
241  return m_data[y + z * this->dim()[1]];
242  }
243  const Line & getLine(int y, int z) const
244  {
245  return m_data[y + z * this->dim()[1]];
246  }
247 
248  // for debuggin purposes: nb of elements on a line
249  int lineLength(const Line & line)
250  {
251  int count = 0;
252  typename Line::const_iterator iRepValue = line.begin();
253  for (; iRepValue != line.end(); ++iRepValue)
254  {
255  count += iRepValue->getRepeat();
256  }
257  return count;
258  }
259 
260 private: // data
261 
262  // data
263  Data m_data;
264 };
265 
266 
268 template < typename T >
269 struct Iterator<ImageRLE<T> >
270 {
273 };
274 
275 
276 
277 
278 
279 
280 
281 
282 
283 
284 
285 
286 
287 
288 
289 
290 
291 
292 
293 
294 
295 
296 
297 
298 
299 
300 
301 
302 
303 
304 
306 //
307 // CODE
308 //
310 
311 
312 // Constructors
313 
314 template < typename T >
316 {
317  this->init();
318 }
319 
320 template < typename T >
322 {
323 }
324 /*
325 template < typename T >
326 template < typename TImage >
327 ImageRLE<T>::ImageRLE(const TImage *im, typename enable_if<is_Image<TImage> >::type) : ImageBase()
328 {
329  this->init<TImage>(im);
330 }
331 
332 template < typename T >
333 template < typename TImage >
334 void ImageRLE<T>::init(const TImage *im, typename enable_if<is_Image<TImage> >::type)
335 {
336  return;
337 }
338 */
339 
340 template < typename T >
341 ImageRLE<T>::ImageRLE(int x, int y, int z, t_voxsize vx, t_voxsize vy, t_voxsize vz) : ImageBase()
342 {
343  this->init(x, y, z, vx, vy, vz);
344 }
345 
346 template < typename T >
347 void ImageRLE<T>::init(int x, int y, int z, t_voxsize vx, t_voxsize vy, t_voxsize vz)
348 {
349  // set dim and vdim
350  this->_init(x, y, z, vx, vy, vz);
351  // allocate data
352  this->allocateData();
353  // set data to zero
354  this->reset();
355  //std::cout << "constr " << this->getLine(this->dim()[1]-1, this->dim()[2]-1).rbegin()->getRepeat() << std::endl;
356 }
357 
358 template < typename T >
360 {
361  this->init(dim, vDim);
362 }
363 
364 template < typename T >
366 {
367  this->init(EXPAND_VECTOR(dim), EXPAND_VECTOR(vDim));
368 }
369 
370 template < typename T >
371 void ImageRLE<T>::_init(int x, int y, int z, t_voxsize vx, t_voxsize vy, t_voxsize vz)
372 {
373  this->set_dim(til::numeric_array<int, 3>(x, y, z));
374  this->set_vdim(til::numeric_array<float,3>(vx, vy, vz));
375 }
376 
377 template < typename T >
379 {
380  this->init(pIm);
381 }
382 
383 template < typename T >
385 {
386  this->init(param.m_dim, param.m_vDim);
387  //this->setOrigin(param.m_ori);
388 }
389 
390 template < typename T >
392 {
393  this->init(param(pIm));
394  m_data = pIm.p_data;
395 }
396 
397 template < typename T >
399 {
400  this->init(param);
401 }
402 
403 
404 template < typename T >
406 {
407  // Make a structure corresponding to a zero repeated dimX times
408  RepeatedValue zeros = this->zeroLine();
409 
410  // Wrap that in a list: you get an image line
411  typename std::list<RepeatedValue> emptyLine(1, zeros);
412 
413  // Push that as many times as there are lines in the image
414  int nLine = this->dim()[1] * this->dim()[2];
415  // TODO: assign might be for vectors only, check if std::fill is what we want.
416  // Also, what is the policy of assign wrt allocation?
417  m_data.assign(nLine, emptyLine);
418 }
419 
420 template < typename T >
421 INLINE T ImageRLE<T>::operator()(int i, int j, int k)
422 {
423  return this->getValue(i,j,k);
424 }
425 
426 //template < typename T >
427 //const T* ImageRLE<T>::getConstPointerOf(int i, int j, int k) const
428 //{
429 // return this->getPointerOf(i,j,k);
430 //}
431 
432 
433 
434 template < typename T >
435 INLINE const T ImageRLE<T>::getValue(int i, int j, int k) const
436 {
437  if (this->contains(numeric_array<int,3>(i,j,k)))
438  {
439  return this->getUnsafeValue(i,j,k);
440  }
441  else
442  {
443  throw std::out_of_range("Position out of image range");
444  }
445 }
446 
447 
448 template < typename T >
449 T ImageRLE<T>::getUnsafeValue(int i, int j, int k) const
450 {
451  //std::cout << "before: size " << this->getLine(this->dim()[1]-1, this->dim()[2]-1).size() << " " << this->getLine(this->dim()[1]-1, this->dim()[2]-1).rbegin()->getRepeat() << std::endl;
452  // Get the (y,z) line
453  const Line & line = this->getLine(j,k);
454  // Scan the line, and stop when the count just went over our x coordinate
455  typename std::list<RepeatedValue>::const_iterator iRepValue;
456  int current_i = 0;
457  for (iRepValue = line.begin(); iRepValue != line.end(); ++iRepValue)
458  {
459  current_i += iRepValue->getRepeat();
460  if (current_i > i)
461  {
462  return iRepValue->getValue();
463  }
464  }
465  // Well -- we scanned the line but the count never went that far!
466  // This is an error probably due to a bug, let's print some debug info.
467  std::cerr << "Problem in ImageRLE probably due to a bug\n";
468  std::cerr << "Coordinate asked: " << i << " on line ( " << j << " , " << k << " ) \n";
469  std::cerr << "Max coordinate reached: " << current_i << "\n";
470  std::cerr << "Current line: \n";
471  for (iRepValue = line.begin(); iRepValue != line.end(); ++iRepValue)
472  {
473  std::cerr << "Repeat: " << iRepValue->getRepeat() << ", value: " << iRepValue->getValue() << "\n";
474  }
475  std::cerr << std::endl;
476  //std::cout << "after " << this->getLine(this->dim()[1]-1, this->dim()[2]-1).rbegin()->getRepeat() << std::endl;
477  throw std::underflow_error("Incomplete image -- cannot return a value");
478 }
479 
480 
481 
482 template < typename T >
483 INLINE void ImageRLE<T>::setValue(T value, int i, int j, int k)
484 {
485  if (this->contains(numeric_array<int,3>(i,j,k)))
486  {
487  this->setUnsafeValue(value,i,j,k);
488  }
489  else
490  {
491  throw std::out_of_range("Index out of range");
492  }
493 }
494 
495 // NB: right now, the whole setValue setup is quite inefficient, as one would have to
496 // redo all the scanning to set another value, which might just be next to it. In order
497 // to have an efficient iterator, one should rather return the current pointer on the
498 // current Repeated value, as well as an update of the 'remaining' number. Right now
499 // this is not used anywhere (and foremost not in the iterator) so I commented out related shit).
500 // Also that would require the remaining passed by reference. Probably one should look at
501 // a cleaner way (?) to do this.
502 
503 // 'remaining' gives the 'local coordinate' inside the repeated value pointed at by iLine.
504 // remaining = 1 if the point is exactly at the end of the RepeatedValue. It is equal
505 // to repeat if it is exactly at the beginning.
506 // NB: this assumes that we have already checked that the value we put is different
507 // from the one that is already there.
508 template < typename T >
510 (
511  T value,
512  Line & line,
513  typename Line::iterator & iRepValue,
514  int & remaining
515  )
516 {
517  // If the pixel already has this value, stop here
518  if (value == iRepValue->getValue()) return;
519 
520  // Get pointers on previous and next repeated value, as well as flags indicating whether
521  // we lie at the very beginning/end of the current line
522  typename Line::iterator iRepValuePrevious = iRepValue;
523  bool atBeginning = (iRepValue == line.begin());
524  if (!atBeginning) --iRepValuePrevious;
525  bool atEnd = (iRepValue == line.end());
526  typename Line::iterator iRepValueNext = iRepValue;
527  ++iRepValueNext;
528 
529 
530  // Is the current repeated sequence made of only one element?
531  if (iRepValue->getRepeat() == 1)
532  {
533  /*
534  typename Line::iterator iRepValuePrevious = iRepValue;
535  if (iRepValue != line.begin()) --iRepValuePrevious;
536  typename Line::iterator iRepValueNext = iRepValue;
537  ++iRepValueNext;
538  */
539 
540  // Is the next value the same?
541  if (!atBeginning && iRepValueNext->getValue() == value)
542  {
543  remaining += iRepValueNext->getRepeat();
544  // Is the previous value the same?
545  if (!atEnd && iRepValuePrevious->getValue() == value)
546  {
547  // Merge all three values
548  iRepValueNext->getRepeat() += iRepValuePrevious->getRepeat()+1;
549  line.erase(iRepValuePrevious);
550  }
551  else
552  {
553  // Merge current and next
554  ++(iRepValueNext->getRepeat());
555  }
556  line.erase(iRepValue);
557  iRepValue = iRepValueNext;
558  return;
559  }
560 
561  // Is the previous value the same?
562  else if (!atBeginning && iRepValuePrevious->getValue() == value)
563  {
564  // Merge current and previous
565  line.erase(iRepValue);
566  ++(iRepValuePrevious->getRepeat());
567 
568  iRepValue = iRepValuePrevious;
569  //assert(remaining == 1);
570  //remaining = 1;
571  return; // Merge previous + 1;
572  }
573  // Then we remain a single point : simply update the value.
574  else
575  {
576  // Simply overwrite the value
577  iRepValue->getValue() = value;
578 
579  //assert(remaining == 1);
580  //remaining = 1;
581  return; // 1
582  }
583  }
584 
585  // Are we exactly at the end of current repeated sequence?
586  else if (remaining == 1)
587  {
588  //typename Line::iterator iRepValueNext = iRepValue;
589  //++iRepValueNext;
590 
591  // Then, decrease current repeat number by one
592  --(iRepValue->getRepeat());
593 
594  // and look at the next sequence
595  // If there is no next sequence, or,
596  // if the next sequence has a different value
597  if (atEnd || iRepValueNext->getValue() != value)
598  {
599  // Insert a new repeat value
600  //RepeatedValue rv;
601  //rv.value = value;
602  //rv.repeat = 1;
603 
604  iRepValue =
605  line.insert(iRepValueNext, RepeatedValue(value, 1));
606  remaining = 1;
607  return; // Split previous + 1
608  }
609  else
610  {
611  // If the next sequence has the same value, just increase
612  // its repeat number by one
613  remaining = ++(iRepValueNext->getRepeat());
614  iRepValue = iRepValueNext;
615  return; // Split previous and merge 1+next
616  }
617  }
618  // Are we at the very first of current repeated value?
619  else if (remaining == iRepValue->getRepeat())
620  {
621  //typename Line::iterator iRepValuePrevious = iRepValue;
622  //if (iRepValue != line.begin()) --iRepValuePrevious;
623 
624  // If so, decrease current repeat number by one
625  --(iRepValue->getRepeat());
626  // Set remaining to one because anyway we'll be at the end of a repvalue
627  remaining = 1;
628 
629  // Is the previous value the same?
630  if (!atBeginning && iRepValuePrevious->getValue() == value)
631  {
632  // Then just increase its repeat number
633  ++(iRepValuePrevious->getRepeat());
634 
635  iRepValue = iRepValuePrevious;
636  return; // Merge previous+1
637  }
638  else
639  {
640  // else insert a new repeat value
641  //RepeatedValue rv;
642  //rv.value = value;
643  //rv.repeat = 1;
644 
645  iRepValue =
646  line.insert(iRepValue, RepeatedValue(value, 1));
647  return; // Split 1+current
648  }
649  }
650  // we are in the middle of a repeated value
651  else
652  {
653  //assert(remaining > 1);
654  // First half
655  line.insert(iRepValue, RepeatedValue(iRepValue->getValue(), iRepValue->getRepeat()-remaining));
656  // New element
657  line.insert(iRepValue, RepeatedValue(value, 1));
658  // last half
659  iRepValue->getRepeat() = remaining-1;
660 
661  --iRepValue;
662  remaining = 1;
663  return; // split previous + 1 + next
664  }
665 }
666 
667 
668 
669 
670 template < typename T >
671 INLINE void ImageRLE<T>::setUnsafeValue(T value, int i, int j, int k)
672 {
673  // Get the (y,z) line
674  Line & line = this->getLine(j,k);
675 
676  // Loop till we reach the x coordinate
677  int current_i = 0;
678  typename Line::iterator iRepValue;
679  for (iRepValue = line.begin(); iRepValue != line.end(); ++iRepValue)
680  {
681  current_i += iRepValue->getRepeat();
682  // Check whether we finally arrived
683  if (current_i > i)
684  {
685  // We have to create this temporary variable 'coz the following function takes a reference
686  int tmp = current_i-i;
687  this->setUnsafeValue(value, line, iRepValue, tmp);
688  // Debugging stuff. TODO: remove this
689  if (this->dim()[0] != this->lineLength(line))
690  {
691  throw std::runtime_error("ImageRLE length not preserved");
692  }
693  return;
694  }
695  }
696 
697  // Well -- we couldn't reach the desired x coordinate! This is probably
698  // due to a bug.
699  throw std::underflow_error("Incomplete ImageRLE (probably a bug) -- cannot set value");
700 }
701 
702 } // namespace
703 
704 
705 #endif
706 
A trait class to assign iterators to image types.
ConstLinearIterator< ImageRLE< T > > ConstLinear
Definition: ImageCPT.h:271
bool contains(const numeric_array< int, 3 > &p) const
Definition: ImageBase.h:86
void set_dim(const numeric_array< int, 3 > &dim)
Definition: ImageBase.h:66
const numeric_array< t_voxsize, 3 > & vdim() const
get voxel size
Definition: ImageBase.h:49
#define EXPAND_VECTOR(v)
Definition: til_common.h:54
ImageParameter param(const TImage &im)
Create an ImageParameter structure out of an Image.
Definition: image_common.h:34
Collects image information to create similar images.
Definition: image_common.h:19
void setValue(T value, const numeric_array< int, 3 > &v)
Definition: ImageCPT.h:101
Image class using run-length encoded data.
Belongs to package Box Do not include directly, include til/Box.h instead.
Definition: Accumulator.h:10
INLINE T operator()(int i, int j, int k)
Definition: ImageCPT.h:421
bool isAllocated() const
Check whether data has been allocated or not.
Definition: ImageCPT.h:110
General macros, definitions and functions.
T getUnsafeValue(const numeric_array< int, 3 > &v) const
Definition: ImageCPT.h:107
numeric_array< t_voxsize, 3 > m_vDim
Voxel size.
Definition: image_common.h:25
INLINE const T getValue(int i, int j, int k) const
Get the value at point (i,j,k) for read-only purpose.
Definition: ImageCPT.h:435
void debugLine(const Line &line) const
Definition: ImageCPT.h:115
void set_vdim(const numeric_array< t_voxsize, 3 > &vdim)
Set the voxel coordinates.
Definition: ImageBase.h:58
#define INLINE
Definition: til_common.h:26
ImageRLE< T > Self
Definition: ImageCPT.h:47
T operator()(const numeric_array< int, 3 > &v)
Definition: ImageCPT.h:93
INLINE void setUnsafeValue(T value, int i, int j, int k)
Definition: ImageCPT.h:671
void debug() const
for debugging purposes
Definition: ImageCPT.h:126
void init()
Definition: ImageCPT.h:321
INLINE void setValue(T value, int i, int j, int k)
Definition: ImageCPT.h:483
void copy(const Self &im)
Definition: ImageCPT.h:134
const numeric_array< int, 3 > & dim() const
get image dimension
Definition: ImageBase.h:34
Collects common code accross all image classes.
Definition: ImageBase.h:19
const T getValue(const numeric_array< int, 3 > &v) const
Definition: ImageCPT.h:98
Collects template tools used for library implementation.
float t_voxsize
type of voxel size
Definition: ImageBase.h:13
T getUnsafeValue(int i, int j, int k) const
Get the value at point (i,j,k) for fast read-only purpose.
Definition: ImageCPT.h:449
numeric_array< int, 3 > m_dim
Image dimensions.
Definition: image_common.h:22
void reset()
Set all values to zero.
Definition: ImageCPT.h:405
LinearIterator< ImageRLE< T > > Linear
Definition: ImageCPT.h:272