1 // This is core/vidl/vidl_pixel_iterator.hxx
2 #ifndef vidl_pixel_iterator_hxx_
3 #define vidl_pixel_iterator_hxx_
4 //:
5 // \file
6 // \brief Templated definitions for pixel iterators
7 //
8 // \author Matt Leotta
9 // \date 3 Mar 2006
10 //
11 // This file contains the template definitions for pixel iterators
12 
13 
14 #include "vidl_pixel_iterator.h"
15 #include "vidl_color.h"
16 #include <vxl_config.h>
17 #include <cassert>
18 #ifdef _MSC_VER
19 #  include <vcl_msvc_warnings.h>
20 #endif
21 
22 //-----------------------------------------------------------------------------
23 
24 
25 template <vidl_pixel_arrangement AR>
26 struct vidl_pixel_iterator_arrange_valid
27 {
28   enum { value = (AR == VIDL_PIXEL_ARRANGE_SINGLE) };
29 };
30 
31 
32 //: The default pixel iterator for single arranged formats
33 template <vidl_pixel_arrangement AR, vidl_pixel_format FMT>
34 class vidl_pixel_iterator_arranged
35 {
36   typedef typename vidl_pixel_traits_of<FMT>::type cmp_type;
37   cmp_type * ptr_;
38  public:
39   //: Constructor
vidl_pixel_iterator_arranged(const vidl_frame & frame)40   vidl_pixel_iterator_arranged(const vidl_frame& frame)
41     : ptr_((cmp_type*)frame.data())
42   {
43     assert(frame.pixel_format() == FMT);
44     // The following should be a static asserts
45     assert(vidl_pixel_traits_of<FMT>::bits_per_pixel%8 == 0);
46     assert(vidl_pixel_traits_of<FMT>::arrangement() == VIDL_PIXEL_ARRANGE_SINGLE);
47   }
48 
49   //: Destructor
50   ~vidl_pixel_iterator_arranged() = default;
51 
52   //: Step to the next pixel
next()53   vidl_pixel_iterator_arranged<AR,FMT>& next()
54   {
55     ptr_ += vidl_pixel_traits_of<FMT>::bits_per_pixel/(sizeof(cmp_type)*8);
56     return *this;
57   }
58 
59   //: Access the data
operator ()(unsigned int i) const60   cmp_type operator () (unsigned int i) const
61   {
62     assert(i<vidl_pixel_traits_of<FMT>::num_channels);
63     return vidl_color_component<FMT>::get(ptr_,i);
64   }
65 
66   //: Access the entire pixel at once
get(cmp_type * data) const67   void get(cmp_type* data) const
68   {
69     vidl_color_component<FMT>::get_all(ptr_,data);
70   }
71 
72   //: write the entire pixel at once
set(const cmp_type * data)73   void set(const cmp_type* data)
74   {
75     vidl_color_component<FMT>::set_all(ptr_,data);
76   }
77 };
78 
79 template <>
80 struct vidl_pixel_iterator_arrange_valid<VIDL_PIXEL_ARRANGE_PLANAR>
81 {
82   enum { value = true };
83 };
84 
85 
86 //: The default pixel iterator for planar arranged formats
87 template <vidl_pixel_format FMT>
88 class vidl_pixel_iterator_arranged<VIDL_PIXEL_ARRANGE_PLANAR,FMT>
89 {
90   typedef typename vidl_pixel_traits_of<FMT>::type cmp_type;
91   enum { csx = vidl_pixel_traits_of<FMT>::chroma_shift_x };
92   enum { csy = vidl_pixel_traits_of<FMT>::chroma_shift_y };
93   enum { x_mask = (1<<(csx+1))-1 }; // last csx+1 bits are 1
94   enum { y_mask = (1<<(csy+1))-1 }; // last csy+1 bits are 1
95   unsigned int line_size_;
96   unsigned int line_cnt_;
97   cmp_type * ptr_[vidl_pixel_traits_of<FMT>::num_channels];
98   //: these act as fractional pixel counters
99   vxl_byte step_x_, step_y_;
100  public:
101   //: Constructor
vidl_pixel_iterator_arranged(const vidl_frame & frame)102   vidl_pixel_iterator_arranged(const vidl_frame& frame)
103     : line_size_(frame.ni()), line_cnt_(0), step_x_(1), step_y_(1)
104   {
105     assert(frame.pixel_format() == FMT);
106     // The following should be a static asserts
107     assert(vidl_pixel_traits_of<FMT>::arrangement() == VIDL_PIXEL_ARRANGE_PLANAR);
108 
109     const unsigned size = frame.ni()*frame.nj();
110 
111     ptr_[0] = (cmp_type*)frame.data();
112     for (unsigned int i=1; i<vidl_pixel_traits_of<FMT>::num_channels; ++i) {
113       if (i==1)
114         ptr_[i] = ptr_[i-1] + size;
115       else
116         ptr_[i] = ptr_[i-1] + ((size>>csx)>>csy);
117     }
118   }
119 
120   //: Destructor
121   ~vidl_pixel_iterator_arranged() = default;
122 
123   //: Step to the next pixel
next()124   vidl_pixel_iterator_arranged<VIDL_PIXEL_ARRANGE_PLANAR,FMT>& next()
125   {
126     ++ptr_[0];
127     if (vidl_pixel_traits_of<FMT>::num_channels > 1) {
128       // step only if the last csx+1 bits of step_x_ are set
129       int chroma_step = ((step_x_&x_mask) == x_mask)?1:0;
130       if (++line_cnt_ < line_size_) {
131         step_x_ += 2;
132       }
133       else
134       {
135         line_cnt_ = 0;
136         step_x_=1;
137         chroma_step = 1;
138         // step back to start of row unless the last csy+1 bits of step_y_ are set
139         if (!((step_y_&y_mask)==y_mask))
140           chroma_step -= (line_size_>>csx);
141         step_y_ += 2;
142       }
143       for (unsigned int i=1; i<vidl_pixel_traits_of<FMT>::num_channels; ++i) {
144         ptr_[i] += chroma_step;
145       }
146     }
147     return *this;
148   }
149 
150   //: Access the data
operator ()(unsigned int i) const151   cmp_type operator () (unsigned int i) const
152   {
153     return *ptr_[i];
154   }
155 
156   //: Access the entire pixel at once
get(cmp_type * data) const157   void get(cmp_type* data) const
158   {
159     for (unsigned int i=0; i<vidl_pixel_traits_of<FMT>::num_channels; ++i)
160       data[i] = *ptr_[i];
161   }
162 
163   //: write the entire pixel at once
set(const cmp_type * data)164   void set(const cmp_type* data)
165   {
166     for (unsigned int i=0; i<vidl_pixel_traits_of<FMT>::num_channels; ++i)
167       *ptr_[i] = data[i];
168   }
169 };
170 
171 
172 template <>
173 struct vidl_pixel_iterator_arrange_valid<VIDL_PIXEL_ARRANGE_PACKED>
174 {
175   enum { value = true };
176 };
177 
178 //: The default pixel iterator for packed arranged formats
179 template <vidl_pixel_format FMT>
180 class vidl_pixel_iterator_arranged<VIDL_PIXEL_ARRANGE_PACKED,FMT>
181 {
182   typedef typename vidl_pixel_traits_of<FMT>::type cmp_type;
183   cmp_type * ptr_;
184   enum { macro_pix_size = 1<<vidl_pixel_traits_of<FMT>::chroma_shift_x };
185   enum { pix_step_size = (vidl_pixel_traits_of<FMT>::bits_per_pixel
186                           <<vidl_pixel_traits_of<FMT>::chroma_shift_x)>>3 };
187   vxl_byte mode_;
188  public:
189 
190   //: Constructor
vidl_pixel_iterator_arranged(const vidl_frame & frame)191   vidl_pixel_iterator_arranged(const vidl_frame& frame)
192     : ptr_((vxl_byte*)frame.data()), mode_(0)
193   {
194   }
195 
196   //: Destructor
197   ~vidl_pixel_iterator_arranged() = default;
198 
199   //: Step to the next pixel
next()200   vidl_pixel_iterator_arranged<VIDL_PIXEL_ARRANGE_PACKED,FMT>& next()
201   {
202     mode_ = vxl_byte((mode_+1)%macro_pix_size);
203     if (mode_==0)
204       ptr_ += pix_step_size;
205     return *this;
206   }
207 
208   //: Access the data
operator ()(unsigned int i) const209   cmp_type operator () (unsigned int i) const
210   {
211     assert(i<vidl_pixel_traits_of<FMT>::num_channels);
212     return ptr_[vidl_pixel_pack_of<FMT>::offset[mode_][i]];
213   }
214 
215   //: Access the entire pixel at once
get(cmp_type * data) const216   void get(cmp_type* data) const
217   {
218     for (unsigned int i=0; i<vidl_pixel_traits_of<FMT>::num_channels; ++i)
219       data[i] = ptr_[vidl_pixel_pack_of<FMT>::offset[mode_][i]];
220   }
221 
222   //: write the entire pixel at once
set(const cmp_type * data)223   void set(const cmp_type* data)
224   {
225     for (unsigned int i=0; i<vidl_pixel_traits_of<FMT>::num_channels; ++i)
226       ptr_[vidl_pixel_pack_of<FMT>::offset[mode_][i]] = data[i];
227   }
228 };
229 
230 
231 template <vidl_pixel_format FMT>
232 struct vidl_pixel_iterator_valid
233 {
234   enum { value = vidl_pixel_iterator_arrange_valid<
235     vidl_pixel_arrangement(vidl_pixel_traits_of<FMT>::arrangement_idx) >::value };
236 };
237 
238 
239 //: The default pixel iterator
240 // used for non-planar non-packed formats
241 template <vidl_pixel_format FMT>
242 class vidl_pixel_iterator_of : public vidl_pixel_iterator
243 {
244   enum { arrangement = vidl_pixel_traits_of<FMT>::arrangement_idx };
245   typedef vidl_pixel_iterator_arranged<vidl_pixel_arrangement(arrangement),FMT> arranged_itr;
246   arranged_itr itr_;
247   typedef typename vidl_pixel_traits_of<FMT>::type cmp_type;
248  public:
249   //: Constructor
vidl_pixel_iterator_of(const vidl_frame & frame)250   vidl_pixel_iterator_of(const vidl_frame& frame) : itr_(frame) {}
251 
252   //: Destructor
253   ~vidl_pixel_iterator_of<FMT>() override = default;
254 
255   //: Return the pixel format
pixel_format() const256   vidl_pixel_format pixel_format() const override
257   { return FMT; }
258 
259   //: Pre-increment: step to the next pixel
operator ++()260   vidl_pixel_iterator& operator++ () override
261   { itr_.next(); return *this; }
262 
263   //: Access the data
operator ()(unsigned int i) const264   cmp_type operator () (unsigned int i) const
265   { return itr_(i); }
266 
267   //: Copy the pixel data into a byte array
get_data(vxl_byte * data) const268   void get_data(vxl_byte* data) const override
269   { itr_.get(reinterpret_cast<cmp_type*>(data)); }
270 
271   //: Set the pixel data from a byte array
set_data(const vxl_byte * data)272   void set_data(const vxl_byte* data) override
273   { itr_.set(reinterpret_cast<const cmp_type*>(data)); }
274 };
275 
276 
277 //-----------------------------------------------------------------------------
278 // Custom Pixel Iterators
279 //-----------------------------------------------------------------------------
280 
281 
282 //: Iterator for monochrome boolean images
283 template <>
284 struct vidl_pixel_iterator_valid<VIDL_PIXEL_FORMAT_MONO_1>
285 { enum { value = true }; };
286 
287 template <>
288 class vidl_pixel_iterator_of<VIDL_PIXEL_FORMAT_MONO_1>
289   : public vidl_pixel_iterator
290 {
291   vxl_byte bit_mask_;
292   vxl_byte * ptr_;
293  public:
294   //: Constructor
vidl_pixel_iterator_of(const vidl_frame & frame)295   vidl_pixel_iterator_of(const vidl_frame& frame)
296     : bit_mask_(128), ptr_((vxl_byte*)frame.data())
297   {
298     assert(frame.pixel_format() == VIDL_PIXEL_FORMAT_MONO_1);
299   }
300 
301   //: Destructor
302   ~vidl_pixel_iterator_of<VIDL_PIXEL_FORMAT_MONO_1>() override = default;
303 
304   //: Return the pixel format
pixel_format() const305   vidl_pixel_format pixel_format() const override
306   { return VIDL_PIXEL_FORMAT_MONO_1; }
307 
308   //: Step to the next pixel
next()309   vidl_pixel_iterator_of<VIDL_PIXEL_FORMAT_MONO_1>& next()
310   {
311     bit_mask_ >>= 1;
312     if (!bit_mask_) {
313       bit_mask_ = 128;
314       ++ptr_;
315     }
316 
317     return *this;
318   }
319 
320   //: Pre-increment: step to the next pixel
operator ++()321   vidl_pixel_iterator& operator++ () override
322   {
323     return this->next();
324   }
325 
326   //: Access the data
operator ()(unsigned int i) const327   bool operator () (unsigned int i) const
328   {
329     assert(i==0);
330     return (ptr_[0] & bit_mask_) != 0;
331   }
332 
333   //: Access the entire pixel at once
get(bool * data) const334   void get(bool* data) const
335   {
336     data[0] = (ptr_[0] & bit_mask_) != 0;
337   }
338 
339   //: write the entire pixel at once
set(const bool * data)340   void set(const bool* data)
341   {
342     ptr_[0] &= ~bit_mask_ & (data[0]?bit_mask_:0);
343   }
344 
345   //: Copy the pixel data into a byte array
get_data(vxl_byte * data) const346   void get_data(vxl_byte* data) const override
347   {
348     this->get(reinterpret_cast<bool*>(data));
349   }
350 
351   //: Set the pixel data from a byte array
set_data(const vxl_byte * data)352   void set_data(const vxl_byte* data) override
353   {
354     this->set(reinterpret_cast<const bool*>(data));
355   }
356 };
357 
358 
359 #endif // vidl_pixel_iterator_hxx_
360