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