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