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