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 SubImage;
00129
00130
00131 template<class T> class ConstSubImageIterator
00132 {
00133 public:
00134 const ConstSubImageIterator& operator++()
00135 {
00136 ptr++;
00137 if(ptr == row_end)
00138 {
00139 ptr += row_increment;
00140 row_end += total_width;
00141
00142 if(ptr >= end)
00143 end = NULL;
00144 }
00145 return *this;
00146 }
00147
00148 void operator++(int)
00149 {
00150 operator++();
00151 }
00152
00153 const T* operator->() const { return ptr; }
00154 const T& operator*() const { return *ptr;}
00155
00156 bool operator<(const ConstSubImageIterator& s) const
00157 {
00158
00159
00160 if(is_end && s.is_end)
00161 return 0;
00162 else if(is_end)
00163 return s.end != NULL;
00164 else if(s.is_end)
00165 return end != NULL;
00166 else
00167 return ptr < s.ptr;
00168 }
00169
00170 bool operator==(const ConstSubImageIterator& s) const
00171 {
00172 return !((*this)!=s);
00173 }
00174
00175 bool operator!=(const ConstSubImageIterator& s) const
00176 {
00177 if(is_end && s.is_end)
00178 return 0;
00179 else if(is_end)
00180 return s.end != NULL;
00181 else if(s.is_end)
00182 return end != NULL;
00183 else
00184 return ptr != s.ptr;
00185 }
00186
00187
00188
00189 typedef std::forward_iterator_tag iterator_category;
00190 typedef T value_type;
00191 typedef ptrdiff_t difference_type;
00192 typedef const T* pointer;
00193 typedef const T& reference;
00194
00195
00196
00197 ConstSubImageIterator()
00198 {}
00199
00200 ConstSubImageIterator(const T* start, int image_width, int row_stride, const T* off_end)
00201 :ptr(const_cast<T*>(start)),
00202 row_end(start + image_width),
00203 end(off_end),
00204 is_end(0),
00205 row_increment(row_stride-image_width),
00206 total_width(row_stride)
00207 { }
00208
00209
00210 explicit ConstSubImageIterator(const T* end)
00211 :ptr(const_cast<T*>(end)),is_end(1),row_increment(0),total_width(0)
00212 { }
00213
00214 protected:
00215 T* ptr;
00216 const T *row_end, *end;
00217 bool is_end;
00218 int row_increment, total_width;
00219 };
00220
00221 template<class T> class SubImageIterator: public ConstSubImageIterator<T>
00222 {
00223 public:
00224 SubImageIterator(T* start, int image_width, int row_stride, const T* off_end)
00225 :ConstSubImageIterator<T>(start, image_width, row_stride, off_end)
00226 {}
00227
00228 explicit SubImageIterator(T* end)
00229 :ConstSubImageIterator<T>(end)
00230 { }
00231
00232 SubImageIterator()
00233 {}
00234
00235 typedef T* pointer;
00236 typedef T& reference;
00237
00238 T* operator->() { return ConstSubImageIterator<T>::ptr; }
00239 T& operator*() { return *ConstSubImageIterator<T>::ptr;}
00240 };
00241
00252 template<class T> class SubImage
00253 {
00254 public:
00259 SubImage(T* data, const ImageRef& size, int stride)
00260 :my_data(data),my_size(size),my_stride(stride)
00261 {
00262 }
00263
00264
00267 bool in_image(const ImageRef& ir) const
00268 {
00269 return ir.x >=0 && ir.y >=0 && ir.x < my_size.x && ir.y < my_size.y;
00270 }
00271
00275 bool in_image_with_border(const ImageRef& ir, int border) const
00276 {
00277 return ir.x >=border && ir.y >=border && ir.x < my_size.x - border && ir.y < my_size.y - border;
00278 }
00279
00281 ~SubImage()
00282 {}
00283
00287 inline T& operator[](const ImageRef& pos)
00288 {
00289 CVD_IMAGE_ASSERT(in_image(pos), ImageError::AccessOutsideImage);
00290 return (my_data[pos.y*my_stride + pos.x]);
00291 }
00292
00296 inline const T& operator[](const ImageRef& pos) const
00297 {
00298 CVD_IMAGE_ASSERT(in_image(pos), ImageError::AccessOutsideImage);
00299 return (my_data[pos.y*my_stride + pos.x]);
00300 }
00301
00306 inline T* operator[](int row)
00307 {
00308 CVD_IMAGE_ASSERT(in_image(ImageRef(0,row)), ImageError::AccessOutsideImage);
00309 return my_data+row*my_stride;
00310 }
00311
00316 inline const T* operator[](int row) const
00317 {
00318 CVD_IMAGE_ASSERT(in_image(ImageRef(0,row)), ImageError::AccessOutsideImage);
00319 return my_data+row*my_stride;
00320 }
00321
00323 inline ImageRef pos(const T* ptr) const
00324 {
00325 int diff = ptr - data();
00326 return ImageRef(diff % my_stride, diff / my_size.x);
00327 }
00328
00330 inline const T* data() const
00331 {
00332 return my_data;
00333 }
00334
00336 inline T* data()
00337 {
00338 return my_data;
00339 }
00340
00341 typedef SubImageIterator<T> iterator;
00342 typedef ConstSubImageIterator<T> const_iterator;
00343
00345 inline iterator begin()
00346 {
00347 return SubImageIterator<T>(data(), size().x, my_stride, end_ptr());
00348 }
00350 inline const_iterator begin() const
00351 {
00352 return ConstSubImageIterator<T>(data(), size().x, my_stride, end_ptr());
00353 }
00354
00356 inline iterator end()
00357 {
00358
00359 return SubImageIterator<T>(end_ptr());
00360 }
00362 inline const_iterator end() const
00363 {
00364
00365 return ConstSubImageIterator<T>(end_ptr());
00366 }
00367
00368 inline void copy_from( const SubImage<T> & other ){
00369 CVD_IMAGE_ASSERT(other.size() == this->size(), Exceptions::Image::IncompatibleImageSizes);
00370 std::copy(other.begin(), other.end(), this->begin());
00371 }
00372
00374 inline ImageRef size() const
00375 {
00376 return my_size;
00377 }
00378
00380 inline int row_stride() const
00381 {
00382 return my_stride;
00383 }
00384
00386 inline int totalsize() const
00387 {
00388 return my_stride * my_size.y;
00389 }
00390
00392 inline void zero()
00393 {
00394 memset(my_data, 0, totalsize()*sizeof(T));
00395 }
00396
00399 inline void fill(const T d)
00400 {
00401 for(int y=0; y < my_size.y; y++)
00402 ImageUtil::memfill( (*this)[y], my_size.x, d);
00403 }
00404
00407 SubImage(const SubImage& copyof)
00408 {
00409 my_size = copyof.my_size;
00410 my_data = copyof.my_data;
00411 my_stride = copyof.my_stride;
00412 }
00413
00414
00418 SubImage sub_image(const ImageRef& start, const ImageRef& size)
00419 {
00420 CVD_IMAGE_ASSERT(in_image(start), ImageError::AccessOutsideImage);
00421 CVD_IMAGE_ASSERT(in_image(start + size - ImageRef(1,1)), ImageError::AccessOutsideImage);
00422 return SubImage( &operator[](start), size, my_stride);
00423 }
00424
00428 const SubImage sub_image(const ImageRef& start, const ImageRef& size) const
00429 {
00430 CVD_IMAGE_ASSERT(in_image(start), ImageError::AccessOutsideImage);
00431 CVD_IMAGE_ASSERT(in_image(start + size - ImageRef(1,1)), ImageError::AccessOutsideImage);
00432
00433 T*ptr = my_data + start.y * my_stride + start.x;
00434 return SubImage(ptr, size, my_stride);
00435 }
00436
00438 SubImage& ref()
00439 {
00440 return *this;
00441 }
00442
00443 protected:
00444 T* my_data;
00445 ImageRef my_size;
00446 int my_stride;
00447
00449 T* end_ptr() { return my_data+my_size.y*my_stride; }
00450
00452 const T* end_ptr() const { return my_data+my_size.y*my_stride; }
00453
00454 SubImage()
00455 {}
00456
00457 };
00458
00459
00475 template<class T> class BasicImage: public SubImage<T>
00476 {
00477 public:
00481 BasicImage(T* data, const ImageRef& size)
00482 :SubImage<T>(data, size, size.x)
00483 {
00484 }
00485
00488 BasicImage(const BasicImage& copyof)
00489 :SubImage<T>(copyof)
00490 {
00491 }
00492
00493 void operator=(const BasicImage©of)
00494 {
00495 SubImage<T>::my_size = copyof.my_size;
00496 SubImage<T>::my_data = copyof.my_data;
00497 SubImage<T>::my_stride = copyof.my_stride;
00498 }
00499
00501 ~BasicImage()
00502 {}
00503
00507 typedef T* iterator;
00511 typedef const T* const_iterator;
00512
00515 const_iterator begin() const { return SubImage<T>::my_data; }
00518 iterator begin() { return SubImage<T>::my_data; }
00519
00522 const_iterator end() const { return SubImage<T>::my_data+SubImage<T>::totalsize(); }
00525 iterator end() { return SubImage<T>::my_data+SubImage<T>::totalsize(); }
00526
00527
00528
00529 protected:
00531 BasicImage()
00532 {}
00533 private:
00534 };
00535
00536
00560 template<class T> class ImageCreationIterator: public std::iterator<std::input_iterator_tag, T, ptrdiff_t>
00561 {
00562 public:
00563 void operator++(int) { num++; }
00564 void operator++() { num++; }
00565 bool operator==(const ImageCreationIterator& i){return num == i.num;}
00566 bool operator!=(const ImageCreationIterator& i){return num != i.num;}
00567
00568 const T& operator*() { return *construct_from_me; }
00569
00570 ImageCreationIterator(const T& data)
00571 :construct_from_me(&data),num(0){}
00572
00573 ImageCreationIterator(int i)
00574 :construct_from_me(0),num(i){}
00575
00576 private:
00577 const T* construct_from_me;
00578 int num;
00579 };
00580
00581
00584 template<class C> inline ImageCreationIterator<C> CreateImagesBegin(const C& from_me)
00585 {
00586 return ImageCreationIterator<C>(from_me);
00587 }
00591 template<class C> inline ImageCreationIterator<C> CreateImagesEnd(const C&, int i)
00592 {
00593 return ImageCreationIterator<C>(i);
00594 }
00595
00598 template<class C> inline ImageCreationIterator<C> CreateImagesEnd(int i)
00599 {
00600 return ImageCreationIterator<C>(i);
00601 }
00602
00620 template<class T>
00621 class Image: public BasicImage<T>
00622 {
00623 private:
00624 struct CopyPlaceHolder
00625 {
00626 const Image* im;
00627 };
00628
00629 public:
00633 Image(const Image& copy) :
00634 BasicImage<T>(copy)
00635 {
00636 dup_from(©);
00637 }
00638
00639
00645 Image(const CopyPlaceHolder& c)
00646 {
00647 dup_from(NULL);
00648 copy_from(*(c.im));
00649 }
00650
00653 CopyPlaceHolder copy_from_me() const
00654 {
00655 CopyPlaceHolder c = {this};
00656 return c;
00657 }
00658
00659
00662 void copy_from(const BasicImage<T>& copy)
00663 {
00664 resize(copy.size());
00665 std::copy(copy.begin(), copy.end(), this->begin());
00666 }
00667
00668
00669
00670
00673 void copy_from(const SubImage<T>& copy)
00674 {
00675 Image<T> tmp(copy.size());
00676 *this = tmp;
00677
00678 std::copy(copy.begin(), copy.end(), this->begin());
00679 }
00680
00682 void make_unique()
00683 {
00684 if(*num_copies > 1)
00685 {
00686 Image<T> tmp(*this);
00687 copy_from(tmp);
00688 }
00689 }
00690
00694 const Image& operator=(const Image& copyof)
00695 {
00696 remove();
00697 dup_from(©of);
00698 return *this;
00699 }
00700
00701 #ifndef DOXYGEN_IGNORE_INTERNAL
00702 template<class C> const Image& operator=(Internal::ImagePromise<C> p)
00703 {
00704 p.execute(*this);
00705 return *this;
00706 }
00707
00708 template<class C> Image(Internal::ImagePromise<C> p)
00709 {
00710 dup_from(NULL);
00711 p.execute(*this);
00712 }
00713 #endif
00714
00716 Image()
00717 {
00718 dup_from(NULL);
00719 }
00720
00723 Image(const ImageRef& size)
00724 {
00725 num_copies = new int;
00726 *num_copies = 1;
00727 this->my_size = size;
00728 this->my_stride = size.x;
00729 this->my_data = Internal::aligned_alloc<T>(this->totalsize(), 16);
00730 }
00731
00735 Image(const ImageRef& size, const T& val)
00736 {
00737 Image<T> tmp(size);
00738 tmp.fill(val);
00739 dup_from(&tmp);
00740 }
00741
00745 Image(const std::pair<ImageRef, T>& p)
00746 {
00747 Image<T> tmp(p.first);
00748 tmp.fill(p.second);
00749 dup_from(&tmp);
00750 }
00751
00755 void resize(const ImageRef& size)
00756 {
00757 if(size != BasicImage<T>::my_size || *num_copies > 1)
00758 {
00759 Image<T> new_im(size);
00760 *this = new_im;
00761 }
00762 }
00763
00766
00769 void resize(const ImageRef& size, const T& val)
00770 {
00771 if(*num_copies > 1 || size != BasicImage<T>::my_size)
00772 {
00773 Image<T> new_im(size, val);
00774 *this = new_im;
00775 }
00776 else fill(val);
00777 }
00778
00780 ~Image()
00781 {
00782 remove();
00783 }
00784
00785
00786 private:
00787
00788
00789 int* num_copies;
00790
00791 inline void remove()
00792 {
00793 if(this->my_data && *num_copies && --(*num_copies) == 0)
00794 {
00795 Internal::aligned_free<T>(this->my_data, this->totalsize());
00796 this->my_data = 0;
00797 delete num_copies;
00798 num_copies = 0;
00799 }
00800 }
00801
00802 inline void dup_from(const Image* copyof)
00803 {
00804 if(copyof != NULL && copyof->my_data != NULL)
00805 {
00806 this->my_size = copyof->my_size;
00807 this->my_stride = copyof->my_stride;
00808 this->my_data = copyof->my_data;
00809 num_copies = copyof->num_copies;
00810 (*num_copies)++;
00811 }
00812 else
00813 {
00814 this->my_size.home();
00815 this->my_stride=0;
00816 this->my_data = 0;
00817 num_copies = 0;
00818 }
00819 }
00820 };
00821
00822
00823 }
00824 #endif