[ VIGRA Homepage | Function Index | Class Index | Namespaces | File List | Main Page ]

imagecontainer.hxx
1 /************************************************************************/
2 /* */
3 /* Copyright 1998-2002 by Ullrich Koethe */
4 /* */
5 /* This file is part of the VIGRA computer vision library. */
6 /* The VIGRA Website is */
7 /* http://hci.iwr.uni-heidelberg.de/vigra/ */
8 /* Please direct questions, bug reports, and contributions to */
9 /* ullrich.koethe@iwr.uni-heidelberg.de or */
10 /* vigra@informatik.uni-hamburg.de */
11 /* */
12 /* Permission is hereby granted, free of charge, to any person */
13 /* obtaining a copy of this software and associated documentation */
14 /* files (the "Software"), to deal in the Software without */
15 /* restriction, including without limitation the rights to use, */
16 /* copy, modify, merge, publish, distribute, sublicense, and/or */
17 /* sell copies of the Software, and to permit persons to whom the */
18 /* Software is furnished to do so, subject to the following */
19 /* conditions: */
20 /* */
21 /* The above copyright notice and this permission notice shall be */
22 /* included in all copies or substantial portions of the */
23 /* Software. */
24 /* */
25 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND */
26 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES */
27 /* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */
28 /* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT */
29 /* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */
30 /* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */
31 /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */
32 /* OTHER DEALINGS IN THE SOFTWARE. */
33 /* */
34 /************************************************************************/
35 
36 #ifndef VIGRA_IMAGECONTAINER_HXX
37 #define VIGRA_IMAGECONTAINER_HXX
38 
39 #include "utilities.hxx"
40 #include "array_vector.hxx"
41 #include "copyimage.hxx"
42 
43 namespace vigra {
44 
45 /** \addtogroup ImageContainers Image Containers
46  Classes to manage multiple images (ImageArray..)
47 */
48 //@{
49 
50 /********************************************************/
51 /* */
52 /* ImageArray */
53 /* */
54 /********************************************************/
55 
56 /** \brief Fundamental class template for arrays of equal-sized images.
57 
58  An ImageArray manages an array of images of the type given as
59  template parameter. Use it like a ArrayVector<ImageType>, it has
60  the same interface, only operator< is missing from ImageArray. It
61  offers additional functions for resizing the images and querying
62  their common size. See \ref imageSize() for additional notes.
63 
64  A custimized allocator can be passed as a template argument and via the constructor.
65  By default, the allocator of the <tt>ImageType</tt> is reused.
66 
67  <b>\#include</b> <<a href="imagecontainer_8hxx-source.html">vigra/imagecontainer.hxx</a>>
68 
69  Namespace: vigra
70 */
71 template <class ImageType,
72  class Alloc = typename ImageType::allocator_type::template rebind<ImageType>::other >
74 {
75  Size2D imageSize_;
76 
77 protected:
79  ImageVector images_;
80 
81 public:
82  /** the type of the contained values/images
83  */
84  typedef ImageType value_type;
85 
86  typedef typename ImageVector::iterator iterator;
87  typedef typename ImageVector::const_iterator const_iterator;
88  typedef typename ImageVector::reverse_iterator reverse_iterator;
89  typedef typename ImageVector::const_reverse_iterator const_reverse_iterator;
90  typedef typename ImageVector::reference reference;
91  typedef typename ImageVector::const_reference const_reference;
92 #if !defined(_MSC_VER) || _MSC_VER >= 1300
93  typedef typename ImageVector::pointer pointer;
94 #endif
95  typedef typename ImageVector::difference_type difference_type;
96  typedef typename ImageVector::size_type size_type;
97 
98  /** init an array of numImages equal-sized images; use the specified allocator.
99  */
100  ImageArray(unsigned int numImages, const Diff2D &imageSize,
101  Alloc const & alloc = Alloc())
102  : imageSize_(imageSize),
103  images_(numImages, ImageType(), alloc)
104  {
105  for(unsigned int i=0; i<numImages; i++)
106  images_[i].resize(Size2D(imageSize));
107  }
108 
109  /** Init an array of numImages equal-sized images. The size
110  depends on ImageType's default constructor (so it will
111  usually be 0x0); use the specified allocator.
112  */
113  ImageArray(unsigned int numImages= 0, Alloc const & alloc = Alloc())
114  : images_(numImages, alloc)
115  {
116  imageSize_= empty()? Size2D(0, 0) : front().size();
117  }
118 
119  /** fill constructor: Init an array with numImages copies of
120  the given image. (STL-Sequence interface); use the specified allocator.
121  */
122  ImageArray(unsigned int numImages, const ImageType &image, Alloc const & alloc = Alloc())
123  : imageSize_(image.size()),
124  images_(numImages, image, alloc)
125  {
126  }
127 
128  /** range constructor: Construct an array containing copies of
129  the images in [begin, end). Those images must all have the
130  same size, see \ref imageSize(). (STL-Sequence interface);
131  use the specified allocator.
132  */
133  template<class InputIterator>
134  ImageArray(InputIterator begin, InputIterator end, Alloc const & alloc = Alloc())
135  : imageSize_(begin!=end? (*begin).size() : Size2D(0,0)),
136  images_(begin, end, alloc)
137  {
138  }
139 
140  virtual ~ImageArray() {}
141 
142  /** Operator for a vector-like access to the contained images
143  (STL-Vector interface)
144  */
145  reference operator [](size_type index)
146  {
147  return images_[index];
148  }
149 
150  /** Operator for a vector-like access to the contained images
151  (STL-Vector interface)
152  */
153  const_reference operator [](size_type index) const
154  {
155  return images_[index];
156  }
157 
158  /** Returns an iterator pointing to the first image
159  (STL-Container interface)
160  */
161  iterator begin()
162  {
163  return images_.begin();
164  }
165 
166  /** Returns an iterator pointing to the first image
167  (STL-Container interface)
168  */
169  const_iterator begin() const
170  {
171  return images_.begin();
172  }
173 
174  /** Returns an iterator pointing behind the last image
175  (STL-Container interface)
176  */
177  iterator end()
178  {
179  return images_.end();
180  }
181 
182  /** Returns an iterator pointing behind the last image
183  (STL-Container interface)
184  */
185  const_iterator end() const
186  {
187  return images_.end();
188  }
189 
190  /** Returns a reverse_iterator pointing to the first image of
191  the reversed view of this array (STL-Reversable Container
192  interface)
193  */
194  reverse_iterator rbegin()
195  {
196  return images_.rbegin();
197  }
198 
199  /** Returns a reverse_iterator pointing to the first image of
200  the reversed view of this array (STL-Reversable Container
201  interface)
202  */
203  const_reverse_iterator rbegin() const
204  {
205  return images_.rbegin();
206  }
207 
208  /** Returns a reverse_iterator pointing behind the last image
209  of the reversed view of this array (STL-Reversable
210  Container interface)
211  */
212  reverse_iterator rend()
213  {
214  return images_.rend();
215  }
216 
217  /** Returns a reverse_iterator pointing behind the last image
218  of the reversed view of this array (STL-Reversable
219  Container interface)
220  */
221  const_reverse_iterator rend() const
222  {
223  return images_.rend();
224  }
225 
226  /** Query size of this ImageArray, that is: the number of
227  images. (STL-Container interface)
228  */
229  size_type size() const
230  {
231  return images_.size();
232  }
233 
234  /** Query maximum size of this ImageArray, that is: the
235  max. parameter you may pass to resize(). (STL-Container
236  interface)
237  */
238  size_type max_size() const
239  {
240  return images_.max_size();
241  }
242 
243  /** Returns true if and only if there are no contained
244  images. (STL-Container interface)
245  */
246  bool empty()
247  {
248  return images_.empty();
249  }
250 
251  /** Returns true if and only if both ImageArrays have exactly
252  the same contents and all images did compare equal with the
253  corresponding image in the other ImageArray. (STL-Forward
254  Container interface)
255  */
257  {
258  return (imageSize() == other.imageSize())
259  && (images_ == other.images_);
260  }
261 
262  /** Insert image at/before pos. (STL-Sequence interface)
263  */
264  iterator insert(iterator pos, const_reference image)
265  {
266  return images_.insert(pos, image);
267  }
268 
269  /** Insert count copies of image at/before pos. (STL-Sequence
270  interface)
271  */
272  void insert (iterator pos, size_type count, const_reference image);
273 
274  /** Insert copies of images from [begin, end) at/before
275  pos. (STL-Sequence interface)
276  */
277  template<class InputIterator>
278  void insert(iterator pos, InputIterator begin, InputIterator end)
279  {
280  images_.insert(pos, begin, end);
281  }
282 
283  /** Removes the image at pos from this array. (STL-Sequence
284  interface)
285  */
286  iterator erase(iterator pos)
287  {
288  return images_.erase(pos);
289  }
290 
291  /** Removes the images from [begin, end) from this
292  array. (STL-Sequence interface)
293  */
294  iterator erase(iterator begin, iterator end)
295  {
296  return images_.erase(begin, end);
297  }
298 
299  /** Empty this array. (STL-Sequence interface)
300  */
301  void clear()
302  {
303  images_.clear();
304  }
305 
306  /** Resize this ImageArray, throwing the last images away if
307  you make the array smaller or appending new images of the
308  right size at the end of the array if you make it
309  larger. (STL-Sequence interface)
310  */
311  void resize(size_type newSize)
312  {
313  if (newSize != size())
314  {
315  size_type oldSize= size();
316  images_.resize(newSize);
317  for (size_type i= oldSize; i<newSize; i++)
318  images_[i].resize(imageSize());
319  }
320  }
321 
322  /** Resize this ImageArray, throwing the last images away if
323  you make the array smaller or appending new copies of image
324  at the end of the array if you make it larger.
325  precondition: <tt>image.size() == imageSize()</tt>
326  (STL-Sequence interface)
327  */
328  void resize(size_type newSize, ImageType &image)
329  {
330  if (newSize != size())
331  {
332  vigra_precondition(image.size() == imageSize(),
333  "trying to append images of wrong size to ImageArray with resize()");
334  images_.resize(newSize, image);
335  }
336  }
337 
338  /** return the first image. (STL-Sequence interface)
339  */
340  reference front()
341  {
342  return images_.front();
343  }
344 
345  /** return the first image. (STL-Sequence interface)
346  */
347  const_reference front() const
348  {
349  return images_.front();
350  }
351 
352  /** return the last image. (STL-Vector interface)
353  */
354  reference back()
355  {
356  return images_.back();
357  }
358 
359  /** return the last image. (STL-Vector interface)
360  */
361  const_reference back() const
362  {
363  return images_.back();
364  }
365 
366  /** append image to array (STL-Back Insertion Sequence interface)
367  */
368  void push_back(const_reference image)
369  {
370  images_.push_back(image);
371  }
372 
373  /** remove last image from array (STL-Back Insertion Sequence interface)
374  */
375  void pop_back()
376  {
377  images_.pop_back();
378  }
379 
380  /** swap contents of this array with the contents of other
381  (STL-Container interface)
382  */
383  void swap(const_reference other)
384  {
385  Size2D oldImageSize = imageSize_;
386  images_.swap(other.images_);
387  imageSize_ = other.imageSize_;
388  other.imageSize_ = oldImageSize;
389  }
390 
391  /** number of image objects for which memory has been allocated
392  (STL-Vector interface)
393  */
394  size_type capacity() const
395  {
396  return images_.capacity();
397  }
398 
399  /** increase capacity(). (STL-Vector interface)
400  */
401  void reserve(size_type n)
402  {
403  images_.reserve(n);
404  }
405 
406  /** Query the size of the contained images. ImageArray will
407  maintain an array of equal-sized images of this
408  size. However, <em>do not resize the contained images
409  manually</em>. ImageArray currently has no way to detect or
410  prevent this.
411  */
413  { return imageSize_; }
414 
415  /** Resize all images to a common new size (No-op if
416  <tt>newSize == imageSize()</tt>). See \ref imageSize() for
417  an important note about resizing the images.
418  */
419  virtual void resizeImages(const Diff2D &newSize)
420  {
421  if (newSize!=imageSize())
422  {
423  for(unsigned int i=0; i<size(); i++)
424  images_[i].resize(Size2D(newSize));
425  imageSize_= newSize;
426  }
427  }
428 
429  /** Resize all images to a common new size (No-op if
430  <tt>newSize == imageSize()</tt>). See \ref imageSize() for
431  an important note about resizing the images.
432 
433  (Convenience function, same as calling
434  <tt>resizeImages(Diff2D(width, height));</tt>.)
435  */
436  void resizeImages(int width, int height)
437  {
438  resizeImages(Size2D(width, height));
439  }
440 };
441 
442 /********************************************************/
443 /* */
444 /* ImagePyramid */
445 /* */
446 /********************************************************/
447 
448 /** \brief Class template for logarithmically tapering image pyramids.
449 
450  An ImagePyramid manages an array of images of the type given as
451  template parameter, where each level has half the width and height
452  of its predecessor. It actually represents a sequence of pyramid
453  levels whose start and end index are configurable. For Burt-style
454  pyramids, see also \ref pyramidReduceBurtFilter and \ref
455  pyramidExpandBurtFilter.
456 
457  A custimized allocator can be passed as a template argument and
458  via the constructor. By default, the allocator of the
459  <tt>ImageType</tt> is reused.
460 
461  <b>\#include</b> <<a href="imagecontainer_8hxx-source.html">vigra/imagecontainer.hxx</a>>
462 
463  Namespace: vigra
464 */
465 template <class ImageType,
466  class Alloc = typename ImageType::allocator_type::template rebind<ImageType>::other >
468 {
469  int lowestLevel_, highestLevel_;
470 
471 protected:
473  ImageVector images_;
474 
475 public:
476  /** the type of the contained values/images
477  */
478  typedef ImageType value_type;
479 
480  typedef typename ImageVector::iterator iterator;
481  typedef typename ImageVector::const_iterator const_iterator;
482  typedef typename ImageVector::reverse_iterator reverse_iterator;
483  typedef typename ImageVector::const_reverse_iterator const_reverse_iterator;
484  typedef typename ImageVector::reference reference;
485  typedef typename ImageVector::const_reference const_reference;
486 #if !defined(_MSC_VER) || _MSC_VER >= 1300
487  typedef typename ImageVector::pointer pointer;
488 #endif
489  typedef typename ImageVector::difference_type difference_type;
490  typedef int size_type;
491 
492  /** Init a pyramid between the given levels (inclusive).
493  *
494  * Allocate the given \a imageSize at the pyramid level given
495  * in \a sizeAppliesToLevel (default: level 0 / bottom) and
496  * size the other levels using recursive reduction/expansion
497  * by factors of 2. Use the specified allocator for image
498  * creation. The image type must be default constructible and
499  * resizable. sizeAppliesToLevel must be the in range
500  * lowestLevel..highestLevel (inclusive).
501  */
503  const Diff2D &imageSize, int sizeAppliesToLevel = 0,
504  Alloc const & alloc = Alloc())
505  : lowestLevel_(0), highestLevel_(-1),
506  images_(alloc)
507  {
508  resize(lowestLevel, highestLevel, imageSize, sizeAppliesToLevel);
509  }
510 
511  /**
512  * Init a pyramid between the given levels (inclusive).
513  *
514  * Copy the given \a image into the pyramid level given in \a
515  * copyImageToLevel (default: level 0 / bottom) and size the
516  * other levels using recursive reduction/expansion by factors
517  * of 2 (their image data is not initialized). Use the
518  * specified allocator for image creation. The image type
519  * must be default constructible and resizable.
520  * sizeAppliesToLevel must be the in range
521  * lowestLevel..highestLevel (inclusive).
522  */
523  ImagePyramid(int lowestLevel, int highestLevel,
524  const ImageType &image, int copyImageToLevel = 0,
525  Alloc const & alloc = Alloc())
526  : lowestLevel_(0), highestLevel_(-1),
527  images_(alloc)
528  {
529  resize(lowestLevel, highestLevel, image.size(), copyImageToLevel);
530  copyImage(srcImageRange(image), destImage((*this)[copyImageToLevel]));
531  }
532 
533  /**
534  * Init a pyramid between the given levels (inclusive).
535  *
536  * Copy the image given by the range \a ul to \a lr into the
537  * pyramid level given in \a copyImageToLevel (default: level
538  * 0 / bottom) and size the other levels using recursive
539  * reduction/expansion by factors of 2 (their image data is
540  * not initialized). Use the specified allocator for image
541  * creation. The image type must be default constructible and
542  * resizable. sizeAppliesToLevel must be the in range
543  * lowestLevel..highestLevel (inclusive).
544  */
545  template <class SrcIterator, class SrcAccessor>
546  ImagePyramid(int lowestLevel, int highestLevel,
547  SrcIterator ul, SrcIterator lr, SrcAccessor src,
548  int copyImageToLevel = 0,
549  Alloc const & alloc = Alloc())
550  : lowestLevel_(0), highestLevel_(-1),
551  images_(alloc)
552  {
553  resize(lowestLevel, highestLevel, lr - ul, copyImageToLevel);
554  copyImage(srcIterRange(ul, lr, src), destImage((*this)[copyImageToLevel]));
555  }
556 
557  /** Init an empty pyramid. Use the specified allocator.
558  */
559  ImagePyramid(Alloc const & alloc = Alloc())
560  : lowestLevel_(0), highestLevel_(-1),
561  images_(alloc)
562  {}
563 
564  virtual ~ImagePyramid() {}
565 
566  /** Get the index of the lowest allocated level of the pyramid.
567  */
568  int lowestLevel() const
569  {
570  return lowestLevel_;
571  }
572 
573  /** Get the index of the highest allocated level of the pyramid.
574  */
575  int highestLevel() const
576  {
577  return highestLevel_;
578  }
579 
580  /** Operator for a vector-like access to the contained images
581  (STL-Vector interface)
582  */
583  reference operator [](size_type index)
584  {
585  return images_[index - lowestLevel_];
586  }
587 
588  /** Operator for a vector-like access to the contained images
589  (STL-Vector interface)
590  */
591  const_reference operator [](size_type index) const
592  {
593  return images_[index - lowestLevel_];
594  }
595 
596  /** Returns an iterator pointing to the first image
597  (STL-Container interface)
598  */
599  iterator begin()
600  {
601  return images_.begin();
602  }
603 
604  /** Returns an iterator pointing to the first image
605  (STL-Container interface)
606  */
607  const_iterator begin() const
608  {
609  return images_.begin();
610  }
611 
612  /** Returns an iterator pointing behind the last image
613  (STL-Container interface)
614  */
615  iterator end()
616  {
617  return images_.end();
618  }
619 
620  /** Returns an iterator pointing behind the last image
621  (STL-Container interface)
622  */
623  const_iterator end() const
624  {
625  return images_.end();
626  }
627 
628  /** Returns a reverse_iterator pointing to the first image of
629  the reversed view of this array (STL-Reversable Container
630  interface)
631  */
632  reverse_iterator rbegin()
633  {
634  return images_.rbegin();
635  }
636 
637  /** Returns a reverse_iterator pointing to the first image of
638  the reversed view of this array (STL-Reversable Container
639  interface)
640  */
641  const_reverse_iterator rbegin() const
642  {
643  return images_.rbegin();
644  }
645 
646  /** Returns a reverse_iterator pointing behind the last image
647  of the reversed view of this array (STL-Reversable
648  Container interface)
649  */
650  reverse_iterator rend()
651  {
652  return images_.rend();
653  }
654 
655  /** Returns a reverse_iterator pointing behind the last image
656  of the reversed view of this array (STL-Reversable
657  Container interface)
658  */
659  const_reverse_iterator rend() const
660  {
661  return images_.rend();
662  }
663 
664  /** Query size of this ImageArray, that is: the number of
665  images. (STL-Container interface)
666  */
667  size_type size() const
668  {
669  return images_.size();
670  }
671 
672  /** Returns true if and only if there are no contained
673  images. (STL-Container interface)
674  */
675  bool empty()
676  {
677  return images_.empty();
678  }
679 
680  /** Returns true if and only if both ImageArrays have exactly
681  the same contents and all images did compare equal with the
682  corresponding image in the other ImageArray. (STL-Forward
683  Container interface)
684  */
686  {
687  return (lowestLevel_ == other.lowestLevel_) && (highestLevel_ == other.highestLevel_) &&
688  (images_ == other.images_);
689  }
690 
691  /** Empty this array. (STL-Sequence interface)
692  */
693  void clear()
694  {
695  images_.clear();
696  lowestLevel_ = 0;
697  highestLevel_ = -1;
698  }
699 
700  /** Resize this ImageArray, throwing the last images away if
701  you make the array smaller or appending new images of the
702  right size at the end of the array if you make it
703  larger. (STL-Sequence interface)
704  */
705  void resize(int lowestLevel, int highestLevel,
706  const Diff2D &imageSize, int sizeAppliesToLevel = 0)
707  {
708  vigra_precondition(lowestLevel <= highestLevel,
709  "ImagePyramid::resize(): lowestLevel <= highestLevel required.");
710  vigra_precondition(lowestLevel <= sizeAppliesToLevel && sizeAppliesToLevel <= highestLevel,
711  "ImagePyramid::resize(): sizeAppliesToLevel must be between lowest and highest level (inclusive).");
712 
713  ImageVector images(highestLevel - lowestLevel + 1, ImageType());
714 
715  images[sizeAppliesToLevel - lowestLevel].resize(imageSize);
716  for(int i=sizeAppliesToLevel + 1; i<=highestLevel; ++i)
717  {
718  unsigned int w = (images[i - 1 - lowestLevel].width() + 1) / 2;
719  unsigned int h = (images[i - 1 - lowestLevel].height() + 1) / 2;
720  images[i - lowestLevel].resize(w, h);
721  }
722  for(int i=sizeAppliesToLevel - 1; i>=lowestLevel; --i)
723  {
724  unsigned int w = 2*images[i + 1 - lowestLevel].width() - 1;
725  unsigned int h = 2*images[i + 1 - lowestLevel].height() - 1;
726  images[i - lowestLevel].resize(w, h);
727  }
728 
729  images_.swap(images);
730  lowestLevel_ = lowestLevel;
731  highestLevel_ = highestLevel;
732  }
733 
734  /** return the first image (lowestLevel()). (STL-Sequence interface)
735  */
736  reference front()
737  {
738  return images_.front();
739  }
740 
741  /** return the first image (lowestLevel()). (STL-Sequence interface)
742  */
743  const_reference front() const
744  {
745  return images_.front();
746  }
747 
748  /** return the last image (highestLevel()). (STL-Vector interface)
749  */
750  reference back()
751  {
752  return images_.back();
753  }
754 
755  /** return the last image (highestLevel()). (STL-Vector interface)
756  */
757  const_reference back() const
758  {
759  return images_.back();
760  }
761 
762  /** swap contents of this array with the contents of other
763  (STL-Container interface)
764  */
766  {
767  images_.swap(other.images_);
768  std::swap(lowestLevel_, other.lowestLevel_);
769  std::swap(highestLevel_, other.highestLevel_);
770  }
771 };
772 
773 //@}
774 
775 } // namespace vigra
776 
777 #endif // VIGRA_IMAGECONTAINER_HXX

© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de)
Heidelberg Collaboratory for Image Processing, University of Heidelberg, Germany

html generated using doxygen and Python
vigra 1.7.1 (Wed Mar 12 2014)