]> Creatis software - clitk.git/blob - tools/clitkImage2DicomSeriesGenericFilter.txx
Add clitkImage2DicomSeries tool to write a Dicom Series from an image without a corre...
[clitk.git] / tools / clitkImage2DicomSeriesGenericFilter.txx
1 /*=========================================================================
2   Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
3
4   Authors belong to:
5   - University of LYON              http://www.universite-lyon.fr/
6   - Léon Bérard cancer center       http://www.centreleonberard.fr
7   - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
8
9   This software is distributed WITHOUT ANY WARRANTY; without even
10   the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
11   PURPOSE.  See the copyright notices for more information.
12
13   It is distributed under dual licence
14
15   - BSD        See included LICENSE.txt file
16   - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
17 ===========================================================================**/
18 #ifndef clitkImage2DicomSeriesGenericFilter_txx
19 #define clitkImage2DicomSeriesGenericFilter_txx
20
21 /* =================================================
22  * @file   clitkImage2DicomSeriesGenericFilter.txx
23  * @author
24  * @date
25  *
26  * @brief
27  *
28  ===================================================*/
29
30 // clitk
31 #include "clitkResampleImageWithOptionsFilter.h"
32 #if GDCM_MAJOR_VERSION >= 2
33 #include "gdcmUIDGenerator.h"
34 #else
35 #include "gdcmFile.h"
36 #include "gdcmUtil.h"
37 #endif
38 #include "itkVersion.h"
39  
40 #include "itkImage.h"
41 #include "itkMinimumMaximumImageFilter.h"
42  
43 #include "itkGDCMImageIO.h"
44 #include "itkGDCMSeriesFileNames.h"
45 #include "itkNumericSeriesFileNames.h"
46  
47 #include "itkImageSeriesReader.h"
48 #include "itkImageSeriesWriter.h"
49  
50 #include "itkResampleImageFilter.h"
51  
52 #if ( ( ITK_VERSION_MAJOR == 4 ) && ( ITK_VERSION_MINOR < 6 ) )
53 #include "itkShiftScaleImageFilter.h"
54 #endif
55  
56 #include "itkIdentityTransform.h"
57 #include "itkLinearInterpolateImageFunction.h"
58  
59 #include <itksys/SystemTools.hxx>
60  
61 #if ITK_VERSION_MAJOR >= 4
62 #include "gdcmUIDGenerator.h"
63 #else
64 #include "gdcm/src/gdcmFile.h"
65 #include "gdcm/src/gdcmUtil.h"
66 #endif
67  
68 #include <string>
69 #include <sstream>
70
71 namespace clitk
72 {
73
74
75 //-----------------------------------------------------------
76 // Constructor
77 //-----------------------------------------------------------
78 template<class args_info_type>
79 Image2DicomSeriesGenericFilter<args_info_type>::Image2DicomSeriesGenericFilter()
80 {
81   m_Verbose=false;
82   m_InputFileName="";
83 }
84
85
86 //-----------------------------------------------------------
87 // Update
88 //-----------------------------------------------------------
89 template<class args_info_type>
90 void Image2DicomSeriesGenericFilter<args_info_type>::Update()
91 {
92   // Read the Dimension and PixelType
93   int Dimension;
94   std::string PixelType;
95   ReadImageDimensionAndPixelType(m_InputFileName, Dimension, PixelType);
96
97
98   // Call UpdateWithDim
99   if(Dimension==2) UpdateWithDim<2>(PixelType);
100   else if(Dimension==3) UpdateWithDim<3>(PixelType);
101   // else if (Dimension==4)UpdateWithDim<4>(PixelType);
102   else {
103     std::cout<<"Error, Only for 2 or 3  Dimensions!!!"<<std::endl ;
104     return;
105   }
106 }
107
108 //-------------------------------------------------------------------
109 // Update with the number of dimensions
110 //-------------------------------------------------------------------
111 template<class args_info_type>
112 template<unsigned int Dimension>
113 void
114 Image2DicomSeriesGenericFilter<args_info_type>::UpdateWithDim(std::string PixelType)
115 {
116   if (m_Verbose) std::cout << "Image was detected to be "<<Dimension<<"D and "<< PixelType<<"..."<<std::endl;
117
118   if(PixelType == "short") {
119     if (m_Verbose) std::cout << "Launching filter in "<< Dimension <<"D and signed short..." << std::endl;
120     UpdateWithDimAndPixelType<Dimension, signed short>();
121   }
122   else if(PixelType == "unsigned_short"){
123     if (m_Verbose) std::cout  << "Launching filter in "<< Dimension <<"D and unsigned_short..." << std::endl;
124     UpdateWithDimAndPixelType<Dimension, unsigned short>();
125   }
126
127   else if (PixelType == "unsigned_char") {
128     if (m_Verbose) std::cout  << "Launching filter in "<< Dimension <<"D and unsigned_char..." << std::endl;
129     UpdateWithDimAndPixelType<Dimension, unsigned char>();
130   }
131
132   //     else if (PixelType == "char"){
133   //       if (m_Verbose) std::cout  << "Launching filter in "<< Dimension <<"D and signed_char..." << std::endl;
134   //       UpdateWithDimAndPixelType<Dimension, signed char>();
135   //     }
136   else if (PixelType == "double") {
137     if (m_Verbose) std::cout  << "Launching filter in "<< Dimension <<"D and double..." << std::endl;
138     UpdateWithDimAndPixelType<Dimension, double>();
139   }
140   else {
141     if (m_Verbose) std::cout  << "Launching filter in "<< Dimension <<"D and float..." << std::endl;
142     UpdateWithDimAndPixelType<Dimension, float>();
143   }
144 }
145
146 //-------------------------------------------------------------------
147 // Update with the number of dimensions and the pixeltype read from
148 // the dicom files. The MHD files may be resampled to match the
149 // dicom spacing (and number of slices). Rounding errors in resampling
150 // are handled by removing files when generating the output dicom
151 // series.
152 //-------------------------------------------------------------------
153 template<class args_info_type>
154 template <unsigned int Dimension, class  PixelType>
155 void
156 Image2DicomSeriesGenericFilter<args_info_type>::UpdateWithDimAndPixelType()
157 {
158
159
160 // Resample a DICOM study
161 //   Usage: ResampleDICOM InputDirectory OutputDirectory
162 //                        xSpacing ySpacing zSpacing
163 //
164 //   Example: ResampleDICOM CT CTResample 0 0 1.5
165 //            will read a series from the CT directory and create a
166 //            new series in the CTResample directory. The new series
167 //            will have the same x,y spacing as the input series, but
168 //            will have a z-spacing of 1.5.
169 //
170 // Description:
171 // ResampleDICOM resamples a DICOM series with user-specified
172 // spacing. The program outputs a new DICOM series with a series
173 // number set to 1001. All non-private DICOM tags are moved from the input
174 // series to the output series. The Image Position Patient is adjusted
175 // for each slice to reflect the z-spacing. The number of slices in
176 // the output series may be larger or smaller due to changes in the
177 // z-spacing. To retain the spacing for a given dimension, specify 0.
178 //
179 // The program progresses as follows:
180 // 1) Read the input series
181 // 2) Resample the series according to the user specified x-y-z
182 //    spacing.
183 // 3) Create a MetaDataDictionary for each slice.
184 // 4) Shift data to undo the effect of a rescale intercept by the
185 //    DICOM reader (only for ITK < 4.6)
186 // 5) Write the new DICOM series
187 //
188  
189
190  
191  
192   // Validate input parameters
193  
194   const unsigned int InputDimension = 3;
195   const unsigned int OutputDimension = 2;
196  
197  
198   typedef itk::Image< PixelType, InputDimension >
199     InputImageType;
200   typedef itk::Image< PixelType, OutputDimension >
201     OutputImageType;
202   typedef itk::ImageSeriesReader< InputImageType >
203     ReaderType;
204   typedef itk::GDCMImageIO
205     ImageIOType;
206   typedef itk::GDCMSeriesFileNames
207     InputNamesGeneratorType;
208   typedef itk::NumericSeriesFileNames
209     OutputNamesGeneratorType;
210   typedef itk::IdentityTransform< double, InputDimension >
211     TransformType;
212   typedef itk::LinearInterpolateImageFunction< InputImageType, double >
213     InterpolatorType;
214   typedef itk::ResampleImageFilter< InputImageType, InputImageType >
215     ResampleFilterType;
216 #if ( ( ITK_VERSION_MAJOR == 4 ) && ( ITK_VERSION_MINOR < 6 ) )
217   typedef itk::ShiftScaleImageFilter< InputImageType, InputImageType >
218     ShiftScaleType;
219 #endif
220   typedef itk::ImageSeriesWriter< InputImageType, OutputImageType >
221     SeriesWriterType;
222  
223 ////////////////////////////////////////////////
224 // 1) Read the input series
225
226 // Read the input (MHD file)
227   typedef typename InputImageType::RegionType RegionType;
228   typedef typename RegionType::SizeType SizeType;
229   typedef itk::ImageFileReader<InputImageType> InputReaderType;
230   typename InputReaderType::Pointer volumeReader = InputReaderType::New();
231   volumeReader->SetFileName( m_ArgsInfo.input_arg );
232   volumeReader->Update();
233   
234   typename InputImageType::Pointer input = volumeReader->GetOutput();
235  
236   ImageIOType::Pointer gdcmIO = ImageIOType::New();
237   gdcmIO->LoadPrivateTagsOn();
238   InputNamesGeneratorType::Pointer inputNames = InputNamesGeneratorType::New();
239   inputNames->SetInputDirectory( m_ArgsInfo.inputDir_arg );
240  
241   const typename ReaderType::FileNamesContainer & filenames =
242                             inputNames->GetInputFileNames();
243  
244   typename ReaderType::Pointer reader = ReaderType::New();
245  
246   reader->SetImageIO( gdcmIO );
247   reader->SetFileNames( filenames );
248   try
249     {
250     reader->Update();
251     }
252   catch (itk::ExceptionObject &excp)
253     {
254     std::cerr << "Exception thrown while reading the series" << std::endl;
255     std::cerr << excp << std::endl;
256     return;
257     }
258     typename InputImageType::SpacingType outputSpacing;
259     typename InputImageType::SizeType   outputSize;
260     for (unsigned int i = 0; i < 3; i++)
261     {
262       outputSpacing[i] = input->GetSpacing()[i];
263       outputSize[i] = input->GetLargestPossibleRegion().GetSize()[i];
264     }
265  
266 ////////////////////////////////////////////////
267 // 2) Resample the series
268 /*  typename InterpolatorType::Pointer interpolator = InterpolatorType::New();
269  
270   TransformType::Pointer transform = TransformType::New();
271   transform->SetIdentity();
272  
273   const typename InputImageType::SpacingType& inputSpacing =
274     reader->GetOutput()->GetSpacing();
275   const typename InputImageType::RegionType& inputRegion =
276     reader->GetOutput()->GetLargestPossibleRegion();
277   const typename InputImageType::SizeType& inputSize =
278     inputRegion.GetSize();
279  
280   std::cout << "The input series in directory " << m_ArgsInfo.inputDir_arg
281             << " has " << filenames.size() << " files with spacing "
282             << inputSpacing
283             << std::endl;
284  
285   // Compute the size of the output. The user specifies a spacing on
286   // the command line. If the spacing is 0, the input spacing will be
287   // used. The size (# of pixels) in the output is recomputed using
288   // the ratio of the input and output sizes.
289   typename InputImageType::SpacingType outputSpacing;
290  
291   bool changeInSpacing = false;
292   for (unsigned int i = 0; i < 3; i++)
293     {
294       outputSpacing[i] = inputSpacing[i];
295     }
296   typename InputImageType::SizeType   outputSize;
297   typedef typename InputImageType::SizeType::SizeValueType SizeValueType;
298   outputSize[0] = static_cast<SizeValueType>(inputSize[0] * inputSpacing[0] / outputSpacing[0] + .5);
299   outputSize[1] = static_cast<SizeValueType>(inputSize[1] * inputSpacing[1] / outputSpacing[1] + .5);
300   outputSize[2] = static_cast<SizeValueType>(inputSize[2] * inputSpacing[2] / outputSpacing[2] + .5);
301  
302   typename ResampleFilterType::Pointer resampler = ResampleFilterType::New();
303   resampler->SetInput( reader->GetOutput() );
304   resampler->SetTransform( transform );
305   resampler->SetInterpolator( interpolator );
306   resampler->SetOutputOrigin ( reader->GetOutput()->GetOrigin());
307   resampler->SetOutputSpacing ( outputSpacing );
308   resampler->SetOutputDirection ( reader->GetOutput()->GetDirection());
309   resampler->SetSize ( outputSize );
310   resampler->Update ();
311  
312  */
313  
314 ////////////////////////////////////////////////
315 // 3) Create a MetaDataDictionary for each slice.
316  
317   // Copy the dictionary from the first image and override slice
318   // specific fields
319   typename ReaderType::DictionaryRawPointer inputDict = (*(reader->GetMetaDataDictionaryArray()))[0];
320   typename ReaderType::DictionaryArrayType outputArray;
321  
322   // To keep the new series in the same study as the original we need
323   // to keep the same study UID. But we need new series and frame of
324   // reference UID's.
325 #if ITK_VERSION_MAJOR >= 4
326   gdcm::UIDGenerator suid;
327   std::string seriesUID = suid.Generate();
328   gdcm::UIDGenerator fuid;
329   std::string frameOfReferenceUID = fuid.Generate();
330 #else
331   std::string seriesUID = gdcm::Util::CreateUniqueUID( gdcmIO->GetUIDPrefix());
332   std::string frameOfReferenceUID = gdcm::Util::CreateUniqueUID( gdcmIO->GetUIDPrefix());
333 #endif
334   std::string studyUID;
335   std::string sopClassUID;
336   itk::ExposeMetaData<std::string>(*inputDict, "0020|000d", studyUID);
337   itk::ExposeMetaData<std::string>(*inputDict, "0008|0016", sopClassUID);
338   gdcmIO->KeepOriginalUIDOn();
339  
340   for (unsigned int f = 0; f < outputSize[2]; f++)
341     {
342     // Create a new dictionary for this slice
343     typename ReaderType::DictionaryRawPointer dict = new typename ReaderType::DictionaryType;
344  
345     // Copy the dictionary from the first slice
346     //CopyDictionary (*inputDict, *dict);
347     
348     typedef itk::MetaDataDictionary DictionaryType;
349
350     DictionaryType::ConstIterator itrDic = (*inputDict).Begin();
351     DictionaryType::ConstIterator endDic = (*inputDict).End();
352     typedef itk::MetaDataObject< std::string > MetaDataStringType;
353  
354     while( itrDic != endDic )
355     {
356       itk::MetaDataObjectBase::Pointer  entry = itrDic->second;
357  
358       MetaDataStringType::Pointer entryvalue =
359       dynamic_cast<MetaDataStringType *>( entry.GetPointer() ) ;
360       if( entryvalue )
361       {
362         std::string tagkey   = itrDic->first;
363         std::string tagvalue = entryvalue->GetMetaDataObjectValue();
364         itk::EncapsulateMetaData<std::string>(*dict, tagkey, tagvalue);
365       }
366       ++itrDic;
367     }
368  
369     // Set the UID's for the study, series, SOP  and frame of reference
370     itk::EncapsulateMetaData<std::string>(*dict,"0020|000d", studyUID);
371     itk::EncapsulateMetaData<std::string>(*dict,"0020|000e", seriesUID);
372     itk::EncapsulateMetaData<std::string>(*dict,"0020|0052", frameOfReferenceUID);
373  
374 #if ITK_VERSION_MAJOR >= 4
375     gdcm::UIDGenerator sopuid;
376     std::string sopInstanceUID = sopuid.Generate();
377 #else
378     std::string sopInstanceUID = gdcm::Util::CreateUniqueUID( gdcmIO->GetUIDPrefix());
379 #endif
380     itk::EncapsulateMetaData<std::string>(*dict,"0008|0018", sopInstanceUID);
381     itk::EncapsulateMetaData<std::string>(*dict,"0002|0003", sopInstanceUID);
382  
383     // Change fields that are slice specific
384     std::ostringstream value;
385     value.str("");
386     //unsigned int f = 0;
387     value << f + 1;
388  
389     // Image Number
390     itk::EncapsulateMetaData<std::string>(*dict,"0020|0013", value.str());
391  
392     // Series Description - Append new description to current series
393     // description
394     std::string oldSeriesDesc;
395     itk::ExposeMetaData<std::string>(*inputDict, "0008|103e", oldSeriesDesc);
396  
397     value.str("");
398     value << oldSeriesDesc
399           << ": Resampled with pixel spacing "
400           << outputSpacing[0] << ", "
401           << outputSpacing[1] << ", "
402           << outputSpacing[2];
403     // This is an long string and there is a 64 character limit in the
404     // standard
405     unsigned lengthDesc = value.str().length();
406  
407     std::string seriesDesc( value.str(), 0,
408                             lengthDesc > 64 ? 64
409                             : lengthDesc);
410     itk::EncapsulateMetaData<std::string>(*dict,"0008|103e", seriesDesc);
411  
412     // Series Number
413     value.str("");
414     value << 1001;
415     itk::EncapsulateMetaData<std::string>(*dict,"0020|0011", value.str());
416  
417     // Derivation Description - How this image was derived
418     value.str("");
419
420     value << ": " << ITK_SOURCE_VERSION;
421  
422     lengthDesc = value.str().length();
423     std::string derivationDesc( value.str(), 0,
424                                 lengthDesc > 1024 ? 1024
425                                 : lengthDesc);
426     itk::EncapsulateMetaData<std::string>(*dict,"0008|2111", derivationDesc);
427  
428     // Image Position Patient: This is calculated by computing the
429     // physical coordinate of the first pixel in each slice.
430     typename InputImageType::PointType position;
431     typename InputImageType::IndexType index;
432     index[0] = 0;
433     index[1] = 0;
434     index[2] = f;
435     input->TransformIndexToPhysicalPoint(index, position);
436  
437     value.str("");
438     value << position[0] << "\\" << position[1] << "\\" << position[2];
439     itk::EncapsulateMetaData<std::string>(*dict,"0020|0032", value.str());
440     // Slice Location: For now, we store the z component of the Image
441     // Position Patient.
442     value.str("");
443     value << position[2];
444     itk::EncapsulateMetaData<std::string>(*dict,"0020|1041", value.str());
445  
446
447       // Slice Thickness: For now, we store the z spacing
448       value.str("");
449       value << outputSpacing[2];
450       itk::EncapsulateMetaData<std::string>(*dict,"0018|0050",
451                                             value.str());
452       // Spacing Between Slices
453       itk::EncapsulateMetaData<std::string>(*dict,"0018|0088",
454                                             value.str());
455       
456       /*
457       value.str("");
458       value << 0.999987 << "\\" << -0.005061 << "\\" << 0.000000 << "\\" << 0.000000 << "\\" << 0.000000 << "\\" << -1.000000;
459       itk::EncapsulateMetaData<std::string>(*dict, "0020|0037", value.str());
460        
461       value.str("");
462       value << 196;
463       itk::EncapsulateMetaData<std::string>(*dict, "0002|0000", value.str());
464       value.str("");
465       value << 510;
466       itk::EncapsulateMetaData<std::string>(*dict, "0008|0000", value.str());
467       value.str("");
468       value << 362;
469       itk::EncapsulateMetaData<std::string>(*dict, "0009|0000", value.str());
470       value.str("");
471       value << 116;
472       itk::EncapsulateMetaData<std::string>(*dict, "0010|0000", value.str());
473       value.str("");
474       value << 1008;
475       itk::EncapsulateMetaData<std::string>(*dict, "0011|0000", value.str());
476       value.str("");
477       value << 0 << "\\" << 0;
478       itk::EncapsulateMetaData<std::string>(*dict, "0011|1011", value.str());
479       value.str("");
480       value << 1 << "\\" << 1;
481       itk::EncapsulateMetaData<std::string>(*dict, "0011|1015", value.str());
482       value.str("");
483       value << 1 << "\\" << 2;
484       itk::EncapsulateMetaData<std::string>(*dict, "0011|1016", value.str());
485       value.str("");
486       value << 0 << "\\" << 0;
487       itk::EncapsulateMetaData<std::string>(*dict, "0011|1017", value.str());
488       value.str("");
489       value << 0 << "\\" << 0;
490       itk::EncapsulateMetaData<std::string>(*dict, "0011|1018", value.str());
491       value.str("");
492       value << 0 << "\\" << 0;
493       itk::EncapsulateMetaData<std::string>(*dict, "0011|1019", value.str());
494       value.str("");
495       value << 0 << "\\" << 0;
496       itk::EncapsulateMetaData<std::string>(*dict, "0011|101a", value.str());
497       value.str("");
498       value << 0 << "\\" << 0;
499       itk::EncapsulateMetaData<std::string>(*dict, "0011|101f", value.str());
500       value.str("");
501       value << 0 << "\\" << 0;
502       itk::EncapsulateMetaData<std::string>(*dict, "0011|1026", value.str());
503       value.str("");
504       value << 0 << "\\" << 0 << "\\" << 0 << "\\" << 0;
505       itk::EncapsulateMetaData<std::string>(*dict, "0011|1027", value.str());
506       value.str("");
507       value << 0 << "\\" << 0 << "\\" << 0 << "\\" << 0;
508       itk::EncapsulateMetaData<std::string>(*dict, "0011|1028", value.str());
509       value.str("");
510       value << 0 << "\\" << 0;
511       itk::EncapsulateMetaData<std::string>(*dict, "0011|102c", value.str());
512       value.str("");
513       value << 0 << "\\" << 0;
514       itk::EncapsulateMetaData<std::string>(*dict, "0011|102d", value.str());
515       value.str("");
516       value << 0 << "\\" << 0;
517       itk::EncapsulateMetaData<std::string>(*dict, "0011|102e", value.str());
518       std::ostringstream valueVec[2];
519       valueVec[0].str("");
520       valueVec[0] << 32767;
521       valueVec[1].str("");
522       valueVec[1] << 32767;
523       std::string valueVec2[2];
524       valueVec2[0]=valueVec[0].str();
525       valueVec2[1]=valueVec[1].str();
526       itk::EncapsulateMetaData<std::string*>(*dict, "0011|102f", valueVec2);
527       value.str("");
528       value << 1 ;
529       itk::EncapsulateMetaData<std::string>(*dict, "0020|1011", value.str());
530       value.str("");
531       value << 63 ;
532       itk::EncapsulateMetaData<std::string>(*dict, "0028|0107", value.str());
533       
534       value.str("");
535       value << 0 ;
536       itk::EncapsulateMetaData<std::string>(*dict, "0018|1130", value.str());
537       value.str("");
538       value << 563.7 ;
539       itk::EncapsulateMetaData<std::string>(*dict, "0018|1131", value.str());
540       value.str("");
541       value << "CC" ;
542       itk::EncapsulateMetaData<std::string>(*dict, "0018|1140", value.str());
543       value.str("");
544       value << 243.5 ;
545       itk::EncapsulateMetaData<std::string>(*dict, "0018|1142", value.str());
546       value.str("");
547       value << 360 ;
548       itk::EncapsulateMetaData<std::string>(*dict, "0018|1143", value.str());
549       value.str("");
550       value << 6 ;
551       itk::EncapsulateMetaData<std::string>(*dict, "0018|1144", value.str());
552       value.str("");
553       value << 10000 ;
554       itk::EncapsulateMetaData<std::string>(*dict, "0018|1242", value.str());
555       value.str("");
556       value << 60 ;
557       itk::EncapsulateMetaData<std::string>(*dict, "0054|0053", value.str());
558       value.str("");
559       value << 180.29 ;
560       itk::EncapsulateMetaData<std::string>(*dict, "0054|0200", value.str());
561       value.str("");
562       value << "F-10450" ;
563       itk::EncapsulateMetaData<std::string>(*dict, "0008|0100", value.str());
564       value.str("");
565       value << "99SDM" ;
566       itk::EncapsulateMetaData<std::string>(*dict, "0008|0102", value.str());
567       value.str("");
568       value << "recumbent" ;
569       itk::EncapsulateMetaData<std::string>(*dict, "0008|0104", value.str());
570       value.str("");
571       value << 114 ;
572       itk::EncapsulateMetaData<std::string>(*dict, "0054|0014", value.str());
573       value.str("");
574       value << 126 ;
575       itk::EncapsulateMetaData<std::string>(*dict, "0054|0015", value.str());
576       value.str("");
577       value << "Tc99m_SC" ;
578       itk::EncapsulateMetaData<std::string>(*dict, "0054|0018", value.str());
579       value.str("");
580       value << 0 ;
581       itk::EncapsulateMetaData<std::string>(*dict, "0018|1120", value.str());
582       value.str("");
583       value << 0 ;
584       itk::EncapsulateMetaData<std::string>(*dict, "0018|1145", value.str());
585       value.str("");
586       value << 0 << "\\" << 0;
587       itk::EncapsulateMetaData<std::string>(*dict, "0018|1149", value.str());
588       value.str("");
589       value << "LEHR" ;
590       itk::EncapsulateMetaData<std::string>(*dict, "0018|1180", value.str());
591       value.str("");
592       value << "PARA" ;
593       itk::EncapsulateMetaData<std::string>(*dict, "0018|1181", value.str());
594       value.str("");
595       value << 0 ;
596       itk::EncapsulateMetaData<std::string>(*dict, "0018|1182", value.str());
597       value.str("");
598       value << 0 ;
599       itk::EncapsulateMetaData<std::string>(*dict, "0018|1183", value.str());
600       value.str("");
601       value << 0 ;
602       itk::EncapsulateMetaData<std::string>(*dict, "0018|1184", value.str());
603       value.str("");
604       value << 1.000000 << "\\" << 1.000000 ;
605       itk::EncapsulateMetaData<std::string>(*dict, "0028|0031", value.str());
606       value.str("");
607       value << 0.000000 << "\\" << 0.000000 ;
608       itk::EncapsulateMetaData<std::string>(*dict, "0028|0032", value.str());
609       value.str("");
610       value << 0 ;
611       itk::EncapsulateMetaData<std::string>(*dict, "0011|101c", value.str());
612       value.str("");
613       value << 0 ;
614       itk::EncapsulateMetaData<std::string>(*dict, "0011|101d", value.str());
615       value.str("");
616       value << 0 ;
617       itk::EncapsulateMetaData<std::string>(*dict, "0013|1016", value.str());
618       value.str("");
619       value << 0 ;
620       itk::EncapsulateMetaData<std::string>(*dict, "0013|1017", value.str());
621       value.str("");
622       value << 0 ;
623       itk::EncapsulateMetaData<std::string>(*dict, "0011|1023", value.str());
624       value.str("");
625       value << 0 ;
626       itk::EncapsulateMetaData<std::string>(*dict, "0011|1024", value.str());
627       value.str("");
628       value << 0 ;
629       itk::EncapsulateMetaData<std::string>(*dict, "0011|1025", value.str());
630       value.str("");
631       value << 0 ;
632       itk::EncapsulateMetaData<std::string>(*dict, "0011|1029", value.str());
633       value.str("");
634       value << 0 ;
635       itk::EncapsulateMetaData<std::string>(*dict, "0011|103e", value.str());
636       value.str("");
637       value << 0 ;
638       itk::EncapsulateMetaData<std::string>(*dict, "0013|1018", value.str());
639       value.str("");
640       value << 0 ;
641       itk::EncapsulateMetaData<std::string>(*dict, "0013|1019", value.str());
642       value.str("");
643       value << 0 ;
644       itk::EncapsulateMetaData<std::string>(*dict, "0013|101a", value.str());
645       value.str("");
646       value << "GEMS_GENIE_1" ;
647       itk::EncapsulateMetaData<std::string>(*dict, "0035|0010", value.str());
648       value.str("");
649       value << 29 ;
650       itk::EncapsulateMetaData<std::string>(*dict, "0035|1001", value.str());
651       
652  */
653     // Save the dictionary
654     outputArray.push_back(dict);
655     }
656  
657 #if ( ( ITK_VERSION_MAJOR == 4 ) && ( ITK_VERSION_MINOR < 6 ) )
658 ////////////////////////////////////////////////
659 // 4) Shift data to undo the effect of a rescale intercept by the
660 //    DICOM reader
661   std::string interceptTag("0028|1052");
662   typedef itk::MetaDataObject< std::string > MetaDataStringType;
663   itk::MetaDataObjectBase::Pointer entry = (*inputDict)[interceptTag];
664  
665   MetaDataStringType::ConstPointer interceptValue =
666     dynamic_cast<const MetaDataStringType *>( entry.GetPointer() ) ;
667  
668   int interceptShift = 0;
669   if( interceptValue )
670     {
671     std::string tagValue = interceptValue->GetMetaDataObjectValue();
672     interceptShift = -atoi ( tagValue.c_str() );
673     }
674  
675   ShiftScaleType::Pointer shiftScale = ShiftScaleType::New();
676   shiftScale->SetInput( resampler->GetOutput());
677   shiftScale->SetShift( interceptShift );
678 #endif
679  
680 ////////////////////////////////////////////////
681 // 5) Write the new DICOM series
682  
683   // Make the output directory and generate the file names.
684   itksys::SystemTools::MakeDirectory( m_ArgsInfo.outputDir_arg );
685  
686   // Generate the file names
687   OutputNamesGeneratorType::Pointer outputNames = OutputNamesGeneratorType::New();
688   std::string seriesFormat(m_ArgsInfo.outputDir_arg);
689   seriesFormat = seriesFormat + "/" + "IM%d.dcm";
690   outputNames->SetSeriesFormat (seriesFormat.c_str());
691   outputNames->SetStartIndex (1);
692   //outputNames->SetEndIndex (1);
693   outputNames->SetEndIndex (outputSize[2]);
694  
695   typename SeriesWriterType::Pointer seriesWriter = SeriesWriterType::New();
696 #if ( ( ITK_VERSION_MAJOR == 4 ) && ( ITK_VERSION_MINOR < 6 ) )
697   seriesWriter->SetInput( input );
698 #else
699   seriesWriter->SetInput( input );
700 #endif
701     seriesWriter->SetImageIO( gdcmIO );
702     seriesWriter->SetFileNames( outputNames->GetFileNames() );
703     seriesWriter->SetMetaDataDictionaryArray( &outputArray );
704   try
705     {
706     seriesWriter->Update();
707     }
708   catch( itk::ExceptionObject & excp )
709     {
710     std::cerr << "Exception thrown while writing the series " << std::endl;
711     std::cerr << excp << std::endl;
712     return;
713     }
714   std::cout << "The output series in directory " << m_ArgsInfo.outputDir_arg
715             << " has " << outputSize[2] << " files with spacing "
716             << outputSpacing
717             << std::endl;
718   return;
719 }
720
721  
722 /*void CopyDictionary (itk::MetaDataDictionary &fromDict, itk::MetaDataDictionary &toDict)
723 {
724   typedef itk::MetaDataDictionary DictionaryType;
725  
726   DictionaryType::ConstIterator itr = fromDict.Begin();
727   DictionaryType::ConstIterator end = fromDict.End();
728   typedef itk::MetaDataObject< std::string > MetaDataStringType;
729  
730   while( itr != end )
731     {
732     itk::MetaDataObjectBase::Pointer  entry = itr->second;
733  
734     MetaDataStringType::Pointer entryvalue =
735       dynamic_cast<MetaDataStringType *>( entry.GetPointer() ) ;
736     if( entryvalue )
737       {
738       std::string tagkey   = itr->first;
739       std::string tagvalue = entryvalue->GetMetaDataObjectValue();
740       itk::EncapsulateMetaData<std::string>(toDict, tagkey, tagvalue);
741       }
742     ++itr;
743     }
744 } */
745
746
747 }//end clitk
748
749 #endif //#define clitkImage2DicomSeriesGenericFilter_txx