00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00023
00024
00025
00026
00027
00028
00029
00030
00032
00033 #ifndef CVD_IMAGE_H
00034 #define CVD_IMAGE_H
00035
00036 #include <string.h>
00037 #include <cvd/image_ref.h>
00038 #include <cvd/exceptions.h>
00039 #include <string>
00040 #include <utility>
00041 #include <iterator>
00042 #include <cvd/internal/aligned_mem.h>
00043
00044 namespace CVD {
00045
00046 namespace Exceptions {
00047
00049 namespace Image {
00052 struct All: public CVD::Exceptions::All {};
00053
00056 struct IncompatibleImageSizes : public All {
00057 IncompatibleImageSizes(const std::string & function)
00058 {
00059 what = "Incompatible image sizes in " + function;
00060 };
00061 };
00062
00065 struct ImageRefNotInImage : public All {
00066 ImageRefNotInImage(const std::string & function)
00067 {
00068 what = "Input ImageRefs not in image in " + function;
00069 };
00070 };
00071 }
00072 }
00073
00074 #ifndef DOXYGEN_IGNORE_INTERNAL
00075 namespace Internal
00076 {
00077 template<class C> class ImagePromise
00078 {};
00079 };
00080 #endif
00081
00082 #ifdef CVD_IMAGE_DEBUG
00083 #define CVD_IMAGE_ASSERT(X,Y) if(!(X)) throw Y()
00084 #else
00085 #define CVD_IMAGE_ASSERT(X,Y)
00086 #endif
00087
00094 namespace ImageError
00095 {
00099 class AccessOutsideImage{};
00100 }
00101
00102
00103 namespace ImageUtil
00104 {
00105 template<class T> inline void memfill(T* data, int n, const T val)
00106 {
00107 T* de = data + n;
00108 for(;data < de; data++)
00109 *data=val;
00110 }
00111
00112 template<> inline void memfill(unsigned char* data, int n, const unsigned char val)
00113 {
00114 memset(data, val, n);
00115 }
00116
00117 template<> inline void memfill(signed char* data, int n, const signed char val)
00118 {
00119 memset(data, val, n);
00120 }
00121
00122 template<> inline void memfill(char* data, int n, const char val)
00123 {
00124 memset(data, val, n);
00125 }
00126 }
00127
00128 template<class T> class SubImageIteratorEnd;
00129 template<class T> class SubImage;
00130 template<class T> class ConstSubImageIteratorEnd;
00131 template<class T> class ConstSubImage;
00132
00133
00134 template<class T> class ConstSubImageIterator
00135 {
00136 public:
00137 void operator++()
00138 {
00139 ptr++;
00140 if(ptr == row_end)
00141 {
00142 ptr += row_increment;
00143 row_end += total_width;
00144
00145 if(ptr >= end)
00146 end = NULL;
00147 }
00148 }
00149
00150 void operator++(int)
00151 {
00152 operator++();
00153 }
00154
00155 const T* operator->() const { return ptr; }
00156 const T& operator*() const { return *ptr;}
00157
00158 bool operator<(const ConstSubImageIterator& s) const { return ptr < s.ptr; }
00159 bool operator==(const ConstSubImageIterator& s) const { return ptr == s.ptr; }
00160 bool operator!=(const ConstSubImageIterator& s) const { return ptr != s.ptr; }
00161
00162
00163 bool operator!=(const ConstSubImageIteratorEnd<T>&) const { return end != NULL; }
00164 bool operator!=(const SubImageIteratorEnd<T>&) const { return end != NULL; }
00165
00166 bool operator<(const ConstSubImageIteratorEnd<T>&) const { return end != NULL; }
00167 bool operator<(const SubImageIteratorEnd<T>&) const { return end != NULL; }
00168
00169
00170
00171 typedef std::forward_iterator_tag iterator_category;
00172 typedef T value_type;
00173 typedef ptrdiff_t difference_type;
00174 typedef const T* pointer;
00175 typedef const T& reference;
00176
00177
00178
00179 ConstSubImageIterator()
00180 {}
00181
00182 ConstSubImageIterator(const T* start, int image_width, int row_stride, const T* off_end)
00183 :ptr(const_cast<T*>(start)),
00184 row_end(start + image_width),
00185 end(off_end),
00186 row_increment(row_stride-image_width),
00187 total_width(row_stride)
00188 { }
00189
00190 ConstSubImageIterator(const T* end)
00191 :ptr(const_cast<T*>(end))
00192 { }
00193
00194 protected:
00195 T* ptr;
00196 const T *row_end, *end;
00197 int row_increment, total_width;
00198 };
00199
00200 template<class T> class SubImageIterator: public ConstSubImageIterator<T>
00201 {
00202 public:
00203 SubImageIterator(T* start, int image_width, int row_stride, const T* off_end)
00204 :ConstSubImageIterator<T>(start, image_width, row_stride, off_end)
00205 {}
00206
00207 SubImageIterator(T* end)
00208 :ConstSubImageIterator<T>(end)
00209 { }
00210
00211 SubImageIterator()
00212 {}
00213
00214 typedef T* pointer;
00215 typedef T& reference;
00216
00217 T* operator->() { return ConstSubImageIterator<T>::ptr; }
00218 T& operator*() { return *ConstSubImageIterator<T>::ptr;}
00219 };
00220
00221 template<class T> class SubImageIteratorEnd
00222 {
00223 public:
00224 SubImageIteratorEnd(SubImage<T>* p)
00225 :i(p){}
00226
00227 operator SubImageIterator<T>()
00228 {
00229 return i->end();
00230 }
00231
00232 private:
00233 SubImage<T>* i;
00234 };
00235
00236
00237 template<class T> class ConstSubImageIteratorEnd
00238 {
00239 public:
00240 ConstSubImageIteratorEnd(const SubImage<T>* p)
00241 :i(p){}
00242
00243 operator ConstSubImageIterator<T>()
00244 {
00245 return i->end();
00246 }
00247
00248 private:
00249 const SubImage<T>* i;
00250 };
00251
00252
00263 template<class T> class SubImage
00264 {
00265 public:
00270 SubImage(T* data, const ImageRef& size, int stride)
00271 :my_data(data),my_size(size),my_stride(stride)
00272 {
00273 }
00274
00275
00278 bool in_image(const ImageRef& ir) const
00279 {
00280 return ir.x >=0 && ir.y >=0 && ir.x < my_size.x && ir.y < my_size.y;
00281 }
00282
00286 bool in_image_with_border(const ImageRef& ir, int border) const
00287 {
00288 return ir.x >=border && ir.y >=border && ir.x < my_size.x - border && ir.y < my_size.y - border;
00289 }
00290
00292 ~SubImage()
00293 {}
00294
00298 inline T& operator[](const ImageRef& pos)
00299 {
00300 CVD_IMAGE_ASSERT(in_image(pos), ImageError::AccessOutsideImage);
00301 return (my_data[pos.y*my_stride + pos.x]);
00302 }
00303
00307 inline const T& operator[](const ImageRef& pos) const
00308 {
00309 CVD_IMAGE_ASSERT(in_image(pos), ImageError::AccessOutsideImage);
00310 return (my_data[pos.y*my_stride + pos.x]);
00311 }
00312
00317 inline T* operator[](int row)
00318 {
00319 CVD_IMAGE_ASSERT(in_image(ImageRef(0,row)), ImageError::AccessOutsideImage);
00320 return my_data+row*my_stride;
00321 }
00322
00327 inline const T* operator[](int row) const
00328 {
00329 CVD_IMAGE_ASSERT(in_image(ImageRef(0,row)), ImageError::AccessOutsideImage);
00330 return my_data+row*my_stride;
00331 }
00332
00334 inline ImageRef pos(const T* ptr) const
00335 {
00336 int diff = ptr - data();
00337 return ImageRef(diff % my_stride, diff / my_size.x);
00338 }
00339
00341 inline const T* data() const
00342 {
00343 return my_data;
00344 }
00345
00347 inline T* data()
00348 {
00349 return my_data;
00350 }
00351
00352 typedef SubImageIterator<T> iterator;
00353 typedef ConstSubImageIterator<T> const_iterator;
00354
00356 inline iterator begin()
00357 {
00358 return SubImageIterator<T>(data(), size().x, my_stride, end_ptr());
00359 }
00361 inline const_iterator begin() const
00362 {
00363 return ConstSubImageIterator<T>(data(), size().x, my_stride, end_ptr());
00364 }
00365
00367 inline iterator end()
00368 {
00369
00370 return SubImageIterator<T>(end_ptr());
00371 }
00373 inline const_iterator end() const
00374 {
00375
00376 return ConstSubImageIterator<T>(end_ptr());
00377 }
00378
00380 inline SubImageIteratorEnd<T> fastend()
00381 {
00382 return SubImageIteratorEnd<T>(this);
00383 }
00385 inline ConstSubImageIteratorEnd<T> fastend() const
00386 {
00387 return ConstSubImageIteratorEnd<T>(this);
00388 }
00389
00390
00391
00392
00393
00394
00396 inline ImageRef size() const
00397 {
00398 return my_size;
00399 }
00400
00402 inline int row_stride() const
00403 {
00404 return my_stride;
00405 }
00406
00408 inline int totalsize() const
00409 {
00410 return my_stride * my_size.y;
00411 }
00412
00414 inline void zero()
00415 {
00416 memset(my_data, 0, totalsize()*sizeof(T));
00417 }
00418
00421 inline void fill(const T d)
00422 {
00423 for(int y=0; y < my_size.y; y++)
00424 ImageUtil::memfill( (*this)[y], my_size.x, d);
00425 }
00426
00429 SubImage(const SubImage& copyof)
00430 {
00431 my_size = copyof.my_size;
00432 my_data = copyof.my_data;
00433 my_stride = copyof.my_stride;
00434 }
00435
00436
00440 SubImage sub_image(const ImageRef& start, const ImageRef& size)
00441 {
00442 CVD_IMAGE_ASSERT(in_image(start), ImageError::AccessOutsideImage);
00443 CVD_IMAGE_ASSERT(in_image(start + size - ImageRef(1,1)), ImageError::AccessOutsideImage);
00444 return SubImage( &operator[](start), size, my_stride);
00445 }
00446
00450 const SubImage sub_image(const ImageRef& start, const ImageRef& size) const
00451 {
00452 CVD_IMAGE_ASSERT(in_image(start), ImageError::AccessOutsideImage);
00453 CVD_IMAGE_ASSERT(in_image(start + size - ImageRef(1,1)), ImageError::AccessOutsideImage);
00454
00455 T*ptr = my_data + start.y * my_stride + start.x;
00456 return SubImage(ptr, size, my_stride);
00457 }
00458
00460 SubImage& ref()
00461 {
00462 return *this;
00463 }
00464
00465 protected:
00466 T* my_data;
00467 ImageRef my_size;
00468 int my_stride;
00469
00471 T* end_ptr() { return my_data+my_size.y*my_stride; }
00472
00474 const T* end_ptr() const { return my_data+my_size.y*my_stride; }
00475
00476 SubImage()
00477 {}
00478
00479 };
00480
00481
00497 template<class T> class BasicImage: public SubImage<T>
00498 {
00499 public:
00503 BasicImage(T* data, const ImageRef& size)
00504 :SubImage<T>(data, size, size.x)
00505 {
00506 }
00507
00510 BasicImage(const BasicImage& copyof)
00511 :SubImage<T>(copyof)
00512 {
00513 }
00514
00515 void operator=(const BasicImage©of)
00516 {
00517 SubImage<T>::my_size = copyof.my_size;
00518 SubImage<T>::my_data = copyof.my_data;
00519 SubImage<T>::my_stride = copyof.my_stride;
00520 }
00521
00523 ~BasicImage()
00524 {}
00525
00529 typedef T* iterator;
00533 typedef const T* const_iterator;
00534
00537 const_iterator begin() const { return SubImage<T>::my_data; }
00540 iterator begin() { return SubImage<T>::my_data; }
00541
00544 const_iterator end() const { return SubImage<T>::my_data+SubImage<T>::totalsize(); }
00547 iterator end() { return SubImage<T>::my_data+SubImage<T>::totalsize(); }
00548
00549
00550
00551 protected:
00553 BasicImage()
00554 {}
00555 private:
00556 };
00557
00558
00582 template<class T> class ImageCreationIterator: public std::iterator<std::input_iterator_tag, T, ptrdiff_t>
00583 {
00584 public:
00585 void operator++(int) { num++; }
00586 void operator++() { num++; }
00587 bool operator==(const ImageCreationIterator& i){return num == i.num;}
00588 bool operator!=(const ImageCreationIterator& i){return num != i.num;}
00589
00590 const T& operator*() { return *construct_from_me; }
00591
00592 ImageCreationIterator(const T& data)
00593 :construct_from_me(&data),num(0){}
00594
00595 ImageCreationIterator(int i)
00596 :construct_from_me(0),num(i){}
00597
00598 private:
00599 const T* construct_from_me;
00600 int num;
00601 };
00602
00603
00606 template<class C> inline ImageCreationIterator<C> CreateImagesBegin(const C& from_me)
00607 {
00608 return ImageCreationIterator<C>(from_me);
00609 }
00613 template<class C> inline ImageCreationIterator<C> CreateImagesEnd(const C&, int i)
00614 {
00615 return ImageCreationIterator<C>(i);
00616 }
00617
00620 template<class C> inline ImageCreationIterator<C> CreateImagesEnd(int i)
00621 {
00622 return ImageCreationIterator<C>(i);
00623 }
00624
00642 template<class T>
00643 class Image: public BasicImage<T>
00644 {
00645 private:
00646 struct CopyPlaceHolder
00647 {
00648 const Image* im;
00649 };
00650
00651 public:
00655 Image(const Image& copy) :
00656 BasicImage<T>(copy)
00657 {
00658 dup_from(©);
00659 }
00660
00661
00667 Image(const CopyPlaceHolder& c)
00668 {
00669 dup_from(NULL);
00670 copy_from(*(c.im));
00671 }
00672
00675 CopyPlaceHolder copy_from_me() const
00676 {
00677 CopyPlaceHolder c = {this};
00678 return c;
00679 }
00680
00681
00684 void copy_from(const BasicImage<T>& copy)
00685 {
00686 resize(copy.size());
00687 std::copy(copy.begin(), copy.end(), this->begin());
00688 }
00689
00690
00691
00692
00695 void copy_from(const SubImage<T>& copy)
00696 {
00697 Image<T> tmp(copy.size());
00698 *this = tmp;
00699
00700
00701 std::copy(copy.begin(), copy.end(), this->begin());
00702 }
00703
00705 void make_unique()
00706 {
00707 if(*num_copies > 1)
00708 {
00709 Image<T> tmp(*this);
00710 copy_from(tmp);
00711 }
00712 }
00713
00717 const Image& operator=(const Image& copyof)
00718 {
00719 remove();
00720 dup_from(©of);
00721 return *this;
00722 }
00723
00724 #ifndef DOXYGEN_IGNORE_INTERNAL
00725 template<class C> const Image& operator=(Internal::ImagePromise<C> p)
00726 {
00727 p.execute(*this);
00728 return *this;
00729 }
00730
00731 template<class C> Image(Internal::ImagePromise<C> p)
00732 {
00733 dup_from(NULL);
00734 p.execute(*this);
00735 }
00736 #endif
00737
00739 Image()
00740 {
00741 dup_from(NULL);
00742 }
00743
00746 Image(const ImageRef& size)
00747 {
00748 num_copies = new int;
00749 *num_copies = 1;
00750 this->my_size = size;
00751 this->my_stride = size.x;
00752 this->my_data = Internal::aligned_alloc<T>(this->totalsize(), 16);
00753 }
00754
00758 Image(const ImageRef& size, const T& val)
00759 {
00760 Image<T> tmp(size);
00761 tmp.fill(val);
00762 dup_from(&tmp);
00763 }
00764
00768 Image(const std::pair<ImageRef, T>& p)
00769 {
00770 Image<T> tmp(p.first);
00771 tmp.fill(p.second);
00772 dup_from(&tmp);
00773 }
00774
00778 void resize(const ImageRef& size)
00779 {
00780 if(size != BasicImage<T>::my_size || *num_copies > 1)
00781 {
00782 Image<T> new_im(size);
00783 *this = new_im;
00784 }
00785 }
00786
00789
00792 void resize(const ImageRef& size, const T& val)
00793 {
00794 if(*num_copies > 1 || size != BasicImage<T>::my_size)
00795 {
00796 Image<T> new_im(size, val);
00797 *this = new_im;
00798 }
00799 else fill(val);
00800 }
00801
00803 ~Image()
00804 {
00805 remove();
00806 }
00807
00808
00809 private:
00810
00811
00812 int* num_copies;
00813
00814 inline void remove()
00815 {
00816 if(this->my_data && *num_copies && --(*num_copies) == 0)
00817 {
00818 Internal::aligned_free<T>(this->my_data, this->totalsize());
00819 this->my_data = 0;
00820 delete num_copies;
00821 num_copies = 0;
00822 }
00823 }
00824
00825 inline void dup_from(const Image* copyof)
00826 {
00827 if(copyof != NULL && copyof->my_data != NULL)
00828 {
00829 this->my_size = copyof->my_size;
00830 this->my_stride = copyof->my_stride;
00831 this->my_data = copyof->my_data;
00832 num_copies = copyof->num_copies;
00833 (*num_copies)++;
00834 }
00835 else
00836 {
00837 this->my_size.home();
00838 this->my_stride=0;
00839 this->my_data = 0;
00840 num_copies = 0;
00841 }
00842 }
00843 };
00844
00845
00846 }
00847 #endif