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