Grid3
Grid3_i.h
1 #ifndef GRID3_I_H
2 #define GRID3_I_H
3 
4 #include "Endian.h"
5 #include "FileName.h"
6 #include <typeinfo>
7 #include <sstream>
8 #include <fstream>
9 using namespace std;
10 
11 // Configure gdcm support
12 // Define 'grid3_use_gdcm' to enable gdcm support.
13 
14 #ifdef grid3_use_gdcm
15 #include "gdcmImageReader.h"
16 #endif
17 
18 inline string ToLower(string s){
19  string result=s;
20  for(int i=0; i<s.size(); i++){
21  result[i]=tolower(s[i]);
22  }
23  return result;
24 
25 }
26 
27 template <class T>
28 inline Grid3<T>::Grid3(int width, int height, int depth, double x_spacing, double y_spacing, double z_spacing){
29  _width=width;
30  _height=height;
31  _depth=depth;
32  _spacingX=x_spacing;
33  _spacingY=y_spacing;
34  _spacingZ=z_spacing;
35  data=std::vector<T>(NumberOfElements());
36 }
37 
38 template <class T>
39 inline Grid3<T>::Grid3(Vec3i dimensions, Vec3d spacing){
40  _width=dimensions.x;
41  _height=dimensions.y;
42  _depth=dimensions.z;
43  _spacingX=spacing.x;
44  _spacingY=spacing.y;
45  _spacingZ=spacing.z;
46  data=std::vector<T>(NumberOfElements());
47 }
48 
49 template <class T>
50 inline void Grid3<T>::Init(int width, int height, int depth, double x_spacing, double y_spacing, double z_spacing) {
51  _width=width;
52  _height=height;
53  _depth=depth;
54  _spacingX=x_spacing;
55  _spacingY=y_spacing;
56  _spacingZ=z_spacing;
57  data=std::vector<T>(NumberOfElements());
58 }
59 
60 
61 template <class T>
62 inline void Grid3<T>::SetSpacing(double x_spacing, double y_spacing, double z_spacing){
63  _spacingX=x_spacing;
64  _spacingY=y_spacing;
65  _spacingZ=z_spacing;
66 }
67 
68 template <class T>
69 inline void Grid3<T>::SetSpacing(Vec3d spacing){
70  _spacingX=spacing.x;
71  _spacingY=spacing.y;
72  _spacingZ=spacing.z;
73 }
74 
75 template <class T>
77  Vec3d result;
78  result.x = p.x / GetSpacingX();
79  result.y = p.y / GetSpacingY();
80  result.z = p.z / GetSpacingZ();
81  return result;
82 }
83 
85 template <class T>
87  Vec3d result;
88  result.x = p.x * GetSpacingX();
89  result.y = p.y * GetSpacingY();
90  result.z = p.z * GetSpacingZ();
91  return result;
92 }
93 
94 template <class T>
96  return _width*_height*_depth;
97 }
98 
99 template <class T>
100 inline T* Grid3<T>::Data(){
101  return &data[0];
102 }
103 
104 template <>
105 inline std::string Grid3<uint8_t>::GetDataType(){
106  return "UINT8";
107 }
108 
109 template <>
110 inline std::string Grid3<int8_t>::GetDataType(){
111  return "INT8";
112 }
113 
114 template <>
115 inline std::string Grid3<uint16_t>::GetDataType(){
116  return "UINT16";
117 }
118 
119 template <>
120 inline std::string Grid3<int16_t>::GetDataType(){
121  return "INT16";
122 }
123 
124 template <>
125 inline std::string Grid3<uint32_t>::GetDataType(){
126  return "UINT32";
127 }
128 
129 template <>
130 inline std::string Grid3<int32_t>::GetDataType(){
131  return "INT32";
132 }
133 
134 template <class T>
135 inline std::string Grid3<T>::GetDataType(){
136  return std::string( typeid(T).name() );
137 }
138 
139 
140 template <class T>
141 inline int Grid3<T>::Offset(int x, int y, int z){
142  return x+ y*_width + z*_width*_height;
143 }
144 
145 template <class T>
146 inline Vec3i Grid3<T>::Coordinate(long index){
147  Vec3i c;
148  c.z = index/(_width*_height);
149  index = index%(_width*_height);
150  c.y = index/_width;
151  c.x = index%_width;
152  return c;
153 }
154 
155 template <class T>
156 inline bool Grid3<T>::IsInside(int x, int y, int z){
157  return (x>=0 && x<_width && y>=0 && y<_height && z>=0 && z<_depth);
158 }
159 
160 template <class T>
161 inline bool Grid3<T>::IsInside(Vec3i p){
162  return IsInside(p.x,p.y,p.z);
163 }
164 
165 template <class T>
166 inline T& Grid3<T>::operator[](long index){
167  return data[index];
168 }
169 
170 template <class T>
171 inline T& Grid3<T>::operator()(int x,int y, int z, bool Safe){
172  if(Safe){
173  x=max(x,0);
174  x=min(x,_width-1);
175  y=max(y,0);
176  y=min(y,_height-1);
177  z=max(z,0);
178  z=min(z,_depth-1);
179  }
180  return data[Offset(x,y,z)];
181 }
182 
183 template <class T>
184 inline T& Grid3<T>::operator()(Vec3i p, bool Safe){
185  if(Safe){
186  p.x=max(p.x,0);
187  p.x=min(p.x,_width-1);
188  p.y=max(p.y,0);
189  p.y=min(p.y,_height-1);
190  p.z=max(p.z,0);
191  p.z=min(p.z,_depth-1);
192  }
193  return data[Offset(p.x,p.y,p.z)];
194 }
195 
196 template <class T>
197 inline T Grid3<T>::LinearAt(double x, double y, double z){
198  double xt=x-floor(x);
199  double yt=y-floor(y);
200  double zt=z-floor(z);
201 
202  int x1=int(floor(x));
203  int x2=int(ceil(x));
204  int y1=int(floor(y));
205  int y2=int(ceil(y));
206  int z1=int(floor(z));
207  int z2=int(ceil(z));
208 
209  return (1-zt)*((1-yt)*((1-xt)*operator()(x1,y1,z1,true)+
210  (xt)*operator()(x2,y1,z1,true))+
211  (yt)*((1-xt)*operator()(x1,y2,z1,true)+
212  (xt)*operator()(x2,y2,z1,true)))+
213  (zt)*((1-yt)*((1-xt)*operator()(x1,y1,z2,true)+
214  (xt)*operator()(x2,y1,z2,true))+
215  (yt)*((1-xt)*operator()(x1,y2,z2,true)+
216  (xt)*operator()(x2,y2,z2,true)));
217 }
218 
219 template <class T>
221  return LinearAt(p.x,p.y,p.z);
222 }
223 
224 template <class T>
225 inline void Grid3<T>::Get6Neighbors(long index, vector<long>& n){
226  n.clear();
227 
228  Vec3i coord=Coordinate(index);
229  if(coord.x+1<_width){
230  n.push_back(Offset(coord.x+1, coord.y, coord.z));
231  }
232 
233  if(coord.x-1>=0){
234  n.push_back(Offset(coord.x-1, coord.y, coord.z));
235  }
236 
237  if(coord.y+1<_height){
238  n.push_back(Offset(coord.x, coord.y+1, coord.z));
239  }
240 
241  if(coord.y- 1>=0){
242  n.push_back(Offset(coord.x, coord.y-1, coord.z));
243  }
244 
245  if(coord.z+1<_depth){
246  n.push_back(Offset(coord.x, coord.y, coord.z+1));
247  }
248 
249  if(coord.z- 1>=0){
250  n.push_back(Offset(coord.x, coord.y, coord.z-1));
251  }
252 
253 }
254 
255 template <class T>
256 inline void Grid3<T>::Get6Neighbors(Vec3i p, vector<Vec3i>& n){
257  n.clear();
258 
259  if(p.x+1<_width){
260  n.push_back(Vec3i(p.x+1, p.y, p.z));
261  }
262 
263  if(p.x-1>=0){
264  n.push_back(Vec3i(p.x-1, p.y, p.z));
265  }
266 
267  if(p.y+1<_height){
268  n.push_back(Vec3i(p.x, p.y+1, p.z));
269  }
270 
271  if(p.y-1>=0){
272  n.push_back(Vec3i(p.x, p.y-1, p.z));
273  }
274 
275  if(p.z+1<_depth){
276  n.push_back(Vec3i(p.x, p.y, p.z+1));
277  }
278 
279  if(p.z-1>=0){
280  n.push_back(Vec3i(p.x, p.y, p.z-1));
281  }
282 }
283 
284 template <class T>
285 inline void Grid3<T>::Fill(T value){
286  std::fill(data.begin(),data.end(),value);
287 }
288 
289 template <class T>
291  return *std::max_element(data.begin(), data.end());
292 }
293 
294 template <class T>
296  return *std::min_element(data.begin(), data.end());
297 }
298 
299 
300 /*template <class T>
301 inline Grid3<T> Grid3<T>::operator*(double x){
302  Grid3<T> result(this->GetDimensions(), this->GetSpacing());
303 
304  #pragma omp parallel for
305  for (long i = 0; i < data.size(); i++){
306  result.data[i] = x*data[i];
307  }
308  return result;
309 }
310 
311 template <class T>
312 inline Grid3<T> Grid3<T>::operator/ (double x){
313  Grid3<T> result(this->GetDimensions(), this->GetSpacing());
314  double x_inv = 1 / x;
315  #pragma omp parallel for
316  for (long i = 0; i < data.size(); i++){
317  result.data[i] = x_inv*data[i];
318  }
319  return result;
320 }
321 
322 template <class T>
323 inline Grid3<T> Grid3<T>::operator+(T x){
324  Grid3<T> result(this->GetDimensions(), this->GetSpacing());
325 #pragma omp parallel for
326  for (long i = 0; i < data.size(); i++){
327  result.data[i] += x;
328  }
329  return result;
330 }
331 
332 template <class T>
333 inline Grid3<T> Grid3<T>::operator-(T x){
334  Grid3<T> result(this->GetDimensions(), this->GetSpacing());
335 #pragma omp parallel for
336  for (long i = 0; i < data.size(); i++){
337  result.data[i] -= x;
338  }
339  return result;
340 }*/
341 
342 template <class T>
344  if(src.NumberOfElements() == this->NumberOfElements()){
345  std::copy(src.data.begin(), src.data.end(), data.begin());
346  }
347 }
348 
349 template <class T>
351  if(this->NumberOfElements() == v.NumberOfElements()){
352  std::swap_ranges(v.data.begin(), v.data.end(), data.begin());
353  }
354 }
355 
356 template <class T>
357 inline bool Grid3<T>::CreateFromFile(std::string filename){
358  if(filename.find(".vtk")!=std::string::npos){
359  return ReadVTK(filename);
360  }
361  else if(filename.find(".mhd")!=string::npos){
362  return ReadMetaImage(filename);
363  }
364  else if(filename.find(".mha")!=string::npos){
365  return ReadMetaImage(filename);
366  }
367  else if(filename.find(".nii")!=string::npos){
368  return ReadNIFTI(filename);
369  }
370  else if(filename.find(".dcm")!=string::npos){
371  return ReadDICOM(filename);
372  }
373  return false;
374 }
375 
376 template <class T>
377 inline bool Grid3<T>::ReadVTK(std::string filename){
378 
379  // # vtk DataFile Version x.x
380  // Some information about the file
381  // BINARY
382  // DATASET STRUCTURED_POINTS
383  // DIMENSIONS 128 128 128
384  // ORIGIN 0.0 0.0 0.0
385  // SPACING 1.0 1.0 1.0
386  // POINT_DATA 2097152
387  // SCALARS image_data unsigned_char
388  // LOOKUP_TABLE default
389  // raw data........
390 
391  //Note: Binary VTK legacy files are assumed to ALWAYS be encoded in big endian format.
392 
393  // open file, use binary mode (necessary on windows)
394  ifstream is;
395  is.open( filename.c_str(), ios::in | ios::binary );
396 
397  if( !is ) {
398  //cout<<"Stream invalid"<<endl;
399  return false;
400  }
401 
402  std::stringstream ss;
403  std::string line;
404 
405  // check if it is a VTK file
406  getline(is,line);
407  ss.str(line);
408 
409  std::string checkvtk;
410  ss >> checkvtk; // '#'
411  ss >> checkvtk; // vtk
412  if( !(ToLower(checkvtk) == "vtk" )){ return false; }
413 
414  bool done=false;
415  string keyword;
416 
417  bool read_dimensions=false;
418  bool read_lut=false;
419  bool read_type=false;
420  bool read_asciibinary=false;
421 
422  bool binary=true;
423  string dataset_type;
424  string typestring;
425  long W,H,D;
426  double spacing_x=1,spacing_y=1,spacing_z=1;
427  double origin_x=0,origin_y=0,origin_z=0;
428 
429  while(!done && getline(is,line)){
430  //ss=std::stringstream(line);
431  std::stringstream ss2(line);
432 
433  ss2>>keyword;
434  if(ToLower(keyword)=="dimensions"){
435 
436  ss2>>W;
437  ss2>>H;
438  ss2>>D;
439  read_dimensions=true;
440  }
441  else if(ToLower(keyword)=="binary"){
442  read_asciibinary=true;
443  }
444  else if(ToLower(keyword)=="ascii"){
445  binary=false;
446  read_asciibinary=true;
447  }
448  else if(ToLower(keyword)=="dataset"){
449  ss2>>dataset_type;
450  if(!(ToLower(dataset_type)=="structured_points")){
451  return false;
452  }
453  }
454  else if(ToLower(keyword)=="spacing" ||ToLower(keyword)=="aspect_ratio" ){
455  ss2>>spacing_x;
456  ss2>>spacing_y;
457  ss2>>spacing_z;
458  }
459  else if(ToLower(keyword)=="origin"){
460  ss2>>origin_x;
461  ss2>>origin_y;
462  ss2>>origin_z;
463  }
464  else if(ToLower(keyword)=="scalars"){
465  ss2>>typestring;
466  ss2>>typestring;
467  read_type=true;
468  }
469  else if(ToLower(keyword)=="lookup_table"){
470  read_lut=true;
471  }
472 
473  done=read_dimensions && read_lut && read_type && read_asciibinary;
474  }
475 
476  if(!done){
477  if(read_dimensions){
478  cout<<"dim"<<endl;
479  }
480  cout<<read_lut<<endl;
481  cout<<read_type<<endl;
482  cout<<read_asciibinary<<endl;
483  return false;
484  }
485 
486  long nelem=W*H*D;
487 
488  Init(W,H,D);
489  T* data=Data();
490 
491  if(typestring=="unsigned_char"){
492  uint8_t* tmpdata=new uint8_t[nelem];
493  is.read((char*)tmpdata, nelem*sizeof(uint8_t));
494  #pragma omp parallel for
495  for(long i=0; i<nelem; i++){ data[i]=T(tmpdata[i]); }
496  delete[] tmpdata;
497  metadata.SetString("ORIGINAL_TYPE", "UINT8");
498  }
499 
500  else if(typestring=="unsigned_short"){
501  uint16_t* tmpdata=new uint16_t[nelem];
502  ReadFromBigEndian((char*)tmpdata, nelem, sizeof(uint16_t), is);
503  #pragma omp parallel for
504  for(long i=0; i<nelem; i++){ data[i]=T(tmpdata[i]); }
505  delete[] tmpdata;
506  metadata.SetString("ORIGINAL_TYPE", "UINT16");
507  }
508 
509  else if(typestring=="unsigned_int"){
510  uint32_t* tmpdata=new uint32_t[nelem];
511  ReadFromBigEndian((char*)tmpdata, nelem, sizeof(uint32_t), is);
512  #pragma omp parallel for
513  for(long i=0; i<nelem; i++){ data[i]=T(tmpdata[i]); }
514  delete[] tmpdata;
515  metadata.SetString("ORIGINAL_TYPE", "UINT32");
516  }
517 
518  else if(typestring=="char"){
519  int8_t* tmpdata=new int8_t[nelem];
520  ReadFromBigEndian((char*)tmpdata, nelem, sizeof(int8_t), is);
521  #pragma omp parallel for
522  for(long i=0; i<nelem; i++){ data[i]=T(tmpdata[i]); }
523  delete[] tmpdata;
524  metadata.SetString("ORIGINAL_TYPE", "INT8");
525  }
526 
527  else if(typestring=="short"){
528  int16_t* tmpdata=new int16_t[nelem];
529  ReadFromBigEndian((char*)tmpdata, nelem, sizeof(int16_t), is);
530  #pragma omp parallel for
531  for(long i=0; i<nelem; i++){ data[i]=T(tmpdata[i]); }
532  delete[] tmpdata;
533  metadata.SetString("ORIGINAL_TYPE", "INT16");
534  }
535 
536  else if(typestring=="int"){
537  int32_t* tmpdata=new int32_t[nelem];
538  ReadFromBigEndian((char*)tmpdata, nelem, sizeof(int32_t), is);
539  #pragma omp parallel for
540  for(long i=0; i<nelem; i++){ data[i]=T(tmpdata[i]); }
541  delete[] tmpdata;
542  metadata.SetString("ORIGINAL_TYPE", "INT32");
543  }
544 
545  else if(typestring=="float"){
546  float* tmpdata=new float[nelem];
547  ReadFromBigEndian((char*)tmpdata, nelem, sizeof(float), is);
548  #pragma omp parallel for
549  for(long i=0; i<nelem; i++){ data[i]=T(tmpdata[i]); }
550  delete[] tmpdata;
551  metadata.SetString("ORIGINAL_TYPE", "FLOAT");
552  }
553 
554  else if(typestring=="double"){
555  double* tmpdata=new double[nelem];
556  ReadFromBigEndian((char*)tmpdata, nelem, sizeof(double), is);
557  #pragma omp parallel for
558  for(long i=0; i<nelem; i++){ data[i]=T(tmpdata[i]); }
559  delete[] tmpdata;
560  metadata.SetString("ORIGINAL_TYPE", "DOUBLE");
561  }
562 
563  _spacingX=spacing_x;
564  _spacingY=spacing_y;
565  _spacingZ=spacing_z;
566 
567  return true;
568 }
569 
570 template <class T>
571 inline bool Grid3<T>::WriteVTK(std::string filename){
572  // # vtk DataFile Version x.x
573  // Some information about the file
574  // BINARY
575  // DATASET STRUCTURED_POINTS
576  // DIMENSIONS 128 128 128
577  // ORIGIN 0.0 0.0 0.0
578  // SPACING 1.0 1.0 1.0
579  // POINT_DATA 2097152
580  // SCALARS image_data unsigned_char
581  // LOOKUP_TABLE default
582  // raw data........
583 
584  ofstream outfile;
585  outfile.open(filename,ofstream::out|ofstream::binary);
586  if(!outfile) { return false; }
587 
588  long nelem= _width*_height*_depth;
589 
590  outfile<<"# vtk DataFile Version 3.0"<<endl;
591  outfile<<"Created using the Grid3 library"<<endl;
592 
593  string Datamode="BINARY";
594  //if(mode=="ASCII"){Datamode="ASCII";}
595  outfile<<Datamode<<endl;
596 
597  outfile<<"DATASET STRUCTURED_POINTS"<<endl;
598 
599  outfile<<"DIMENSIONS "<<_width<<" "<<_height<<" "<<_depth<<endl;
600  outfile<<"ORIGIN 0.0 0.0 0.0"<<endl;
601  outfile<<"SPACING "<<_spacingX<<" "<<_spacingY<<" "<<_spacingZ<<endl;
602  outfile<<"POINT_DATA "<<nelem<<endl;
603 
604  string datatype=GetDataType();
605  string vtk_datatype="";
606 
607  if(datatype=="UINT8"){vtk_datatype="unsigned_char";}
608  else if(datatype=="INT8"){vtk_datatype="char";}
609  else if(datatype=="UINT16"){vtk_datatype="unsigned_short";}
610  else if(datatype=="INT16"){vtk_datatype="short";}
611  else if(datatype=="UINT32"){vtk_datatype="unsigned_int";}
612  else if(datatype=="INT32"){vtk_datatype="int";}
613  else if(datatype=="float"){vtk_datatype="float";}
614  else if(datatype=="double"){vtk_datatype="double";}
615 
616  outfile<<"SCALARS image_data "<<vtk_datatype<<endl;
617  outfile<<"LOOKUP_TABLE default"<<endl;
618 
619  //if(Datamode=="BINARY"){
620  //ReadFromBigEndian((char*)tmpdata, nelem, sizeof(uint16_t), is);
621 
622  T* data=Data();
623  WriteToBigEndian(reinterpret_cast<char*>(data), nelem, sizeof(T), outfile);
624 
625  outfile.close();
626 
627  return true;
628 }
629 
630 /*template <class T>
631 inline bool Grid3<T>::ReadAmira(std::string filename){
632  return false;
633 }*/
634 
635 /*template <class T>
636 inline bool Grid3<T>::WriteAmira(std::string filename){
637  return false;
638 }*/
639 
640 template <class T>
641 inline bool Grid3<T>::ReadMetaImage(std::string filename){
642 
643  //See http://www.itk.org/Wiki/ITK/MetaIO/Documentation for fileformat specification
644 
645  map<string,string> header_info;
646 
647  ifstream f;
648  f.open(filename);
649  if(!f){return false;}
650 
651  string line,key, value;
652 
653  //Read key/value pairs from header file and store in header_info
654  while(!f.eof()){
655  getline(f,line);
656  size_t pos=line.find("=");
657  if(pos!=string::npos){
658  line.erase(pos,1);
659  key=line.substr(0,pos);
660  value=line.substr(pos);
661 
662  //remove trailing and leading whitespaces
663  size_t first_non_space=key.find_first_not_of(" ");
664  size_t last_non_space=key.find_last_not_of(" ");
665  key=key.substr(first_non_space,last_non_space+1);
666 
667  //remove trailing and leading whitespaces
668  first_non_space=value.find_first_not_of(" ");
669  last_non_space=value.find_last_not_of(" ");
670  value=value.substr(first_non_space,last_non_space+1);
671 
672  header_info[key]=value;
673  }
674  }
675 
676  f.close();
677 
678  map<string,string>::iterator it;
679  stringstream ss;
680 
681  //Verify that the object is an image
682  it=header_info.find("ObjectType");
683  if(it==header_info.end() || it->second!="Image"){ return false;}
684 
685  //Read the NDims field
686  it=header_info.find("NDims");
687  if(it==header_info.end()){return false;}
688  int ndims;
689  ss=stringstream(it->second);
690  ss>>ndims;
691  if(!(ndims==2 || ndims==3)){return false;}
692 
693 
694  //Read the dimsize field
695  it=header_info.find("DimSize");
696  if(it==header_info.end()){return false;}
697  ss=stringstream(it->second);
698  int dimx, dimy, dimz;
699  dimx=1;
700  dimy=1;
701  dimz=1;
702  ss>>dimx>>dimy;;
703  if(ndims==3){ss>>dimz;}
704 
705 
706  //Read the ElementDataFile field
707  it=header_info.find("ElementDataFile");
708  if(it==header_info.end()){return false;}
709  string datafile=it->second;
710 
711  //Read the ElementType field
712  it=header_info.find("ElementType");
713  if(it==header_info.end()){return false;}
714  string typestring=it->second;
715 
716  //Read the binarydata field
717  bool BinaryData=true;
718  it=header_info.find("BinaryData");
719  if(it!=header_info.end()){
720  BinaryData=(it->second=="True");
721  }
722 
723  //Read the BinaryDataByteOrderMSB field
724  bool BinaryDataByteOrderMSB=IsBigEndian(); //default byte ordering is the same as the native ordering
725  it=header_info.find("BinaryDataByteOrderMSB");
726  if(it!=header_info.end()){
727  BinaryDataByteOrderMSB=(it->second=="True");
728  }
729 
730  //Read the HeaderSize field
731  int HeaderSize=-1;
732  it=header_info.find("HeaderSize");
733  if(it!=header_info.end()){
734  ss=stringstream(it->second);
735  ss>>HeaderSize;
736  }
737 
738  //Read the ElementSíze field
739  it=header_info.find("ElementSize");
740  double voxelsize_x=1, voxelsize_y=1, voxelsize_z=1;
741  if(it!=header_info.end()){
742  ss=stringstream(it->second);
743  ss>>voxelsize_x>>voxelsize_y;
744  if(ndims==3){ ss>>voxelsize_z;}
745  }
746 
747  //Read the ElementSpacing field
748  it=header_info.find("ElementSpacing");
749  _spacingX=voxelsize_x;
750  _spacingY=voxelsize_y;
751  _spacingZ=voxelsize_z;
752  if(it!=header_info.end()){
753  ss=stringstream(it->second);
754  ss>>_spacingX>>_spacingY;
755  if(ndims==3){ ss>>_spacingZ;}
756 
757  }
758 
759  long nelem=dimx*dimy*dimz;
760  Init(dimx,dimy,dimz,_spacingX,_spacingY,_spacingZ);
761 
762  T* data=Data();
763 
764 
765  /*typedef enum
766  {
767  MET_NONE,
768  MET_ASCII_CHAR,
769  MET_CHAR,
770  MET_UCHAR,
771  MET_SHORT,
772  MET_USHORT,
773  MET_INT,
774  MET_UINT,
775  MET_LONG,
776  MET_ULONG,
777  MET_LONG_LONG,
778  MET_ULONG_LONG,
779  MET_FLOAT,
780  MET_DOUBLE,
781  MET_STRING,
782  MET_CHAR_ARRAY,
783  MET_UCHAR_ARRAY,
784  MET_SHORT_ARRAY,
785  MET_USHORT_ARRAY,
786  MET_INT_ARRAY,
787  MET_UINT_ARRAY,
788  MET_LONG_ARRAY,
789  MET_ULONG_ARRAY,
790  MET_LONG_LONG_ARRAY,
791  MET_ULONG_LONG_ARRAY,
792  MET_FLOAT_ARRAY,
793  MET_DOUBLE_ARRAY,
794  MET_FLOAT_MATRIX,
795  MET_OTHER
796  } MET_ValueEnumType;*/
797 
798 
799  string Datafile_fullpath="";
800 
801  size_t found=filename.find_last_of("/\\");
802  if(found!=string::npos){
803  Datafile_fullpath.append(filename.substr(0,found+1));
804  }
805 
806  Datafile_fullpath.append(datafile);
807 
808 
809  //Determine file size automatically
810  f.open(Datafile_fullpath,ios::binary | ios::ate);
811  if(!f.good()){
812 
813  return false;
814  }
815  int fileSize=f.tellg();
816  f.close();
817 
818  f.open(Datafile_fullpath,ios::in|ios::binary);
819 
820  if(!f.good()){
821  cout << Datafile_fullpath << endl;
822  return false;
823  }
824 
825  if(typestring=="MET_UCHAR"){
826  uint8_t* tmpdata=new uint8_t[nelem];
827  if(BinaryDataByteOrderMSB){
828  ReadFromBigEndian((char*)tmpdata, nelem, sizeof(uint8_t), f);
829  }
830  else{
831  ReadFromLittleEndian((char*)tmpdata, nelem, sizeof(uint8_t), f);
832  }
833 
834  #pragma omp parallel for
835  for(long i=0; i<nelem; i++){ data[i]=T(tmpdata[i]); }
836  delete[] tmpdata;
837  metadata.SetString("ORIGINAL_TYPE", "UINT8");
838 
839 
840  }
841 
842  else if(typestring=="MET_CHAR"){
843  int8_t* tmpdata=new int8_t[nelem];
844  if(BinaryDataByteOrderMSB){
845  ReadFromBigEndian((char*)tmpdata, nelem, sizeof(int8_t), f);
846  }
847  else{
848  ReadFromLittleEndian((char*)tmpdata, nelem, sizeof(int8_t), f);
849  }
850 
851  #pragma omp parallel for
852  for(long i=0; i<nelem; i++){ data[i]=T(tmpdata[i]); }
853  delete[] tmpdata;
854  metadata.SetString("ORIGINAL_TYPE", "INT8");
855 
856  }
857 
858  else if(typestring=="MET_USHORT"){
859  uint16_t* tmpdata=new uint16_t[nelem];
860  if(BinaryDataByteOrderMSB){
861  ReadFromBigEndian((char*)tmpdata, nelem, sizeof(uint16_t), f);
862  }
863  else{
864  ReadFromLittleEndian((char*)tmpdata, nelem, sizeof(uint16_t), f);
865  }
866 
867  #pragma omp parallel for
868  for(long i=0; i<nelem; i++){ data[i]=T(tmpdata[i]); }
869  delete[] tmpdata;
870  metadata.SetString("ORIGINAL_TYPE", "UINT16");
871 
872  }
873 
874  else if(typestring=="MET_SHORT"){
875  int16_t* tmpdata=new int16_t[nelem];
876  if(BinaryDataByteOrderMSB){
877  ReadFromBigEndian((char*)tmpdata, nelem, sizeof(int16_t), f);
878  }
879  else{
880  ReadFromLittleEndian((char*)tmpdata, nelem, sizeof(int16_t), f);
881  }
882 
883  #pragma omp parallel for
884  for(long i=0; i<nelem; i++){ data[i]=T(tmpdata[i]); }
885  delete[] tmpdata;
886  metadata.SetString("ORIGINAL_TYPE", "INT16");
887 
888  }
889  else if(typestring=="MET_UINT"){
890  uint32_t* tmpdata=new uint32_t[nelem];
891  if(BinaryDataByteOrderMSB){
892  ReadFromBigEndian((char*)tmpdata, nelem, sizeof(uint32_t), f);
893  }
894  else{
895  ReadFromLittleEndian((char*)tmpdata, nelem, sizeof(uint32_t), f);
896  }
897 
898  #pragma omp parallel for
899  for(long i=0; i<nelem; i++){ data[i]=T(tmpdata[i]); }
900  delete[] tmpdata;
901  metadata.SetString("ORIGINAL_TYPE", "UINT32");
902 
903  }
904 
905  else if(typestring=="MET_INT"){
906  int32_t* tmpdata=new int32_t[nelem];
907  if(BinaryDataByteOrderMSB){
908  ReadFromBigEndian((char*)tmpdata, nelem, sizeof(int32_t), f);
909  }
910  else{
911  ReadFromLittleEndian((char*)tmpdata, nelem, sizeof(int32_t), f);
912  }
913 
914  #pragma omp parallel for
915  for(long i=0; i<nelem; i++){ data[i]=T(tmpdata[i]); }
916  delete[] tmpdata;
917  metadata.SetString("ORIGINAL_TYPE", "INT32");
918 
919  }
920 
921  else if(typestring=="MET_FLOAT"){
922  float* tmpdata=new float[nelem];
923  if(BinaryDataByteOrderMSB){
924  ReadFromBigEndian((char*)tmpdata, nelem, sizeof(float), f);
925  }
926  else{
927  ReadFromLittleEndian((char*)tmpdata, nelem, sizeof(float), f);
928  }
929 
930  #pragma omp parallel for
931  for(long i=0; i<nelem; i++){ data[i]=T(tmpdata[i]); }
932  delete[] tmpdata;
933  metadata.SetString("ORIGINAL_TYPE", "FLOAT");
934 
935  }
936  else if(typestring=="MET_DOUBLE"){
937  double* tmpdata=new double[nelem];
938  if(BinaryDataByteOrderMSB){
939  ReadFromBigEndian((char*)tmpdata, nelem, sizeof(double), f);
940  }
941  else{
942  ReadFromLittleEndian((char*)tmpdata, nelem, sizeof(double), f);
943  }
944 
945  #pragma omp parallel for
946  for(long i=0; i<nelem; i++){ data[i]=T(tmpdata[i]); }
947  delete[] tmpdata;
948  metadata.SetString("ORIGINAL_TYPE", "DOUBLE");
949 
950  }
951 
952  f.close();
953 
954 
955  //Set metadata
956 
957  //Read the Comment field
958  it=header_info.find("Comment");
959  if(it!=header_info.end()){
960  metadata.SetString(it->first,it->second);
961  }
962 
963  //Read the Name field
964  it=header_info.find("Name");
965  if(it!=header_info.end()){
966  metadata.SetString(it->first,it->second);
967  }
968 
969  //Read the ID field
970  it=header_info.find("ID");
971  if(it!=header_info.end()){
972  metadata.SetString(it->first,it->second);
973  }
974 
975  //Read the Position field
976  it=header_info.find("Position");
977  if(it!=header_info.end()){
978  metadata.SetString(it->first,it->second);
979  }
980 
981  //Read the Orientation field
982  it=header_info.find("Orientation");
983  if(it!=header_info.end()){
984  metadata.SetString(it->first,it->second);
985  }
986 
987  //Read the AnatomicalOrientation field
988  it=header_info.find("AnatomicalOrientation");
989  if(it!=header_info.end()){
990  metadata.SetString(it->first,it->second);
991  }
992 
993  //Read the Modality field
994  it=header_info.find("Modality");
995  if(it!=header_info.end()){
996  metadata.SetString(it->first,it->second);
997  }
998 
999 
1000  return true;
1001 }
1002 
1003 template <class T>
1004 inline bool Grid3<T>::WriteMetaImage(std::string filename){
1005 
1006  //string datatype=GetDataType();
1007 
1008 
1009  FileName f(filename);
1010  f.SetExtension("mhd");
1011  string headerfile_name=f.GetAsString();
1012 
1013  f.SetExtension("raw");
1014  string datafile=f.GetAsString();
1015 
1016  f.ClearPath();
1017  string relative_datafile=f.GetAsString();
1018 
1019  ofstream outfile;
1020  string datatype=GetDataType();
1021  string metaimage_datatype="";
1022  if(datatype=="UINT8"){metaimage_datatype="MET_UCHAR";}
1023  else if(datatype=="UINT16"){metaimage_datatype="MET_USHORT";}
1024  else if(datatype=="UINT32"){metaimage_datatype="MET_UINT";}
1025  else if(datatype=="INT8"){metaimage_datatype="MET_CHAR";}
1026  else if(datatype=="INT16"){metaimage_datatype="MET_SHORT";}
1027  else if(datatype=="INT32"){metaimage_datatype="MET_INT";}
1028  else{return false;} //Unsupported datatype for this format
1029 
1030  outfile.open(headerfile_name,ofstream::out|ofstream::binary);
1031  if(!outfile) { return false; }
1032 
1033  outfile<<"ObjectType = Image"<<endl;
1034 
1035  int ndims=3;
1036  if( GetDepth()==1){ ndims=2; }
1037  outfile<<"NDims = "<<ndims<<endl;
1038 
1039  outfile<<"DimSize = "<<GetWidth()<<" "<<GetHeight();
1040  if(ndims==3){outfile<<" "<<GetDepth();}
1041  outfile<<endl;
1042 
1043  outfile<<"HeaderSize = 0"<<endl;
1044  outfile<<"ElementSize = 1 1 1"<<endl;
1045  outfile<<"ElementSpacing = "<<GetSpacingX()<<" "<<GetSpacingY()<<" "<<GetSpacingZ()<<" "<<endl;
1046 
1047  outfile<<"ElementType = "<<metaimage_datatype<<endl;
1048 
1049  if(IsBigEndian()){
1050  outfile<<"ElementByteOrderMSB = True"<<endl;
1051  }
1052  else{
1053  outfile<<"ElementByteOrderMSB = False"<<endl;
1054  }
1055 
1056  outfile<<"ElementDataFile = "<<relative_datafile<<endl;
1057 
1058  outfile.close();
1059 
1060  long nelem= _width*_height*_depth;
1061 
1062  T* data=Data();
1063  outfile.open(datafile,ofstream::out|ofstream::binary);
1064  outfile.write((char*)data, nelem*sizeof(T));
1065  //WriteToBigEndian((char*)&data[0], nelem, sizeof(T), outfile);
1066  outfile.close();
1067 
1068  return true;
1069 }
1070 
1071 template <class T>
1072 inline bool Grid3<T>::ReadNIFTI(std::string filename){
1073  //TODO: Handle Endianness
1074  //It is assumed that sizeof(float)==4
1075 
1076  //Volume* result = NULL;
1077 
1078  ifstream f;
1079 
1080  f.open( filename.c_str(), std::ios::in | std::ios::binary );
1081  if( !f ) { return false; }
1082 
1083  //Read size of the header. Must be 348 (bytes).
1084  int32_t sizeof_hdr=0;
1085  f.read((char*)&sizeof_hdr,4);
1086  if(sizeof_hdr!=348){
1087 
1088  f.close();
1089  return false;
1090  }
1091 
1092 
1093  //Read data array dimensions. Grid3 only supports 3 dimensions.
1094  f.seekg(40);
1095  int16_t dim[8];
1096  f.read((char*)&dim[0],16);
1097 
1098  if(!(dim[0]>0 && dim[0]<5)){
1099  f.close();
1100  return false;
1101  }
1102 
1103  int dimx=dim[1];
1104  int dimy=1;
1105  if(dim[0]>=2){ dimy=dim[2]; }
1106  int dimz=1;
1107  if(dim[0]>=3){ dimz=dim[3]; }
1108  int nchannels=1;
1109  if(dim[0]>=4){ nchannels=dim[4]; }
1110 
1111  //Read data type
1112  f.seekg(70);
1113  int16_t datatype=0;
1114  f.read((char*)&datatype,2);
1115  if(datatype==0){
1116  f.close();
1117  return false;
1118  }
1119 
1120  //Read grid spacings (unit per dimension)
1121  f.seekg(76);
1122  float pixdim[8];
1123  f.read((char*)&pixdim[0],32);
1124  _spacingX=pixdim[1];
1125  _spacingY=pixdim[2];
1126  _spacingZ=pixdim[3];
1127 
1128  //Read offset into a .nii file
1129  float vox_offset=0;
1130  f.read((char*)&vox_offset,4);
1131 
1132  //Read data
1133  f.seekg(std::streamoff(vox_offset));
1134 
1135  long nelem=dimx*dimy*dimz;
1136  Init(dimx,dimy,dimz);
1137 
1138  T* data=Data();
1139 
1140  switch (datatype){
1141  case 1: //bool, unsupported
1142  f.close();
1143  return false;
1144  break;
1145 
1146  case 2: //unsigned char
1147  {uint8_t* tmpdata=new uint8_t[nelem];
1148  metadata.SetString("ORIGINAL_TYPE", "UINT8");
1149  f.read((char*)tmpdata, nelem*sizeof(uint8_t));
1150  #pragma omp parallel for
1151  for(long i=0; i<nelem; i++){
1152  data[i]=T(tmpdata[i]);
1153  }
1154  delete[] tmpdata;}
1155  break;
1156 
1157  case 4: // signed short
1158  {int16_t* tmpdata=new int16_t[nelem];
1159  metadata.SetString("ORIGINAL_TYPE", "INT16");
1160  f.read((char*)tmpdata, nelem*sizeof(int16_t));
1161  #pragma omp parallel for
1162  for(long i=0; i<nelem; i++){
1163  data[i]=T(tmpdata[i]);
1164  }
1165  delete[] tmpdata;
1166  }
1167  break;
1168  case 8: // signed int
1169  {int32_t* tmpdata=new int32_t[nelem];
1170  metadata.SetString("ORIGINAL_TYPE", "INT32");
1171  f.read((char*)tmpdata, nelem*sizeof(int32_t));
1172  #pragma omp parallel for
1173  for(long i=0; i<nelem; i++){
1174  data[i]=T(tmpdata[i]);
1175  }
1176  delete[] tmpdata;
1177  }
1178  break;
1179  case 16: // float
1180  {float* tmpdata=new float[nelem];
1181  metadata.SetString("ORIGINAL_TYPE", "FLOAT");
1182  f.read((char*)tmpdata, nelem*sizeof(float));
1183  #pragma omp parallel for
1184  for(long i=0; i<nelem; i++){
1185  data[i]=T(tmpdata[i]);
1186  }
1187  delete[] tmpdata;
1188  }
1189  break;
1190  case 32: // complex, unsupported
1191  f.close();
1192  return false;
1193  break;
1194  case 64: // double
1195  {double* tmpdata=new double[nelem];
1196  metadata.SetString("ORIGINAL_TYPE", "DOUBLE");
1197  f.read((char*)tmpdata, nelem*sizeof(double));
1198  #pragma omp parallel for
1199  for(long i=0; i<nelem; i++){
1200  data[i]=T(tmpdata[i]);
1201  }
1202  delete[] tmpdata;
1203  }
1204  break;
1205  case 256: // signed char
1206  {int8_t* tmpdata=new int8_t[nelem];
1207  metadata.SetString("ORIGINAL_TYPE", "INT8");
1208  f.read((char*)tmpdata, nelem*sizeof(int8_t));
1209  #pragma omp parallel for
1210  for(long i=0; i<nelem; i++){
1211  data[i]=T(tmpdata[i]);
1212  }
1213  delete[] tmpdata;
1214  }
1215  break;
1216  case 512: // unsigned short
1217  {uint16_t* tmpdata=new uint16_t[nelem];
1218  metadata.SetString("ORIGINAL_TYPE", "UINT16");
1219  f.read((char*)tmpdata, nelem*sizeof(uint16_t));
1220  #pragma omp parallel for
1221  for(long i=0; i<nelem; i++){
1222  data[i]=T(tmpdata[i]);
1223  }
1224  delete[] tmpdata;
1225  }
1226  break;
1227  case 768: // unsigned int
1228  {uint32_t* tmpdata=new uint32_t[nelem];
1229  metadata.SetString("ORIGINAL_TYPE", "UINT32");
1230  f.read((char*)tmpdata, nelem*sizeof(uint32_t));
1231  #pragma omp parallel for
1232  for(long i=0; i<nelem; i++){
1233  data[i]=T(tmpdata[i]);
1234  }
1235  delete[] tmpdata;
1236  }
1237  break;
1238  default: //unsupported types
1239  f.close();
1240  return false;
1241  break;
1242  }
1243  f.close();
1244  return true;
1245 }
1246 
1247 template <class T>
1248 inline bool Grid3<T>::WriteNIFTI(std::string filename){
1249  //Not done yet
1250  ofstream outfile;
1251  outfile.open(filename);
1252  if( !outfile ) { return false; }
1253 
1254  //Write header size, always 348
1255  int32_t sizeof_hdr=348;
1256  outfile.write((char*)&sizeof_hdr,4);
1257 
1258  //Write image dimensions
1259  int16_t dim[8];
1260  dim[0]=3;
1261  dim[1]= GetWidth();
1262  dim[2]=GetHeight();
1263  dim[3]=GetDepth();
1264  dim[4]=0;
1265  dim[5]=0;
1266  dim[6]=0;
1267  dim[7]=0;
1268 
1269  outfile.seekp(40);
1270  outfile.write((char*)&dim[0],16);
1271 
1272  //Read data type
1273  int16_t datatype=0;
1274 
1275  string datatype_name=GetDataType();
1276 
1277  if(datatype_name=="UINT8"){datatype=2;}
1278  else if(datatype_name=="INT8"){datatype=256;}
1279  else if(datatype_name=="UINT16"){datatype=512;}
1280  else if(datatype_name=="INT16"){datatype=4;}
1281  else if(datatype_name=="UINT32"){datatype=768;}
1282  else if(datatype_name=="INT32"){datatype=8;}
1283  else if(datatype_name=="float"){datatype=16;}
1284  else if(datatype_name=="double"){datatype=64;}
1285 
1286  outfile.seekp(70);
1287  outfile.write((char*)&datatype,2);
1288 
1289  //Write grid spacing
1290  outfile.seekp(76);
1291  float pixdim[8];
1292  pixdim[0]=1; //This entry has a special meaning, unused by Grid3
1293  pixdim[1]=_spacingX;
1294  pixdim[2]=_spacingY;
1295  pixdim[3]=_spacingZ;
1296  outfile.write((char*)&pixdim[0],32);
1297 
1298  //Write offset to data
1299  float vox_offset=352;
1300  outfile.seekp(108);
1301  outfile.write((char*)&vox_offset,4);
1302 
1303  //Write "magic" string
1304  char magic[4]={'n','+','1','\0'}; //Single .nii file
1305  outfile.seekp(344);
1306  outfile.write((char*)&magic[0],4);
1307 
1308  //Write data
1309  outfile.seekp(352);
1310  T* data=Data();
1311  outfile.write((char*)data,sizeof(T)*NumberOfElements());
1312 
1313  outfile.close();
1314  return true;
1315 }
1316 
1317 
1318 template <class T>
1319 inline bool Grid3<T>::ReadDICOM(std::string filename){
1320  #ifdef grid3_use_gdcm
1321 
1322  gdcm::ImageReader ir;
1323  ir.SetFileName(filename.c_str());
1324  if(!ir.Read()){ return false; }
1325 
1326  const gdcm::Image &image = ir.GetImage();
1327 
1328  const unsigned int* dim = image.GetDimensions();
1329  Init(dim[0], dim[1], dim[2], image.GetSpacing(0), image.GetSpacing(1), image.GetSpacing(2));
1330 
1331  gdcm::PixelFormat pf= image.GetPixelFormat();
1332  if(pf.GetSamplesPerPixel()!=1){return false;} //Only scalar images supported
1333 
1334  long nelem=NumberOfElements();
1335  string type= string(pf.GetScalarTypeAsString());
1336 
1337  //Defined data types for DICOM:
1338  //UINT8,
1339  //INT8,
1340  //UINT12,
1341  //INT12,
1342  //UINT16,
1343  //INT16,
1344  //UINT32,
1345  //INT32,
1346  //FLOAT16,
1347  //FLOAT32,
1348  //FLOAT64,
1349  //SINGLEBIT,
1350  //UNKNOWN
1351 
1352 
1353  if(type=="UINT8"){
1354  uint8_t* tmpdata=new uint8_t[nelem];
1355  metadata.SetString("ORIGINAL_TYPE", "UINT8");
1356  if( !image.GetBuffer( (char*)tmpdata) ){
1357  delete[] tmpdata;
1358  return false;
1359  }
1360  #pragma omp parallel for
1361  for(long i=0; i<nelem; i++){
1362  data[i]=T(tmpdata[i]);
1363  }
1364  delete[] tmpdata;
1365  }
1366  else if(type=="UINT16"){
1367  uint16_t* tmpdata = new uint16_t[nelem];
1368  metadata.SetString("ORIGINAL_TYPE", "UINT16");
1369  if (!image.GetBuffer((char*)tmpdata)){
1370  delete[] tmpdata;
1371  return false;
1372  }
1373  #pragma omp parallel for
1374  for (long i = 0; i<nelem; i++){
1375  data[i] = T(tmpdata[i]);
1376  }
1377  delete[] tmpdata;
1378 
1379  }
1380  else if (type == "UINT32"){
1381  uint32_t* tmpdata = new uint32_t[nelem];
1382  metadata.SetString("ORIGINAL_TYPE", "UINT32");
1383  if (!image.GetBuffer((char*)tmpdata)){
1384  delete[] tmpdata;
1385  return false;
1386  }
1387  #pragma omp parallel for
1388  for (long i = 0; i<nelem; i++){
1389  data[i] = T(tmpdata[i]);
1390  }
1391  delete[] tmpdata;
1392  }
1393  else if (type == "INT8"){
1394  int8_t* tmpdata = new int8_t[nelem];
1395  metadata.SetString("ORIGINAL_TYPE", "INT8");
1396  if (!image.GetBuffer((char*)tmpdata)){
1397  delete[] tmpdata;
1398  return false;
1399  }
1400  #pragma omp parallel for
1401  for (long i = 0; i<nelem; i++){
1402  data[i] = T(tmpdata[i]);
1403  }
1404  delete[] tmpdata;
1405 
1406  }
1407  else if (type == "INT16"){
1408  int16_t* tmpdata = new int16_t[nelem];
1409  metadata.SetString("ORIGINAL_TYPE", "INT16");
1410  if (!image.GetBuffer((char*)tmpdata)){
1411  delete[] tmpdata;
1412  return false;
1413  }
1414  #pragma omp parallel for
1415  for (long i = 0; i<nelem; i++){
1416  data[i] = T(tmpdata[i]);
1417  }
1418  delete[] tmpdata;
1419  }
1420  else if (type == "INT32"){
1421  metadata.SetString("ORIGINAL_TYPE", "INT32");
1422  int32_t* tmpdata = new int32_t[nelem];
1423  if (!image.GetBuffer((char*)tmpdata)){
1424  delete[] tmpdata;
1425  return false;
1426  }
1427  #pragma omp parallel for
1428  for (long i = 0; i<nelem; i++){
1429  data[i] = T(tmpdata[i]);
1430  }
1431  delete[] tmpdata;
1432  }
1433  else if (type == "FLOAT16"){
1434  return false; //unsupported
1435  }
1436  else if (type == "FLOAT32"){
1437  //We require the float type to have 32 bits
1438  if (CHAR_BIT*sizeof(float) != 32){
1439  return false;
1440  }
1441  float* tmpdata = new float[nelem];
1442  metadata.SetString("ORIGINAL_TYPE", "FLOAT");
1443  if (!image.GetBuffer((char*)tmpdata)){
1444  delete[] tmpdata;
1445  return false;
1446  }
1447  #pragma omp parallel for
1448  for (long i = 0; i<nelem; i++){
1449  data[i] = T(tmpdata[i]);
1450  }
1451  delete[] tmpdata;
1452  }
1453  else if (type == "FLOAT64"){
1454  //We require the double type to have 64 bits
1455  if (CHAR_BIT*sizeof(double) != 64){
1456  return false;
1457  }
1458  double* tmpdata = new double[nelem];
1459  metadata.SetString("ORIGINAL_TYPE", "DOUBLE");
1460  if (!image.GetBuffer((char*)tmpdata)){
1461  delete[] tmpdata;
1462  return false;
1463  }
1464  #pragma omp parallel for
1465  for (long i = 0; i<nelem; i++){
1466  data[i] = T(tmpdata[i]);
1467  }
1468  delete[] tmpdata;
1469  }
1470 
1471  return true;
1472  #endif
1473 
1474  return false;
1475 }
1476 
1477 
1478 #endif
bool WriteVTK(std::string filename)
Save grid in VTK legacy format.
Definition: Grid3_i.h:571
int NumberOfElements()
Return the total number of grid points.
Definition: Grid3_i.h:95
Class representing 3D vectors, with elements of type T.
Definition: Vector3.h:9
T * Data()
Returns a pointer to the beginning of the internal data array. The called object owns the pointer...
Definition: Grid3_i.h:100
bool ReadVTK(std::string filename)
Construct grid from an image file in VTK legacy format.
Definition: Grid3_i.h:377
void Fill(T value)
Set all points in the grid to a specified value.
Definition: Grid3_i.h:285
std::string GetDataType()
Return a string representation of the voxel type.
Definition: Grid3_i.h:135
Grid3()
Default constructor.
Definition: Grid3.h:63
Definition: FileName.h:26
T & operator[](long index)
Access to the grid value at a specified index. The passed index is assumed to be within the grid boun...
Definition: Grid3_i.h:166
T GetMaxValue()
Return the maximum value in the grid.
Definition: Grid3_i.h:290
Vec3d GridToWorld(Vec3d p)
Transform point p from grid coordinates to world coordinates.
Definition: Grid3_i.h:86
T LinearAt(double x, double y, double z)
Get the grid value at a specified coordinate using trilinear interpolation.
Definition: Grid3_i.h:197
void Get6Neighbors(long index, vector< long > &n)
Fill the vector n with the indices of the 6-neighbors of the gridpoint at the specified index...
Definition: Grid3_i.h:225
void SetSpacing(double x_spacing, double y_spacing, double z_spacing)
Set spacing.
Definition: Grid3_i.h:62
void Init(int width, int height, int depth=1, double x_spacing=1.0, double y_spacing=1.0, double z_spacing=1.0)
Initialize the grid with given dimensions. Any previous data in the grid will be overwritten.
Definition: Grid3_i.h:50
void CopyDataFrom(Grid3< T > &src)
Replace the current grid data with that of another grid. If the two grids do not have the same Number...
Definition: Grid3_i.h:343
Class representing a 3D image grid, each voxel being of type T.
Definition: Grid3.h:53
bool ReadMetaImage(std::string filename)
Construct grid from an image file in MetaImage format.
Definition: Grid3_i.h:641
Vec3d WorldToGrid(Vec3d p)
Transform point p from world coordinates to grid coordinates.
Definition: Grid3_i.h:76
void SwapContentsWith(Grid3< T > &v)
Swap the contents of two grids. If the two grids do not have the same NumberOfElements(), nothing happens.
Definition: Grid3_i.h:350
int Offset(int x, int y, int z)
Returns the index of a specified coordinate in the internal data array.
Definition: Grid3_i.h:141
bool WriteMetaImage(std::string filename)
Save grid in MetaImage format.
Definition: Grid3_i.h:1004
bool WriteNIFTI(std::string filename)
Save grid in NIFTI format.
Definition: Grid3_i.h:1248
T GetMinValue()
Return the minimum value in the grid.
Definition: Grid3_i.h:295
bool IsInside(int x, int y, int z)
Test if the given grid point is within the bounds of the grid.
Definition: Grid3_i.h:156
bool CreateFromFile(std::string filename)
Construct grid from an image file.
Definition: Grid3_i.h:357
Vec3i Coordinate(long index)
Returns the coordinate corresponding to a specified index in the internal data array.
Definition: Grid3_i.h:146
bool ReadDICOM(std::string filename)
Construct grid from an image file in DICOM format.
Definition: Grid3_i.h:1319
T & operator()(int x, int y, int z=0, bool Safe=false)
Access to the grid value at a specified coordinate. If "Safe" is false, the passed coordinate is assu...
Definition: Grid3_i.h:171
bool ReadNIFTI(std::string filename)
Construct grid from an image file in NIFTI format.
Definition: Grid3_i.h:1072