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