core/vidl/vidl_pixel_iterator.txx
Go to the documentation of this file.
00001 // This is core/vidl/vidl_pixel_iterator.txx
00002 #ifndef vidl_pixel_iterator_txx_
00003 #define vidl_pixel_iterator_txx_
00004 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00005 #pragma interface
00006 #endif
00007 //:
00008 // \file
00009 // \brief Templated definitions for pixel iterators
00010 //
00011 // \author Matt Leotta
00012 // \date 3 Mar 2006
00013 //
00014 // This file contains the template definitions for pixel iterators
00015 
00016 
00017 #include "vidl_pixel_iterator.h"
00018 #include "vidl_color.h"
00019 #include <vxl_config.h>
00020 #include <vcl_cassert.h>
00021 
00022 //-----------------------------------------------------------------------------
00023 
00024 
00025 template <vidl_pixel_arrangement AR>
00026 struct vidl_pixel_iterator_arrange_valid
00027 {
00028   enum { value = (AR == VIDL_PIXEL_ARRANGE_SINGLE) };
00029 };
00030 
00031 
00032 //: The default pixel iterator for single arranged formats
00033 template <vidl_pixel_arrangement AR, vidl_pixel_format FMT>
00034 class vidl_pixel_iterator_arranged
00035 {
00036   typedef typename vidl_pixel_traits_of<FMT>::type cmp_type;
00037   cmp_type * ptr_;
00038  public:
00039   //: Constructor
00040   vidl_pixel_iterator_arranged(const vidl_frame& frame)
00041     : ptr_((cmp_type*)frame.data())
00042   {
00043     assert(frame.pixel_format() == FMT);
00044     // The following should be a static asserts
00045     assert(vidl_pixel_traits_of<FMT>::bits_per_pixel%8 == 0);
00046     assert(vidl_pixel_traits_of<FMT>::arrangement() == VIDL_PIXEL_ARRANGE_SINGLE);
00047   }
00048 
00049   //: Destructor
00050   ~vidl_pixel_iterator_arranged() {}
00051 
00052   //: Step to the next pixel
00053   vidl_pixel_iterator_arranged<AR,FMT>& next()
00054   {
00055     ptr_ += vidl_pixel_traits_of<FMT>::bits_per_pixel/(sizeof(cmp_type)*8);
00056     return *this;
00057   }
00058 
00059   //: Access the data
00060   cmp_type operator () (unsigned int i) const
00061   {
00062     assert(i<vidl_pixel_traits_of<FMT>::num_channels);
00063     return vidl_color_component<FMT>::get(ptr_,i);
00064   }
00065 
00066   //: Access the entire pixel at once
00067   void get(cmp_type* data) const
00068   {
00069     vidl_color_component<FMT>::get_all(ptr_,data);
00070   }
00071 
00072   //: write the entire pixel at once
00073   void set(const cmp_type* data)
00074   {
00075     vidl_color_component<FMT>::set_all(ptr_,data);
00076   }
00077 };
00078 
00079 
00080 #if VCL_CAN_DO_PARTIAL_SPECIALIZATION
00081 
00082 template <>
00083 struct vidl_pixel_iterator_arrange_valid<VIDL_PIXEL_ARRANGE_PLANAR>
00084 {
00085   enum { value = true };
00086 };
00087 
00088 
00089 //: The default pixel iterator for planar arranged formats
00090 template <vidl_pixel_format FMT>
00091 class vidl_pixel_iterator_arranged<VIDL_PIXEL_ARRANGE_PLANAR,FMT>
00092 {
00093   typedef typename vidl_pixel_traits_of<FMT>::type cmp_type;
00094   enum { csx = vidl_pixel_traits_of<FMT>::chroma_shift_x };
00095   enum { csy = vidl_pixel_traits_of<FMT>::chroma_shift_y };
00096   enum { x_mask = (1<<(csx+1))-1 }; // last csx+1 bits are 1
00097   enum { y_mask = (1<<(csy+1))-1 }; // last csy+1 bits are 1
00098   unsigned int line_size_;
00099   unsigned int line_cnt_;
00100   cmp_type * ptr_[vidl_pixel_traits_of<FMT>::num_channels];
00101   //: these act as fractional pixel counters
00102   vxl_byte step_x_, step_y_;
00103  public:
00104   //: Constructor
00105   vidl_pixel_iterator_arranged(const vidl_frame& frame)
00106     : line_size_(frame.ni()), line_cnt_(0), step_x_(1), step_y_(1)
00107   {
00108     assert(frame.pixel_format() == FMT);
00109     // The following should be a static asserts
00110     assert(vidl_pixel_traits_of<FMT>::arrangement() == VIDL_PIXEL_ARRANGE_PLANAR);
00111 
00112     const unsigned size = frame.ni()*frame.nj();
00113 
00114     ptr_[0] = (cmp_type*)frame.data();
00115     for (unsigned int i=1; i<vidl_pixel_traits_of<FMT>::num_channels; ++i) {
00116       if (i==1)
00117         ptr_[i] = ptr_[i-1] + size;
00118       else
00119         ptr_[i] = ptr_[i-1] + ((size>>csx)>>csy);
00120     }
00121   }
00122 
00123   //: Destructor
00124   ~vidl_pixel_iterator_arranged() {}
00125 
00126   //: Step to the next pixel
00127   vidl_pixel_iterator_arranged<VIDL_PIXEL_ARRANGE_PLANAR,FMT>& next()
00128   {
00129     ++ptr_[0];
00130     if (vidl_pixel_traits_of<FMT>::num_channels > 1) {
00131       // step only if the last csx+1 bits of step_x_ are set
00132       int chroma_step = ((step_x_&x_mask) == x_mask)?1:0;
00133       if (++line_cnt_ < line_size_) {
00134         step_x_ += 2;
00135       }
00136       else
00137       {
00138         line_cnt_ = 0;
00139         step_x_=1;
00140         chroma_step = 1;
00141         // step back to start of row unless the last csy+1 bits of step_y_ are set
00142         if (!((step_y_&y_mask)==y_mask))
00143           chroma_step -= (line_size_>>csx);
00144         step_y_ += 2;
00145       }
00146       for (unsigned int i=1; i<vidl_pixel_traits_of<FMT>::num_channels; ++i) {
00147         ptr_[i] += chroma_step;
00148       }
00149     }
00150     return *this;
00151   }
00152 
00153   //: Access the data
00154   cmp_type operator () (unsigned int i) const
00155   {
00156     return *ptr_[i];
00157   }
00158 
00159   //: Access the entire pixel at once
00160   void get(cmp_type* data) const
00161   {
00162     for (unsigned int i=0; i<vidl_pixel_traits_of<FMT>::num_channels; ++i)
00163       data[i] = *ptr_[i];
00164   }
00165 
00166   //: write the entire pixel at once
00167   void set(const cmp_type* data)
00168   {
00169     for (unsigned int i=0; i<vidl_pixel_traits_of<FMT>::num_channels; ++i)
00170       *ptr_[i] = data[i];
00171   }
00172 };
00173 
00174 
00175 template <>
00176 struct vidl_pixel_iterator_arrange_valid<VIDL_PIXEL_ARRANGE_PACKED>
00177 {
00178   enum { value = true };
00179 };
00180 
00181 //: The default pixel iterator for packed arranged formats
00182 template <vidl_pixel_format FMT>
00183 class vidl_pixel_iterator_arranged<VIDL_PIXEL_ARRANGE_PACKED,FMT>
00184 {
00185   typedef typename vidl_pixel_traits_of<FMT>::type cmp_type;
00186   cmp_type * ptr_;
00187   enum { macro_pix_size = 1<<vidl_pixel_traits_of<FMT>::chroma_shift_x };
00188   enum { pix_step_size = (vidl_pixel_traits_of<FMT>::bits_per_pixel
00189                           <<vidl_pixel_traits_of<FMT>::chroma_shift_x)>>3 };
00190   vxl_byte mode_;
00191  public:
00192 
00193   //: Constructor
00194   vidl_pixel_iterator_arranged(const vidl_frame& frame)
00195     : ptr_((vxl_byte*)frame.data()), mode_(0)
00196   {
00197   }
00198 
00199   //: Destructor
00200   ~vidl_pixel_iterator_arranged() {}
00201 
00202   //: Step to the next pixel
00203   vidl_pixel_iterator_arranged<VIDL_PIXEL_ARRANGE_PACKED,FMT>& next()
00204   {
00205     mode_ = vxl_byte((mode_+1)%macro_pix_size);
00206     if (mode_==0)
00207       ptr_ += pix_step_size;
00208     return *this;
00209   }
00210 
00211   //: Access the data
00212   cmp_type operator () (unsigned int i) const
00213   {
00214     assert(i<vidl_pixel_traits_of<FMT>::num_channels);
00215     return ptr_[vidl_pixel_pack_of<FMT>::offset[mode_][i]];
00216   }
00217 
00218   //: Access the entire pixel at once
00219   void get(cmp_type* data) const
00220   {
00221     for (unsigned int i=0; i<vidl_pixel_traits_of<FMT>::num_channels; ++i)
00222       data[i] = ptr_[vidl_pixel_pack_of<FMT>::offset[mode_][i]];
00223   }
00224 
00225   //: write the entire pixel at once
00226   void set(const cmp_type* data)
00227   {
00228     for (unsigned int i=0; i<vidl_pixel_traits_of<FMT>::num_channels; ++i)
00229       ptr_[vidl_pixel_pack_of<FMT>::offset[mode_][i]] = data[i];
00230   }
00231 };
00232 
00233 
00234 #endif
00235 
00236 
00237 template <vidl_pixel_format FMT>
00238 struct vidl_pixel_iterator_valid
00239 {
00240   enum { value = vidl_pixel_iterator_arrange_valid<
00241     vidl_pixel_arrangement(vidl_pixel_traits_of<FMT>::arrangement_idx) >::value };
00242 };
00243 
00244 
00245 //: The default pixel iterator
00246 // used for non-planar non-packed formats
00247 template <vidl_pixel_format FMT>
00248 class vidl_pixel_iterator_of : public vidl_pixel_iterator
00249 {
00250   enum { arrangement = vidl_pixel_traits_of<FMT>::arrangement_idx };
00251   typedef vidl_pixel_iterator_arranged<vidl_pixel_arrangement(arrangement),FMT> arranged_itr;
00252   arranged_itr itr_;
00253   typedef typename vidl_pixel_traits_of<FMT>::type cmp_type;
00254  public:
00255   //: Constructor
00256   vidl_pixel_iterator_of(const vidl_frame& frame) : itr_(frame) {}
00257 
00258   //: Destructor
00259   virtual ~vidl_pixel_iterator_of<FMT>() {}
00260 
00261   //: Return the pixel format
00262   virtual vidl_pixel_format pixel_format() const
00263   { return FMT; }
00264 
00265   //: Pre-increment: step to the next pixel
00266   virtual vidl_pixel_iterator& operator++ ()
00267   { itr_.next(); return *this; }
00268 
00269   //: Access the data
00270   cmp_type operator () (unsigned int i) const
00271   { return itr_(i); }
00272 
00273   //: Copy the pixel data into a byte array
00274   virtual void get_data(vxl_byte* data) const
00275   { itr_.get(reinterpret_cast<cmp_type*>(data)); }
00276 
00277   //: Set the pixel data from a byte array
00278   virtual void set_data(const vxl_byte* data)
00279   { itr_.set(reinterpret_cast<const cmp_type*>(data)); }
00280 };
00281 
00282 
00283 //-----------------------------------------------------------------------------
00284 // Custom Pixel Iterators
00285 //-----------------------------------------------------------------------------
00286 
00287 
00288 //: Iterator for monochrome boolean images
00289 VCL_DEFINE_SPECIALIZATION
00290 struct vidl_pixel_iterator_valid<VIDL_PIXEL_FORMAT_MONO_1>
00291 { enum { value = true }; };
00292 
00293 VCL_DEFINE_SPECIALIZATION
00294 class vidl_pixel_iterator_of<VIDL_PIXEL_FORMAT_MONO_1>
00295   : public vidl_pixel_iterator
00296 {
00297   vxl_byte bit_mask_;
00298   vxl_byte * ptr_;
00299  public:
00300   //: Constructor
00301   vidl_pixel_iterator_of(const vidl_frame& frame)
00302     : bit_mask_(128), ptr_((vxl_byte*)frame.data())
00303   {
00304     assert(frame.pixel_format() == VIDL_PIXEL_FORMAT_MONO_1);
00305   }
00306 
00307   //: Destructor
00308   virtual ~vidl_pixel_iterator_of<VIDL_PIXEL_FORMAT_MONO_1>() {}
00309 
00310   //: Return the pixel format
00311   virtual vidl_pixel_format pixel_format() const
00312   { return VIDL_PIXEL_FORMAT_MONO_1; }
00313 
00314   //: Step to the next pixel
00315   vidl_pixel_iterator_of<VIDL_PIXEL_FORMAT_MONO_1>& next()
00316   {
00317     bit_mask_ >>= 1;
00318     if (!bit_mask_) {
00319       bit_mask_ = 128;
00320       ++ptr_;
00321     }
00322 
00323     return *this;
00324   }
00325 
00326   //: Pre-increment: step to the next pixel
00327   virtual vidl_pixel_iterator& operator++ ()
00328   {
00329     return this->next();
00330   }
00331 
00332   //: Access the data
00333   bool operator () (unsigned int i) const
00334   {
00335     assert(i==0);
00336     return (ptr_[0] & bit_mask_) != 0;
00337   }
00338 
00339   //: Access the entire pixel at once
00340   void get(bool* data) const
00341   {
00342     data[0] = (ptr_[0] & bit_mask_) != 0;
00343   }
00344 
00345   //: write the entire pixel at once
00346   void set(const bool* data)
00347   {
00348     ptr_[0] &= ~bit_mask_ & (data[0]?bit_mask_:0);
00349   }
00350 
00351   //: Copy the pixel data into a byte array
00352   virtual void get_data(vxl_byte* data) const
00353   {
00354     this->get(reinterpret_cast<bool*>(data));
00355   }
00356 
00357   //: Set the pixel data from a byte array
00358   virtual void set_data(const vxl_byte* data)
00359   {
00360     this->set(reinterpret_cast<const bool*>(data));
00361   }
00362 };
00363 
00364 
00365 #endif // vidl_pixel_iterator_txx_