Orfeo Toolbox  3.16
itkMetaImageIO.cxx
Go to the documentation of this file.
1 /*=========================================================================
2 
3  Program: Insight Segmentation & Registration Toolkit
4  Module: $RCSfile: itkMetaImageIO.cxx,v $
5  Language: C++
6  Date: $Date: 2010-06-01 11:22:47 $
7  Version: $Revision: 1.106 $
8 
9  Copyright (c) Insight Software Consortium. All rights reserved.
10  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.
11 
12  This software is distributed WITHOUT ANY WARRANTY; without even
13  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14  PURPOSE. See the above copyright notices for more information.
15 
16 =========================================================================*/
17 #ifdef _MSC_VER
18 #pragma warning ( disable : 4786 )
19 #endif
20 
21 #include <string>
22 #include <stdlib.h>
23 #include "itkMetaImageIO.h"
24 #include "itkExceptionObject.h"
25 #include "itkSpatialOrientation.h"
27 #include "itkMetaDataObject.h"
28 #include "itkIOCommon.h"
29 #include <itksys/SystemTools.hxx>
30 
31 namespace itk
32 {
33 
35 {
38  if(MET_SystemByteOrderMSB())
39  {
41  }
42  else
43  {
45  }
46 
47  this->AddSupportedWriteExtension(".mha");
48  this->AddSupportedWriteExtension(".mhd");
49 
50  this->AddSupportedReadExtension(".mha");
51  this->AddSupportedReadExtension(".mhd");
52 
53 }
54 
56 {
57 }
58 
59 void MetaImageIO::PrintSelf(std::ostream& os, Indent indent) const
60 {
61  Superclass::PrintSelf(os, indent);
62  m_MetaImage.PrintInfo();
63  os << indent << "SubSamplingFactor: " << m_SubSamplingFactor << "\n";
64 }
65 
66 
67 void MetaImageIO::SetDataFileName( const char* filename )
68 {
69  m_MetaImage.ElementDataFileName( filename );
70 }
71 
72 // This method will only test if the header looks like a
73 // MetaImage. Some code is redundant with ReadImageInformation
74 // a StateMachine could provide a better implementation
75 bool MetaImageIO::CanReadFile( const char* filename )
76 {
77  // First check the extension
78  std::string fname = filename;
79  if( fname == "" )
80  {
81  itkDebugMacro(<<"No filename specified.");
82  return false;
83  }
84 
85  return m_MetaImage.CanRead(filename);
86 }
87 
88 
90 {
91  if(!m_MetaImage.Read(m_FileName.c_str(), false))
92  {
93  itkExceptionMacro("File cannot be read: "
94  << this->GetFileName() << " for reading."
95  << std::endl
96  << "Reason: "
97  << itksys::SystemTools::GetLastSystemError());
98  }
99 
100  if(m_MetaImage.BinaryData())
101  {
102  this->SetFileType(Binary);
103  }
104  else
105  {
106  this->SetFileType(ASCII);
107  }
108 
109  this->SetNumberOfComponents(m_MetaImage.ElementNumberOfChannels());
110 
111  switch(m_MetaImage.ElementType())
112  {
113  default:
114  case MET_OTHER:
115  case MET_NONE:
118  break;
119  case MET_CHAR:
120  case MET_ASCII_CHAR:
121  this->SetPixelType( SCALAR );
122  this->SetComponentType( CHAR );
123  break;
124  case MET_CHAR_ARRAY:
125  case MET_STRING:
126  this->SetPixelType( VECTOR );
127  this->SetComponentType( CHAR );
128  break;
129  case MET_UCHAR:
130  this->SetPixelType( SCALAR );
131  this->SetComponentType( UCHAR );
132  break;
133  case MET_UCHAR_ARRAY:
134  this->SetPixelType( VECTOR );
135  this->SetComponentType( UCHAR );
136  break;
137  case MET_SHORT:
138  this->SetPixelType( SCALAR );
139  this->SetComponentType( SHORT );
140  break;
141  case MET_SHORT_ARRAY:
142  this->SetPixelType( VECTOR );
143  this->SetComponentType( SHORT );
144  break;
145  case MET_USHORT:
146  this->SetPixelType( SCALAR );
147  this->SetComponentType( USHORT );
148  break;
149  case MET_USHORT_ARRAY:
150  this->SetPixelType( VECTOR );
151  this->SetComponentType( USHORT );
152  break;
153  case MET_INT:
154  this->SetPixelType( SCALAR );
155  if(sizeof(int) == MET_ValueTypeSize[MET_INT])
156  {
157  this->SetComponentType( INT );
158  }
159  else if(sizeof(long) == MET_ValueTypeSize[MET_INT])
160  {
161  this->SetComponentType( LONG );
162  }
163  break;
164  case MET_INT_ARRAY:
165  this->SetPixelType( VECTOR );
166  if(sizeof(int) == MET_ValueTypeSize[MET_INT])
167  {
168  this->SetComponentType( INT );
169  }
170  else if(sizeof(long) == MET_ValueTypeSize[MET_INT])
171  {
172  this->SetComponentType( LONG );
173  }
174  break;
175  case MET_UINT:
176  this->SetPixelType( SCALAR );
177  if(sizeof(unsigned int) == MET_ValueTypeSize[MET_UINT])
178  {
179  this->SetComponentType( UINT );
180  }
181  else if(sizeof(unsigned long) == MET_ValueTypeSize[MET_UINT])
182  {
183  this->SetComponentType( ULONG );
184  }
185  break;
186  case MET_UINT_ARRAY:
187  this->SetPixelType( VECTOR );
188  if(sizeof(int) == MET_ValueTypeSize[MET_INT])
189  {
190  this->SetComponentType( UINT );
191  }
192  else if(sizeof(long) == MET_ValueTypeSize[MET_INT])
193  {
194  this->SetComponentType( ULONG );
195  }
196  break;
197  case MET_LONG:
198  this->SetPixelType( SCALAR );
199  if(sizeof(long) == MET_ValueTypeSize[MET_LONG])
200  {
201  this->SetComponentType( LONG );
202  }
203  else if(sizeof(int) == MET_ValueTypeSize[MET_LONG])
204  {
205  this->SetComponentType( INT );
206  }
207  break;
208  case MET_LONG_ARRAY:
209  this->SetPixelType( VECTOR );
210  if(sizeof(long) == MET_ValueTypeSize[MET_LONG])
211  {
212  this->SetComponentType( LONG );
213  }
214  else if(sizeof(int) == MET_ValueTypeSize[MET_LONG])
215  {
216  this->SetComponentType( INT );
217  }
218  break;
219  case MET_ULONG:
220  this->SetPixelType( SCALAR );
221  if(sizeof(unsigned long) == MET_ValueTypeSize[MET_ULONG])
222  {
223  this->SetComponentType( ULONG );
224  }
225  else if(sizeof(unsigned int) == MET_ValueTypeSize[MET_ULONG])
226  {
227  this->SetComponentType( UINT );
228  }
229  break;
230  case MET_ULONG_ARRAY:
231  this->SetPixelType( VECTOR );
232  if(sizeof(unsigned long) == MET_ValueTypeSize[MET_ULONG])
233  {
234  this->SetComponentType( ULONG );
235  }
236  else if(sizeof(unsigned int) == MET_ValueTypeSize[MET_ULONG])
237  {
238  this->SetComponentType( UINT );
239  }
240  break;
241  case MET_LONG_LONG:
242  this->SetPixelType( SCALAR );
243  if(sizeof(long) == MET_ValueTypeSize[MET_LONG_LONG])
244  {
245  this->SetComponentType( LONG );
246  }
247  else if(sizeof(int) == MET_ValueTypeSize[MET_LONG_LONG])
248  {
249  this->SetComponentType( INT );
250  }
251  else
252  {
254  }
255  break;
256  case MET_LONG_LONG_ARRAY:
257  this->SetPixelType( VECTOR );
258  if(sizeof(long) == MET_ValueTypeSize[MET_LONG_LONG])
259  {
260  this->SetComponentType( LONG );
261  }
262  else if(sizeof(int) == MET_ValueTypeSize[MET_LONG_LONG])
263  {
264  this->SetComponentType( INT );
265  }
266  else
267  {
269  }
270  break;
271  case MET_ULONG_LONG:
272  this->SetPixelType( SCALAR );
273  if(sizeof(unsigned long) == MET_ValueTypeSize[MET_ULONG_LONG])
274  {
275  this->SetComponentType( ULONG );
276  }
277  else if(sizeof(unsigned int) == MET_ValueTypeSize[MET_ULONG_LONG])
278  {
279  this->SetComponentType( UINT );
280  }
281  else
282  {
284  }
285  break;
286  case MET_ULONG_LONG_ARRAY:
287  this->SetPixelType( VECTOR );
288  if(sizeof(unsigned long) == MET_ValueTypeSize[MET_ULONG_LONG])
289  {
290  this->SetComponentType( ULONG );
291  }
292  else if(sizeof(unsigned int) == MET_ValueTypeSize[MET_ULONG_LONG])
293  {
294  this->SetComponentType( UINT );
295  }
296  else
297  {
299  }
300  break;
301  case MET_FLOAT:
302  this->SetPixelType( SCALAR );
303  if(sizeof(float) == MET_ValueTypeSize[MET_FLOAT])
304  {
305  this->SetComponentType( FLOAT );
306  }
307  else if(sizeof(double) == MET_ValueTypeSize[MET_FLOAT])
308  {
309  this->SetComponentType( DOUBLE );
310  }
311  break;
312  case MET_FLOAT_ARRAY:
313  this->SetPixelType( VECTOR );
314  if(sizeof(float) == MET_ValueTypeSize[MET_FLOAT])
315  {
316  this->SetComponentType( FLOAT );
317  }
318  else if(sizeof(double) == MET_ValueTypeSize[MET_FLOAT])
319  {
320  this->SetComponentType( DOUBLE );
321  }
322  break;
323  case MET_DOUBLE:
324  this->SetPixelType( SCALAR );
325  this->SetComponentType( DOUBLE );
326  if(sizeof(double) == MET_ValueTypeSize[MET_DOUBLE])
327  {
328  this->SetComponentType( DOUBLE );
329  }
330  else if(sizeof(float) == MET_ValueTypeSize[MET_DOUBLE])
331  {
332  this->SetComponentType( FLOAT );
333  }
334  break;
335  case MET_DOUBLE_ARRAY:
336  this->SetPixelType( VECTOR );
337  if(sizeof(double) == MET_ValueTypeSize[MET_DOUBLE])
338  {
339  this->SetComponentType( DOUBLE );
340  }
341  else if(sizeof(float) == MET_ValueTypeSize[MET_DOUBLE])
342  {
343  this->SetComponentType( FLOAT );
344  }
345  break;
346  case MET_FLOAT_MATRIX:
347  this->SetPixelType( VECTOR );
348  if(sizeof(float) == MET_ValueTypeSize[MET_FLOAT])
349  {
350  this->SetComponentType( FLOAT );
351  }
352  else if(sizeof(double) == MET_ValueTypeSize[MET_FLOAT])
353  {
354  this->SetComponentType( DOUBLE );
355  }
357  break;
358  }
359 
360  // BUG: 8732
361  // The above use to MET_*_ARRAY may not be correct, as this MetaIO
362  // ElementType was not designed to indicate vectors, but something
363  // else
364  //
365  // if the file has multiple components then we default to a vector
366  // pixel type, support could be added to MetaIO format to define
367  // different pixel types
368  if ( m_MetaImage.ElementNumberOfChannels() > 1 )
369  {
370  this->SetPixelType( VECTOR );
371  }
372 
373  this->SetNumberOfDimensions(m_MetaImage.NDims());
374 
375  unsigned int i;
376  for(i=0; i<m_NumberOfDimensions; i++)
377  {
378  this->SetDimensions(i,m_MetaImage.DimSize(i)/m_SubSamplingFactor);
379  this->SetSpacing(i, m_MetaImage.ElementSpacing(i)*m_SubSamplingFactor);
380  this->SetOrigin(i, m_MetaImage.Position(i));
381  }
382 
383 
384 #if defined(ITKIO_DEPRECATED_METADATA_ORIENTATION)
385  MetaDataDictionary & thisMetaDict = this->GetMetaDataDictionary();
386 #endif
387  /* TO - DO */
388  /*
389  Record type read - as in:
390  EncapsulateMetaData<std::string>(thisMetaDict, ITK_OnDiskStorageTypeName,
391  std::string(typeid(float).name()));
392  */
393  if(m_NumberOfDimensions == 3)
394  {
396  int zero = 0;
397  bool coordUndefined = false;
398  switch(m_MetaImage.AnatomicalOrientation(zero))
399  {
400  case MET_ORIENTATION_UNKNOWN:
401  default:
402  {
403  coordUndefined = true;
404  break;
405  }
406  case MET_ORIENTATION_RL:
407  {
408  switch(m_MetaImage.AnatomicalOrientation(1))
409  {
410  case MET_ORIENTATION_UNKNOWN:
411  default:
412  {
413  coordUndefined = true;
414  break;
415  }
416  case MET_ORIENTATION_PA:
417  {
418  if(m_MetaImage.AnatomicalOrientation(2) == MET_ORIENTATION_IS)
419  {
420  coordOrient =
422  }
423  else
424  {
425  coordOrient =
427  }
428  break;
429  }
430  case MET_ORIENTATION_AP:
431  {
432  if(m_MetaImage.AnatomicalOrientation(2) == MET_ORIENTATION_IS)
433  {
434  coordOrient =
436  }
437  else
438  {
439  coordOrient =
441  }
442  break;
443  }
444  case MET_ORIENTATION_IS:
445  {
446  if(m_MetaImage.AnatomicalOrientation(2) == MET_ORIENTATION_PA)
447  {
448  coordOrient =
450  }
451  else
452  {
453  coordOrient =
455  }
456  break;
457  }
458  case MET_ORIENTATION_SI:
459  {
460  if(m_MetaImage.AnatomicalOrientation(2) == MET_ORIENTATION_PA)
461  {
462  coordOrient =
464  }
465  else
466  {
467  coordOrient =
469  }
470  break;
471  }
472  }
473  break;
474  }
475  case MET_ORIENTATION_LR:
476  {
477  switch(m_MetaImage.AnatomicalOrientation(1))
478  {
479  case MET_ORIENTATION_UNKNOWN:
480  default:
481  {
482  coordUndefined = true;
483  break;
484  }
485  case MET_ORIENTATION_PA:
486  {
487  if(m_MetaImage.AnatomicalOrientation(2) == MET_ORIENTATION_IS)
488  {
489  coordOrient =
491  }
492  else
493  {
494  coordOrient =
496  }
497  break;
498  }
499  case MET_ORIENTATION_AP:
500  {
501  if(m_MetaImage.AnatomicalOrientation(2) == MET_ORIENTATION_IS)
502  {
503  coordOrient =
505  }
506  else
507  {
508  coordOrient =
510  }
511  break;
512  }
513  case MET_ORIENTATION_IS:
514  {
515  if(m_MetaImage.AnatomicalOrientation(2) == MET_ORIENTATION_PA)
516  {
517  coordOrient =
519  }
520  else
521  {
522  coordOrient =
524  }
525  break;
526  }
527  case MET_ORIENTATION_SI:
528  {
529  if(m_MetaImage.AnatomicalOrientation(2) == MET_ORIENTATION_PA)
530  {
531  coordOrient =
533  }
534  else
535  {
536  coordOrient =
538  }
539  break;
540  }
541  }
542  break;
543  }
544  case MET_ORIENTATION_PA:
545  {
546  switch(m_MetaImage.AnatomicalOrientation(1))
547  {
548  case MET_ORIENTATION_UNKNOWN:
549  default:
550  {
551  coordUndefined = true;
552  break;
553  }
554  case MET_ORIENTATION_RL:
555  {
556  if(m_MetaImage.AnatomicalOrientation(2) == MET_ORIENTATION_IS)
557  {
558  coordOrient =
560  }
561  else
562  {
563  coordOrient =
565  }
566  break;
567  }
568  case MET_ORIENTATION_LR:
569  {
570  if(m_MetaImage.AnatomicalOrientation(2) == MET_ORIENTATION_IS)
571  {
572  coordOrient =
574  }
575  else
576  {
577  coordOrient =
579  }
580  break;
581  }
582  case MET_ORIENTATION_IS:
583  {
584  if(m_MetaImage.AnatomicalOrientation(2) == MET_ORIENTATION_RL)
585  {
586  coordOrient =
588  }
589  else
590  {
591  coordOrient =
593  }
594  break;
595  }
596  case MET_ORIENTATION_SI:
597  {
598  if(m_MetaImage.AnatomicalOrientation(2) == MET_ORIENTATION_RL)
599  {
600  coordOrient =
602  }
603  else
604  {
605  coordOrient =
607  }
608  break;
609  }
610  }
611  break;
612  }
613  case MET_ORIENTATION_AP:
614  {
615  switch(m_MetaImage.AnatomicalOrientation(1))
616  {
617  case MET_ORIENTATION_UNKNOWN:
618  default:
619  {
620  coordUndefined = true;
621  break;
622  }
623  case MET_ORIENTATION_RL:
624  {
625  if(m_MetaImage.AnatomicalOrientation(2) == MET_ORIENTATION_IS)
626  {
627  coordOrient =
629  }
630  else
631  {
632  coordOrient =
634  }
635  break;
636  }
637  case MET_ORIENTATION_LR:
638  {
639  if(m_MetaImage.AnatomicalOrientation(2) == MET_ORIENTATION_IS)
640  {
641  coordOrient =
643  }
644  else
645  {
646  coordOrient =
648  }
649  break;
650  }
651  case MET_ORIENTATION_IS:
652  {
653  if(m_MetaImage.AnatomicalOrientation(2) == MET_ORIENTATION_RL)
654  {
655  coordOrient =
657  }
658  else
659  {
660  coordOrient =
662  }
663  break;
664  }
665  case MET_ORIENTATION_SI:
666  {
667  if(m_MetaImage.AnatomicalOrientation(2) == MET_ORIENTATION_RL)
668  {
669  coordOrient =
671  }
672  else
673  {
674  coordOrient =
676  }
677  break;
678  }
679  }
680  break;
681  }
682  case MET_ORIENTATION_IS:
683  {
684  switch(m_MetaImage.AnatomicalOrientation(1))
685  {
686  case MET_ORIENTATION_UNKNOWN:
687  default:
688  {
689  coordUndefined = true;
690  break;
691  }
692  case MET_ORIENTATION_RL:
693  {
694  if(m_MetaImage.AnatomicalOrientation(2) == MET_ORIENTATION_PA)
695  {
696  coordOrient =
698  }
699  else
700  {
701  coordOrient =
703  }
704  break;
705  }
706  case MET_ORIENTATION_LR:
707  {
708  if(m_MetaImage.AnatomicalOrientation(2) == MET_ORIENTATION_PA)
709  {
710  coordOrient =
712  }
713  else
714  {
715  coordOrient =
717  }
718  break;
719  }
720  case MET_ORIENTATION_PA:
721  {
722  if(m_MetaImage.AnatomicalOrientation(2) == MET_ORIENTATION_RL)
723  {
724  coordOrient =
726  }
727  else
728  {
729  coordOrient =
731  }
732  break;
733  }
734  case MET_ORIENTATION_AP:
735  {
736  if(m_MetaImage.AnatomicalOrientation(2) == MET_ORIENTATION_RL)
737  {
738  coordOrient =
740  }
741  else
742  {
743  coordOrient =
745  }
746  break;
747  }
748  }
749  break;
750  }
751  case MET_ORIENTATION_SI:
752  {
753  switch(m_MetaImage.AnatomicalOrientation(1))
754  {
755  case MET_ORIENTATION_UNKNOWN:
756  default:
757  {
758  coordUndefined = true;
759  break;
760  }
761  case MET_ORIENTATION_RL:
762  {
763  if(m_MetaImage.AnatomicalOrientation(2) == MET_ORIENTATION_PA)
764  {
765  coordOrient =
767  }
768  else
769  {
770  coordOrient =
772  }
773  break;
774  }
775  case MET_ORIENTATION_LR:
776  {
777  if(m_MetaImage.AnatomicalOrientation(2) == MET_ORIENTATION_PA)
778  {
779  coordOrient =
781  }
782  else
783  {
784  coordOrient =
786  }
787  break;
788  }
789  case MET_ORIENTATION_PA:
790  {
791  if(m_MetaImage.AnatomicalOrientation(2) == MET_ORIENTATION_RL)
792  {
793  coordOrient =
795  }
796  else
797  {
798  coordOrient =
800  }
801  break;
802  }
803  case MET_ORIENTATION_AP:
804  {
805  if(m_MetaImage.AnatomicalOrientation(2) == MET_ORIENTATION_RL)
806  {
807  coordOrient =
809  }
810  else
811  {
812  coordOrient =
814  }
815  break;
816  }
817  }
818  break;
819  }
820  }
821 #if defined(ITKIO_DEPRECATED_METADATA_ORIENTATION)
822  if(!coordUndefined)
823  {
824  EncapsulateMetaData<SpatialOrientation::ValidCoordinateOrientationFlags>(
825  thisMetaDict, ITK_CoordinateOrientation, coordOrient);
826  }
827 #endif
828  }
829 
830  //
831  // Read direction cosines
832  //
833  const double *transformMatrix = m_MetaImage.TransformMatrix();
834  vnl_vector< double > directionAxis( this->GetNumberOfDimensions() );
835  for( unsigned int ii=0; ii < this->GetNumberOfDimensions(); ii++)
836  {
837  for( unsigned int jj=0; jj < this->GetNumberOfDimensions(); jj++)
838  {
839  directionAxis[jj] = transformMatrix[ii*this->GetNumberOfDimensions() + jj];
840  }
841  this->SetDirection( ii, directionAxis );
842  }
843 
844 
845  //
846  // Read some metadata
847  //
848  MetaDataDictionary & metaDict = this->GetMetaDataDictionary();
849 
850  // Look at default metaio fields
851  if ( m_MetaImage.DistanceUnits() != MET_DISTANCE_UNITS_UNKNOWN )
852  {
853  EncapsulateMetaData<std::string>(
854  metaDict, ITK_VoxelUnits, std::string(m_MetaImage.DistanceUnitsName()) );
855  }
856 
857  if ( strlen( m_MetaImage.AcquisitionDate() ) > 0 )
858  {
859  EncapsulateMetaData<std::string>(
860  metaDict, ITK_ExperimentDate, std::string(m_MetaImage.AcquisitionDate()) );
861  }
862 }
863 
864 
865 void MetaImageIO::Read(void* buffer)
866 {
867  const unsigned int nDims = this->GetNumberOfDimensions();
868 
869  // this will check to see if we are actually streaming
870  // we initialize with the dimensions of the file, since if
871  // largestRegion and ioRegion don't match, we'll use the streaming
872  // path since the comparison will fail
873  ImageIORegion largestRegion(nDims);
874  for(unsigned int i=0; i<nDims; i++)
875  {
876  largestRegion.SetIndex(i, 0);
877  largestRegion.SetSize(i, this->GetDimensions(i));
878  }
879 
880 
881  if(largestRegion != m_IORegion)
882  {
883  int* indexMin = new int[nDims];
884  int* indexMax = new int[nDims];
885  for(unsigned int i=0;i<nDims;i++)
886  {
887  if ( i < m_IORegion.GetImageDimension() )
888  {
889  indexMin[i] = m_IORegion.GetIndex()[i];
890  indexMax[i] = indexMin[i] + m_IORegion.GetSize()[i] - 1;
891  }
892  else
893  {
894  indexMin[i] = 0;
895  // this is zero since this is a (size - 1)
896  indexMax[i] = 0;
897  }
898  }
899 
900  if (!m_MetaImage.ReadROI(indexMin, indexMax,
901  m_FileName.c_str(), true, buffer,
903  {
904  delete [] indexMin;
905  delete [] indexMax;
906  itkExceptionMacro("File cannot be read: "
907  << this->GetFileName() << " for reading."
908  << std::endl
909  << "Reason: "
910  << itksys::SystemTools::GetLastSystemError());
911  }
912 
913  delete [] indexMin;
914  delete [] indexMax;
915 
916 
917  m_MetaImage.ElementByteOrderFix( m_IORegion.GetNumberOfPixels() );
918 
919  }
920  else
921  {
922  if(!m_MetaImage.Read(m_FileName.c_str(), true, buffer))
923  {
924  itkExceptionMacro("File cannot be read: "
925  << this->GetFileName() << " for reading."
926  << std::endl
927  << "Reason: "
928  << itksys::SystemTools::GetLastSystemError());
929  }
930 
931  // since we are not streaming m_IORegion may not be set, so
932  m_MetaImage.ElementByteOrderFix( this->GetImageSizeInPixels() );
933  }
934 
935 }
936 
938 {
939  return & m_MetaImage;
940 }
941 
942 
943 bool MetaImageIO::CanWriteFile( const char * name )
944 {
945  std::string filename = name;
946  if( filename == "" )
947  {
948  return false;
949  }
950 
951  std::string::size_type mhaPos = filename.rfind(".mha");
952  if ((mhaPos != std::string::npos)
953  && (mhaPos == filename.length() - 4))
954  {
955  return true;
956  }
957 
958  std::string::size_type mhdPos = filename.rfind(".mhd");
959  if ((mhdPos != std::string::npos)
960  && (mhdPos == filename.length() - 4))
961  {
962  return true;
963  }
964 
965  return false;
966 }
967 
968 
969 void
972 {
973  MetaDataDictionary & metaDict = this->GetMetaDataDictionary();
974  std::string metaDataStr;
975 
976  // Look at default metaio fields
977  if ( ExposeMetaData<std::string>( metaDict, ITK_VoxelUnits, metaDataStr ) )
978  {
979  // Handle analyze style unit string
980  if ( metaDataStr == "um. " )
981  {
982  m_MetaImage.DistanceUnits( MET_DISTANCE_UNITS_UM );
983  }
984  else if ( metaDataStr == "mm. " )
985  {
986  m_MetaImage.DistanceUnits( MET_DISTANCE_UNITS_MM );
987  }
988  else if ( metaDataStr == "cm. " )
989  {
990  m_MetaImage.DistanceUnits( MET_DISTANCE_UNITS_MM );
991  }
992  else
993  {
994  m_MetaImage.DistanceUnits( metaDataStr.c_str() );
995  }
996  }
997 
998  if ( ExposeMetaData<std::string>( metaDict, ITK_ExperimentDate, metaDataStr ) )
999  {
1000  m_MetaImage.AcquisitionDate( metaDataStr.c_str() );
1001  }
1002 }
1003 
1004 
1008 void
1010 ::Write( const void* buffer)
1011 {
1012  unsigned int nDims = this->GetNumberOfDimensions();
1013 
1014  bool binaryData = true;
1015  if(this->GetFileType() == ASCII)
1016  {
1017  binaryData = false;
1018  }
1019 
1020  int nChannels = this->GetNumberOfComponents();
1021 
1022  MET_ValueEnumType eType = MET_OTHER;
1023  switch(m_ComponentType)
1024  {
1025  default:
1026  case UNKNOWNCOMPONENTTYPE:
1027  eType = MET_OTHER;
1028  break;
1029  case CHAR:
1030  eType = MET_CHAR;
1031  break;
1032  case UCHAR:
1033  eType = MET_UCHAR;
1034  break;
1035  case SHORT:
1036  eType = MET_SHORT;
1037  break;
1038  case USHORT:
1039  eType = MET_USHORT;
1040  break;
1041  case LONG:
1042  if(sizeof(long) == MET_ValueTypeSize[MET_LONG])
1043  {
1044  eType = MET_LONG;
1045  }
1046  else if(sizeof(long) == MET_ValueTypeSize[MET_INT])
1047  {
1048  eType = MET_INT;
1049  }
1050  else if(sizeof(long) == MET_ValueTypeSize[MET_LONG_LONG])
1051  {
1052  eType = MET_LONG_LONG;
1053  }
1054  break;
1055  case ULONG:
1056  if(sizeof(long) == MET_ValueTypeSize[MET_LONG])
1057  {
1058  eType = MET_ULONG;
1059  }
1060  else if(sizeof(long) == MET_ValueTypeSize[MET_INT])
1061  {
1062  eType = MET_UINT;
1063  }
1064  else if(sizeof(long) == MET_ValueTypeSize[MET_LONG_LONG])
1065  {
1066  eType = MET_ULONG_LONG;
1067  }
1068  break;
1069  case INT:
1070  eType = MET_INT;
1071  if(sizeof(int) == MET_ValueTypeSize[MET_INT])
1072  {
1073  eType = MET_INT;
1074  }
1075  else if(sizeof(int) == MET_ValueTypeSize[MET_LONG])
1076  {
1077  eType = MET_LONG;
1078  }
1079  break;
1080  case UINT:
1081  if(sizeof(int) == MET_ValueTypeSize[MET_INT])
1082  {
1083  eType = MET_UINT;
1084  }
1085  else if(sizeof(int) == MET_ValueTypeSize[MET_LONG])
1086  {
1087  eType = MET_ULONG;
1088  }
1089  break;
1090  case FLOAT:
1091  if(sizeof(float) == MET_ValueTypeSize[MET_FLOAT])
1092  {
1093  eType = MET_FLOAT;
1094  }
1095  else if(sizeof(float) == MET_ValueTypeSize[MET_DOUBLE])
1096  {
1097  eType = MET_DOUBLE;
1098  }
1099  break;
1100  case DOUBLE:
1101  if(sizeof(double) == MET_ValueTypeSize[MET_DOUBLE])
1102  {
1103  eType = MET_DOUBLE;
1104  }
1105  else if(sizeof(double) == MET_ValueTypeSize[MET_FLOAT])
1106  {
1107  eType = MET_FLOAT;
1108  }
1109  break;
1110  }
1111 
1112  unsigned int i;
1113  int * dSize = new int[nDims];
1114  float * eSpacing = new float[nDims];
1115  double * eOrigin = new double[nDims];
1116  for(i=0; i<nDims; i++)
1117  {
1118  dSize[i] = this->GetDimensions(i);
1119  eSpacing[i] = static_cast<float>(this->GetSpacing(i));
1120  eOrigin[i] = this->GetOrigin(i);
1121  }
1122 
1123  m_MetaImage.InitializeEssential(nDims, dSize, eSpacing, eType, nChannels,
1124  const_cast<void *>(buffer));
1125  m_MetaImage.Position(eOrigin);
1126  m_MetaImage.BinaryData(binaryData);
1127 
1128  //Write the image Information
1129  this->WriteImageInformation();
1130 
1131  if(nDims == 3)
1132  {
1133 #if defined(ITKIO_DEPRECATED_METADATA_ORIENTATION)
1134  MetaDataDictionary & thisMetaDict = this->GetMetaDataDictionary();
1135 #endif
1138 #if defined(ITKIO_DEPRECATED_METADATA_ORIENTATION)
1139  if( !ExposeMetaData
1141  (thisMetaDict, ITK_CoordinateOrientation, coordOrient) )
1142  {
1143 #endif
1144  std::vector<double> dirx, diry, dirz;
1146  dirx = this->GetDirection(0);
1147  diry = this->GetDirection(1);
1148  dirz = this->GetDirection(2);
1149  for(unsigned ii = 0; ii < 3; ii++)
1150  {
1151  dir[ii][0] = dirx[ii];
1152  dir[ii][1] = diry[ii];
1153  dir[ii][2] = dirz[ii];
1154  }
1155  coordOrient = SpatialOrientationAdapter().FromDirectionCosines(dir);
1156 #if defined(ITKIO_DEPRECATED_METADATA_ORIENTATION)
1157  }
1158 #endif
1159 
1160  switch(coordOrient)
1161  {
1162  default:
1171  {
1172  m_MetaImage.AnatomicalOrientation(0, MET_ORIENTATION_RL);
1173  break;
1174  }
1183  {
1184  m_MetaImage.AnatomicalOrientation(0, MET_ORIENTATION_LR);
1185  break;
1186  }
1195  {
1196  m_MetaImage.AnatomicalOrientation(0, MET_ORIENTATION_AP);
1197  break;
1198  }
1207  {
1208  m_MetaImage.AnatomicalOrientation(0, MET_ORIENTATION_PA);
1209  break;
1210  }
1219  {
1220  m_MetaImage.AnatomicalOrientation(0, MET_ORIENTATION_IS);
1221  break;
1222  }
1231  {
1232  m_MetaImage.AnatomicalOrientation(0, MET_ORIENTATION_SI);
1233  break;
1234  }
1235  }
1236  switch(coordOrient)
1237  {
1246  {
1247  m_MetaImage.AnatomicalOrientation(1, MET_ORIENTATION_RL);
1248  break;
1249  }
1258  {
1259  m_MetaImage.AnatomicalOrientation(1, MET_ORIENTATION_LR);
1260  break;
1261  }
1270  {
1271  m_MetaImage.AnatomicalOrientation(1, MET_ORIENTATION_AP);
1272  break;
1273  }
1274  default:
1283  {
1284  m_MetaImage.AnatomicalOrientation(1, MET_ORIENTATION_PA);
1285  break;
1286  }
1295  {
1296  m_MetaImage.AnatomicalOrientation(1, MET_ORIENTATION_IS);
1297  break;
1298  }
1307  {
1308  m_MetaImage.AnatomicalOrientation(1, MET_ORIENTATION_SI);
1309  break;
1310  }
1311  }
1312  switch(coordOrient)
1313  {
1322  {
1323  m_MetaImage.AnatomicalOrientation(2, MET_ORIENTATION_RL);
1324  break;
1325  }
1334  {
1335  m_MetaImage.AnatomicalOrientation(2, MET_ORIENTATION_LR);
1336  break;
1337  }
1346  {
1347  m_MetaImage.AnatomicalOrientation(2, MET_ORIENTATION_AP);
1348  break;
1349  }
1358  {
1359  m_MetaImage.AnatomicalOrientation(2, MET_ORIENTATION_PA);
1360  break;
1361  }
1362  default:
1371  {
1372  m_MetaImage.AnatomicalOrientation(2, MET_ORIENTATION_IS);
1373  break;
1374  }
1383  {
1384  m_MetaImage.AnatomicalOrientation(2, MET_ORIENTATION_SI);
1385  break;
1386  }
1387  }
1388 
1389  }
1390 
1391  // Propagage direction cosine information .
1392  double *transformMatrix =
1393  static_cast< double *>(malloc(this->GetNumberOfDimensions() *
1394  this->GetNumberOfDimensions() * sizeof(double)));
1395  for( unsigned int ii=0; ii < this->GetNumberOfDimensions(); ii++ )
1396  {
1397  for( unsigned int jj=0; jj < this->GetNumberOfDimensions(); jj++ )
1398  {
1399  transformMatrix[ ii*this->GetNumberOfDimensions() + jj ] =
1400  this->GetDirection( ii )[ jj ];
1401  }
1402  }
1403  m_MetaImage.TransformMatrix( transformMatrix );
1404  free( transformMatrix );
1405 
1406  m_MetaImage.CompressedData( m_UseCompression );
1407 
1408  // this is a check to see if we are actually streaming
1409  // we initialize with m_IORegion to match dimensions
1410  ImageIORegion largestRegion(m_IORegion);
1411  for(i=0; i<nDims; i++)
1412  {
1413  largestRegion.SetIndex(i, 0);
1414  largestRegion.SetSize(i, this->GetDimensions(i));
1415  }
1416 
1417  if( m_UseCompression && (largestRegion != m_IORegion) )
1418  {
1419  std::cout << "Compression in use: cannot stream the file writing" << std::endl;
1420  }
1421  else if( largestRegion != m_IORegion )
1422  {
1423  int* indexMin = new int[nDims];
1424  int* indexMax = new int[nDims];
1425  for( unsigned int k=0; k<nDims; k++ )
1426  {
1427  // the dimensions of m_IORegion should match out requested
1428  // dimensions, but ImageIORegion will throw an
1429  // exception if out of bounds
1430  indexMin[k] = m_IORegion.GetIndex()[k];
1431  indexMax[k] = m_IORegion.GetIndex()[k] + m_IORegion.GetSize()[k] - 1;
1432  }
1433 
1434  if (!m_MetaImage.WriteROI( indexMin, indexMax, m_FileName.c_str() ))
1435  {
1436  delete [] indexMin;
1437  delete [] indexMax;
1438  itkExceptionMacro("File ROI cannot be written: "
1439  << this->GetFileName()
1440  << std::endl
1441  << "Reason: "
1442  << itksys::SystemTools::GetLastSystemError());
1443  }
1444 
1445  delete [] indexMin;
1446  delete [] indexMax;
1447  }
1448  else
1449  {
1450  if ( !m_MetaImage.Write( m_FileName.c_str() ) )
1451  {
1452  itkExceptionMacro("File cannot be written: "
1453  << this->GetFileName()
1454  << std::endl
1455  << "Reason: "
1456  << itksys::SystemTools::GetLastSystemError());
1457  }
1458  }
1459 
1460  // we leak when exceptions are thrown :(
1461  delete []dSize;
1462  delete []eSpacing;
1463  delete []eOrigin;
1464 }
1465 
1473 {
1474  //
1475  // The default implementations determines that the streamable region is
1476  // equal to the largest possible region of the image.
1477  //
1478  ImageIORegion streamableRegion(this->m_NumberOfDimensions);
1479  if(!m_UseStreamedReading)
1480  {
1481  for( unsigned int i=0; i < this->m_NumberOfDimensions; i++ )
1482  {
1483  streamableRegion.SetSize( i, this->m_Dimensions[i] );
1484  streamableRegion.SetIndex( i, 0 );
1485  }
1486  }
1487  else
1488  {
1489  streamableRegion = requestedRegion;
1490  }
1491 
1492  return streamableRegion;
1493 }
1494 
1495 unsigned int
1496 MetaImageIO::GetActualNumberOfSplitsForWriting(unsigned int numberOfRequestedSplits,
1497  const ImageIORegion &pasteRegion,
1498  const ImageIORegion &largestPossibleRegion)
1499 {
1500  if (this->GetUseCompression())
1501  {
1502  // we can not stream or paste with compression
1503  if (pasteRegion != largestPossibleRegion)
1504  {
1505  itkExceptionMacro("Pasting and compression is not supported! Can't write:" << this->GetFileName());
1506  }
1507  else if (numberOfRequestedSplits != 1)
1508  {
1509  itkDebugMacro("Requested streaming and compression");
1510  itkDebugMacro("Meta IO is not streaming now!");
1511  }
1512  return 1;
1513  }
1514 
1515  if (!itksys::SystemTools::FileExists( m_FileName.c_str() ))
1516  {
1517  // file doesn't exits so we don't have potential problems
1518  }
1519  else if (pasteRegion != largestPossibleRegion)
1520  {
1521  // we are going to be pasting (may be streaming too)
1522 
1523  // need to check to see if the file is compatible
1524  std::string errorMessage;
1525  Pointer headerImageIOReader = Self::New();
1526 
1527  try
1528  {
1529  headerImageIOReader->SetFileName(m_FileName.c_str());
1530  headerImageIOReader->ReadImageInformation();
1531  }
1532  catch (...)
1533  {
1534  errorMessage = "Unable to read information from file: " + m_FileName;
1535  }
1536 
1537 
1538 
1539  // we now need to check that the following match:
1540  // 1)file is not compressed
1541  // 2)pixel type
1542  // 3)dimensions
1543  // 4)size/origin/spacing
1544  // 5)direction cosines
1545  //
1546 
1547  if (errorMessage.size())
1548  {
1549  // 0) Can't read file
1550  }
1551  // 1)file is not compressed
1552  else if (headerImageIOReader->m_MetaImage.CompressedData())
1553  {
1554  errorMessage = "File is compressed: " + m_FileName;
1555  }
1556  // 2)pixel type
1557  // this->GetPixelType() is not verified becasue the metaio file format
1558  // stores all multi-component types as arrays, so it does not
1559  // distinguish between pixel types. Also as long as the compoent
1560  // and number of compoents match we should be able to paste, that
1561  // is the numbers should be the same it is just the interpretation
1562  // that is not matching
1563  else if ( headerImageIOReader->GetNumberOfComponents() != this->GetNumberOfComponents() ||
1564  headerImageIOReader->GetComponentType() != this->GetComponentType() )
1565  {
1566  errorMessage = "Component type does not match in file: " + m_FileName;
1567  }
1568  // 3)dimensions/size
1569  else if (headerImageIOReader->GetNumberOfDimensions() != this->GetNumberOfDimensions())
1570  {
1571  errorMessage = "Dimensions does not match in file: " + m_FileName;
1572  }
1573  else
1574  {
1575  for (unsigned int i = 0; i < this->GetNumberOfDimensions(); ++i)
1576  {
1577  // 4)size/origin/spacing
1578  if (headerImageIOReader->GetDimensions(i) != this->GetDimensions(i) ||
1579  headerImageIOReader->GetSpacing(i) != this->GetSpacing(i) ||
1580  headerImageIOReader->GetOrigin(i) != this->GetOrigin(i))
1581  {
1582  errorMessage = "Size, spacing or origin does not match in file: " + m_FileName;
1583  break;
1584  }
1585  // 5)direction cosines
1586  if (headerImageIOReader->GetDirection(i) != this->GetDirection(i))
1587  {
1588  errorMessage = "Direction cosines does not match in file: " + m_FileName;
1589  break;
1590  }
1591  }
1592  }
1593 
1594  if (errorMessage.size())
1595  {
1596  itkExceptionMacro("Unable to paste because pasting file exists and is different. " << errorMessage);
1597  }
1598  else if ( headerImageIOReader->GetPixelType() != this->GetPixelType() )
1599  {
1600  // since there is currently poor support for pixel types in
1601  // MetaIO we will just warn when it does not match
1602  itkWarningMacro("Pixel types does not match file, but component type and number of components do.");
1603  }
1604  }
1605  else if (numberOfRequestedSplits != 1)
1606  {
1607  // we are going be streaming
1608 
1609  // need to remove the file incase the file doesn't match our
1610  // current header/meta data information
1611  if (!itksys::SystemTools::RemoveFile(m_FileName.c_str()))
1612  itkExceptionMacro("Unable to remove file for streaming: " << m_FileName);
1613  }
1614 
1615  return GetActualNumberOfSplitsForWritingCanStreamWrite(numberOfRequestedSplits, pasteRegion);
1616 }
1617 
1618 
1621  unsigned int numberOfActualSplits,
1622  const ImageIORegion &pasteRegion,
1623  const ImageIORegion &itkNotUsed(largestPossibleRegion) )
1624 {
1625 
1626  return GetSplitRegionForWritingCanStreamWrite(ithPiece, numberOfActualSplits, pasteRegion);
1627 }
1628 
1629 } // end namespace itk

Generated at Sat Feb 2 2013 23:52:45 for Orfeo Toolbox with doxygen 1.8.1.1