Rev Author Line No. Line
178 kaklik 1 #ifndef IMAGE_REF_H
2 #define IMAGE_REF_H
3  
4 #include <cassert>
5 #include "object.h"
6  
7 namespace mimas {
8  
9 /** To represent a displacement in an image.
10 Used by image iterator */
11 struct dist2D{
12 dist2D(int x = 0, int y = 0):
13 width(x), height(y){}
14  
15 int width;
16 int height;
17 };
18  
19 /** Wrapper for read-only access of image-data.
20 This class is used for wrapping raw constant data to make it accessible to
21 the Mimas-library. */
22 template<
23 typename T,
24 typename TPtr = const T* >
25 class const_image_ref: public object
26 {
27 public:
28 /** Default constructor.
29 Creates an empty image. */
30 const_image_ref(void): data(NULL), width(0), height(0) { dummy = T(); }
31 ///
32 const_image_ref( TPtr _data, int _width, int _height ):
33 data(_data), width(_width), height(_height) { dummy = T(); }
34 ///
35 template< typename OPtr >
36 const_image_ref( const const_image_ref< T, OPtr > &_imgref ):
37 data( _imgref.rawData() ),
38 width( _imgref.getWidth() ), height( _imgref.getHeight() )
39 { dummy = T(); }
40 ///
41 class const_iterator{
42 public:
43 typedef T value_type;
44 typedef const value_type * MoveX;
45  
46 struct MoveY{
47 MoveY(unsigned int width = 0):
48 width(width),offset(0){
49 }
50  
51 void operator++(void){
52 offset += width;
53 }
54  
55 //postfix operator. There is no difference as we don't return any value
56 //but avoid any warning message
57 void operator++(int){
58 offset += width;
59 }
60  
61 void operator--(void){
62 offset -= width;
63 }
64  
65 //postfix operator. There is no difference as we don't return any value
66 //but avoid any warning message
67 void operator--(int){
68 offset -= width;
69 }
70  
71 MoveY & operator+=(int n)
72 {
73 offset += width * n;
74 return *this;
75 }
76  
77 MoveY & operator-=(int n)
78 {
79 offset -= width * n;
80 return *this;
81 }
82  
83 int operator-(const MoveY &y2) const
84 {
85 return (offset - y2.offset)/width;
86 }
87  
88 MoveY & operator=(const MoveY &y2)
89 {
90 offset = y2.offset;
91 width = y2.width;
92 return *this;
93 }
94  
95 bool operator==(const MoveY &y2) const
96 {
97 return (offset == y2.offset) && (width == y2.width);
98 }
99  
100 bool operator<(const MoveY &y2) const
101 {
102 return offset < y2.offset;
103 }
104  
105 unsigned int width;
106 unsigned int offset;
107 };
108  
109 MoveX x;
110 MoveY y;
111  
112 const_iterator(const value_type *data = NULL, unsigned int width = 0):
113 x(data), y(width) {}
114  
115 const_iterator(const const_iterator & rhs)
116 {
117 x = rhs.x;
118 y = MoveY(rhs.y.width);
119 y.offset = rhs.y.offset;
120 }
121  
122 const_iterator & operator=(const const_iterator & rhs)
123 {
124 x = rhs.x;
125 y = rhs.y;
126 return *this;
127 }
128  
129 const_iterator & operator+=(const dist2D & dist)
130 {
131 x += dist.width;
132 y += dist.height;
133 return *this;
134 }
135  
136 const_iterator & operator-=(const dist2D & dist)
137 {
138 x -= dist.width;
139 y -= dist.height;
140 return *this;
141 }
142  
143 const_iterator operator+(const dist2D & dist) const
144 {
145 const_iterator k(*this);
146 k += dist;
147 return k;
148 }
149  
150 const_iterator operator-(const dist2D & dist) const
151 {
152 const_iterator k(*this);
153 k -= dist;
154 return k;
155 }
156  
157 //mechanism to check the iterator of both images are of same width.
158 dist2D operator-(const const_iterator & rhs) const
159 {
160 #ifndef NDEBUG
161 if(y.width != rhs.y.width){
162 std::cerr<<"const_iterator (in image.h): you cannot compare"
163 "2 iterators if both images don't have the same width" <<std::endl;
164 }
165 #endif
166 return dist2D(x - rhs.x, (y.offset - rhs.y.offset)/ rhs.y.width);
167 }
168  
169 bool operator==(const const_iterator & imIt) const
170 {
171 return (x == imIt.x) && (y == imIt);
172 }
173  
174 const value_type & operator*()
175 {
176 return *(x + y.offset);
177 }
178  
179 const value_type operator*() const
180 {
181 return *(x + y.offset);
182 }
183  
184 const value_type &operator[](const dist2D dist)
185 {
186 return *(x + y.offset + dist.width + dist.height * y.width);
187 }
188  
189 const value_type operator[](const dist2D dist) const
190 {
191 return *(x + y.offset + dist.width + dist.height * y.width);
192 }
193  
194 };
195  
196 /// Width of image.
197 int getWidth(void) const { return width; }
198 /// Height of image.
199 int getHeight(void) const { return height; }
200  
201 /// Size
202 int getSize(void) const { return width * height; }
203  
204 /** Get const-reference to a pixel.
205 This method includes clipping! Specifying out-of-image
206 coordinates will result in a const-reference to the dummy
207 pixel.
208 @param x x-coordinate
209 @param y y-coordinate
210 @see pixel
211 @see dummy */
212 const T &getPixel( int x, int y ) const {
213 if ( x>=0 && y>=0 && x<getWidth() && y<getHeight() )
214 return data[ y * getWidth() + x ];
215 else
216 return dummy;
217 }
218  
219 /** Get const-reference to a pixel.
220 No clipping!
221 @param x x-coordinate
222 @param y y-coordinate
223 @see getPixel */
224 const T& pixel( int x, int y ) const {
225 assert( x>=0 && y>=0 && x<getWidth() && y<getHeight() );
226 return data[ y * getWidth() + x ];
227 }
228  
229 /// Read-only access to data.
230 const T *rawData( void ) const {
231 return data;
232 }
233  
234 ///
235 bool initialised( void ) const {
236 assert( ( data != NULL ) == ( width > 0 && height > 0 ) );
237 return data != NULL;
238 }
239  
240 //to return const values
241 inline const_iterator upperLeft(void) const
242 {
243 return const_iterator(data,getWidth());
244 }
245  
246 inline const_iterator lowerRight(void) const
247 {
248 const_iterator t(data,getWidth());
249 t.x += getWidth();
250 t.y += getHeight();
251 return t;
252 }
253  
254 inline const_iterator ul(void) const
255 {
256 return const_iterator(data,getWidth());
257 }
258  
259 inline const_iterator lr(void) const
260 {
261 const_iterator t(data,getWidth());
262 t.x += getWidth();
263 t.y += getHeight();
264 return t;
265 }
266 protected:
267 /** Data-pointer.
268 Pointer to the data in row-major format. */
269 TPtr data;
270 int width;
271 int height;
272 T dummy;
273 };
274  
275 /** Wrapper to access image-data.
276 This class is used for wrapping raw data for the purpose of making it
277 accessible to the Mimas-library. */
278 template< typename T >
279 class image_ref: public const_image_ref< T, T* >
280 {
281 public:
282 /**iterator
283 implementation of iterator for images as described in the paper
284 STL-style generic programming with images
285 by Ullrich Kothe
286  
287 Still not thoroughly tested
288 @author Manuel Boissenin */
289 class iterator {
290 public:
291 typedef T value_type;
292 typedef value_type * MoveX;
293  
294 struct MoveY{
295 MoveY(unsigned int width = 0):
296 width(width),offset(0) {
297 // std::cerr<< "constructor MoveY"<<std::endl;
298 }
299  
300 void operator++(void){
301 offset += width;
302 }
303  
304 //postfix operator. There is no difference as we don't return any value
305 //but avoid any warning message
306 void operator++(int) {
307 offset += width;
308 }
309  
310 void operator--(void) {
311 offset -= width;
312 }
313  
314 //postfix operator. There is no difference as we don't return any value
315 //but avoid any warning message
316 void operator--(int) {
317 offset -= width;
318 }
319  
320 MoveY & operator+=(int n)
321 {
322 offset += width * n;
323 return *this;
324 }
325  
326 MoveY & operator-=(int n)
327 {
328 offset -= width * n;
329 return *this;
330 }
331  
332 int operator-(const MoveY &y2) const
333 {
334 return (offset - y2.offset)/width;
335 }
336  
337 MoveY & operator=(const MoveY &y2)
338 {
339 offset = y2.offset;
340 width = y2.width;
341 return *this;
342 }
343  
344 bool operator==(const MoveY &y2) const
345 {
346 return (offset == y2.offset) && (width == y2.width);
347 }
348  
349 bool operator<(const MoveY &y2) const
350 {
351 return offset < y2.offset;
352 }
353  
354 unsigned int width;
355 unsigned int offset;
356 };
357  
358 MoveX x;
359 MoveY y;
360  
361 iterator(value_type *data = NULL, unsigned int width = 0):
362 x(data), y(width) {}
363  
364 iterator(const iterator & rhs)
365 {
366 x = rhs.x;
367 y = MoveY(rhs.y.width);
368 y.offset = rhs.y.offset;
369 }
370  
371 iterator & operator=(const iterator & rhs)
372 {
373 //std::cerr<< "operator= iterator"<<std::endl;
374 x = rhs.x;
375 y = rhs.y;
376 return *this;
377 }
378  
379 iterator & operator+=(const dist2D & dist)
380 {
381 x += dist.width;
382 y += dist.height;
383 return *this;
384 }
385  
386 iterator & operator-=(const dist2D & dist)
387 {
388 x -= dist.width;
389 y -= dist.height;
390 return *this;
391 }
392  
393 iterator operator+(const dist2D & dist) const
394 {
395 iterator k(*this);
396 k += dist;
397 return k;
398 }
399  
400 iterator operator-(const dist2D & dist) const
401 {
402 iterator k(*this);
403 k -= dist;
404 return k;
405 }
406  
407 //mechanism to check the iterator of both images are of same width.
408 dist2D operator-(const iterator & rhs) const
409 {
410 #ifndef NDEBUG
411 if(y.width != rhs.y.width){
412 std::cerr<<"Image iterator (in image.h): you cannot compare"
413 "2 iterators if both images don't have the same width" <<std::endl;
414 }
415 #endif
416 return dist2D(x - rhs.x, (y.offset - rhs.y.offset)/ rhs.y.width);
417 }
418  
419 bool operator==(const iterator & imIt) const
420 {
421 return (x == imIt.x) && (y == imIt);
422 }
423  
424 value_type & operator*()
425 {
426 return *(x + y.offset);
427 }
428  
429 value_type operator*() const
430 {
431 return *(x + y.offset);
432 }
433  
434 value_type &operator[](const dist2D dist)
435 {
436 return *(x + y.offset + dist.width + (signed)( dist.height * y.width ) );
437 }
438  
439 value_type operator[](const dist2D dist) const
440 {
441 return *(x + y.offset + dist.width + (signed)( dist.height * y.width ) );
442 }
443  
444 };
445  
446 /** Default constructor.
447 Creates an empty image. */
448 image_ref(void) {}
449 /** Copy constructor.
450 The data-pointer of the other object is copied (i.e. the data will be
451 shared). */
452 explicit image_ref( const image_ref< T > &_imgref ):
453 const_image_ref< T, T* >( _imgref ) {}
454  
455 ///
456 image_ref( T *_data, int _width, int _height ):
457 const_image_ref< T, T* >( _data, _width, _height ) {}
458  
459 /// Fill all pixel with a value.
460 virtual void fill( const T &initVal ) {
461 int size = image_ref< T >::getSize();
462 std::fill( image_ref< T >::data,
463 image_ref< T >::data + size, initVal );
464 };
465  
466 /** Get reference to a pixel.
467 This method includes clipping! Specifying out-of-image
468 coordinates will result in a reference to a dummy pixel.
469 @param x x-coordinate
470 @param y y-coordinate
471 @see pixel
472 @see dummy */
473 T &getPixel( int x, int y ) {
474 if ( x>=0 && y>=0 &&
475 x<image_ref< T >::getWidth() &&
476 y<image_ref< T >::getHeight() )
477 return image_ref< T >::data
478 [ y * image_ref< T >::getWidth() + x ];
479 else
480 return image_ref< T >::dummy;
481 }
482  
483 /** Get const-reference to a pixel.
484 This method includes clipping! Specifying out-of-image
485 coordinates will result in a const-reference to the dummy
486 pixel.
487 @param x x-coordinate
488 @param y y-coordinate
489 @see pixel
490 @see dummy */
491 const T &getPixel( int x, int y ) const {
492 if ( x>=0 && y>=0 &&
493 x<image_ref< T >::getWidth() &&
494 y<image_ref< T >::getHeight() )
495 return image_ref< T >::data
496 [ y * image_ref< T >::getWidth() + x ];
497 else
498 return image_ref< T >::dummy;
499 }
500  
501 /** Set value of a pixel.
502 This method includes clipping!
503 @param x x-coordinate
504 @param y y-coordinate
505 @param val New value.
506 @see pixel */
507 virtual void setPixel( int x, int y, T val ) {
508 if ( x>=0 &&
509 y>=0 &&
510 x<image_ref< T >::getWidth() &&
511 y<image_ref< T >::getHeight() )
512 image_ref< T >::data
513 [ y * image_ref< T >::getWidth() + x ] = val;
514 }
515  
516 /** Get reference to a pixel.
517 No clipping!
518 @param x x-coordinate
519 @param y y-coordinate
520 @see setPixel */
521 T& pixel( int x, int y ) {
522 assert( x>=0 && y>=0 && x<image_ref< T >::getWidth()&& y<image_ref< T >::getHeight() );
523 return image_ref< T >::data
524 [ y * image_ref< T >::getWidth() + x ];
525 }
526  
527 /** Get const-reference to a pixel.
528 No clipping!
529 @param x x-coordinate
530 @param y y-coordinate
531 @see getPixel */
532 const T& pixel( int x, int y ) const {
533 assert( x>=0 && y>=0 &&
534 x<image_ref< T >::getWidth() &&
535 y<image_ref< T >::getHeight() );
536 return image_ref< T >::data
537 [ y * image_ref< T >::getWidth() + x ];
538 }
539  
540 /// Read-only access to data.
541 const T *rawData( void ) const {
542 return image_ref< T >::data;
543 }
544  
545 /// Access to aggregated data.
546 T *rawData(void) {
547 return image_ref< T >::data;
548 }
549  
550 inline iterator upperLeft(void)
551 {
552 return iterator(image_ref< T >::data,
553 image_ref< T >::getWidth());
554 }
555  
556 inline iterator lowerRight(void)
557 {
558 iterator t(image_ref< T >::data,
559 image_ref< T >::getWidth());
560 t.x += image_ref< T >::getWidth();
561 t.y += image_ref< T >::getHeight();
562 return t;
563 }
564  
565 //For lazy guys/pals/mates/fellows only!!!
566 //the same as uperLeft
567 inline iterator ul(void)
568 {
569 return iterator(image_ref< T >::data,
570 image_ref< T >::getWidth());
571 }
572  
573 //the same as lowerRight
574 inline iterator lr(void)
575 {
576 iterator t(image_ref< T >::data,
577 image_ref< T >::getWidth());
578 t.x += image_ref< T >::getWidth();
579 t.y += image_ref< T >::getHeight();
580 return t;
581 }
582  
583 };
584  
585 }
586  
587 #endif