CVD 0.8
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     #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&copyof)
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(&copy);
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(&copyof);
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