]> Creatis software - clitk.git/commitdiff
Add clitkImage2Dicom tool
authortbaudier <thomas.baudier@creatis.insa-lyon.fr>
Thu, 28 Feb 2019 13:25:04 +0000 (14:25 +0100)
committertbaudier <thomas.baudier@creatis.insa-lyon.fr>
Thu, 28 Feb 2019 13:25:04 +0000 (14:25 +0100)
The difference with clitkWriteDicomSerie is that the number of slice can be different between the input image and the input dicom

tools/CMakeLists.txt
tools/clitkImage2Dicom.cxx [new file with mode: 0644]
tools/clitkImage2Dicom.ggo [new file with mode: 0644]
tools/clitkImage2DicomGenericFilter.cxx [new file with mode: 0644]
tools/clitkImage2DicomGenericFilter.h [new file with mode: 0644]
tools/clitkImage2DicomGenericFilter.txx [new file with mode: 0644]

index 0a044fed096838487b6043b9e4083bcb771068f7..34bb132d7bf6dcd6a695bc5fa688bb99c2206cf3 100644 (file)
@@ -104,7 +104,12 @@ if(CLITK_BUILD_TOOLS)
   add_executable(clitkWriteDicomSeries clitkWriteDicomSeries.cxx ${clitkWriteDicomSeries_GGO_C})
   target_link_libraries(clitkWriteDicomSeries clitkCommon )
   set(TOOLS_INSTALL ${TOOLS_INSTALL} clitkWriteDicomSeries)
-  
+
+  WRAP_GGO(clitkImage2Dicom_GGO_C clitkImage2Dicom.ggo)
+  add_executable(clitkImage2Dicom clitkImage2Dicom.cxx ${clitkImage2Dicom_GGO_C})
+  target_link_libraries(clitkImage2Dicom clitkCommon )
+  set(TOOLS_INSTALL ${TOOLS_INSTALL} clitkImage2Dicom)
+
   WRAP_GGO(clitkSpect2Dicom_GGO_C clitkSpect2Dicom.ggo)
   add_executable(clitkSpect2Dicom clitkSpect2Dicom.cxx ${clitkSpect2Dicom_GGO_C})
   target_link_libraries(clitkSpect2Dicom clitkCommon )
diff --git a/tools/clitkImage2Dicom.cxx b/tools/clitkImage2Dicom.cxx
new file mode 100644 (file)
index 0000000..cebeb02
--- /dev/null
@@ -0,0 +1,53 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to:
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://www.centreleonberard.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+===========================================================================**/
+
+/* =================================================
+ * @file   clitkImage2Dicom.cxx
+ * @author Thomas B
+ * @date   2018
+ *
+ * @brief Write a volume into a series with the header of another series
+ *
+ ===================================================*/
+
+
+// clitk
+#include "clitkImage2Dicom_ggo.h"
+#include "clitkIO.h"
+#include "clitkImage2DicomGenericFilter.h"
+#include "clitkCommon.h"
+
+//--------------------------------------------------------------------
+int main(int argc, char * argv[])
+{
+
+  // Init command line
+  GGO(clitkImage2Dicom, args_info);
+  CLITK_INIT;
+
+  // Filter
+  typedef clitk::Image2DicomGenericFilter<args_info_clitkImage2Dicom> FilterType;
+  FilterType::Pointer genericFilter = FilterType::New();
+
+  genericFilter->SetArgsInfo(args_info);
+  genericFilter->Update();
+
+  return EXIT_SUCCESS;
+}// end main
+
+//--------------------------------------------------------------------
diff --git a/tools/clitkImage2Dicom.ggo b/tools/clitkImage2Dicom.ggo
new file mode 100644 (file)
index 0000000..d790cbf
--- /dev/null
@@ -0,0 +1,12 @@
+#File clitkImage2Dicom.ggo
+package "clitkImage2Dicom"
+version "1.0"
+purpose "Convert the 3D mhd input image (int image) into a 3D dicom (outputDcm) based on the dictionary of the dicoms in inputDcm. The number of slice between the input and the inputDcm could be different"
+
+option "config"     - "Config file"             string  no
+option "verbose"    v "Verbose"                 flag    off
+
+option "input"      i "Input image filename"    string  no
+option "inputDcm"   d "Input dicom filename"    string  no
+option "outputDcm"  o "Output dicom filename"   string  no
+
diff --git a/tools/clitkImage2DicomGenericFilter.cxx b/tools/clitkImage2DicomGenericFilter.cxx
new file mode 100644 (file)
index 0000000..641681c
--- /dev/null
@@ -0,0 +1,39 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to:
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://www.centreleonberard.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+===========================================================================**/
+#ifndef clitkImage2DicomGenericFilter_cxx
+#define clitkImage2DicomGenericFilter_cxx
+
+/* =================================================
+ * @file   clitkImage2DicomGenericFilter.cxx
+ * @author
+ * @date
+ *
+ * @brief
+ *
+ ===================================================*/
+
+#include "clitkImage2DicomGenericFilter.h"
+
+
+namespace clitk
+{
+
+
+} //end clitk
+
+#endif  //#define clitkImage2DicomGenericFilter_cxx
diff --git a/tools/clitkImage2DicomGenericFilter.h b/tools/clitkImage2DicomGenericFilter.h
new file mode 100644 (file)
index 0000000..3e47a34
--- /dev/null
@@ -0,0 +1,152 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://www.centreleonberard.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+===========================================================================**/
+#ifndef clitkImage2DicomGenericFilter_h
+#define clitkImage2DicomGenericFilter_h
+
+/* =================================================
+ * @file   clitkImage2DicomGenericFilter.h
+ * @author 
+ * @date   
+ * 
+ * @brief 
+ * 
+ ===================================================*/
+
+
+// clitk include
+#include "clitkIO.h"
+#include "clitkImageCommon.h"
+#include "clitkImage2Dicom_ggo.h"
+
+//itk include
+#include "itkLightObject.h"
+#include "itkGDCMImageIO.h"
+#include "itkMetaDataDictionary.h"
+#include "itkGDCMSeriesFileNames.h"
+#include "itkImageSeriesReader.h"
+#include "itkImageSeriesWriter.h"
+#include <vector>
+#include <itksys/SystemTools.hxx>
+
+#include "itkImage.h"
+#include "itkMinimumMaximumImageFilter.h"
+#include "itkGDCMImageIO.h"
+#include "itkGDCMSeriesFileNames.h"
+#include "itkNumericSeriesFileNames.h"
+#include "itkImageSeriesReader.h"
+#include "itkImageSeriesWriter.h"
+#include "itkResampleImageFilter.h"
+#if ( ( ITK_VERSION_MAJOR == 4 ) && ( ITK_VERSION_MINOR < 6 ) )
+#include "itkShiftScaleImageFilter.h"
+#endif
+#include "itkIdentityTransform.h"
+#include "itkLinearInterpolateImageFunction.h"
+#include <itksys/SystemTools.hxx>
+#if ITK_VERSION_MAJOR >= 4
+#include "gdcmUIDGenerator.h"
+#else
+#include "gdcm/src/gdcmFile.h"
+#include "gdcm/src/gdcmUtil.h"
+#endif
+#include <string>
+#include <sstream>
+
+namespace clitk 
+{
+  template<class args_info_type>
+  class ITK_EXPORT Image2DicomGenericFilter : public itk::LightObject
+  {
+  public:
+    //----------------------------------------
+    // ITK
+    //----------------------------------------
+    typedef Image2DicomGenericFilter                   Self;
+    typedef itk::LightObject                   Superclass;
+    typedef itk::SmartPointer<Self>            Pointer;
+    typedef itk::SmartPointer<const Self>      ConstPointer;
+   
+    // Method for creation through the object factory
+    itkNewMacro(Self);  
+
+    // Run-time type information (and related methods)
+    itkTypeMacro( Image2DicomGenericFilter, LightObject );
+
+
+    //----------------------------------------
+    // Typedefs
+    //----------------------------------------
+
+
+    //----------------------------------------
+    // Set & Get
+    //----------------------------------------    
+    void SetArgsInfo(const args_info_type & a)
+    {
+      m_ArgsInfo=a;
+      m_Verbose=m_ArgsInfo.verbose_flag;
+      m_InputFileName=m_ArgsInfo.input_arg;
+    }
+    
+    
+    //----------------------------------------  
+    // Update
+    //----------------------------------------  
+    void Update();
+
+  protected:
+
+    //----------------------------------------  
+    // Constructor & Destructor
+    //----------------------------------------  
+    Image2DicomGenericFilter();
+    ~Image2DicomGenericFilter() {};
+
+    
+    //void CopyDictionary (itk::MetaDataDictionary &fromDict, itk::MetaDataDictionary &toDict);
+    //----------------------------------------  
+    // Templated members
+    //----------------------------------------  
+    template <unsigned int Dimension>  void UpdateWithDim(std::string PixelType);
+    template <unsigned int Dimension, class PixelType>  void UpdateWithDimAndPixelType();
+    
+    
+     //----------------------------------------  
+    // Data members
+    //----------------------------------------
+    args_info_type m_ArgsInfo;
+    bool m_Verbose;
+    std::string m_InputFileName;
+
+  };
+
+
+} // end namespace clitk
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "clitkImage2DicomGenericFilter.txx"
+#endif
+
+#endif // #define clitkImage2DicomGenericFilter_h
diff --git a/tools/clitkImage2DicomGenericFilter.txx b/tools/clitkImage2DicomGenericFilter.txx
new file mode 100644 (file)
index 0000000..c58bd2f
--- /dev/null
@@ -0,0 +1,425 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to:
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://www.centreleonberard.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+===========================================================================**/
+#ifndef clitkImage2DicomGenericFilter_txx
+#define clitkImage2DicomGenericFilter_txx
+
+/* =================================================
+ * @file   clitkImage2DicomGenericFilter.txx
+ * @author
+ * @date
+ *
+ * @brief
+ *
+ ===================================================*/
+
+#include "itkVersion.h"
+#include "itkImage.h"
+#include "itkGDCMImageIO.h"
+#include "itkGDCMSeriesFileNames.h"
+#include "itkNumericSeriesFileNames.h"
+#include "itkImageSeriesReader.h"
+#include "itkImageSeriesWriter.h"
+
+#include "itkThresholdImageFilter.h"
+
+#if ( ( ITK_VERSION_MAJOR == 4 ) && ( ITK_VERSION_MINOR < 6 ) )
+#include "itkShiftScaleImageFilter.h"
+#endif
+
+#include <string>
+#include <sstream>
+#if GDCM_MAJOR_VERSION >= 2
+#include <gdcmUIDGenerator.h>
+#include <gdcmImageHelper.h>
+#include <gdcmAttribute.h>
+#include <gdcmReader.h>
+#include <gdcmWriter.h>
+#include <gdcmDataElement.h>
+#include <gdcmTag.h>
+#else
+#include "gdcmFile.h"
+#include "gdcmUtil.h"
+#endif
+
+namespace clitk
+{
+
+
+//-----------------------------------------------------------
+// Constructor
+//-----------------------------------------------------------
+template<class args_info_type>
+Image2DicomGenericFilter<args_info_type>::Image2DicomGenericFilter()
+{
+  m_Verbose=false;
+  m_InputFileName="";
+}
+
+
+//-----------------------------------------------------------
+// Update
+//-----------------------------------------------------------
+template<class args_info_type>
+void Image2DicomGenericFilter<args_info_type>::Update()
+{
+  // Read the Dimension and PixelType
+  int Dimension;
+  std::string PixelType;
+  ReadImageDimensionAndPixelType(m_InputFileName, Dimension, PixelType);
+
+
+  // Call UpdateWithDim
+  if(Dimension==2) UpdateWithDim<2>(PixelType);
+  else if(Dimension==3) UpdateWithDim<3>(PixelType);
+  // else if (Dimension==4)UpdateWithDim<4>(PixelType);
+  else {
+    std::cout<<"Error, Only for 2 or 3  Dimensions!!!"<<std::endl ;
+    return;
+  }
+}
+
+//-------------------------------------------------------------------
+// Update with the number of dimensions
+//-------------------------------------------------------------------
+template<class args_info_type>
+template<unsigned int Dimension>
+void
+Image2DicomGenericFilter<args_info_type>::UpdateWithDim(std::string PixelType)
+{
+  if (m_Verbose) std::cout << "Image was detected to be "<<Dimension<<"D and "<< PixelType<<"..."<<std::endl;
+
+  if(PixelType == "short") {
+    if (m_Verbose) std::cout << "Launching filter in "<< Dimension <<"D and signed short..." << std::endl;
+    UpdateWithDimAndPixelType<Dimension, signed short>();
+  }
+  else if(PixelType == "unsigned_short"){
+    if (m_Verbose) std::cout  << "Launching filter in "<< Dimension <<"D and unsigned_short..." << std::endl;
+    UpdateWithDimAndPixelType<Dimension, unsigned short>();
+  }
+
+  else if (PixelType == "unsigned_char") {
+    if (m_Verbose) std::cout  << "Launching filter in "<< Dimension <<"D and unsigned_char..." << std::endl;
+    UpdateWithDimAndPixelType<Dimension, unsigned char>();
+  }
+
+  //     else if (PixelType == "char"){
+  //       if (m_Verbose) std::cout  << "Launching filter in "<< Dimension <<"D and signed_char..." << std::endl;
+  //       UpdateWithDimAndPixelType<Dimension, signed char>();
+  //     }
+  else if (PixelType == "double") {
+    if (m_Verbose) std::cout  << "Launching filter in "<< Dimension <<"D and double..." << std::endl;
+    UpdateWithDimAndPixelType<Dimension, double>();
+  }
+  else {
+    if (m_Verbose) std::cout  << "Launching filter in "<< Dimension <<"D and float..." << std::endl;
+    UpdateWithDimAndPixelType<Dimension, float>();
+  }
+}
+
+//-------------------------------------------------------------------
+// Update with the number of dimensions and the pixeltype read from
+// the dicom files. The MHD files may be resampled to match the
+// dicom spacing (and number of slices). Rounding errors in resampling
+// are handled by removing files when generating the output dicom
+// series.
+//-------------------------------------------------------------------
+template<class args_info_type>
+template <unsigned int Dimension, class  PixelType>
+void
+Image2DicomGenericFilter<args_info_type>::UpdateWithDimAndPixelType()
+{
+  // Validate input parameters
+
+  const unsigned int InputDimension = Dimension;
+  const unsigned int OutputDimension = Dimension-1;
+
+  typedef itk::Image< PixelType, InputDimension > InputImageType;
+  typedef itk::Image< PixelType, OutputDimension > OutputImageType;
+  typedef itk::ImageSeriesReader< InputImageType > ReaderType;
+  typedef itk::GDCMImageIO ImageIOType;
+#if ( ( ITK_VERSION_MAJOR == 4 ) && ( ITK_VERSION_MINOR < 6 ) )
+  typedef itk::ShiftScaleImageFilter< InputImageType, InputImageType > ShiftScaleType;
+#endif
+  typedef itk::ImageSeriesWriter< InputImageType, OutputImageType > SeriesWriterType;
+
+////////////////////////////////////////////////
+// 1) Read the input series
+
+// Read the input (MHD file)
+  typedef typename InputImageType::RegionType RegionType;
+  typedef typename RegionType::SizeType SizeType;
+  typedef itk::ImageFileReader<InputImageType> InputReaderType;
+  typename InputReaderType::Pointer volumeReader = InputReaderType::New();
+  volumeReader->SetFileName(m_ArgsInfo.input_arg);
+  volumeReader->Update();
+  typename InputImageType::Pointer input = volumeReader->GetOutput();
+  typedef itk::NumericSeriesFileNames OutputNamesGeneratorType;
+
+  ImageIOType::Pointer gdcmIO = ImageIOType::New();
+  gdcmIO->LoadPrivateTagsOn();
+  typename ReaderType::FileNamesContainer filenames;
+  filenames.push_back(m_ArgsInfo.inputDcm_arg);
+  typename ReaderType::Pointer reader = ReaderType::New();
+  reader->SetImageIO(gdcmIO);
+  reader->SetFileNames(filenames);
+  try {
+    reader->Update();
+  } catch (itk::ExceptionObject &excp) {
+    std::cerr << "Exception thrown while reading the series" << std::endl;
+    std::cerr << excp << std::endl;
+    return;
+  }
+
+  typename InputImageType::SpacingType outputSpacing;
+  typename InputImageType::SizeType   outputSize;
+  for (unsigned int i = 0; i < 3; i++) {
+      outputSpacing[i] = input->GetSpacing()[i];
+      outputSize[i] = input->GetLargestPossibleRegion().GetSize()[i];
+  }
+
+////////////////////////////////////////////////
+// 2) Ensure to have value >= -1024
+
+  typedef itk::ThresholdImageFilter <InputImageType> ThresholdImageFilterType;
+  typename ThresholdImageFilterType::Pointer thresholdFilter = ThresholdImageFilterType::New();
+  thresholdFilter->SetInput(input);
+  thresholdFilter->ThresholdBelow(-1024);
+  thresholdFilter->SetOutsideValue(-1024);
+  thresholdFilter->Update();
+
+  input=thresholdFilter->GetOutput();
+
+////////////////////////////////////////////////
+// 3) Create a MetaDataDictionary for each slice.
+
+  // Copy the dictionary from the first image and override slice
+  // specific fields
+  typename ReaderType::DictionaryRawPointer inputDict = (*(reader->GetMetaDataDictionaryArray()))[0];
+  typename ReaderType::DictionaryArrayType outputArray;
+
+  // To keep the new series in the same study as the original we need
+  // to keep the same study UID. But we need new series and frame of
+  // reference UID's.
+#if ITK_VERSION_MAJOR >= 4
+  gdcm::UIDGenerator suid;
+  std::string seriesUID = suid.Generate();
+  gdcm::UIDGenerator fuid;
+  std::string frameOfReferenceUID = fuid.Generate();
+#else
+  std::string seriesUID = gdcm::Util::CreateUniqueUID( gdcmIO->GetUIDPrefix());
+  std::string frameOfReferenceUID = gdcm::Util::CreateUniqueUID( gdcmIO->GetUIDPrefix());
+#endif
+  std::string studyUID;
+  std::string sopClassUID;
+  itk::ExposeMetaData<std::string>(*inputDict, "0020|000d", studyUID);
+  itk::ExposeMetaData<std::string>(*inputDict, "0008|0016", sopClassUID);
+  gdcmIO->KeepOriginalUIDOn();
+  for (unsigned int f = 0; f < outputSize[2]; f++)
+  {
+    // Create a new dictionary for this slice
+    typename ReaderType::DictionaryRawPointer dict = new typename ReaderType::DictionaryType;
+
+    typedef itk::MetaDataDictionary DictionaryType;
+
+    DictionaryType::ConstIterator itrDic = (*inputDict).Begin();
+    DictionaryType::ConstIterator endDic = (*inputDict).End();
+    typedef itk::MetaDataObject< std::string > MetaDataStringType;
+
+    while( itrDic != endDic )
+    {
+      itk::MetaDataObjectBase::Pointer  entry = itrDic->second;
+
+      MetaDataStringType::Pointer entryvalue =
+      dynamic_cast<MetaDataStringType *>( entry.GetPointer() ) ;
+      if( entryvalue )
+      {
+        std::string tagkey   = itrDic->first;
+        std::string tagvalue = entryvalue->GetMetaDataObjectValue();
+        itk::EncapsulateMetaData<std::string>(*dict, tagkey, tagvalue);
+      }
+      ++itrDic;
+    }
+
+    // Set the UID's for the study, series, SOP  and frame of reference
+    itk::EncapsulateMetaData<std::string>(*dict,"0020|000d", studyUID);
+    itk::EncapsulateMetaData<std::string>(*dict,"0020|000e", seriesUID);
+    itk::EncapsulateMetaData<std::string>(*dict,"0020|0052", frameOfReferenceUID);
+
+  #if ITK_VERSION_MAJOR >= 4
+    gdcm::UIDGenerator sopuid;
+    std::string sopInstanceUID = sopuid.Generate();
+  #else
+    std::string sopInstanceUID = gdcm::Util::CreateUniqueUID( gdcmIO->GetUIDPrefix());
+  #endif
+    itk::EncapsulateMetaData<std::string>(*dict,"0008|0018", sopInstanceUID);
+    itk::EncapsulateMetaData<std::string>(*dict,"0002|0003", sopInstanceUID);
+
+    // Change fields that are slice specific
+    std::ostringstream value;
+    value.str("");
+    value << f + 1;
+    // Image Number
+    itk::EncapsulateMetaData<std::string>(*dict,"0020|0013", value.str());
+
+    // Series Description - Append new description to current series
+    // description
+    std::string oldSeriesDesc;
+    itk::ExposeMetaData<std::string>(*inputDict, "0008|103e", oldSeriesDesc);
+
+    value.str("");
+    value << oldSeriesDesc
+          << ": Resampled with pixel spacing "
+          << outputSpacing[0] << ", "
+          << outputSpacing[1] << ", "
+          << outputSpacing[2];
+    // This is an long string and there is a 64 character limit in the
+    // standard
+    unsigned lengthDesc = value.str().length();
+
+    std::string seriesDesc( value.str(), 0,
+                            lengthDesc > 64 ? 64
+                            : lengthDesc);
+    itk::EncapsulateMetaData<std::string>(*dict,"0008|103e", seriesDesc);
+
+    // Series Number
+    value.str("");
+    value << 1001;
+    itk::EncapsulateMetaData<std::string>(*dict,"0020|0011", value.str());
+
+    // Derivation Description - How this image was derived
+    value.str("");
+
+
+
+
+
+    value << ": " << ITK_SOURCE_VERSION;
+
+    lengthDesc = value.str().length();
+    std::string derivationDesc( value.str(), 0,
+                                lengthDesc > 1024 ? 1024
+                                : lengthDesc);
+    itk::EncapsulateMetaData<std::string>(*dict,"0008|2111", derivationDesc);
+
+    // Image Position Patient: This is calculated by computing the
+    // physical coordinate of the first pixel in each slice.
+    typename InputImageType::PointType position;
+    typename InputImageType::IndexType index;
+    index[0] = 0;
+    index[1] = 0;
+    index[2] = f;
+    input->TransformIndexToPhysicalPoint(index, position);
+
+    value.str("");
+    value << position[0] << "\\" << position[1] << "\\" << position[2];
+    itk::EncapsulateMetaData<std::string>(*dict,"0020|0032", value.str());
+    // Slice Location: For now, we store the z component of the Image
+    // Position Patient.
+    value.str("");
+    value << position[2];
+    itk::EncapsulateMetaData<std::string>(*dict,"0020|1041", value.str());
+
+    // Slice Thickness: For now, we store the z spacing
+    value.str("");
+    value << outputSpacing[2];
+    itk::EncapsulateMetaData<std::string>(*dict,"0018|0050", value.str());
+    // Spacing Between Slices
+    itk::EncapsulateMetaData<std::string>(*dict,"0018|0088", value.str());
+    // Save the dictionary
+    outputArray.push_back(dict);
+  }
+
+#if ( ( ITK_VERSION_MAJOR == 4 ) && ( ITK_VERSION_MINOR < 6 ) )
+////////////////////////////////////////////////
+// 4) Shift data to undo the effect of a rescale intercept by the
+//    DICOM reader
+  std::string interceptTag("0028|1052");
+  typedef itk::MetaDataObject<std::string> MetaDataStringType;
+  itk::MetaDataObjectBase::Pointer entry = (*inputDict)[interceptTag];
+
+  MetaDataStringType::ConstPointer interceptValue =
+    dynamic_cast<const MetaDataStringType *>(entry.GetPointer());
+
+  int interceptShift = 0;
+  if(interceptValue ) {
+    std::string tagValue = interceptValue->GetMetaDataObjectValue();
+    interceptShift = -atoi (tagValue.c_str());
+  }
+
+  ShiftScaleType::Pointer shiftScale = ShiftScaleType::New();
+  shiftScale->SetInput(resampler->GetOutput());
+  shiftScale->SetShift(interceptShift );
+#endif
+
+////////////////////////////////////////////////
+// 5) Write the new DICOM series
+  // Generate the file names
+  typename ReaderType::FileNamesContainer fileNamesOutput;
+
+  // Generate the file names
+  OutputNamesGeneratorType::Pointer outputNames = OutputNamesGeneratorType::New();
+  std::string seriesFormat(m_ArgsInfo.outputDcm_arg);
+  seriesFormat = seriesFormat + "/" + "IM%d.dcm";
+  outputNames->SetSeriesFormat(seriesFormat.c_str());
+  outputNames->SetStartIndex(1);
+  outputNames->SetEndIndex(outputSize[2]);
+
+  typename SeriesWriterType::Pointer seriesWriter = SeriesWriterType::New();
+#if ( ( ITK_VERSION_MAJOR == 4 ) && ( ITK_VERSION_MINOR < 6 ) )
+  seriesWriter->SetInput(input);
+#else
+  seriesWriter->SetInput(input);
+#endif
+  seriesWriter->SetImageIO(gdcmIO);
+  seriesWriter->SetFileNames(outputNames->GetFileNames());
+  seriesWriter->SetMetaDataDictionaryArray(&outputArray);
+  try {
+    seriesWriter->Update();
+  } catch(itk::ExceptionObject & excp) {
+    std::cerr << "Exception thrown while writing the series " << std::endl;
+    std::cerr << excp << std::endl;
+    return;
+  }
+/*
+////////////////////////////////////////////////
+// 5) Read the new dicom data tag and copy it in the model data tag to have all dicom tags
+  gdcm::Reader readerModel, readerOutput;
+  readerModel.SetFileName(filenames[0].c_str());
+  readerOutput.SetFileName(fileNamesOutput[0].c_str());
+  readerModel.Read();
+  readerOutput.Read();
+  gdcm::File &fileModel = readerModel.GetFile();
+  gdcm::File &fileOutput = readerOutput.GetFile();
+  gdcm::DataSet &dsModel = fileModel.GetDataSet();
+  gdcm::DataSet &dsOutput = fileOutput.GetDataSet();
+  const unsigned int ptr_len = 42;
+  char *ptr = new char[ptr_len];
+  memset(ptr,0,ptr_len);
+
+  const gdcm::DataElement &dataOutput = dsOutput.GetDataElement(gdcm::Tag(0x7fe0, 0x10));
+  dsModel.Replace(dataOutput);
+  gdcm::Writer w;
+  w.SetFile(fileModel);
+  w.SetFileName(fileNamesOutput[0].c_str());
+  w.Write();
+  return;
+*/
+}
+}//end clitk
+
+#endif //#define clitkImage2DicomGenericFilter_txx