]> Creatis software - clitk.git/blobdiff - tools/clitkImageConvertGenericFilter.cxx
Debug clitkNormalizeImage
[clitk.git] / tools / clitkImageConvertGenericFilter.cxx
index b7702cc694aa5450cff434d37f0c6a5698df53a4..51a43a029a60fa239ebd0840465751af3198cd63 100644 (file)
   - BSD        See included LICENSE.txt file
   - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
   ===========================================================================**/
+
 #ifndef CLITKIMAGECONVERTGENERICFILTER_CXX
 #define CLITKIMAGECONVERTGENERICFILTER_CXX
 
 #include "clitkImageConvertGenericFilter.h"
+#include "vvImageReader.h"
+#include "vvImageWriter.h"
+#include "itkFlipImageFilter.h"
+#include "itkGDCMImageIO.h"
+#include <itkChangeInformationImageFilter.h>
+
+#include "gdcmReader.h"
+#include "gdcmAttribute.h"
+#include "gdcmPrinter.h"
+#include "gdcmDict.h"
+#include "gdcmStringFilter.h"
 
 //--------------------------------------------------------------------
 clitk::ImageConvertGenericFilter::ImageConvertGenericFilter():
   clitk::ImageToImageGenericFilter<Self>("ImageConvert")
 {
   mOutputPixelTypeName = "NotSpecified";
-  mWarningOccur = false;
-  mWarning = "";
   mDisplayWarning = true;
+  mWarning = "";
+  mWarningOccur = false;
+  SetCorrectNegativeSpacingFlag(false);
+
   InitializeImageType<2>();
   InitializeImageType<3>();
   InitializeImageType<4>();
@@ -40,6 +54,10 @@ template<unsigned int Dim>
 void clitk::ImageConvertGenericFilter::InitializeImageType()
 {
   ADD_DEFAULT_IMAGE_TYPES(Dim);
+  ADD_VEC_IMAGE_TYPE(Dim, 2, float);
+  ADD_VEC_IMAGE_TYPE(Dim, 3, float);
+  ADD_VEC_IMAGE_TYPE(Dim, 2, double);
+  ADD_VEC_IMAGE_TYPE(Dim, 3, double);
 }
 //--------------------------------------------------------------------
 
@@ -48,7 +66,6 @@ void clitk::ImageConvertGenericFilter::InitializeImageType()
 template<class InputImageType>
 void clitk::ImageConvertGenericFilter::UpdateWithInputImageType()
 {
-
   // Verbose stuff
   if (m_IOVerbose) {
     if (m_InputFilenames.size() == 1) {
@@ -66,92 +83,169 @@ void clitk::ImageConvertGenericFilter::UpdateWithInputImageType()
     }
   }
 
+  if(mVV) {
+    if (mOutputPixelTypeName != "NotSpecified" || m_WriteCompression) {
+      std::cerr << "--vv is not compatible with --compression and --type options." << std::endl;
+      exit(-1);
+    }
 
-  if ((m_PixelTypeName == mOutputPixelTypeName) || (mOutputPixelTypeName == "NotSpecified")) {
-    //    typename InputImageType::Pointer input = clitk::readImage<InputImageType>(m_InputFilenames);
+    vvImageReader::Pointer reader = vvImageReader::New();
+    reader->SetInputFilenames(m_InputFilenames);
+    reader->Update(vvImageReader::IMAGE);
+
+    vvImageWriter::Pointer writer = vvImageWriter::New();
+    writer->SetOutputFileName(m_OutputFilenames.front());
+    writer->SetSaveTransform(true);
+    writer->SetInput(reader->GetOutput());
+    writer->Update();
+    return;
+  }
+  else if ((m_PixelTypeName == mOutputPixelTypeName) || (mOutputPixelTypeName == "NotSpecified")) {
+
+    // Get input image
     typename InputImageType::Pointer input = this->template GetInput<InputImageType>(0);
-    //clitk::writeImage<InputImageType>(input, mOutputFilename, m_IOVerbose);
+
+    if (mCorrectNegativeSpacingFlag) {
+      // Read dicom
+      gdcm::Reader reader;
+      reader.SetFileName(m_InputFilenames[0].c_str());
+      // if (!reader.CanReadFile(m_InputFilenames[0])) {
+      //   std::cout << "Error: " << m_InputFilenames[0] << " is not a dicom file. Abort." << std::endl;
+      //   exit(0);
+      // }
+      reader.Read();
+
+      // the dataset is the the set of element we are interested in:
+      gdcm::DataSet & ds = reader.GetFile().GetDataSet();
+
+      // Read the attribute SpacingBetweenSlices, check if negative and replace
+      gdcm::Attribute<0x0018,0x0088> SpacingBetweenSlices;
+      SpacingBetweenSlices.SetFromDataSet(ds);
+      double s = SpacingBetweenSlices.GetValue();
+      if (s >=0) {
+        std::cout << "Error: no negative spacing found SpacingBetweenSlices = " << s << " Abort. " << std::endl;
+        exit(0);
+      }
+      s = -s;
+
+      // Set spacing
+      typename InputImageType::SpacingType spacing = input->GetSpacing();
+      spacing[2] = s;
+      input->SetSpacing(spacing);
+
+      // Flip
+      typedef itk::FlipImageFilter< InputImageType >  FilterType;
+      typename FilterType::Pointer filter = FilterType::New();
+      typedef typename FilterType::FlipAxesArrayType     FlipAxesArrayType;
+      FlipAxesArrayType flipArray;
+      flipArray[0] = false;
+      flipArray[1] = false;
+      flipArray[2] = true;
+      filter->SetFlipAxes(flipArray);
+      filter->SetInput(input);
+      filter->Update();
+
+      // Read the attribute  Image Position (Patient)
+      gdcm::Tag  DetectorInformationSequenceTag(0x0054,0x0022);
+      const gdcm::DataElement & DIS = ds.GetDataElement(DetectorInformationSequenceTag);
+      if (!DIS.GetByteValue()) {
+        std::cout << "Error: could not find 0x0054,0x0022 tag. Abort." << std::endl;
+        exit(0);
+      }
+      gdcm::SmartPointer<gdcm::SequenceOfItems> sqf = DIS.GetValueAsSQ();
+      gdcm::Item & item = sqf->GetItem(1);
+      gdcm::DataSet & ds_position = item.GetNestedDataSet();
+      gdcm::Attribute<0x0020,0x0032> ImagePositionPatient;
+      ImagePositionPatient.SetFromDataSet(ds_position);
+      double x = ImagePositionPatient.GetValue(0);
+      double y = ImagePositionPatient.GetValue(1);
+      double z = ImagePositionPatient.GetValue(2);
+
+      // Set offset
+      typename InputImageType::PointType origin = input->GetOrigin();
+      origin[0] = x;
+      origin[1] = y;
+      origin[2] = z;
+      input->SetOrigin(origin);
+
+      // Orientation
+      typename InputImageType::DirectionType direction = input->GetDirection();
+      direction[2][2] = -1;
+      input->SetDirection(direction);
+
+      // Empty meta info
+      itk::MetaDataDictionary dict;// = new itk::MetaDataDictionary;
+      input->SetMetaDataDictionary(dict);
+    }
+
+    typedef itk::ChangeInformationImageFilter<InputImageType> CIType;
+    typename CIType::Pointer changeInfo = CIType::New();
+    if(mNoNiiMeta) {
+      changeInfo->SetInput(input);
+      typename CIType::PointType o = input->GetOrigin();
+      o[0] *= -1.;
+      o[1] *= -1.;
+      typename CIType::DirectionType d = input->GetDirection();
+      d[0][0] *= -1.;
+      d[1][1] *= -1.;
+      changeInfo->ChangeDirectionOn();
+      changeInfo->ChangeOriginOn();
+      changeInfo->SetOutputOrigin(o);
+      changeInfo->SetOutputDirection(d);
+      changeInfo->Update();
+      input = changeInfo->GetOutput();
+    }
+
     this->SetNextOutput<InputImageType>(input);
+
   } else {
-#define TRY_TYPE(TYPE)                                                 \
-    if (IsSameType<TYPE>(mOutputPixelTypeName)) { UpdateWithOutputType<InputImageType, TYPE>(); return; }
-    TRY_TYPE(char);
-    //    TRY_TYPE(signed char);
-    TRY_TYPE(uchar);
-    TRY_TYPE(short);
-    TRY_TYPE(ushort);
-    TRY_TYPE(int); // no uint ...
-    TRY_TYPE(float);
-    TRY_TYPE(double);
-#undef TRY_TYPE
-
-    std::string list = CreateListOfTypes<char, uchar, short, ushort, int, float, double>();
-    std::cerr << "Error, I don't know the output type '" << mOutputPixelTypeName
-              << "'. " << std::endl << "Known types are " << list << "." << std::endl;
-    exit(0);
+    // "trick" to call independent versions of update according to the
+    // pixel type (vector or scalar), using partial specializations
+    if (!UpdateWithSelectiveOutputType<InputImageType, ImageConvertTraits<typename InputImageType::PixelType>::IS_VECTOR>::Run(*this, mOutputPixelTypeName))
+      exit(-1);
   }
 }
 //====================================================================
 
 //====================================================================
-template<class InputImageType, class OutputPixelType>
-void clitk::ImageConvertGenericFilter::UpdateWithOutputType()
-{
-  // Read
-  typename InputImageType::Pointer input =this->template GetInput<InputImageType>(0);
-
-  // Typedef
-  typedef typename InputImageType::PixelType PixelType;
 
-  // Warning
+template<class PixelType, class OutputPixelType>
+void clitk::ImageConvertGenericFilter::CheckTypes(
+  std::string inType, std::string outType
+)
+{
   std::ostringstream osstream;
   if (std::numeric_limits<PixelType>::is_signed) {
     if (!std::numeric_limits<OutputPixelType>::is_signed) {
-      osstream << "Warning, input type is signed (" << m_PixelTypeName << ") while output type is not ("
-               << mOutputPixelTypeName << "), use at your own responsability." << std::endl;
-      mWarningOccur = true;
+      osstream << "Warning, input type is signed (";
     }
   }
   if (!std::numeric_limits<PixelType>::is_integer) {
     if (std::numeric_limits<OutputPixelType>::is_integer) {
-      osstream << "Warning, input type is not integer (" << m_PixelTypeName << ") while output type is ("
-               << mOutputPixelTypeName << "), use at your own responsability." << std::endl;
-      mWarningOccur = true;
+      osstream << "Warning, input type is not integer (";
     }
   }
   //  DD(std::numeric_limits<PixelType>::digits10);
   // DD(std::numeric_limits<OutputPixelType>::digits10);
   if (!std::numeric_limits<PixelType>::is_integer) {
     if (std::numeric_limits<OutputPixelType>::is_integer) {
-      osstream << "Warning, input type is not integer (" << m_PixelTypeName << ") while output type is ("
-               << mOutputPixelTypeName << "), use at your own responsability." << std::endl;
-      mWarningOccur = true;
+      osstream << "Warning, input type is not integer (";
     }
   }
   if (std::numeric_limits<PixelType>::digits10 > std::numeric_limits<OutputPixelType>::digits10) {
-    osstream << "Warning, possible loss of precision : input type is (" << m_PixelTypeName << ") while output type is ("
-             << mOutputPixelTypeName << "), use at your own responsability." << std::endl;
-    mWarningOccur = true;
+    osstream << "Warning, possible loss of precision : input type is (" ;
   }
 
-  mWarning = osstream.str();
-  if (mDisplayWarning) {
-    std::cerr << mWarning;
+  if (!osstream.str().empty())
+  {
+    mWarningOccur = true;
+    osstream << inType << ") while output type is (" << outType << "), use at your own responsability." << std::endl;
+    mWarning = osstream.str();
+    if (mDisplayWarning) {
+      std::cerr << mWarning;
+    }
   }
-
-  // Cast
-  typedef itk::Image<OutputPixelType,InputImageType::ImageDimension> OutputImageType;
-  typedef itk::CastImageFilter<InputImageType, OutputImageType> FilterType;
-  typename FilterType::Pointer filter = FilterType::New();
-  filter->SetInput(input);
-  filter->Update();
-
-  // Write
-  SetNextOutput<OutputImageType>(filter->GetOutput());
-  //clitk::writeImage<OutputImageType>(filter->GetOutput(), mOutputFilename, m_IOVerbose);
 }
-//====================================================================
 
 
 #endif /* end #define CLITKIMAGECONVERTGENERICFILTER_CXX */
-