SMILX  1.01
milxFile.h
1 /*=========================================================================
2  The Software is copyright (c) Commonwealth Scientific and Industrial Research Organisation (CSIRO)
3  ABN 41 687 119 230.
4  All rights reserved.
5 
6  Licensed under the CSIRO BSD 3-Clause License
7  You may not use this file except in compliance with the License.
8  You may obtain a copy of the License in the file LICENSE.md or at
9 
10  https://stash.csiro.au/projects/SMILI/repos/smili/browse/license.txt
11 
12  Unless required by applicable law or agreed to in writing, software
13  distributed under the License is distributed on an "AS IS" BASIS,
14  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  See the License for the specific language governing permissions and
16  limitations under the License.
17 =========================================================================*/
18 #ifndef __MILXFILE_H
19 #define __MILXFILE_H
20 
21 //STL
22 #include <utility>
23 #include <string>
24 #include <algorithm>
25 #include <vector>
26 #include <sys/stat.h> //exists check
27 //ITK
28 #ifndef VTK_ONLY
29  #include <itksys/SystemTools.hxx>
30  #include <itkImage.h>
31  #include <itkImageFileReader.h>
32  #include <itkImageSeriesReader.h>
33  #include <itkImageFileWriter.h>
34  #include <itkTransformFileReader.h>
35  #include <itkTransform.h>
36  #include <itkTransformFactoryBase.h>
37  #include <itkGDCMImageIO.h>
38  #include <itkGDCMSeriesFileNames.h>
39  #include <itkOrientImageFilter.h> //for dicom orientation
40  #include <itkExtractImageFilter.h>
41  #if (ITK_VERSION_MAJOR > 3)
42  #include <itkComposeImageFilter.h>
43  #endif
44 #endif
45 //VTK
46 #ifndef ITK_ONLY
47  #include <vtkSmartPointer.h>
48  #include <vtkCommand.h>
49  #include <vtkMatrix4x4.h>
50  #include <vtkImageData.h>
51  #include <vtkImageFlip.h>
52  #include <vtkPolyData.h>
53  #include <vtkPolyDataCollection.h>
54  #include <vtkTransformCollection.h>
55  #include <vtkTable.h>
56  #include <vtkCamera.h>
57  #include <vtkXMLImageDataReader.h>
58  #include <vtkXMLImageDataWriter.h>
59  //MILX
60  #ifndef VTK_ONLY
61  #include "itkImageToVTKImageFilter.h"
62  #include "itkVTKImageToImageFilter.h"
63  #endif
64 #endif
65 //SMILI
66 #include <milxGlobal.h>
67 
68 namespace milx
69 {
70 
91 //template<class Type = float>
93 {
94 public:
99  File() {};
104  virtual ~File() {};
105 
106 public:
107  //Images
108 #ifndef VTK_ONLY
109 
115  static bool CanReadImage(const std::string filename);
130  static bool ReadImageInformation(const std::string filename, std::string &pixeltype, std::string &componentType, size_t &dimensions);
137  static std::vector<std::string> GetSupportedImageFileExtensions();
145  template<class TImage>
146  static bool OpenImage(const std::string filename, typename itk::SmartPointer<TImage> &data);
147 #if (ITK_VERSION_MAJOR > 3)
148 
166  template<class TImage, size_t TDim>
167  static bool OpenAsVectorImage(const std::string filename, typename itk::SmartPointer< itk::VectorImage< typename TImage::InternalPixelType, TDim> > &data);
168 #endif
169 
176  template<class TImage>
177  static bool OpenImages(std::vector<std::string> &filenames, std::vector< typename itk::SmartPointer<TImage> > &images);
185  template<class TImage>
186  static bool SaveImage(const std::string filename, typename itk::SmartPointer<TImage> data, itk::ImageIOBase *io = NULL);
194  template<class TImage>
195  static bool SaveImages(std::vector<std::string> &filenames, const std::vector< typename itk::SmartPointer<TImage> > images);
196 
198 
206  static std::vector<std::string> GetDICOMSeriesUIDs(const std::string directoryPath, bool recursive = false);
215  static std::vector<std::string> GetDICOMSeriesFilenames(const std::string directoryPath, const std::string seriesName, bool recursive = false);
224  template<class TImage>
225  static bool GetDICOMData(const std::string directoryPath, typename itk::SmartPointer<TImage> &data, itk::MetaDataDictionary &dict, std::string &seriesName, std::string &caseID, std::string &echoID, std::string &seriesID, std::string &acqID, std::string &instanceID, bool recursive = false);
232  template<class TImage>
233  static bool GetDICOMMetaData(const std::string directoryPath, itk::MetaDataDictionary &dict, std::string &seriesName, std::string &caseID, std::string &echoID, std::string &seriesID, std::string &acqID, std::string &instanceID, bool recursive = false);
240  template<class TImage>
241  static bool GetDICOMTags(const std::string directoryPath, std::vector< std::pair<std::string, std::string> > &tags, std::string &seriesName, std::string &caseID, std::string &echoID, std::string &seriesID, std::string &acqID, std::string &instanceID, bool recursive = false);
242  template<class TImage>
243  static bool GetDICOMTags(const itk::MetaDataDictionary dictionary, std::vector< std::pair<std::string, std::string> > &tags);
253  template<class TImage>
254  static bool OpenDICOMSeries(const std::string directoryPath, typename itk::SmartPointer<TImage> &data, std::string &seriesName, std::string &caseID, std::string &echoID, std::string &seriesID, std::string &acqID, std::string &instanceID, bool recursive = false);
255  template<class TImage>
256  static bool OpenDICOMSeriesAndTags(const std::string directoryPath, typename itk::SmartPointer<TImage> &data, std::vector< std::pair<std::string, std::string> > &tags, std::string &seriesName, std::string &caseID, std::string &echoID, std::string &seriesID, std::string &acqID, std::string &instanceID, bool recursive = false);
257 #endif
258 
259 #ifndef ITK_ONLY
260  #ifndef VTK_ONLY
261 
268  template<class TImage>
269  static bool OpenImage(const std::string filename, vtkSmartPointer<vtkImageData> &data);
277  template<class TImage>
278  static bool SaveImage(const std::string filename, vtkSmartPointer<vtkImageData> &data);
279  #endif
280 #endif
281 
282 #ifndef VTK_ONLY
283 
288  template<class TImage>
289  inline static itk::SmartPointer<TImage> ReadImageUsingITK(const std::string filename);
295  template<class TImage>
296  inline static bool WriteImageUsingITK(const std::string filename, itk::SmartPointer<TImage> data);
297 #endif
298 
299  //Transforms
300 #ifndef VTK_ONLY
301 
306  template<class TType>
307  static itk::SmartPointer< itk::Transform<TType> > OpenTransform(std::string filename);
308 #endif
309 #ifndef ITK_ONLY
310  #ifndef VTK_ONLY
311 
316  static vtkMatrix4x4* OpenITKTransform(std::string filename);
317 
323  static vtkMatrix4x4* OpenVTKTransform(std::string filename);
324 
330  static void SaveITKTransform(std::string filename, const vtkMatrix4x4 * matrix);
331 
346  static void SaveVTKTransform(std::string filename, const vtkMatrix4x4 * matrix);
347 
348  #endif
349 #endif
350 
351 #ifndef ITK_ONLY
352  //Surfaces/Models
359  static bool OpenModel(const std::string filename, vtkSmartPointer<vtkPolyData> &data);
366  static bool OpenModelCollection(std::vector<std::string> filenames, vtkSmartPointer<vtkPolyDataCollection> &collection);
373  static bool SaveModel(const std::string filename, vtkSmartPointer<vtkPolyData> data, const bool binary = false);
380  static bool SaveModelCollection(std::vector<std::string> filenames, vtkSmartPointer<vtkPolyDataCollection> collection, const bool binary = false);
387  static bool SaveTransform(const std::string filename, vtkSmartPointer<vtkTransform> data, const bool ITK = false);
394  static bool SaveTransformCollection(std::vector<std::string> filenames, vtkSmartPointer<vtkTransformCollection> collection, const bool ITK = false);
395 
396  //CSV files
403  static bool OpenDelimitedText(const std::string filename, vtkSmartPointer<vtkTable> &data, const std::string delimiter = ",");
410  static bool SaveDelimitedText(const std::string filename, const vtkSmartPointer<vtkTable> data, const std::string delimiter = ",");
411 
412  //Camera
413  static bool SaveCamera(const std::string filename, const vtkSmartPointer<vtkCamera> camera);
414  static bool LoadCamera(const std::string filename, vtkSmartPointer<vtkCamera> &camera);
415 #endif
416 
421  static inline std::string StringToLowerCase(std::string filename)
422  {
423  std::transform(filename.begin(), filename.end(), filename.begin(), ::tolower);
424  return filename;
425  }
432  static inline std::string StripFileExtension(const std::string &filename)
433  {
434  return filename.substr(0, filename.find_last_of("."));
435  }
442  static inline std::string ExtractFilename(const std::string &filename, char delimiter = '/')
443  {
444  return filename.substr( filename.find_last_of( delimiter ) + 1 );
445  }
452  static inline std::string ExtractPath(const std::string &filename, char delimiter = '/')
453  {
454  return filename.substr( 0, filename.find_last_of( delimiter ) + 1 );
455  }
462  static inline std::string GetBaseName(const std::string &filename)
463  {
464  return StripFileExtension( ExtractFilename(filename) );
465  }
472  static inline std::string GetFileExtension(const std::string &filename)
473  {
474  if (filename.find_last_of(".") != std::string::npos)
475  return StringToLowerCase( filename.substr(filename.find_last_of(".")+1) );
476  return "";
477  }
482  static bool Exists(const std::string filename)
483  {
484  struct stat buffer;
485  if (stat(filename.c_str(), &buffer) != -1)
486  return true;
487  return false;
488  }
489 
490 #ifndef VTK_ONLY
491 
495  static inline void MakeDirectory(std::string name)
496  {
497  itksys::SystemTools::MakeDirectory( itksys::SystemTools::GetRealPath(name) );
498  }
499 #endif
500 
501 protected:
502 
503 private:
504 
505 };
506 
507 #ifndef VTK_ONLY
508 template<class TImage>
509 bool File::OpenImage(const std::string filename, typename itk::SmartPointer<TImage> &data)
510 {
511  if(!Exists(filename))
512  {
513  std::cerr << "File " << filename << " doesn't exist. Ignoring." << std::endl;
514  return false;
515  }
516 
517  data = ReadImageUsingITK<TImage>(filename);
518 
519  if(!data)
520  return false;
521 
522  return true;
523 }
524 
525 #if (ITK_VERSION_MAJOR > 3)
526  template<class TImage, size_t TDim>
527  //template<class TPixel, class TDim>
528  bool File::OpenAsVectorImage(const std::string filename, typename itk::SmartPointer< itk::VectorImage< typename TImage::InternalPixelType, TDim> > &data)
529  {
530  if(!Exists(filename))
531  {
532  std::cerr << "File " << filename << " doesn't exist. Ignoring." << std::endl;
533  return false;
534  }
535 
537  typename TImage::Pointer image = ReadImageUsingITK<TImage>(filename);
538 
539  if(!image)
540  return false;
541 
542  typedef itk::Image< typename TImage::InternalPixelType, TDim > TImageSlice;
543  typedef itk::ComposeImageFilter<TImageSlice> ImageToVectorImageFilterType;
544  typename ImageToVectorImageFilterType::Pointer imageToVectorImageFilter = ImageToVectorImageFilterType::New();
545  typename TImage::SizeType size = image->GetLargestPossibleRegion().GetSize();
546  std::cout << "Image Size: " << size[0] << "x" << size[1] << "x" << size[2] << "x" << size[3] << std::endl;
547  for(size_t j = 0; j < size[3]; j ++)
548  {
549  typename TImage::IndexType desiredStart;
550  desiredStart.Fill(0);
551  desiredStart[3] = j;
552 
553  typename TImage::SizeType desiredSize;
554  desiredSize[0] = size[0];
555  desiredSize[1] = size[1];
556  desiredSize[2] = size[2];
557  desiredSize[3] = 0; //Needs to be zero to create slice
558 
559  typename TImage::RegionType desiredRegion(desiredStart, desiredSize);
560 
562  typedef itk::ExtractImageFilter<TImage, TImageSlice> FilterType;
563  typename FilterType::Pointer filter = FilterType::New();
564  filter->SetExtractionRegion(desiredRegion);
565  filter->SetInput(image);
566  #if ITK_VERSION_MAJOR >= 4
567  filter->SetDirectionCollapseToIdentity(); // This is required.
568  #endif
569  filter->Update();
570 
572  imageToVectorImageFilter->SetInput(j, filter->GetOutput());
573  }
574  imageToVectorImageFilter->Update();
575 
576  data = imageToVectorImageFilter->GetOutput();
577 
578  if(!data)
579  return false;
580 
581  return true;
582  }
583 #endif
584 
585 template<class TImage>
586 bool File::OpenImages(std::vector<std::string> &filenames, std::vector< typename itk::SmartPointer<TImage> > &images)
587 {
588  if(filenames.empty())
589  return false;
590 
591  std::vector<std::string> readFilenames;
592  for(size_t j = 0; j < filenames.size(); j ++)
593  {
594  typename itk::SmartPointer<TImage> image;
595  bool success = OpenImage(filenames[j], image);
596  if(success && image)
597  {
598  readFilenames.push_back(filenames[j]);
599  images.push_back(image);
600  }
601  }
602 
603  if(images.empty())
604  return false;
605  filenames = readFilenames;
606 
607  return true;
608 }
609 
610 template<class TImage>
611 bool File::SaveImage(const std::string filename, typename itk::SmartPointer<TImage> data, itk::ImageIOBase *io)
612 {
613  typedef itk::ImageFileWriter<TImage> ImageWriter;
614 
615  typename ImageWriter::Pointer writer = ImageWriter::New();
616  writer->UseInputMetaDataDictionaryOn();
617  writer->SetInput(data);
618  writer->SetFileName(filename.c_str());
619  if(io)
620  writer->SetImageIO(io);
621  writer->AddObserver(itk::ProgressEvent(), ProgressUpdates);
622  try
623  {
624  writer->Update();
625  }
626  catch( itk::ExceptionObject & err )
627  {
628  std::cerr << "File Exception caught while writing!" << std::endl;
629  std::cerr << err << std::endl;
630  return false;
631  }
632 
633  return true;
634 }
635 
636 template<class TImage>
637 bool File::SaveImages(std::vector<std::string> &filenames, const std::vector< typename itk::SmartPointer<TImage> > images)
638 {
639  if(filenames.empty())
640  return false;
641 
642  std::vector<std::string> readFilenames;
643  for(size_t j = 0; j < filenames.size(); j ++)
644  {
645  bool success = SaveImage<TImage>(filenames[j], images[j]);
646  if(success && images[j])
647  readFilenames.push_back(filenames[j]);
648  }
649 
650  if(images.empty())
651  return false;
652  filenames = readFilenames;
653 
654  return true;
655 }
656 
657 //DICOM related
658 template<class TImage>
659 bool File::GetDICOMData(const std::string directoryPath, typename itk::SmartPointer<TImage> &data, itk::MetaDataDictionary &dict, std::string &seriesName, std::string &caseID, std::string &echoID, std::string &seriesID, std::string &acqID, std::string &instanceID, bool recursive)
660 {
661  typedef itk::ImageSeriesReader<TImage> ReaderType;
662  typedef itk::GDCMImageIO ImageIOType;
663 
664  const std::vector<std::string> filenames = GetDICOMSeriesFilenames(directoryPath, seriesName, recursive);
665 
666  ImageIOType::Pointer gdcmIO = ImageIOType::New();
667  typename ReaderType::Pointer reader = ReaderType::New();
668  reader->SetImageIO(gdcmIO);
669  reader->SetFileNames(filenames);
670  reader->AddObserver(itk::ProgressEvent(), ProgressUpdates);
671  try
672  {
673  reader->Update();
674  }
675  catch (itk::ExceptionObject &excp)
676  {
677  std::cerr << "File Exception caught while reading series!" << std::endl;
678  std::cerr << excp << std::endl;
679  return false;
680  }
681 
683  typedef itk::MetaDataObject< std::string > MetaDataStringType;
684  std::string series_type_id("0008|103e");
685  itk::MetaDataDictionary & dic = gdcmIO->GetMetaDataDictionary();
686  itk::MetaDataDictionary::ConstIterator series_type_itr = dic.Find(series_type_id);
687  std::string caseId = "0010|0020";
688  itk::MetaDataDictionary::ConstIterator case_itr = dic.Find(caseId);
689  std::string echoNumber = "0018|0086";
690  itk::MetaDataDictionary::ConstIterator echoNumber_itr = dic.Find(echoNumber);
691  std::string seriesNumber = "0020|0011";
692  itk::MetaDataDictionary::ConstIterator seriesNumber_itr = dic.Find(seriesNumber);
693  std::string acqNumber = "0020|0012";
694  itk::MetaDataDictionary::ConstIterator acqNumber_itr = dic.Find(acqNumber);
695  std::string instanceNumber = "0020|0013";
696  itk::MetaDataDictionary::ConstIterator instanceNumber_itr = dic.Find(instanceNumber);
697  std::string itemNumber = "0020|0019";
698  itk::MetaDataDictionary::ConstIterator itemNumber_itr = dic.Find(itemNumber);
699 
700  MetaDataStringType::ConstPointer entryValue = dynamic_cast<const MetaDataStringType *>(series_type_itr->second.GetPointer());
701  if (entryValue)
702  {
703  seriesName = entryValue->GetMetaDataObjectValue();
704  std::cout << "Series: " << entryValue->GetMetaDataObjectValue() << std::endl;
705  }
706  MetaDataStringType::ConstPointer entryValue2 = dynamic_cast<const MetaDataStringType *>(case_itr->second.GetPointer());
707  if (entryValue2)
708  {
709  caseID = entryValue2->GetMetaDataObjectValue();
710  std::cout << "Case: " << entryValue2->GetMetaDataObjectValue() << std::endl;
711  }
712  MetaDataStringType::ConstPointer entryValue3;
713  if (dic.HasKey(echoNumber))
714  {
715  entryValue3 = dynamic_cast<const MetaDataStringType *>(echoNumber_itr->second.GetPointer());
716  echoID = entryValue3->GetMetaDataObjectValue();
717  std::cout << "Echo Number: " << entryValue3->GetMetaDataObjectValue() << std::endl;
718  }
719  MetaDataStringType::ConstPointer entryValue4;
720  if (dic.HasKey(seriesNumber))
721  {
722  entryValue4 = dynamic_cast<const MetaDataStringType *>(seriesNumber_itr->second.GetPointer());
723  seriesID = entryValue4->GetMetaDataObjectValue();
724  std::cout << "Series Number: " << entryValue4->GetMetaDataObjectValue() << std::endl;
725  }
726  MetaDataStringType::ConstPointer entryValue5;
727  if (dic.HasKey(acqNumber))
728  {
729  entryValue5 = dynamic_cast<const MetaDataStringType *>(acqNumber_itr->second.GetPointer());
730  acqID = entryValue5->GetMetaDataObjectValue();
731  std::cout << "Acquisition Number: " << entryValue5->GetMetaDataObjectValue() << std::endl;
732  }
733  MetaDataStringType::ConstPointer entryValue6;
734  if (dic.HasKey(instanceNumber))
735  {
736  entryValue6 = dynamic_cast<const MetaDataStringType *>(instanceNumber_itr->second.GetPointer());
737  instanceID = entryValue6->GetMetaDataObjectValue();
738  std::cout << "Instance Number: " << entryValue6->GetMetaDataObjectValue() << std::endl;
739  }
740  MetaDataStringType::ConstPointer entryValue7;
741  if (dic.HasKey(itemNumber))
742  {
743  entryValue7 = dynamic_cast<const MetaDataStringType *>(itemNumber_itr->second.GetPointer());
744  std::cout << "Item Number: " << entryValue7->GetMetaDataObjectValue() << std::endl;
745  }
746 
748  dict = gdcmIO->GetMetaDataDictionary();
750  data = reader->GetOutput();
751 
752  return true;
753 }
754 
755 template<class TImage>
756 bool File::GetDICOMMetaData(const std::string directoryPath, itk::MetaDataDictionary &dict, std::string &seriesName, std::string &caseID, std::string &echoID, std::string &seriesID, std::string &acqID, std::string &instanceID, bool recursive)
757 {
758  typename itk::SmartPointer<TImage> data;
759 
760  if (!GetDICOMData<TImage>(directoryPath, data, dict, seriesName, caseID, echoID, seriesID, acqID, instanceID, recursive))
761  return false;
762 
763  return true;
764 }
765 
766 template<class TImage>
767 bool File::GetDICOMTags(const std::string directoryPath, std::vector< std::pair<std::string, std::string> > &tags, std::string &seriesName, std::string &caseID, std::string &echoID, std::string &seriesID, std::string &acqID, std::string &instanceID, bool recursive)
768 {
769  typedef itk::MetaDataObject< std::string > MetaDataStringType;
770  typedef itk::MetaDataDictionary DictionaryType;
771  DictionaryType dictionary;
772  if (!GetDICOMMetaData<TImage>(directoryPath, dictionary, seriesName, caseID, echoID, seriesID, acqID, instanceID, recursive))
773  return false;
774 
775  DictionaryType::ConstIterator itr = dictionary.Begin();
776  DictionaryType::ConstIterator end = dictionary.End();
777 
778  while (itr != end)
779  {
780  itk::MetaDataObjectBase::Pointer entry = itr->second;
781  MetaDataStringType::Pointer entryvalue = dynamic_cast<MetaDataStringType *>(entry.GetPointer());
782  std::string entryTag = itr->first;
783  if (entryvalue) //convert MetaDataObject pair to string pair
784  {
785  std::pair<std::string, std::string> entryPair = std::make_pair(entryTag, entryvalue->GetMetaDataObjectValue());
786  tags.push_back(entryPair);
787  }
788  ++itr;
789  }
790 
791  return true;
792 }
793 
794 template<class TImage>
795 bool File::GetDICOMTags(const itk::MetaDataDictionary dictionary, std::vector< std::pair<std::string, std::string> > &tags)
796 {
797  typedef itk::MetaDataObject< std::string > MetaDataStringType;
798  typedef itk::MetaDataDictionary DictionaryType;
799 
800  DictionaryType::ConstIterator itr = dictionary.Begin();
801  DictionaryType::ConstIterator end = dictionary.End();
802 
803  while (itr != end)
804  {
805  itk::MetaDataObjectBase::Pointer entry = itr->second;
806  MetaDataStringType::Pointer entryvalue = dynamic_cast<MetaDataStringType *>(entry.GetPointer());
807  std::string entryTag = itr->first;
808  if (entryvalue) //convert MetaDataObject pair to string pair
809  {
810  std::pair<std::string, std::string> entryPair = std::make_pair(entryTag, entryvalue->GetMetaDataObjectValue());
811  tags.push_back(entryPair);
812  }
813  ++itr;
814  }
815 
816  return true;
817 }
818 
819 template<class TImage>
820 bool File::OpenDICOMSeries(const std::string directoryPath, typename itk::SmartPointer<TImage> &data, std::string &seriesName, std::string &caseID, std::string &echoID, std::string &seriesID, std::string &acqID, std::string &instanceID, bool recursive)
821 {
822  typedef itk::MetaDataDictionary DictionaryType;
823  DictionaryType dictionary;
824 
825  if (!GetDICOMData<TImage>(directoryPath, data, dictionary, seriesName, caseID, echoID, seriesID, acqID, instanceID, recursive))
826  return false;
827 
828  return true;
829 }
830 
831 template<class TImage>
832 bool File::OpenDICOMSeriesAndTags(const std::string directoryPath, typename itk::SmartPointer<TImage> &data, std::vector< std::pair<std::string, std::string> > &tags, std::string &seriesName, std::string &caseID, std::string &echoID, std::string &seriesID, std::string &acqID, std::string &instanceID, bool recursive)
833 {
834  typedef itk::MetaDataDictionary DictionaryType;
835  DictionaryType dictionary;
836 
837  if (!GetDICOMData<TImage>(directoryPath, data, dictionary, seriesName, caseID, echoID, seriesID, acqID, instanceID, recursive))
838  return false;
839 
840  if (!milx::File::GetDICOMTags<TImage>(dictionary, tags))
841  return false;
842 
843  return true;
844 }
845 #endif
846 
847 #ifndef ITK_ONLY
848  #ifndef VTK_ONLY
849  template<class TImage>
850  bool File::OpenImage(const std::string filename, vtkSmartPointer<vtkImageData> &data)
851  {
852  std::string extension = GetFileExtension(filename);
853  vtkSmartPointer<vtkErrorWarning> errorObserver = vtkSmartPointer<vtkErrorWarning>::New();
854 
855  if(!Exists(filename))
856  return false;
857 
858  if(extension == "vti") //VTK XML Image format
859  {
860  vtkSmartPointer<vtkXMLImageDataReader> reader = vtkSmartPointer<vtkXMLImageDataReader>::New();
861 
862  if(reader->CanReadFile(filename.c_str()))
863  {
864  reader->SetFileName(filename.c_str());
865  reader->AddObserver(vtkCommand::ErrorEvent, errorObserver);
866  //~ linkProgressEventOf(reader);
867  reader->Update();
868 
869  if(!errorObserver->ReportsFailure())
870  {
871  data = reader->GetOutput();
872  }
873  else
874  {
875  std::cerr << "VTK XML Image Reader Encountered the following error." << std::endl;
876  std::cerr << errorObserver->GetMessage() << std::endl;
877  return false;
878  }
879  }
880  else
881  {
882  std::cerr << "Could not locate VTK XML Image (VTI) file!" << std::endl;
883  return false;
884  }
885  }
886  else
887  {
888  typename itk::SmartPointer<TImage> tmpImage;
889 
890  if( !OpenImage(filename, tmpImage) )
891  return false;
892 
893  typedef itk::ImageToVTKImageFilter<TImage> ConnectorType;
895  typename ConnectorType::Pointer connector = ConnectorType::New();
896  connector->SetInput(tmpImage);
897  connector->Update();
898 
900  vtkSmartPointer<vtkImageFlip> imageReorient = vtkSmartPointer<vtkImageFlip>::New();
901  #if VTK_MAJOR_VERSION <= 5
902  imageReorient->SetInput(connector->GetOutput());
903  #else
904  imageReorient->SetInputData(connector->GetOutput());
905  #endif
906  imageReorient->SetFilteredAxis(1);
907  imageReorient->FlipAboutOriginOn();
908  imageReorient->AddObserver(vtkCommand::ErrorEvent, errorObserver);
909  imageReorient->Update();
910 
911  if(errorObserver->ReportsFailure())
912  {
913  std::cerr << "Reader Encountered the following error." << endl;
914  std::cerr << errorObserver->GetMessage() << endl;
915  return false;
916  }
917 
918  data = imageReorient->GetOutput();
919  }
920 
921  return true;
922  }
923 
924  template<class TImage>
925  bool File::SaveImage(const std::string filename, vtkSmartPointer<vtkImageData> &data)
926  {
927  std::string extension = GetFileExtension(filename);
928 
930  vtkSmartPointer<vtkErrorWarning> errorObserver = vtkSmartPointer<vtkErrorWarning>::New();
931  vtkSmartPointer<vtkImageFlip> imageReorient = vtkSmartPointer<vtkImageFlip>::New();
932  #if VTK_MAJOR_VERSION <= 5
933  imageReorient->SetInput(data);
934  #else
935  imageReorient->SetInputData(data);
936  #endif
937  imageReorient->SetFilteredAxis(1);
938  imageReorient->FlipAboutOriginOn();
939  imageReorient->AddObserver(vtkCommand::ErrorEvent, errorObserver);
940  imageReorient->Update();
941 
942  if(errorObserver->ReportsFailure())
943  {
944  std::cerr << "Writer Encountered the following error." << std::endl;
945  std::cerr << errorObserver->GetMessage() << std::endl;
946  return false;
947  }
948 
949  if(extension == "vti") //VTK XML Image format
950  {
951  vtkSmartPointer<vtkXMLImageDataWriter> writer = vtkSmartPointer<vtkXMLImageDataWriter>::New();
952  #if VTK_MAJOR_VERSION <= 5
953  writer->SetInput(data);
954  #else
955  writer->SetInputData(data);
956  #endif
957  writer->SetFileName(filename.c_str());
958  writer->SetDataModeToBinary();
959  writer->AddObserver(vtkCommand::ErrorEvent, errorObserver);
960  //~ linkProgressEventOf(writer);
961  writer->Write();
962 
963  if(errorObserver->ReportsFailure())
964  {
965  std::cerr << "VTK XML Image Writer Encountered the following error." << std::endl;
966  std::cerr << errorObserver->GetMessage() << std::endl;
967  }
968  }
969  else
970  {
971  typedef itk::VTKImageToImageFilter<TImage> ConnectorType;
973  typename ConnectorType::Pointer connector = ConnectorType::New();
974  connector->SetInput(imageReorient->GetOutput());
975  connector->Update();
976 
977  if( !SaveImage<TImage>(filename, connector->GetOutput()) )
978  return false;
979  }
980 
981  return true;
982  }
983  #endif
984 #endif
985 
986 #ifndef VTK_ONLY
987 template<class TImage>
988 itk::SmartPointer<TImage> File::ReadImageUsingITK(const std::string filename)
989 {
990  typedef itk::ImageFileReader<TImage, itk::DefaultConvertPixelTraits<typename TImage::InternalPixelType> > ImageReader; //InternalPixelType != PixelType for vector images
991  typename ImageReader::Pointer reader = ImageReader::New();
992  reader->SetFileName(filename.c_str());
993  reader->AddObserver(itk::ProgressEvent(), milx::ProgressUpdates);
994  try
995  {
996  reader->Update();
997  }
998  catch( itk::ExceptionObject & err )
999  {
1000  std::cerr << "Reader Encountered the following error." << std::endl;
1001  std::cerr << err << std::endl;
1002  return NULL;
1003  }
1004 
1005  return reader->GetOutput();
1006 }
1007 
1008 template<class TImage>
1009 bool File::WriteImageUsingITK(const std::string filename, itk::SmartPointer<TImage> data)
1010 {
1011  typedef itk::ImageFileWriter<TImage> ImageWriter;
1012  typename ImageWriter::Pointer writer = ImageWriter::New();
1013  writer->SetFileName(filename.c_str());
1014  writer->SetInput(data);
1015  writer->AddObserver(itk::ProgressEvent(), milx::ProgressUpdates);
1016  try
1017  {
1018  writer->Update();
1019  }
1020  catch( itk::ExceptionObject & err )
1021  {
1022  std::cerr << "Writer Encountered the following error." << std::endl;
1023  std::cerr << err << std::endl;
1024  return false;
1025  }
1026 
1027  return true;
1028 }
1029 
1030 template<class TType>
1031 itk::SmartPointer< itk::Transform<TType> > File::OpenTransform(std::string filename)
1032 {
1033  typedef itk::TransformFileReader TransformReaderType;
1034  typedef TransformReaderType::TransformListType * TransformListType;
1035 
1036  // Register default transforms
1037  itk::TransformFactoryBase::RegisterDefaultTransforms();
1038 
1039  TransformReaderType::Pointer affineReader = TransformReaderType::New();
1040  affineReader->SetFileName(filename);
1041  affineReader->AddObserver(itk::ProgressEvent(), milx::ProgressUpdates);
1042  try
1043  {
1044  affineReader->Update();
1045  }
1046  catch(itk::ExceptionObject &ex)
1047  {
1048  PrintError("milxFile: Failed reading Transform " + std::string(ex.GetDescription()));
1049  return NULL;
1050  }
1051 
1052  return static_cast< itk::Transform<TType> *>( (*(affineReader->GetTransformList()->begin())).GetPointer() );
1053 }
1054 #endif
1055 
1056 } //end namespace milx
1057 
1058 #endif //__MILXFILE_H
static bool GetDICOMMetaData(const std::string directoryPath, itk::MetaDataDictionary &dict, std::string &seriesName, std::string &caseID, std::string &echoID, std::string &seriesID, std::string &acqID, std::string &instanceID, bool recursive=false)
Opens a DICOM series and returns the image meta data read by ITK/GDCM, i.e. the DICOM tags from the h...
Definition: milxFile.h:756
static bool OpenDICOMSeries(const std::string directoryPath, typename itk::SmartPointer< TImage > &data, std::string &seriesName, std::string &caseID, std::string &echoID, std::string &seriesID, std::string &acqID, std::string &instanceID, bool recursive=false)
Opens a DICOM series from the path given. Returns the image volume from the series read by ITK/GDCM...
Definition: milxFile.h:820
static std::string ExtractFilename(const std::string &filename, char delimiter='/')
Returns filename (with extension) with paths removed.
Definition: milxFile.h:442
static itk::SmartPointer< TImage > ReadImageUsingITK(const std::string filename)
Opens the image using the ITK file reader class. Returns NULL if failed and outputs the error to std ...
Definition: milxFile.h:988
static std::string ExtractPath(const std::string &filename, char delimiter='/')
Returns the path of the filename with the basename removed.
Definition: milxFile.h:452
void PrintError(const std::string msg)
Displays a generic msg to standard error with carriage return.
Definition: milxGlobal.h:202
static bool Exists(const std::string filename)
Returns true if the file already exists.
Definition: milxFile.h:482
static bool GetDICOMTags(const std::string directoryPath, std::vector< std::pair< std::string, std::string > > &tags, std::string &seriesName, std::string &caseID, std::string &echoID, std::string &seriesID, std::string &acqID, std::string &instanceID, bool recursive=false)
Opens a DICOM series and returns the DICOM tags read by ITK/GDCM, i.e. the DICOM tags from the header...
Definition: milxFile.h:767
#define SMILI_EXPORT
DLL Function Symbol for Windows. It is empty for other OSes.
Definition: milxGlobal.h:227
static bool GetDICOMData(const std::string directoryPath, typename itk::SmartPointer< TImage > &data, itk::MetaDataDictionary &dict, std::string &seriesName, std::string &caseID, std::string &echoID, std::string &seriesID, std::string &acqID, std::string &instanceID, bool recursive=false)
Opens a DICOM series and returns the image meta data read by ITK/GDCM, i.e. the DICOM tags from the h...
Definition: milxFile.h:659
static bool OpenImage(const std::string filename, typename itk::SmartPointer< TImage > &data)
Opens an image file, which is any of the following: JPEG, PNG, DICOM, TIFF, NIFTI etc...
Definition: milxFile.h:509
static bool SaveImage(const std::string filename, typename itk::SmartPointer< TImage > data, itk::ImageIOBase *io=NULL)
Saves an image file, which is any of the following: JPEG, PNG, DICOM, TIFF, NIFTI etc...
Definition: milxFile.h:611
static bool OpenImages(std::vector< std::string > &filenames, std::vector< typename itk::SmartPointer< TImage > > &images)
Opens a number of images, which are any of the following: JPEG, PNG, DICOM, TIFF, NIFTI etc...
Definition: milxFile.h:586
File()
Standard constructor.
Definition: milxFile.h:99
static bool WriteImageUsingITK(const std::string filename, itk::SmartPointer< TImage > data)
Saves the image using the ITK file writer class. Returns NULL if failed and outputs the error to std ...
Definition: milxFile.h:1009
static void MakeDirectory(std::string name)
Creates directory (using ITK) if none exists.
Definition: milxFile.h:495
virtual ~File()
Standard Destructor.
Definition: milxFile.h:104
static std::string StringToLowerCase(std::string filename)
Returns a lower case version of the string.
Definition: milxFile.h:421
static itk::SmartPointer< itk::Transform< TType > > OpenTransform(std::string filename)
Opens an ITK transform file and returns.
Definition: milxFile.h:1031
A general file IO class for reading writing images and models.
Definition: milxFile.h:92
static std::string GetFileExtension(const std::string &filename)
Returns the file extension (in lower case) of the given filename.
Definition: milxFile.h:472
static bool SaveImages(std::vector< std::string > &filenames, const std::vector< typename itk::SmartPointer< TImage > > images)
Saves a number of images, which are any of the following: JPEG, PNG, DICOM, TIFF, NIFTI etc...
Definition: milxFile.h:637