]> Creatis software - clitk.git/blob - tools/clitkDicom2Image.cxx
Image Orientation with Dicom debug
[clitk.git] / tools / clitkDicom2Image.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 // clitk includes
20 #include "clitkDicom2Image_ggo.h"
21 #include "clitkCommon.h"
22 #include "clitkImageCommon.h"
23 #include "vvImageReader.h"
24 #include "vvImageWriter.h"
25 #include <gdcmFile.h>
26 #include <vtkVersion.h>
27 #include <vtkImageChangeInformation.h>
28 #if GDCM_MAJOR_VERSION == 2
29   #include <gdcmImageHelper.h>
30   #include <gdcmAttribute.h>
31   #include <gdcmReader.h>
32 #endif
33
34 #include <set>
35
36 //====================================================================
37 int main(int argc, char * argv[])
38 {
39   // init command line
40   GGO(clitkDicom2Image, args_info);
41   std::vector<std::string> input_files;
42   ///if std_input is given, read the input files from stdin
43   if (args_info.std_input_given) {
44     while (true) {
45       std::string tmp;
46       std::cin >> tmp;
47       if(std::cin.good())
48         input_files.push_back(tmp);
49       else break;
50     }
51     args_info.inputs_num=input_files.size();
52   } else for (unsigned int i=0; i<args_info.inputs_num; i++)
53       input_files.push_back(args_info.inputs[i]);
54
55
56   //===========================================
57   /// Get slices locations ...
58   int series_number = -1;
59   std::set<int> series_numbers;
60   std::map< int, std::vector<double> > theorigin;
61   std::map< int, std::vector<double> > theorientation;
62   std::map< int, std::vector<double> > sliceLocations;
63   std::map< int, std::vector<std::string> > seriesFiles;
64 #if GDCM_MAJOR_VERSION == 2
65   if (args_info.verbose_flag)
66     std::cout << "Using GDCM-2.x" << std::endl;
67 #else
68   if (args_info.verbose_flag) {
69     std::cout << "Not using GDCM-2.x" << std::endl;
70     std::cout<< "The image orientation is not supported with this version of GDCM" <<std::endl;
71   }
72 #endif
73   for(unsigned int i=0; i<args_info.inputs_num; i++) {
74     if (args_info.verbose_flag)
75         std::cout << "Reading <" << input_files[i] << std::endl;
76 #if GDCM_MAJOR_VERSION == 2
77     gdcm::Reader hreader;
78     hreader.SetFileName(input_files[i].c_str());
79     hreader.Read();
80     gdcm::DataSet& ds = hreader.GetFile().GetDataSet();
81
82     if (args_info.extract_series_flag) {
83       gdcm::Attribute<0x20,0x11> series_number_att;
84       series_number_att.SetFromDataSet(ds);
85       series_number = series_number_att.GetValue();
86     }
87     
88     series_numbers.insert(series_number);
89     theorigin[series_number] = gdcm::ImageHelper::GetOriginValue(hreader.GetFile());
90     theorientation[series_number] = gdcm::ImageHelper::GetDirectionCosinesValue(hreader.GetFile());
91     double n1 = theorientation[series_number][1]*theorientation[series_number][5]-
92                 theorientation[series_number][2]*theorientation[series_number][4];
93     double n2 = theorientation[series_number][3]*theorientation[series_number][2]-
94                 theorientation[series_number][5]*theorientation[series_number][0];
95     double n3 = theorientation[series_number][0]*theorientation[series_number][4]-
96                 theorientation[series_number][1]*theorientation[series_number][3];
97     double sloc = theorigin[series_number][0]*n1+
98                   theorigin[series_number][1]*n2+
99                   theorigin[series_number][2]*n3;
100     sliceLocations[series_number].push_back(sloc);
101     seriesFiles[series_number].push_back(input_files[i]);
102     
103     gdcm::Attribute<0x28, 0x100> pixel_size;
104     pixel_size.SetFromDataSet(ds);
105     /* if (pixel_size.GetValue() != 16)
106        {
107        std::cerr << "Pixel type not 2 bytes ! " << std::endl;
108        std::cerr << "In file " << input_files[i] << std::endl;
109        exit(0);
110        }
111     */
112 #else
113   gdcm::File *header = new gdcm::File();
114   header->SetFileName(input_files[i]);
115   header->SetMaxSizeLoadEntry(16384); // required ?
116   header->Load();
117
118   if (args_info.extract_series_flag) {
119     series_number = atoi(header->GetEntryValue(0x20,0x11).c_str());
120   }
121   
122   series_numbers.insert(series_number);
123   theorigin[series_number].resize(3);
124   theorigin[series_number][0] = header->GetXOrigin();
125   theorigin[series_number][1] = header->GetYOrigin();
126   theorigin[series_number][2] = header->GetZOrigin();
127   sliceLocations[series_number].push_back(theorigin[series_number][2]);
128   seriesFiles[series_number].push_back(input_files[i]);
129   /*if (header->GetPixelSize() != 2) {
130     std::cerr << "Pixel type 2 bytes ! " << std::endl;
131     std::cerr << "In file " << input_files[i] << std::endl;
132     exit(0);
133   }
134   */
135 #endif
136   }
137
138   //===========================================
139   // Sort slices locations ...
140   std::set<int>::iterator sn = series_numbers.begin();
141   while ( sn != series_numbers.end() ) {
142     std::vector<double> locs = sliceLocations[*sn];
143     std::vector<double> origin = theorigin[*sn];
144     std::vector<std::string> files = seriesFiles[*sn];
145     std::vector<int> sliceIndex;
146     clitk::GetSortedIndex(locs, sliceIndex);
147     if (args_info.verbose_flag) {
148       std::cout << locs[sliceIndex[0]] << " -> "
149                 << sliceIndex[0] << " / " << 0 << " => "
150                 << "0 mm "
151                 << files[sliceIndex[0]]
152                 << std::endl;
153       for(unsigned int i=1; i<sliceIndex.size(); i++) {
154         std::cout << locs[sliceIndex[i]] << " -> "
155                   << sliceIndex[i] << " / " << i << " => "
156                   << locs[sliceIndex[i]] - locs[sliceIndex[i-1]]
157                   << "mm "
158                   << files[sliceIndex[i]]
159                   << std::endl;
160       }
161     }
162
163     //===========================================
164     // Analyze slices locations ...
165     double currentDist;
166     double dist=0;
167     double tolerance = args_info.tolerance_arg;
168     double previous = locs[sliceIndex[0]];
169     for(unsigned int i=1; i<sliceIndex.size(); i++) {
170       currentDist = locs[sliceIndex[i]]-previous;
171       if (i!=1) {
172         if (fabs(dist-currentDist) > tolerance) {
173           std::cout << "ERROR : " << std::endl
174                     << "Current slice pos is  = " << locs[sliceIndex[i]] << std::endl
175                     << "Previous slice pos is = " << previous << std::endl
176                     << "Current file is       = " << files[sliceIndex[i]] << std::endl
177                     << "Current index is      = " << i << std::endl
178                     << "Current sortindex is  = " << sliceIndex[i] << std::endl
179                     << "Current slice diff    = " << dist << std::endl
180                     << "Current error         = " << fabs(dist-currentDist) << std::endl;
181           exit(1);
182         }
183       } else dist = currentDist;
184       previous = locs[sliceIndex[i]];
185     }
186
187     //===========================================
188     // Create ordered vector of filenames
189     std::vector<std::string> sorted_files;
190     sorted_files.resize(sliceIndex.size());
191     for(unsigned int i=0; i<sliceIndex.size(); i++)
192       sorted_files[i] = files[ sliceIndex[i] ];
193
194     //===========================================
195     // Read write serie
196     vvImageReader::Pointer reader = vvImageReader::New();
197     reader->SetInputFilenames(sorted_files);
198     reader->Update(vvImageReader::DICOM);
199     if (reader->GetLastError().size() != 0) {
200       std::cerr << reader->GetLastError() << std::endl;
201       return 1;
202     }
203     
204     vvImage::Pointer image = reader->GetOutput();
205     vtkImageData* vtk_image = image->GetFirstVTKImageData();
206     vtkImageChangeInformation* modifier = vtkImageChangeInformation::New();
207     if  (args_info.focal_origin_given) {
208       std::vector<double> spacing = image->GetSpacing();
209       std::vector<int> size = image->GetSize();
210       origin[0] = -spacing[0]*size[0]/2.0;
211       origin[1] = -spacing[1]*size[1]/2.0;
212 #if VTK_MAJOR_VERSION <= 5
213       modifier->SetInput(vtk_image);
214 #else
215       modifier->SetInputData(vtk_image);
216 #endif
217       modifier->SetOutputOrigin(origin[0], origin[1], locs[sliceIndex[0]]);
218       modifier->Update();
219       vvImage::Pointer focal_image = vvImage::New();
220       focal_image->AddVtkImage(modifier->GetOutput());
221       image = focal_image;
222     }
223
224     std::string outfile;
225     if (series_numbers.size() == 1)
226       outfile = args_info.output_arg;
227     else {
228       std::ostringstream name;
229       name << *sn << "_" << args_info.output_arg;
230       outfile = name.str();
231     }
232     //Check on transform
233     bool bId = true;
234     for(unsigned int i=0; i<4; i++) {
235       for(unsigned int j=0; j<4; j++) {
236         double elt = image->GetTransform()[0]->GetMatrix()->GetElement(i,j);
237         if(i==j && elt!=1.) {
238           bId = false;
239         }
240         if(i!=j && elt!=0.) {
241           bId = false;
242         }
243       }
244     }
245     vvImageWriter::Pointer writer = vvImageWriter::New();
246     writer->SetInput(image);
247     if(!bId) {
248         writer->SetSaveTransform(true);
249     }
250     writer->SetOutputFileName(outfile);
251     writer->Update();
252
253     modifier->Delete();
254     
255     sn++;
256   }
257   
258   return 0;
259 }