00001 #ifndef IMG_IMAGE_H_
00002 #define IMG_IMAGE_H_
00003
00009 #include "img/img_base.h"
00010 #include "img/img_attributes.h"
00011
00012 namespace img {
00013
00025 template<int Channels=3, typename ScalarType=double, bool Safe=true>
00026 class Image
00027 {
00028 private:
00029
00030
00031
00033 int _width;
00035 int _height;
00037 ScalarType *_data;
00038
00039
00040 public:
00042 ImgAttributes<ScalarType> attributes;
00043
00044
00049 Image()
00050 :_width(0),_height(0),_data(NULL),attributes()
00051 {
00052 STATIC_ASSERT( Channels>0 );
00053 STATIC_FLOAT_OR_DOUBLE_TYPECHECK( ScalarType );
00054 }
00055
00062 Image(const Image<Channels,ScalarType,Safe> &image)
00063 {
00064 STATIC_ASSERT( Channels>0 );
00065 STATIC_FLOAT_OR_DOUBLE_TYPECHECK( ScalarType );
00066
00067 assert(image._width > 0);
00068 assert(image._height > 0);
00069 assert(image._data != NULL);
00070 if(Safe) {
00071 if(image._width <= 0) throw ImageException("Image(Image): Nonpositive width");
00072 if(image._height <= 0) throw ImageException("Image(Image): Nonpositive height");
00073 if(image._data == NULL) throw ImageException("Image(Image): NULL data");
00074 }
00075 _width = image._width;
00076 _height = image._height;
00077 _data = new ScalarType[Channels * _width * _height];
00078 attributes=image.attributes;
00079
00080 memcpy(_data, image._data, sizeof(ScalarType) * Channels * _width * _height);
00081 }
00082
00087 template<typename OtherScalarType, bool OtherSafe>
00088 Image(const Image<Channels,OtherScalarType,OtherSafe> &image)
00089 :_width(0),_height(0),_data(NULL)
00090 {
00091 STATIC_ASSERT( Channels>0 );
00092 STATIC_FLOAT_OR_DOUBLE_TYPECHECK( ScalarType );
00093
00094 assert(image._width > 0);
00095 assert(image._height > 0);
00096 assert(image._data != NULL);
00097 if(Safe || OtherSafe) {
00098 if(image._width <= 0) throw ImageException("Image(Image): Nonpositive width");
00099 if(image._height <= 0) throw ImageException("Image(Image): Nonpositive height");
00100 if(image._data == NULL) throw ImageException("Image(Image): NULL data");
00101 }
00102 _width = image._width;
00103 _height = image._height;
00104 _data = new ScalarType[Channels * _width * _height];
00105 attributes=image.attributes;
00106
00107 if(typeid( ScalarType ) == typeid( OtherScalarType ))
00108 memcpy(_data, image._data, sizeof(ScalarType) * Channels * _width * _height);
00109 else
00110 for(int offset=0;offset< Channels * _width * _height; ++offset)
00111 _data[offset] = static_cast<ScalarType>(image._data[offset]);
00112 }
00113
00120 Image(int arg_width,int arg_height)
00121 :_width(arg_width),_height(arg_height),_data(NULL),attributes()
00122 {
00123 STATIC_ASSERT( Channels>0 );
00124 STATIC_FLOAT_OR_DOUBLE_TYPECHECK( ScalarType );
00125
00126 assert(arg_width>0);
00127 assert(arg_height>0);
00128 if(Safe) {
00129 if(arg_width <= 0) throw ImageException("Image(int,int): Nonpositive width");
00130 if(arg_height <= 0) throw ImageException("Image(int,int): Nonpositive height");
00131 }
00132 _data = new ScalarType[Channels * _width * _height];
00133 for(int offset=0;offset< Channels * _width * _height; ++offset)
00134 _data[offset] = 0.0f;
00135 }
00136
00138 ~Image()
00139 {
00140 attributes.reset();
00141 if(_data!=NULL){
00142 delete [] _data;
00143 _data=NULL;
00144 }
00145 }
00146
00147
00148 public:
00154 template<typename OtherScalarType, bool OtherSafe>
00155 inline Image< Channels,ScalarType,Safe> & operator =(const Image<Channels,OtherScalarType,OtherSafe> &image)
00156 {
00157 assert(image._width > 0);
00158 assert(image._height > 0);
00159 assert(image._data != NULL);
00160 if(Safe || OtherSafe) {
00161 if(image._width <= 0) throw ImageException("operator =: Nonpositive width");
00162 if(image._height <= 0) throw ImageException("operator =: Nonpositive height");
00163 if(image._data == NULL) throw ImageException("operator =: NULL data");
00164 }
00165 _width = image._width;
00166 _height = image._height;
00167 _data = new ScalarType[Channels * _width * _height];
00168 attributes=image.attributes;
00169
00170 if(typeid( ScalarType ) == typeid( OtherSafe ))
00171 memcpy(_data, image._data, sizeof(ScalarType) * Channels * _width * _height);
00172 else
00173 for(int offset=0;offset < Channels * _width * _height; ++offset)
00174 _data[offset] = static_cast<ScalarType>(image._data[offset]);
00175 return *this;
00176 }
00177
00184 inline void setZero(int arg_width, int arg_height)
00185 {
00186 assert(arg_width>0);
00187 assert(arg_height>0);
00188 if(Safe) {
00189 if(arg_width <= 0) throw ImageException("setZero: Nonpositive width");
00190 if(arg_height <= 0) throw ImageException("setZero: Nonpositive height");
00191 }
00192 if(_data!=NULL){
00193 delete [] _data;
00194 _data=NULL;
00195 }
00196 _width = arg_width;
00197 _height = arg_height;
00198 _data = new ScalarType[Channels * _width * _height];
00199 attributes.reset();
00200
00201 for(int offset=0;offset< Channels * _width * _height; ++offset)
00202 _data[offset] = 0.0f;
00203 }
00204
00209 inline void deleteData()
00210 {
00211 if(_data!=NULL){
00212 delete [] _data;
00213 _data=NULL;
00214 }
00215 _width = 0;
00216 _height = 0;
00217 }
00218
00219
00226 inline void getPixel(int x, int y, ScalarType (& ret_pixel)[Channels]) const
00227 {
00228 assert( _data != NULL );
00229 assert( x >= 0 && x < _width );
00230 assert( y >= 0 && y < _height );
00231 if( Safe ){
00232 if ( _data == NULL ) throw ImageException("getPixel: NULL data");
00233 if ( !( x >= 0 && x < _width ) ) throw ImageException("getPixel: x out of bounds");
00234 if ( !( y >= 0 && y < _height ) ) throw ImageException("getPixel: y out of bounds");
00235 }
00236 for (int channel=0;channel<Channels;++channel)
00237 ret_pixel[channel] = _data[ (x + y * _width) * Channels + channel ];
00238 }
00239
00246 inline void setPixel(int x, int y, const ScalarType (& pixel)[Channels])
00247 {
00248 assert( _data != NULL );
00249 assert( x >= 0 && x < _width );
00250 assert( y >= 0 && y < _height );
00251 if( Safe ){
00252 if ( _data == NULL ) throw ImageException("setPixel: NULL data");
00253 if ( !( x >= 0 && x < _width ) ) throw ImageException("setPixel: x out of bounds");
00254 if ( !( y >= 0 && y < _height ) ) throw ImageException("setPixel: y out of bounds");
00255 }
00256 for (int channel=0;channel<Channels;++channel)
00257 _data[ (x + y * _width) * Channels + channel ] = pixel[channel];
00258 }
00259
00267 inline ScalarType getValue(int x, int y, int channel) const
00268 {
00269 assert( _data != NULL );
00270 assert( x >= 0 && x < _width );
00271 assert( y >= 0 && y < _height );
00272 assert( channel >=0 && channel < Channels );
00273 if( Safe ){
00274 if ( _data == NULL ) throw ImageException("getFloat: NULL data");
00275 if ( !( x >= 0 && x < _width ) ) throw ImageException("getFloat: x out of bounds");
00276 if ( !( y >= 0 && y < _height ) ) throw ImageException("getFloat: y out of bounds");
00277 if ( !( channel >=0 && channel < Channels ) ) throw ImageException("channel out of bounds");
00278 }
00279 return _data[ (x + y * _width) * Channels + channel ];
00280 }
00281
00289 inline void setValue(int x, int y, int channel, ScalarType value)
00290 {
00291 assert( _data != NULL );
00292 assert( x >= 0 && x < _width );
00293 assert( y >= 0 && y < _height );
00294 assert( channel >=0 && channel < Channels );
00295 if( Safe ){
00296 if ( _data == NULL ) throw ImageException("setFloat: NULL data");
00297 if ( !( x >= 0 && x < _width ) ) throw ImageException("setFloat: x out of bounds");
00298 if ( !( y >= 0 && y < _height ) ) throw ImageException("setFloat: y out of bounds");
00299 if ( !( channel >=0 && channel < Channels ) ) throw ImageException("channel out of bounds");
00300 }
00301 _data[(x + y * _width) * Channels + channel] = value;
00302 }
00303
00310 inline void getPixelAsClamped(int x, int y, ScalarType (& ret_pixel)[Channels]) const
00311 {
00312 getPixel(x<0?0:(x<_width?x:_width-1), y<0?0:(y<_height?y:_height-1), ret_pixel);
00313 }
00314
00322 inline float getValueAsClamped(int x, int y, int channel) const
00323 {
00324 return getValue(x<0?0:(x<_width?x:_width-1), y<0?0:(y<_height?y:_height-1),channel);
00325 }
00326
00333 inline void nearestPixel(float x, float y, ScalarType (& ret_pixel)[Channels]) const
00334 {
00335 getPixel(static_cast<int>(floor(x+0.5f)),static_cast<int>(floor(y+0.5f)), ret_pixel);
00336 }
00337
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376 public:
00381 inline int width() const
00382 {
00383 return _width;
00384 }
00385
00390 inline int height() const
00391 {
00392 return _height;
00393 }
00394
00400 inline void setWidth(int width)
00401 {
00402 assert(width > 0);
00403 if(Safe){
00404 if(width <= 0) throw ImageException("setWidth: Nonpositive width");
00405 }
00406 _width=width;
00407 }
00408
00414 inline void setHeight(int height)
00415 {
00416 assert(height > 0);
00417 if(Safe){
00418 if(height <= 0) throw ImageException("setHeight: Nonpositive height");
00419 }
00420 _height=height;
00421 }
00422
00428 inline ScalarType* dataValues() const
00429 {
00430 return _data;
00431 }
00432
00437 inline int dataValuesSize() const
00438 {
00439 return _width * _height * Channels;
00440 }
00441
00442
00448 inline void setValues(ScalarType* data)
00449 {
00450 assert(data!=NULL);
00451 if(Safe){
00452 if(data == NULL) throw ImageException("setValues: NULL data");
00453 }
00454 _data = data;
00455 }
00456
00463 inline bool isInside(int x, int y) const
00464 {
00465 return x >= 0 && x < _width && y >= 0 && y < _height;
00466 }
00467
00474 inline bool isInside(float x, float y) const
00475 {
00476 return x >= 0.0f && x <= _width-1.0f && y >= 0.0f && y <= _height-1.0f;
00477 }
00478
00483 inline bool isValid() const
00484 {
00485 return _data != NULL && _width > 0 && _height > 0;
00486 }
00487
00492 inline int channels() const
00493 {
00494 return Channels;
00495 }
00496
00503 inline void setRawValue(int i, ScalarType value)
00504 {
00505 _data[i] = value;
00506 }
00507
00508 };
00509
00510 }
00511
00512 #endif