00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #ifndef __OPENKN_IMAGE__IMAGE_HPP__
00027 #define __OPENKN_IMAGE__IMAGE_HPP__
00028
00029 #if defined(_MSC_VER) && (_MSC_VER >= 1020)
00030 #pragma warning(disable:4996)
00031 #endif
00032
00033
00034
00035
00036 #include <iostream>
00037 #include <sstream>
00038 #include <string>
00039 #include <cstring>
00040 #include <algorithm>
00041
00042
00043
00044
00045 #include "ImageException.hpp"
00046
00047
00048
00049
00050 namespace kn{
00051
00052
00053
00054
00055
00062 template<typename T>
00063 class Image {
00064
00065
00066
00067
00068 public:
00071 Image();
00072
00079 Image(const size_t width, const size_t height, const size_t nbChannel, T* buffer=0);
00080
00084 Image(const Image<T> & i);
00085
00088 virtual ~Image();
00089
00095 friend int kn::loadPPM(Image<unsigned char>& res,const std::string& filename);
00101 friend int kn::loadTGA(Image<unsigned char>& res,const std::string& filename);
00107 friend int kn::loadJPG(Image<unsigned char>& res,const std::string& filename);
00113 friend int kn::loadHDR(Image<float>& res,const std::string& filename);
00114
00115 protected :
00118 T * data;
00119
00122 T ** rows;
00123
00126 void initRows();
00127
00130 T * begin_;
00131
00134 T * end_;
00135
00136 public :
00140 inline virtual T * begin() const {return begin_;}
00141
00145 inline virtual T * end() const {return end_;}
00146
00147 protected :
00150 size_t imageWidth;
00151
00154 size_t imageHeight;
00155
00158 size_t imageNbChannel;
00159
00162 size_t imageSize;
00163 public:
00167 inline virtual size_t width() const {return imageWidth; }
00168
00172 inline virtual size_t height() const {return imageHeight; }
00173
00177 inline virtual size_t nbChannel() const {return imageNbChannel; }
00178
00182 inline virtual size_t size() const {return imageSize; }
00183
00189 inline virtual T * operator()(const unsigned int x, const unsigned int y) const {
00190 return (rows[y]+x*nbChannel());
00191 }
00192
00199 inline virtual T * at(const unsigned int x, const unsigned int y) const {
00200 if (x>=width() || y>=height() ) {
00201 std::ostringstream o("Operator("); o << x << "," << y << ") " ;
00202 throw ImageException(o.str(), "Invalid range");
00203 }
00204 return (*this)(x,y);
00205 }
00206
00213 inline virtual T & operator()(const unsigned int x, const unsigned int y, const unsigned int d) {
00214 return (*this)(x,y)[d];
00215 }
00216
00223 inline virtual T & at(const unsigned int x, const unsigned int y, const unsigned int d) {
00224 if (d>=imageNbChannel || x>=width() || y>=height()) {
00225 std::ostringstream o("Operator("); o << x << "," << y << "," <<d <<") " ;
00226 throw ImageException(o.str(), "Invalid range");
00227 }
00228 return ((*this)(x,y)[d]);
00229 }
00230
00237 inline virtual const T & operator()(const unsigned int x, const unsigned int y, const unsigned int d)const {
00238 return (*this)(x,y)[d];
00239 }
00240
00249 inline virtual const T & at(const unsigned int x, const unsigned int y, const unsigned int d)const {
00250 if (d>=imageNbChannel || x>=width() || y>=height()) {
00251 std::ostringstream o("Operator("); o << x << "," << y << "," <<d <<") " ;
00252 throw ImageException(o.str(), "Invalid range");
00253 }
00254 return (*this)(x,y)[d];
00255 }
00256
00257
00263 virtual Image<T> & operator=(const Image &i) ;
00264
00265
00269 inline void fill(const T &value) {
00270 std::fill(begin_,end_,value);
00271 }
00272
00273
00276 inline void flip() {
00277 for(unsigned int i=0; i<imageHeight/2; i++)
00278 std::swap_ranges(rows[i],rows[i+1],rows[imageHeight-i-1]);
00279 }
00280
00283 inline void flop() {
00284 for(unsigned int i=0; i<imageHeight; i++)
00285 for(unsigned int j=0; j<imageWidth/2; j++)
00286 for(unsigned int c=0; c<imageNbChannel;c++)
00287 std::swap(rows[i][imageNbChannel*j+c],rows[i][imageNbChannel*(imageWidth-j-1)+c]);
00288 }
00289
00292 inline void rotate() {
00293 T* buffer = new T[size()*sizeof(T)];
00294 T* b = buffer;
00295 for(int j=imageWidth-1, d=(imageWidth-1)*imageNbChannel; j>=0; j--,d-=imageNbChannel)
00296 for(unsigned int i=0; i<imageHeight; i++)
00297 for(unsigned int c=0; c<imageNbChannel;c++,b++)
00298 *b = rows[i][d+c];
00299 imageSize = 0;
00300 buildImageFromBuffer(imageHeight, imageWidth, imageNbChannel, buffer, false);
00301 }
00302
00305 inline void rotateInverse() {
00306 T* buffer = new T[size()*sizeof(T)];
00307 T* b = buffer;
00308 for(unsigned int j=0, d=0; j<imageWidth; j++,d+=imageNbChannel)
00309 for(int i=imageHeight-1; i>=0; i--)
00310 for(unsigned int c=0; c<imageNbChannel;c++,b++)
00311 *b = rows[i][d+c];
00312 imageSize = 0;
00313 buildImageFromBuffer(imageHeight, imageWidth, imageNbChannel, buffer, false);
00314 }
00315
00316
00323 void getSubImage(unsigned int x, unsigned int y, Image<T>& sub)const;
00324
00331 void setSubImage(unsigned int x, unsigned int y, const Image<T>& sub);
00332
00333
00334
00335
00336
00337 private:
00345 void buildImageFromBuffer(const size_t width, const size_t height, const size_t nbChannel, T* buffer, const bool copy=true);
00346
00351 void buildImageFromImage(const Image<T> & i, const bool copy=true);
00352
00353 private:
00359 void buildEmptyImage(const size_t width, const size_t height, const size_t nbChannel);
00360
00363 void erase();
00364
00365 };
00366
00367
00368
00369
00370
00371
00372
00373
00374 template<typename T>
00375 Image<T>::Image() {
00376 imageWidth = 0;
00377 imageHeight = 0;
00378 imageNbChannel = 0;
00379 imageSize = 0;
00380
00381 rows = 0;
00382 data = 0;
00383 begin_ = 0;
00384 end_ = 0;
00385
00386 }
00387
00388 template<typename T>
00389 Image<T>::Image(const size_t w, const size_t h, const size_t d, T* buffer) {
00390 imageSize = 0;
00391 imageWidth = 0;
00392 imageHeight = 0;
00393 imageNbChannel = 0;
00394 imageSize = 0;
00395
00396 rows=0;
00397 data=0;
00398 begin_ = 0;
00399 end_ = 0;
00400
00401 if (buffer) {
00402 buildImageFromBuffer(w,h,d,buffer);
00403 }
00404 else {
00405 buildEmptyImage(w,h,d);
00406 }
00407 }
00408
00409 template<typename T>
00410 Image<T>::Image(const Image<T> & i) {
00411 imageSize = 0;
00412 imageSize = 0;
00413 imageWidth = 0;
00414 imageHeight = 0;
00415 imageNbChannel = 0;
00416 imageSize = 0;
00417
00418 rows=0;
00419 data=0;
00420 begin_ = 0;
00421 end_ = 0;
00422
00423 buildImageFromImage(i,true);
00424 }
00425
00426 template<typename T>
00427 Image<T>::~Image() {
00428 erase();
00429 }
00430
00431 template<typename T>
00432 void Image<T>::initRows() {
00433 unsigned int i;
00434 if(rows) {
00435 delete[] rows;
00436 rows = 0;
00437 }
00438 rows = new T*[imageHeight];
00439 for (i =0; i <imageHeight; i++) {
00440 rows[i] = (data+(i*imageWidth*imageNbChannel));
00441 }
00442 }
00443
00444 template<typename T>
00445 void Image<T>::buildImageFromBuffer(const size_t width, const size_t height,
00446 const size_t nbChannel, T* buffer, const bool copy) {
00447 if (size()) {
00448 throw ImageException("buildImageFromImage","Image already allocated");
00449 }
00450 imageWidth = width;
00451 imageHeight = height;
00452 if (imageNbChannel == 0) imageNbChannel = nbChannel;
00453 imageSize = imageWidth*imageHeight*imageNbChannel;
00454 if (copy) {
00455 if(data){
00456 delete[] data;
00457 data = 0;
00458 }
00459 data = new T[size()*sizeof(T)];
00460 std::copy(buffer,buffer+size(),data);
00461 }
00462 else {
00463 if(data){
00464 delete[] data;
00465 }
00466 data = buffer;
00467 }
00468 initRows();
00469
00470 begin_ = data;
00471 end_ = data+imageSize;
00472 }
00473
00474 template<typename T>
00475 void Image<T>::buildImageFromImage(const Image<T> & i, const bool copy) {
00476 buildImageFromBuffer(i.imageWidth,i.imageHeight,i.imageNbChannel,i.begin_,copy);
00477 }
00478
00479 template<typename T>
00480 void Image<T>::buildEmptyImage(const size_t width, const size_t height, const size_t nbChannel) {
00481 if(imageSize) {
00482 throw ImageException("buildEmptyImage","Image already allocated");
00483 }
00484 imageWidth = width;
00485 imageHeight = height;
00486 imageNbChannel = nbChannel;
00487 imageSize = width * height * nbChannel;
00488 if(data){
00489 delete[] data;
00490 data = 0;
00491 }
00492 data = new T[imageSize * sizeof(T)];
00493 initRows();
00494
00495 begin_ = data;
00496 end_ = data+imageSize;
00497 }
00498
00499
00500 template<typename T>
00501 void Image<T>::erase() {
00502 imageWidth = 0;
00503 imageHeight = 0;
00504 imageNbChannel = 0;
00505 imageSize = 0;
00506 if(data) delete[] data;
00507 if(rows) delete[] rows;
00508 data = 0;
00509 rows = 0;
00510 begin_ = 0;
00511 end_ = 0;
00512 }
00513
00514
00515 template<typename T>
00516 Image<T> & Image<T>::operator=(const Image &i) {
00517
00518 if(&i == this) return *this;
00519
00520
00521 if(this->imageWidth == 0 && this->imageHeight ==0){
00522 buildImageFromImage(i);
00523 return *this;
00524 }
00525
00526
00527 if(this->imageWidth == i.imageWidth &&
00528 this->imageHeight == i.imageHeight &&
00529 this->imageNbChannel == i.imageNbChannel)
00530 std::copy(i.begin_,i.end_,this->begin_);
00531 else throw ImageException("operator=","incompatible image size");
00532
00533 return *this;
00534 }
00535
00536 template<typename T>
00537 void Image<T>::getSubImage(unsigned int x, unsigned int y, Image<T>& sub)const{
00538 if(sub.imageNbChannel != imageNbChannel)
00539 throw ImageException("incompatible nb channel","Image<T>::getSubImage");
00540 if(sub.imageWidth+x > imageWidth || sub.imageHeight+y > imageHeight)
00541 throw ImageException("incompatible dimensions","Image<T>::getSubImage");
00542 unsigned int dx = x*imageNbChannel;
00543 unsigned int s = sub.imageWidth*imageNbChannel;
00544 for(unsigned int j = 0; j < sub.imageNbChannel; j++)
00545 std::copy(rows[j+y]+dx,rows[j+y]+dx+s, sub.rows[j]);
00546 }
00547
00548
00549 template<typename T>
00550 void Image<T>::setSubImage(unsigned int x, unsigned int y, const Image<T>& sub){
00551 if(sub.imageNbChannel != imageNbChannel)
00552 throw ImageException("incompatible nb channel","Image<T>::setSubImage");
00553 if(sub.imageWidth+x > imageWidth || sub.imageHeight+y > imageHeight)
00554 throw ImageException("incompatible dimensions","Image<T>::setSubImage");
00555 unsigned int dx = x*imageNbChannel;
00556 unsigned int s = sub.imageWidth*imageNbChannel;
00557 for(unsigned int j = 0; j < sub.imageNbChannel; j++)
00558 std::copy(sub.rows[j],sub.rows[j]+s,rows[j+y]+dx);
00559 }
00560
00561
00562
00563
00564 }
00565
00566
00567
00568
00569 #endif