CVD 0.8
|
00001 /* 00002 This file is part of the CVD Library. 00003 00004 Copyright (C) 2005 The Authors 00005 00006 This library is free software; you can redistribute it and/or 00007 modify it under the terms of the GNU Lesser General Public 00008 License as published by the Free Software Foundation; either 00009 version 2.1 of the License, or (at your option) any later version. 00010 00011 This library is distributed in the hope that it will be useful, 00012 but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 Lesser General Public License for more details. 00015 00016 You should have received a copy of the GNU Lesser General Public 00017 License along with this library; if not, write to the Free Software 00018 Foundation, Inc., 00019 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00020 */ 00021 //-*- c++ -*- 00023 // // 00024 // CVD::image.h // 00025 // // 00026 // Definitions for of template class CVD::Image, fast_image // 00027 // // 00028 // derived from IPRS_* developed by Tom Drummond // 00029 // Reworked to provide class heirachy and memory managementby E. Rosten// 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 #define CVD_IMAGE_ASSERT2(X,Y,Z) if(!(X)) throw Y(Z) 00085 #else 00086 #define CVD_IMAGE_ASSERT(X,Y) 00087 #define CVD_IMAGE_ASSERT2(X,Y,Z) 00088 #endif 00089 00096 namespace ImageError 00097 { 00101 class AccessOutsideImage{}; 00102 } 00103 00104 00105 namespace ImageUtil 00106 { 00107 template<class T> inline void memfill(T* data, int n, const T val) 00108 { 00109 T* de = data + n; 00110 for(;data < de; data++) 00111 *data=val; 00112 } 00113 00114 template<> inline void memfill(unsigned char* data, int n, const unsigned char val) 00115 { 00116 memset(data, val, n); 00117 } 00118 00119 template<> inline void memfill(signed char* data, int n, const signed char val) 00120 { 00121 memset(data, val, n); 00122 } 00123 00124 template<> inline void memfill(char* data, int n, const char val) 00125 { 00126 memset(data, val, n); 00127 } 00128 } 00129 00130 template<class T> class SubImage; 00131 00132 00133 template<class T> class ConstSubImageIterator 00134 { 00135 public: 00136 const ConstSubImageIterator& operator++() 00137 { 00138 ptr++; 00139 if(ptr == row_end) 00140 { 00141 ptr += row_increment; 00142 row_end += total_width; 00143 00144 if(ptr >= end) 00145 end = NULL; 00146 } 00147 return *this; 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 00159 { 00160 //It's illegal to iterate _past_ end(), so < is equivalent to != 00161 //for end iterators. 00162 if(is_end && s.is_end) 00163 return 0; 00164 else if(is_end) 00165 return s.end != NULL; 00166 else if(s.is_end) 00167 return end != NULL; 00168 else 00169 return ptr < s.ptr; 00170 } 00171 00172 bool operator==(const ConstSubImageIterator& s) const 00173 { 00174 return !((*this)!=s); 00175 } 00176 00177 bool operator!=(const ConstSubImageIterator& s) const 00178 { 00179 if(is_end && s.is_end) 00180 return 0; 00181 else if(is_end) 00182 return s.end != NULL; 00183 else if(s.is_end) 00184 return end != NULL; 00185 else 00186 return ptr != s.ptr; 00187 } 00188 00189 00190 //Make it look like a standard iterator 00191 typedef std::forward_iterator_tag iterator_category; 00192 typedef T value_type; 00193 typedef std::ptrdiff_t difference_type; 00194 typedef const T* pointer; 00195 typedef const T& reference; 00196 00197 00198 00199 ConstSubImageIterator() 00200 {} 00201 00202 ConstSubImageIterator(const T* start, int image_width, int row_stride, const T* off_end) 00203 :ptr(const_cast<T*>(start)), 00204 row_end(start + image_width), 00205 end(off_end), 00206 is_end(0), 00207 row_increment(row_stride-image_width), 00208 total_width(row_stride) 00209 { } 00210 00211 //Prevent automatic conversion from a pointer (ie Image::iterator) 00212 explicit ConstSubImageIterator(const T* end) 00213 :ptr(const_cast<T*>(end)),is_end(1),row_increment(0),total_width(0) 00214 { } 00215 00216 protected: 00217 T* ptr; 00218 const T *row_end, *end; 00219 bool is_end; 00220 int row_increment, total_width; 00221 }; 00222 00223 template<class T> class SubImageIterator: public ConstSubImageIterator<T> 00224 { 00225 public: 00226 SubImageIterator(T* start, int image_width, int row_stride, const T* off_end) 00227 :ConstSubImageIterator<T>(start, image_width, row_stride, off_end) 00228 {} 00229 00230 explicit SubImageIterator(T* end) 00231 :ConstSubImageIterator<T>(end) 00232 { } 00233 00234 SubImageIterator() 00235 {} 00236 00237 typedef T* pointer; 00238 typedef T& reference; 00239 00240 T* operator->() { return ConstSubImageIterator<T>::ptr; } 00241 T& operator*() { return *ConstSubImageIterator<T>::ptr;} 00242 }; 00243 00254 template<class T> class SubImage 00255 { 00256 public: 00261 SubImage(T* data, const ImageRef& size, int stride) 00262 :my_data(data),my_size(size),my_stride(stride) 00263 { 00264 } 00265 00266 00269 bool in_image(const ImageRef& ir) const 00270 { 00271 return ir.x >=0 && ir.y >=0 && ir.x < my_size.x && ir.y < my_size.y; 00272 } 00273 00277 bool in_image_with_border(const ImageRef& ir, int border) const 00278 { 00279 return ir.x >=border && ir.y >=border && ir.x < my_size.x - border && ir.y < my_size.y - border; 00280 } 00281 00283 ~SubImage() 00284 {} 00285 00289 inline T& operator[](const ImageRef& pos) 00290 { 00291 CVD_IMAGE_ASSERT(in_image(pos), ImageError::AccessOutsideImage); 00292 return (my_data[pos.y*my_stride + pos.x]); 00293 } 00294 00298 inline const T& operator[](const ImageRef& pos) const 00299 { 00300 CVD_IMAGE_ASSERT(in_image(pos), ImageError::AccessOutsideImage); 00301 return (my_data[pos.y*my_stride + pos.x]); 00302 } 00303 00308 inline T* operator[](int row) 00309 { 00310 CVD_IMAGE_ASSERT(in_image(ImageRef(0,row)), ImageError::AccessOutsideImage); 00311 return my_data+row*my_stride; 00312 } 00313 00318 inline const T* operator[](int row) const 00319 { 00320 CVD_IMAGE_ASSERT(in_image(ImageRef(0,row)), ImageError::AccessOutsideImage); 00321 return my_data+row*my_stride; 00322 } 00323 00325 inline ImageRef pos(const T* ptr) const 00326 { 00327 int diff = ptr - data(); 00328 return ImageRef(diff % my_stride, diff / my_size.x); 00329 } 00330 00332 inline const T* data() const 00333 { 00334 return my_data; 00335 } 00336 00338 inline T* data() 00339 { 00340 return my_data; 00341 } 00342 00343 typedef SubImageIterator<T> iterator; 00344 typedef ConstSubImageIterator<T> const_iterator; 00345 00347 typedef T value_type; 00348 00350 inline iterator begin() 00351 { 00352 return SubImageIterator<T>(data(), size().x, my_stride, end_ptr()); 00353 } 00355 inline const_iterator begin() const 00356 { 00357 return ConstSubImageIterator<T>(data(), size().x, my_stride, end_ptr()); 00358 } 00359 00361 inline iterator end() 00362 { 00363 //Operator [] would always throw here! 00364 return SubImageIterator<T>(end_ptr()); 00365 } 00367 inline const_iterator end() const 00368 { 00369 //Operator [] would always throw here! 00370 return ConstSubImageIterator<T>(end_ptr()); 00371 } 00372 00373 inline void copy_from( const SubImage<T> & other ){ 00374 CVD_IMAGE_ASSERT2(other.size() == this->size(), Exceptions::Image::IncompatibleImageSizes, "copy_from"); 00375 std::copy(other.begin(), other.end(), this->begin()); 00376 } 00377 00379 inline ImageRef size() const 00380 { 00381 return my_size; 00382 } 00383 00385 inline int row_stride() const 00386 { 00387 return my_stride; 00388 } 00389 00391 inline int totalsize() const 00392 { 00393 return my_stride * my_size.y; 00394 } 00395 00397 inline void zero() 00398 { 00399 memset(my_data, 0, totalsize()*sizeof(T)); 00400 } 00401 00404 inline void fill(const T d) 00405 { 00406 for(int y=0; y < my_size.y; y++) 00407 ImageUtil::memfill( (*this)[y], my_size.x, d); 00408 } 00409 00412 SubImage(const SubImage& copyof) 00413 { 00414 my_size = copyof.my_size; 00415 my_data = copyof.my_data; 00416 my_stride = copyof.my_stride; 00417 } 00418 00419 00423 SubImage sub_image(const ImageRef& start, const ImageRef& size) 00424 { 00425 CVD_IMAGE_ASSERT(in_image(start), ImageError::AccessOutsideImage); 00426 CVD_IMAGE_ASSERT(in_image(start + size - ImageRef(1,1)), ImageError::AccessOutsideImage); 00427 return SubImage( &operator[](start), size, my_stride); 00428 } 00429 00433 const SubImage sub_image(const ImageRef& start, const ImageRef& size) const 00434 { 00435 CVD_IMAGE_ASSERT(in_image(start), ImageError::AccessOutsideImage); 00436 CVD_IMAGE_ASSERT(in_image(start + size - ImageRef(1,1)), ImageError::AccessOutsideImage); 00437 00438 T*ptr = my_data + start.y * my_stride + start.x; 00439 return SubImage(ptr, size, my_stride); 00440 } 00441 00443 SubImage& ref() 00444 { 00445 return *this; 00446 } 00447 00448 protected: 00449 T* my_data; 00450 ImageRef my_size; 00451 int my_stride; 00452 00454 T* end_ptr() { return my_data+my_size.y*my_stride; } 00455 00457 const T* end_ptr() const { return my_data+my_size.y*my_stride; } 00458 00459 SubImage() 00460 {} 00461 00462 }; 00463 00464 00480 template<class T> class BasicImage: public SubImage<T> 00481 { 00482 public: 00486 BasicImage(T* data, const ImageRef& size) 00487 :SubImage<T>(data, size, size.x) 00488 { 00489 } 00490 00493 BasicImage(const BasicImage& copyof) 00494 :SubImage<T>(copyof) 00495 { 00496 } 00497 00498 void operator=(const BasicImage©of) 00499 { 00500 SubImage<T>::my_size = copyof.my_size; 00501 SubImage<T>::my_data = copyof.my_data; 00502 SubImage<T>::my_stride = copyof.my_stride; 00503 } 00504 00506 ~BasicImage() 00507 {} 00508 00512 typedef T* iterator; 00516 typedef const T* const_iterator; 00517 00519 typedef T value_type; 00520 00523 const_iterator begin() const { return SubImage<T>::my_data; } 00526 iterator begin() { return SubImage<T>::my_data; } 00527 00530 const_iterator end() const { return SubImage<T>::my_data+SubImage<T>::totalsize(); } 00533 iterator end() { return SubImage<T>::my_data+SubImage<T>::totalsize(); } 00534 00535 00536 00537 protected: 00539 BasicImage() 00540 {} 00541 private: 00542 }; 00543 00544 00568 template<class T> class ImageCreationIterator: public std::iterator<std::input_iterator_tag, T, std::ptrdiff_t> 00569 { 00570 public: 00571 void operator++(int) { num++; } 00572 void operator++() { num++; } 00573 bool operator==(const ImageCreationIterator& i){return num == i.num;} 00574 bool operator!=(const ImageCreationIterator& i){return num != i.num;} 00575 00576 const T& operator*() { return *construct_from_me; } 00577 00578 ImageCreationIterator(const T& data) 00579 :construct_from_me(&data),num(0){} 00580 00581 ImageCreationIterator(int i) 00582 :construct_from_me(0),num(i){} 00583 00584 private: 00585 const T* construct_from_me; 00586 int num; 00587 }; 00588 00589 00592 template<class C> inline ImageCreationIterator<C> CreateImagesBegin(const C& from_me) 00593 { 00594 return ImageCreationIterator<C>(from_me); 00595 } 00599 template<class C> inline ImageCreationIterator<C> CreateImagesEnd(const C&, int i) 00600 { 00601 return ImageCreationIterator<C>(i); 00602 } 00603 00606 template<class C> inline ImageCreationIterator<C> CreateImagesEnd(int i) 00607 { 00608 return ImageCreationIterator<C>(i); 00609 } 00610 00632 template<class T> 00633 class Image: public BasicImage<T> 00634 { 00635 private: 00636 struct CopyPlaceHolder 00637 { 00638 const Image* im; 00639 }; 00640 00641 public: 00642 00644 typedef T value_type; 00645 00649 Image(const Image& copy) : 00650 BasicImage<T>(copy) 00651 { 00652 dup_from(©); 00653 } 00654 00655 00661 Image(const CopyPlaceHolder& c) 00662 { 00663 dup_from(NULL); 00664 copy_from(*(c.im)); 00665 } 00666 00669 CopyPlaceHolder copy_from_me() const 00670 { 00671 CopyPlaceHolder c = {this}; 00672 return c; 00673 } 00674 00675 00678 void copy_from(const BasicImage<T>& copy) 00679 { 00680 resize(copy.size()); 00681 std::copy(copy.begin(), copy.end(), this->begin()); 00682 } 00683 00684 00685 00686 00689 void copy_from(const SubImage<T>& copy) 00690 { 00691 Image<T> tmp(copy.size()); 00692 *this = tmp; 00693 00694 std::copy(copy.begin(), copy.end(), this->begin()); 00695 } 00696 00698 void make_unique() 00699 { 00700 if(*num_copies > 1) 00701 { 00702 Image<T> tmp(*this); 00703 copy_from(tmp); 00704 } 00705 } 00706 00710 const Image& operator=(const Image& copyof) 00711 { 00712 remove(); 00713 dup_from(©of); 00714 return *this; 00715 } 00716 00717 #ifndef DOXYGEN_IGNORE_INTERNAL 00718 template<class C> const Image& operator=(Internal::ImagePromise<C> p) 00719 { 00720 p.execute(*this); 00721 return *this; 00722 } 00723 00724 template<class C> Image(Internal::ImagePromise<C> p) 00725 { 00726 dup_from(NULL); 00727 p.execute(*this); 00728 } 00729 #endif 00730 00732 Image() 00733 { 00734 dup_from(NULL); 00735 } 00736 00739 Image(const ImageRef& size) 00740 { 00741 //If the size of the image is zero pixels along any dimension, 00742 //still keep any of the non-zero dimensions in the size. The 00743 //caller should expect the size passed to the constructor 00744 //to be the same as the value returned by .size() 00745 if (size.x == 0 || size.y == 0) { 00746 dup_from(NULL); 00747 this->my_size = size; 00748 this->my_stride = size.x; 00749 } 00750 else 00751 { 00752 num_copies = new int; 00753 *num_copies = 1; 00754 this->my_size = size; 00755 this->my_stride = size.x; 00756 this->my_data = Internal::aligned_alloc<T>(this->totalsize(), 16); 00757 } 00758 } 00759 00763 Image(const ImageRef& size, const T& val) 00764 { 00765 Image<T> tmp(size); 00766 tmp.fill(val); 00767 dup_from(&tmp); 00768 } 00769 00773 Image(const std::pair<ImageRef, T>& p) 00774 { 00775 Image<T> tmp(p.first); 00776 tmp.fill(p.second); 00777 dup_from(&tmp); 00778 } 00779 00783 void resize(const ImageRef& size) 00784 { 00785 if(size != BasicImage<T>::my_size || *num_copies > 1) 00786 { 00787 Image<T> new_im(size); 00788 *this = new_im; 00789 } 00790 } 00791 00794 //The resized image is filled with val. 00797 void resize(const ImageRef& size, const T& val) 00798 { 00799 if(*num_copies > 1 || size != BasicImage<T>::my_size) 00800 { 00801 Image<T> new_im(size, val); 00802 *this = new_im; 00803 } 00804 else fill(val); 00805 } 00806 00808 ~Image() 00809 { 00810 remove(); 00811 } 00812 00813 00814 private: 00815 00816 00817 int* num_copies; //Reference count. 00818 00819 inline void remove() //Get rid of a reference to the data 00820 { 00821 if(this->my_data && *num_copies && --(*num_copies) == 0) 00822 { 00823 Internal::aligned_free<T>(this->my_data, this->totalsize()); 00824 this->my_data = 0; 00825 delete num_copies; 00826 num_copies = 0; 00827 } 00828 } 00829 00830 inline void dup_from(const Image* copyof) //Duplicate from another image 00831 { 00832 if(copyof != NULL) 00833 { 00834 //For images with zero pixels (e.g. 0 by 100 image), 00835 //we still want to preserve non-zero dimensions in the size. 00836 this->my_size = copyof->my_size; 00837 this->my_stride = copyof->my_stride; 00838 if (copyof->my_data != NULL) { 00839 this->my_data = copyof->my_data; 00840 num_copies = copyof->num_copies; 00841 (*num_copies)++; 00842 } 00843 else { 00844 this->my_data = 0; 00845 num_copies = 0; 00846 } 00847 } 00848 else 00849 { 00850 this->my_size.home(); 00851 this->my_data = 0; 00852 this->my_stride = 0; 00853 num_copies = 0; 00854 } 00855 } 00856 }; 00857 00858 00859 } // end namespace 00860 #endif