]> Creatis software - clitk.git/blob - tools/clitkImageConvertGenericFilter.cxx
Set the Root Tree maximum size to 1TB instead of 1GB
[clitk.git] / tools / clitkImageConvertGenericFilter.cxx
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
19 #ifndef CLITKIMAGECONVERTGENERICFILTER_CXX
20 #define CLITKIMAGECONVERTGENERICFILTER_CXX
21
22 #include "clitkImageConvertGenericFilter.h"
23 #include "vvImageReader.h"
24 #include "vvImageWriter.h"
25 #include "itkFlipImageFilter.h"
26 #include "itkGDCMImageIO.h"
27 #include <itkChangeInformationImageFilter.h>
28
29 #include "gdcmReader.h"
30 #include "gdcmAttribute.h"
31 #include "gdcmPrinter.h"
32 #include "gdcmDict.h"
33 #include "gdcmStringFilter.h"
34
35 //--------------------------------------------------------------------
36 clitk::ImageConvertGenericFilter::ImageConvertGenericFilter():
37   clitk::ImageToImageGenericFilter<Self>("ImageConvert")
38 {
39   mOutputPixelTypeName = "NotSpecified";
40   mDisplayWarning = true;
41   mWarning = "";
42   mWarningOccur = false;
43   SetCorrectNegativeSpacingFlag(false);
44
45   InitializeImageType<2>();
46   InitializeImageType<3>();
47   InitializeImageType<4>();
48 }
49 //--------------------------------------------------------------------
50
51
52 //--------------------------------------------------------------------
53 template<unsigned int Dim>
54 void clitk::ImageConvertGenericFilter::InitializeImageType()
55 {
56   ADD_DEFAULT_IMAGE_TYPES(Dim);
57   ADD_VEC_IMAGE_TYPE(Dim, 2, float);
58   ADD_VEC_IMAGE_TYPE(Dim, 3, float);
59   ADD_VEC_IMAGE_TYPE(Dim, 2, double);
60   ADD_VEC_IMAGE_TYPE(Dim, 3, double);
61 }
62 //--------------------------------------------------------------------
63
64
65 //--------------------------------------------------------------------
66 template<class InputImageType>
67 void clitk::ImageConvertGenericFilter::UpdateWithInputImageType()
68 {
69   // Verbose stuff
70   if (m_IOVerbose) {
71     if (m_InputFilenames.size() == 1) {
72       std::cout << "Input image <" << m_InputFilenames[0] << "> is ";
73       itk::ImageIOBase::Pointer header = clitk::readImageHeader(m_InputFilenames[0]);
74       printImageHeader(header, std::cout);
75       std::cout << std::endl;
76     } else {
77       for(unsigned int i=0; i<m_InputFilenames.size(); i++) {
78         std::cout << "Input image " << i << " <" << m_InputFilenames[i] << "> is ";
79         itk::ImageIOBase::Pointer h = clitk::readImageHeader(m_InputFilenames[i]);
80         printImageHeader(h, std::cout);
81         std::cout << std::endl;
82       }
83     }
84   }
85
86   if(mVV) {
87     if (mOutputPixelTypeName != "NotSpecified" || m_WriteCompression) {
88       std::cerr << "--vv is not compatible with --compression and --type options." << std::endl;
89       exit(-1);
90     }
91
92     vvImageReader::Pointer reader = vvImageReader::New();
93     reader->SetInputFilenames(m_InputFilenames);
94     reader->Update(vvImageReader::IMAGE);
95
96     vvImageWriter::Pointer writer = vvImageWriter::New();
97     writer->SetOutputFileName(m_OutputFilenames.front());
98     writer->SetSaveTransform(true);
99     writer->SetInput(reader->GetOutput());
100     writer->Update();
101     return;
102   }
103   else if ((m_PixelTypeName == mOutputPixelTypeName) || (mOutputPixelTypeName == "NotSpecified")) {
104
105     // Get input image
106     typename InputImageType::Pointer input = this->template GetInput<InputImageType>(0);
107
108     if (mCorrectNegativeSpacingFlag) {
109       // Read dicom
110       gdcm::Reader reader;
111       reader.SetFileName(m_InputFilenames[0].c_str());
112       // if (!reader.CanReadFile(m_InputFilenames[0])) {
113       //   std::cout << "Error: " << m_InputFilenames[0] << " is not a dicom file. Abort." << std::endl;
114       //   exit(0);
115       // }
116       reader.Read();
117
118       // the dataset is the the set of element we are interested in:
119       gdcm::DataSet & ds = reader.GetFile().GetDataSet();
120
121       // Read the attribute SpacingBetweenSlices, check if negative and replace
122       gdcm::Attribute<0x0018,0x0088> SpacingBetweenSlices;
123       SpacingBetweenSlices.SetFromDataSet(ds);
124       double s = SpacingBetweenSlices.GetValue();
125       if (s >=0) {
126         std::cout << "Error: no negative spacing found SpacingBetweenSlices = " << s << " Abort. " << std::endl;
127         exit(0);
128       }
129       s = -s;
130
131       // Set spacing
132       typename InputImageType::SpacingType spacing = input->GetSpacing();
133       spacing[2] = s;
134       input->SetSpacing(spacing);
135
136       // Flip
137       typedef itk::FlipImageFilter< InputImageType >  FilterType;
138       typename FilterType::Pointer filter = FilterType::New();
139       typedef typename FilterType::FlipAxesArrayType     FlipAxesArrayType;
140       FlipAxesArrayType flipArray;
141       flipArray[0] = false;
142       flipArray[1] = false;
143       flipArray[2] = true;
144       filter->SetFlipAxes(flipArray);
145       filter->SetInput(input);
146       filter->Update();
147
148       // Read the attribute  Image Position (Patient)
149       gdcm::Tag  DetectorInformationSequenceTag(0x0054,0x0022);
150       const gdcm::DataElement & DIS = ds.GetDataElement(DetectorInformationSequenceTag);
151       if (!DIS.GetByteValue()) {
152         std::cout << "Error: could not find 0x0054,0x0022 tag. Abort." << std::endl;
153         exit(0);
154       }
155       gdcm::SmartPointer<gdcm::SequenceOfItems> sqf = DIS.GetValueAsSQ();
156       gdcm::Item & item = sqf->GetItem(1);
157       gdcm::DataSet & ds_position = item.GetNestedDataSet();
158       gdcm::Attribute<0x0020,0x0032> ImagePositionPatient;
159       ImagePositionPatient.SetFromDataSet(ds_position);
160       double x = ImagePositionPatient.GetValue(0);
161       double y = ImagePositionPatient.GetValue(1);
162       double z = ImagePositionPatient.GetValue(2);
163
164       // Set offset
165       typename InputImageType::PointType origin = input->GetOrigin();
166       origin[0] = x;
167       origin[1] = y;
168       origin[2] = z;
169       input->SetOrigin(origin);
170
171       // Orientation
172       typename InputImageType::DirectionType direction = input->GetDirection();
173       direction[2][2] = -1;
174       input->SetDirection(direction);
175
176       // Empty meta info
177       itk::MetaDataDictionary dict;// = new itk::MetaDataDictionary;
178       input->SetMetaDataDictionary(dict);
179     }
180
181     typedef itk::ChangeInformationImageFilter<InputImageType> CIType;
182     typename CIType::Pointer changeInfo = CIType::New();
183     if(mNoNiiMeta) {
184       changeInfo->SetInput(input);
185       typename CIType::PointType o = input->GetOrigin();
186       o[0] *= -1.;
187       o[1] *= -1.;
188       typename CIType::DirectionType d = input->GetDirection();
189       d[0][0] *= -1.;
190       d[1][1] *= -1.;
191       changeInfo->ChangeDirectionOn();
192       changeInfo->ChangeOriginOn();
193       changeInfo->SetOutputOrigin(o);
194       changeInfo->SetOutputDirection(d);
195       changeInfo->Update();
196       input = changeInfo->GetOutput();
197     }
198
199     this->SetNextOutput<InputImageType>(input);
200
201   } else {
202     // "trick" to call independent versions of update according to the
203     // pixel type (vector or scalar), using partial specializations
204     if (!UpdateWithSelectiveOutputType<InputImageType, ImageConvertTraits<typename InputImageType::PixelType>::IS_VECTOR>::Run(*this, mOutputPixelTypeName))
205       exit(-1);
206   }
207 }
208 //====================================================================
209
210 //====================================================================
211
212 template<class PixelType, class OutputPixelType>
213 void clitk::ImageConvertGenericFilter::CheckTypes(
214   std::string inType, std::string outType
215 )
216 {
217   std::ostringstream osstream;
218   if (std::numeric_limits<PixelType>::is_signed) {
219     if (!std::numeric_limits<OutputPixelType>::is_signed) {
220       osstream << "Warning, input type is signed (";
221     }
222   }
223   if (!std::numeric_limits<PixelType>::is_integer) {
224     if (std::numeric_limits<OutputPixelType>::is_integer) {
225       osstream << "Warning, input type is not integer (";
226     }
227   }
228   //  DD(std::numeric_limits<PixelType>::digits10);
229   // DD(std::numeric_limits<OutputPixelType>::digits10);
230   if (!std::numeric_limits<PixelType>::is_integer) {
231     if (std::numeric_limits<OutputPixelType>::is_integer) {
232       osstream << "Warning, input type is not integer (";
233     }
234   }
235   if (std::numeric_limits<PixelType>::digits10 > std::numeric_limits<OutputPixelType>::digits10) {
236     osstream << "Warning, possible loss of precision : input type is (" ;
237   }
238
239   if (!osstream.str().empty())
240   {
241     mWarningOccur = true;
242     osstream << inType << ") while output type is (" << outType << "), use at your own responsability." << std::endl;
243     mWarning = osstream.str();
244     if (mDisplayWarning) {
245       std::cerr << mWarning;
246     }
247   }
248 }
249
250
251 #endif /* end #define CLITKIMAGECONVERTGENERICFILTER_CXX */