00001 #ifndef IMAGE_REF_H
00002 #define IMAGE_REF_H
00003
00004 #include <cassert>
00005 #include "object.h"
00006 #include "primitives.h"
00007
00008 namespace mimas {
00009
00012 struct dist2D{
00013 dist2D(int x = 0, int y = 0):
00014 width(x), height(y){}
00015
00016 int width;
00017 int height;
00018 };
00019
00023 template<
00024 typename T,
00025 typename TPtr = const T* >
00026 class const_image_ref: public object
00027 {
00028 public:
00031 const_image_ref(void): data(NULL), width(0), height(0) { dummy = T(); }
00033 const_image_ref( TPtr _data, int _width, int _height ):
00034 data(_data), width(_width), height(_height) { dummy = T(); }
00036 template< typename OPtr >
00037 const_image_ref( const const_image_ref< T, OPtr > &_imgref ):
00038 data( _imgref.rawData() ),
00039 width( _imgref.getWidth() ), height( _imgref.getHeight() )
00040 { dummy = T(); }
00042 class const_iterator{
00043 public:
00044 typedef T value_type;
00045 typedef const value_type * MoveX;
00046
00047 struct MoveY{
00048 MoveY(unsigned int width = 0):
00049 width(width),offset(0){
00050 }
00051
00052 void operator++(void){
00053 offset += width;
00054 }
00055
00056
00057
00058 void operator++(int){
00059 offset += width;
00060 }
00061
00062 void operator--(void){
00063 offset -= width;
00064 }
00065
00066
00067
00068 void operator--(int){
00069 offset -= width;
00070 }
00071
00072 MoveY & operator+=(int n)
00073 {
00074 offset += width * n;
00075 return *this;
00076 }
00077
00078 MoveY & operator-=(int n)
00079 {
00080 offset -= width * n;
00081 return *this;
00082 }
00083
00084 int operator-(const MoveY &y2) const
00085 {
00086 return (offset - y2.offset)/width;
00087 }
00088
00089 MoveY & operator=(const MoveY &y2)
00090 {
00091 offset = y2.offset;
00092 width = y2.width;
00093 return *this;
00094 }
00095
00096 bool operator==(const MoveY &y2) const
00097 {
00098 return (offset == y2.offset) && (width == y2.width);
00099 }
00100
00101 bool operator<(const MoveY &y2) const
00102 {
00103 return offset < y2.offset;
00104 }
00105
00106 unsigned int width;
00107 unsigned int offset;
00108 };
00109
00110 MoveX x;
00111 MoveY y;
00112
00113 const_iterator(const value_type *data = NULL, unsigned int width = 0):
00114 x(data), y(width) {}
00115
00116 const_iterator(const const_iterator & rhs)
00117 {
00118 x = rhs.x;
00119 y = MoveY(rhs.y.width);
00120 y.offset = rhs.y.offset;
00121 }
00122
00123 const_iterator & operator=(const const_iterator & rhs)
00124 {
00125 x = rhs.x;
00126 y = rhs.y;
00127 return *this;
00128 }
00129
00130 const_iterator & operator+=(const dist2D & dist)
00131 {
00132 x += dist.width;
00133 y += dist.height;
00134 return *this;
00135 }
00136
00137 const_iterator & operator-=(const dist2D & dist)
00138 {
00139 x -= dist.width;
00140 y -= dist.height;
00141 return *this;
00142 }
00143
00144 const_iterator operator+(const dist2D & dist) const
00145 {
00146 const_iterator k(*this);
00147 k += dist;
00148 return k;
00149 }
00150
00151 const_iterator operator-(const dist2D & dist) const
00152 {
00153 const_iterator k(*this);
00154 k -= dist;
00155 return k;
00156 }
00157
00158
00159 dist2D operator-(const const_iterator & rhs) const
00160 {
00161 #ifndef NDEBUG
00162 if(y.width != rhs.y.width){
00163 std::cerr<<"const_iterator (in image.h): you cannot compare"
00164 "2 iterators if both images don't have the same width" <<std::endl;
00165 }
00166 #endif
00167 return dist2D(x - rhs.x, (y.offset - rhs.y.offset)/ rhs.y.width);
00168 }
00169
00170 bool operator==(const const_iterator & imIt) const
00171 {
00172 return (x == imIt.x) && (y == imIt);
00173 }
00174
00175 const value_type & operator*()
00176 {
00177 return *(x + y.offset);
00178 }
00179
00180 const value_type operator*() const
00181 {
00182 return *(x + y.offset);
00183 }
00184
00185 const value_type &operator[](const dist2D dist)
00186 {
00187 return *(x + y.offset + dist.width + dist.height * y.width);
00188 }
00189
00190 const value_type operator[](const dist2D dist) const
00191 {
00192 return *(x + y.offset + dist.width + dist.height * y.width);
00193 }
00194
00195 };
00196
00198 int getWidth(void) const { return width; }
00200 int getHeight(void) const { return height; }
00201
00203 int getSize(void) const { return width * height; }
00204
00213 const T &getPixel( int x, int y ) const {
00214 if ( x>=0 && y>=0 && x<getWidth() && y<getHeight() )
00215 return data[ y * getWidth() + x ];
00216 else
00217 {
00218 #ifndef NDEBUG
00219 std::cerr << "The usage of the dummy variable is deprecated."<<std::endl
00220 << "Instead use the pixel() function or the getPixel() function in conjunction with the in() function."
00221 << std::endl << "If you do not have this message you are succesfully not using the dummy variable."
00222 << std::endl<< std::endl;
00223 #endif
00224 return dummy;
00225 }
00226 }
00227
00233 const T& pixel( int x, int y ) const {
00234 assert( x>=0 && y>=0 && x<getWidth() && y<getHeight() );
00235 return data[ y * getWidth() + x ];
00236 }
00237
00239 const T *rawData( void ) const {
00240 return data;
00241 }
00242
00244 bool initialised( void ) const {
00245 assert( ( data != NULL ) == ( width > 0 && height > 0 ) );
00246 return data != NULL;
00247 }
00248
00249
00250
00251
00252 bool in(const mimas::point p) const {
00253 if ( p.x < 0 || p.y < 0 ||
00254 p.x >= getWidth() || p.y >= getHeight() ) {
00255 return false;
00256 }
00257 return true;
00258 }
00259
00260 bool in(const mimas::pixel p) const{
00261 if (p.x < 0 || p.y < 0 ||
00262 p.x >= getWidth() || p.y >= getHeight()) {
00263 return false;
00264 }
00265 return true;
00266 }
00267
00268 bool in(int x, int y) const{
00269 if (x < 0 || y < 0 ||
00270 x >= getWidth() || y >= getHeight()) {
00271 return false;
00272 }
00273 return true;
00274 }
00275
00276
00277 inline const_iterator upperLeft(void) const
00278 {
00279 return const_iterator(data,getWidth());
00280 }
00281
00282 inline const_iterator lowerRight(void) const
00283 {
00284 const_iterator t(data,getWidth());
00285 t.x += getWidth();
00286 t.y += getHeight();
00287 return t;
00288 }
00289
00290 inline const_iterator ul(void) const
00291 {
00292 return const_iterator(data,getWidth());
00293 }
00294
00295 inline const_iterator lr(void) const
00296 {
00297 const_iterator t(data,getWidth());
00298 t.x += getWidth();
00299 t.y += getHeight();
00300 return t;
00301 }
00302 protected:
00305 TPtr data;
00306 int width;
00307 int height;
00308 T dummy;
00309 };
00310
00314 template< typename T >
00315 class image_ref: public const_image_ref< T, T* >
00316 {
00317 public:
00325 class iterator {
00326 public:
00327 typedef T value_type;
00328 typedef value_type * MoveX;
00329
00330 struct MoveY{
00331 MoveY(unsigned int width = 0):
00332 width(width),offset(0) {
00333
00334 }
00335
00336 void operator++(void){
00337 offset += width;
00338 }
00339
00340
00341
00342 void operator++(int) {
00343 offset += width;
00344 }
00345
00346 void operator--(void) {
00347 offset -= width;
00348 }
00349
00350
00351
00352 void operator--(int) {
00353 offset -= width;
00354 }
00355
00356 MoveY & operator+=(int n)
00357 {
00358 offset += width * n;
00359 return *this;
00360 }
00361
00362 MoveY & operator-=(int n)
00363 {
00364 offset -= width * n;
00365 return *this;
00366 }
00367
00368 int operator-(const MoveY &y2) const
00369 {
00370 return (offset - y2.offset)/width;
00371 }
00372
00373 MoveY & operator=(const MoveY &y2)
00374 {
00375 offset = y2.offset;
00376 width = y2.width;
00377 return *this;
00378 }
00379
00380 bool operator==(const MoveY &y2) const
00381 {
00382 return (offset == y2.offset) && (width == y2.width);
00383 }
00384
00385 bool operator<(const MoveY &y2) const
00386 {
00387 return offset < y2.offset;
00388 }
00389
00390 unsigned int width;
00391 unsigned int offset;
00392 };
00393
00394 MoveX x;
00395 MoveY y;
00396
00397 iterator(value_type *data = NULL, unsigned int width = 0):
00398 x(data), y(width) {}
00399
00400 iterator(const iterator & rhs)
00401 {
00402 x = rhs.x;
00403 y = MoveY(rhs.y.width);
00404 y.offset = rhs.y.offset;
00405 }
00406
00407 iterator & operator=(const iterator & rhs)
00408 {
00409
00410 x = rhs.x;
00411 y = rhs.y;
00412 return *this;
00413 }
00414
00415 iterator & operator+=(const dist2D & dist)
00416 {
00417 x += dist.width;
00418 y += dist.height;
00419 return *this;
00420 }
00421
00422 iterator & operator-=(const dist2D & dist)
00423 {
00424 x -= dist.width;
00425 y -= dist.height;
00426 return *this;
00427 }
00428
00429 iterator operator+(const dist2D & dist) const
00430 {
00431 iterator k(*this);
00432 k += dist;
00433 return k;
00434 }
00435
00436 iterator operator-(const dist2D & dist) const
00437 {
00438 iterator k(*this);
00439 k -= dist;
00440 return k;
00441 }
00442
00443
00444 dist2D operator-(const iterator & rhs) const
00445 {
00446 #ifndef NDEBUG
00447 if(y.width != rhs.y.width){
00448 std::cerr<<"Image iterator (in image.h): you cannot compare"
00449 "2 iterators if both images don't have the same width" <<std::endl;
00450 }
00451 #endif
00452 return dist2D(x - rhs.x, (y.offset - rhs.y.offset)/ rhs.y.width);
00453 }
00454
00455 bool operator==(const iterator & imIt) const
00456 {
00457 return (x == imIt.x) && (y == imIt);
00458 }
00459
00460 value_type & operator*()
00461 {
00462 return *(x + y.offset);
00463 }
00464
00465 value_type operator*() const
00466 {
00467 return *(x + y.offset);
00468 }
00469
00470 value_type &operator[](const dist2D dist)
00471 {
00472 return *(x + y.offset + dist.width + (signed)( dist.height * y.width ) );
00473 }
00474
00475 value_type operator[](const dist2D dist) const
00476 {
00477 return *(x + y.offset + dist.width + (signed)( dist.height * y.width ) );
00478 }
00479
00480 };
00481
00484 image_ref(void) {}
00488 explicit image_ref( const image_ref< T > &_imgref ):
00489 const_image_ref< T, T* >( _imgref ) {}
00490
00492 image_ref( T *_data, int _width, int _height ):
00493 const_image_ref< T, T* >( _data, _width, _height ) {}
00494
00496 virtual void fill( const T &initVal ) {
00497 int size = image_ref< T >::getSize();
00498 std::fill( image_ref< T >::data,
00499 image_ref< T >::data + size, initVal );
00500 };
00501
00509 T &getPixel( int x, int y ) {
00510 if ( x>=0 && y>=0 &&
00511 x<image_ref< T >::getWidth() &&
00512 y<image_ref< T >::getHeight() )
00513 return image_ref< T >::data
00514 [ y * image_ref< T >::getWidth() + x ];
00515 else
00516 {
00517 #ifndef NDEBUG
00518 std::cerr << "The usage of the dummy variable is deprecated."<<std::endl
00519 << "Instead use the pixel() function or the getPixel() function in conjunction with the in() function."
00520 << std::endl << "If you do not have this message you are succesfully not using the dummy variable."
00521 << std::endl<< std::endl;
00522 #endif
00523 return image_ref< T >::dummy;
00524 }
00525 }
00526
00535 const T &getPixel( int x, int y ) const {
00536 if ( x>=0 && y>=0 &&
00537 x<image_ref< T >::getWidth() &&
00538 y<image_ref< T >::getHeight() )
00539 return image_ref< T >::data
00540 [ y * image_ref< T >::getWidth() + x ];
00541 else
00542 {
00543 #ifndef NDEBUG
00544 std::cerr << "The usage of the dummy variable is deprecated."<<std::endl
00545 << "Instead use the pixel() function or the getPixel() function in conjunction with the in() function."
00546 << std::endl << "If you do not have this message you are succesfully not using the dummy variable."
00547 << std::endl<< std::endl;
00548 #endif
00549 return image_ref< T >::dummy;
00550 }
00551 }
00552
00559 virtual void setPixel( int x, int y, T val ) {
00560 if ( x>=0 &&
00561 y>=0 &&
00562 x<image_ref< T >::getWidth() &&
00563 y<image_ref< T >::getHeight() )
00564 image_ref< T >::data
00565 [ y * image_ref< T >::getWidth() + x ] = val;
00566 }
00567
00573 T& pixel( int x, int y ) {
00574 assert( x>=0 && y>=0 && x<image_ref< T >::getWidth()&& y<image_ref< T >::getHeight() );
00575 return image_ref< T >::data
00576 [ y * image_ref< T >::getWidth() + x ];
00577 }
00578
00584 const T& pixel( int x, int y ) const {
00585 assert( x>=0 && y>=0 &&
00586 x<image_ref< T >::getWidth() &&
00587 y<image_ref< T >::getHeight() );
00588 return image_ref< T >::data
00589 [ y * image_ref< T >::getWidth() + x ];
00590 }
00591
00593 const T *rawData( void ) const {
00594 return image_ref< T >::data;
00595 }
00596
00598 T *rawData(void) {
00599 return image_ref< T >::data;
00600 }
00601
00602 inline iterator upperLeft(void)
00603 {
00604 return iterator(image_ref< T >::data,
00605 image_ref< T >::getWidth());
00606 }
00607
00608 inline iterator lowerRight(void)
00609 {
00610 iterator t(image_ref< T >::data,
00611 image_ref< T >::getWidth());
00612 t.x += image_ref< T >::getWidth();
00613 t.y += image_ref< T >::getHeight();
00614 return t;
00615 }
00616
00617
00618
00619 inline iterator ul(void)
00620 {
00621 return iterator(image_ref< T >::data,
00622 image_ref< T >::getWidth());
00623 }
00624
00625
00626 inline iterator lr(void)
00627 {
00628 iterator t(image_ref< T >::data,
00629 image_ref< T >::getWidth());
00630 t.x += image_ref< T >::getWidth();
00631 t.y += image_ref< T >::getHeight();
00632 return t;
00633 }
00634
00635 };
00636
00637 }
00638
00639 #endif