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__IMAGE3D_HPP__
00027 #define __OPENKN_IMAGE__IMAGE3D_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 #include "Image.hpp"
00047
00048
00049
00050 namespace kn{
00051
00052
00053
00054
00055
00062 template<typename T>
00063 class Image3D {
00064
00065
00066
00067
00068 public:
00071 Image3D();
00072
00080 Image3D(const size_t width, const size_t height, const size_t depth, const size_t nbChannel, T* buffer=0);
00081
00085 Image3D(const Image3D<T> & i);
00086
00089 virtual ~Image3D();
00090
00091
00092 protected :
00095 T * data;
00096
00097
00100 T ** frames;
00101
00104 T *** rows;
00105
00106
00109 void initRowsAndFrames();
00110
00113 T * begin_;
00114
00117 T * end_;
00118
00119 public :
00123 inline virtual T * begin() const {return begin_;}
00124
00128 inline virtual T * end() const {return end_;}
00129
00130 protected :
00133 size_t imageWidth;
00134
00137 size_t imageHeight;
00138
00141 size_t imageDepth;
00142
00145 size_t imageNbChannel;
00146
00149 size_t imageSize;
00150 public:
00154 inline virtual size_t width() const {return imageWidth; }
00155
00159 inline virtual size_t height() const {return imageHeight; }
00160
00164 inline virtual size_t depth() const {return imageDepth; }
00165
00169 inline virtual size_t nbChannel() const {return imageNbChannel; }
00170
00174 inline virtual size_t size() const {return imageSize; }
00175
00181 inline virtual T * operator()(const unsigned int x, const unsigned int y, const unsigned int z) const {
00182 return (rows[y][z]+x*imageNbChannel);
00183 }
00184
00191 inline virtual T * at(const unsigned int x, const unsigned int y, const unsigned int z) const {
00192 if (x>=imageWidth || y>=imageHeight || z>=imageDepth ) {
00193 std::ostringstream o("Operator("); o << x << "," << y << "," << z << ") " ;
00194 throw ImageException(o.str(), "Invalid range");
00195 }
00196 return (*this)(x,y,z);
00197 }
00198
00206 inline virtual T & operator()(const unsigned int x, const unsigned int y, const unsigned int z, const unsigned int channel) {
00207 return (*this)(x,y,z)[channel];
00208 }
00209
00217 inline virtual T & at(const unsigned int x, const unsigned int y, const unsigned int z, const unsigned int channel) {
00218 if (channel>=imageNbChannel) {
00219 std::ostringstream o("Operator("); o << x << "," << y << "," << z << "," << channel <<") " ;
00220 throw ImageException(o.str(), "Invalid range");
00221 }
00222 return (at(x,y,z)[channel]);
00223 }
00224
00232 inline virtual const T & operator()(const unsigned int x, const unsigned int y, const unsigned int z, const unsigned int channel)const {
00233 return (*this)(x,y,z)[channel];
00234 }
00235
00245 inline virtual const T & at(const unsigned int x, const unsigned int y, const unsigned int z, const unsigned int channel)const {
00246 if (channel>=imageNbChannel) {std::ostringstream o("Operator("); o << x << "," << y << "," << z << "," <<channel<< ") " ; throw ImageException(o.str(), "Invalid range"); }
00247 return (*this)(x,y,z)[channel];
00248 }
00249
00250
00256 virtual Image3D<T> & operator=(const Image3D &i) ;
00257
00258
00262 inline void fill(const T &value) {
00263 std::fill(begin_,end_,value);
00264 }
00265
00272 inline void setFrame(unsigned int index, Image<T>& frame){
00273 if(frame.width() != imageWidth || frame.height() != imageHeight || frame.nbChannel() != imageNbChannel)
00274 throw ImageException("invalid frame dimensions", "Image3D::setFrame");
00275 if(index >= imageDepth)
00276 throw ImageException("index out of bound", "Image3D::setFrame");
00277 std::copy(frame.begin(), frame.end(), frames[index]);
00278 }
00279
00286 inline void getFrame(unsigned int index, Image<T>& frame){
00287 if(frame.width() != imageWidth || frame.height() != imageHeight || frame.nbChannel() != imageNbChannel)
00288 throw ImageException("Invalid frame dimensions", "Image3D::setFrame");
00289 if(index >= imageDepth)
00290 throw ImageException("index out of bound", "Image3D::setFrame");
00291 std::copy(frames[index], frames[index]+frame.size(), frame.begin());
00292 }
00293
00294
00295
00296
00297 private:
00306 void buildImageFromBuffer(const size_t width, const size_t height, const size_t depth, const size_t nbChannel, T* buffer, const bool copy=true);
00307
00312 void buildImageFromImage(const Image3D<T> & i, const bool copy=true);
00313
00314 private:
00321 void buildEmptyImage(const size_t width, const size_t height, const size_t depth, const size_t nbChannel);
00322
00325 void erase();
00326
00327 };
00328
00329
00330
00331
00332
00333
00334
00335
00336 template<typename T>
00337 Image3D<T>::Image3D() {
00338 imageWidth = 0;
00339 imageHeight = 0;
00340 imageDepth = 0;
00341 imageNbChannel = 0;
00342 imageSize = 0;
00343 frames = 0;
00344 rows = 0;
00345 data = 0;
00346 begin_ = 0;
00347 end_ = 0;
00348
00349 }
00350
00351 template<typename T>
00352 Image3D<T>::Image3D(const size_t width, const size_t height, const size_t depth, const size_t nbChannel, T* buffer) {
00353 imageSize = 0;
00354 imageWidth = 0;
00355 imageHeight = 0;
00356 imageDepth = 0;
00357 imageNbChannel = 0;
00358 imageSize = 0;
00359
00360 rows=0;
00361 frames = 0;
00362 data=0;
00363 begin_ = 0;
00364 end_ = 0;
00365
00366 if (buffer) {
00367 buildImageFromBuffer(width,height,depth,nbChannel,buffer);
00368 }
00369 else {
00370 buildEmptyImage(width,height,depth,nbChannel);
00371 }
00372 }
00373
00374 template<typename T>
00375 Image3D<T>::Image3D(const Image3D<T> & i) {
00376 imageSize = 0;
00377 imageSize = 0;
00378 imageWidth = 0;
00379 imageHeight = 0;
00380 imageDepth = 0;
00381 imageNbChannel = 0;
00382 imageSize = 0;
00383
00384 rows=0;
00385 frames=0;
00386 data=0;
00387 begin_ = 0;
00388 end_ = 0;
00389
00390 buildImageFromImage(i,true);
00391 }
00392
00393 template<typename T>
00394 Image3D<T>::~Image3D() {
00395 erase();
00396 }
00397
00398 template<typename T>
00399 void Image3D<T>::initRowsAndFrames() {
00400 unsigned int i,j;
00401 if(rows) {
00402 delete[] rows;
00403 rows = 0;
00404 }
00405 if(frames) {
00406 delete[] frames;
00407 frames = 0;
00408 }
00409
00410 frames = new T*[imageDepth*imageHeight];
00411 rows = new T**[imageHeight];
00412
00413 unsigned int frameDec = imageHeight*imageWidth*imageNbChannel;
00414 unsigned int rowDec = imageWidth*imageNbChannel;
00415
00416 for (i =0; i <imageHeight; i++) {
00417 rows[i] = frames+i*imageDepth;
00418 for (j =0; j <imageDepth; j++) {
00419 frames[i*imageDepth+j] = data+j*frameDec+i*rowDec;
00420 }
00421 }
00422 }
00423
00424 template<typename T>
00425 void Image3D<T>::buildImageFromBuffer(const size_t width, const size_t height, const size_t depth, const size_t nbChannel, T* buffer, const bool copy) {
00426 if (size()) {
00427 throw ImageException("buildImageFromImage","Image already allocated");
00428 }
00429 imageWidth = width;
00430 imageHeight = height;
00431 imageDepth = depth;
00432 imageNbChannel = nbChannel;
00433 imageSize = imageWidth*imageHeight*imageDepth*imageNbChannel;
00434 if (copy) {
00435 if(data){
00436 delete[] data;
00437 data = 0;
00438 }
00439 data = new T[size()*sizeof(T)];
00440 std::copy(buffer,buffer+size(),data);
00441 }
00442 else {
00443 if(data){
00444 delete[] data;
00445 }
00446 data = buffer;
00447 }
00448 initRowsAndFrames();
00449
00450 begin_ = data;
00451 end_ = data+imageSize;
00452 }
00453
00454 template<typename T>
00455 void Image3D<T>::buildImageFromImage(const Image3D<T> & i, const bool copy) {
00456 buildImageFromBuffer(i.imageWidth,i.imageHeight,i.imageDepth,i.imageNbChannel,i.begin_,copy);
00457 }
00458
00459 template<typename T>
00460 void Image3D<T>::buildEmptyImage(const size_t width, const size_t height, const size_t depth, const size_t nbChannel) {
00461 if(imageSize) {
00462 throw ImageException("buildEmptyImage","Image already allocated");
00463 }
00464 imageWidth = width;
00465 imageHeight = height;
00466 imageDepth = depth;
00467 imageNbChannel = nbChannel;
00468 imageSize = width * height * depth * nbChannel;
00469 if(data){
00470 delete[] data;
00471 data = 0;
00472 }
00473 data = new T[imageSize * sizeof(T)];
00474 initRowsAndFrames();
00475
00476 begin_ = data;
00477 end_ = data+imageSize;
00478 }
00479
00480
00481 template<typename T>
00482 void Image3D<T>::erase() {
00483 imageWidth = 0;
00484 imageHeight = 0;
00485 imageDepth = 0;
00486 imageNbChannel = 0;
00487 imageSize = 0;
00488 if(data) delete[] data;
00489 if(rows) delete[] rows;
00490 if(frames) delete[] frames;
00491 data = 0;
00492 rows = 0;
00493 frames = 0;
00494 begin_ = 0;
00495 end_ = 0;
00496 }
00497
00498
00499 template<typename T>
00500 Image3D<T> & Image3D<T>::operator=(const Image3D &i) {
00501
00502 if(&i == this) return *this;
00503
00504
00505 if(this->imageWidth == 0 && this->imageHeight ==0 && this->imageDepth ==0){
00506 buildImageFromImage(i);
00507 return *this;
00508 }
00509
00510
00511 if(this->imageWidth == i.imageWidth &&
00512 this->imageHeight == i.imageHeight &&
00513 this->imageDepth == i.imageDepth &&
00514 this->imageNbChannel == i.imageNbChannel)
00515 std::copy(i.begin_,i.end_,this->begin_);
00516 else throw ImageException("operator=","incompatible image size");
00517
00518 return *this;
00519 }
00520
00521
00522
00523
00524
00525
00526 }
00527
00528
00529
00530
00531 #endif