cvd/image.h

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 #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         //It's illegal to iterate _past_ end(), so < is equivalent to !=
00166         bool operator<(const ConstSubImageIteratorEnd<T>&) const { return end != NULL; }
00167         bool operator<(const SubImageIteratorEnd<T>&) const { return end != NULL; }
00168 
00169         
00170         //Make it look like a standard iterator
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             //Operator [] would always throw here!
00370             return SubImageIterator<T>(end_ptr());
00371         }
00373         inline const_iterator end() const
00374         {
00375             //Operator [] would always throw here!
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&copyof)
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(&copy);
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             // FIXME: this is currently slow. Use fastend().
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(&copyof);
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         //The resized image is filled with val.
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;            //Reference count.
00813 
00814         inline void remove()        //Get rid of a reference to the data
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)  //Duplicate from another image
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 } // end namespace
00847 #endif

Generated on Wed Feb 18 10:23:01 2009 for CVD by  doxygen 1.5.3