]> Creatis software - clitk.git/blob - tools/clitkDicom2Image.cxx
bug in Z origin in clitkDicom2Image
[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 //====================================================================
34 int main(int argc, char * argv[])
35 {
36   // init command line
37   GGO(clitkDicom2Image, args_info);
38   std::vector<std::string> input_files;
39   ///if std_input is given, read the input files from stdin
40   if (args_info.std_input_given) {
41     while (true) {
42       std::string tmp;
43       std::cin >> tmp;
44       if(std::cin.good())
45         input_files.push_back(tmp);
46       else break;
47     }
48     args_info.inputs_num=input_files.size();
49   } else for (unsigned int i=0; i<args_info.inputs_num; i++)
50       input_files.push_back(args_info.inputs[i]);
51
52
53   //===========================================
54   /// Get slices locations ...
55   std::vector<double> theorigin(3);
56   std::vector<double> sliceLocations;
57   for(unsigned int i=0; i<args_info.inputs_num; i++) {
58     //std::cout << "Reading <" << input_files[i] << std::endl;
59 #if GDCM_MAJOR_VERSION == 2
60     gdcm::Reader hreader;
61     hreader.SetFileName(input_files[i].c_str());
62     hreader.Read();
63     theorigin = gdcm::ImageHelper::GetOriginValue(hreader.GetFile());
64     sliceLocations.push_back(theorigin[2]);
65     gdcm::Attribute<0x28, 0x100> pixel_size;
66     gdcm::DataSet& ds = hreader.GetFile().GetDataSet();
67     pixel_size.SetFromDataSet(ds);
68     if (pixel_size.GetValue() != 16)
69     {
70       std::cerr << "Pixel type 2 bytes ! " << std::endl;
71       std::cerr << "In file " << input_files[i] << std::endl;
72       exit(0);
73     }
74 #else
75   gdcm::File *header = new gdcm::File();
76   header->SetFileName(input_files[i]);
77   header->SetMaxSizeLoadEntry(16384); // required ?
78   header->Load();
79   theorigin[0] = header->GetXOrigin();
80   theorigin[1] = header->GetYOrigin();
81   theorigin[2] = header->GetZOrigin();
82   sliceLocations.push_back(theorigin[2]);
83   if (header->GetPixelSize() != 2) {
84     std::cerr << "Pixel type 2 bytes ! " << std::endl;
85     std::cerr << "In file " << input_files[i] << std::endl;
86     exit(0);
87   }
88 #endif
89   }
90
91   //===========================================
92   // Sort slices locations ...
93   std::vector<int> sliceIndex;
94   clitk::GetSortedIndex(sliceLocations, sliceIndex);
95   if (args_info.verboseSliceLocation_flag) {
96     std::cout << sliceLocations[sliceIndex[0]] << " -> "
97               << sliceIndex[0] << " / " << 0 << " => "
98               << "0 mm "
99               << input_files[sliceIndex[0]]
100               << std::endl;
101     for(unsigned int i=1; i<sliceIndex.size(); i++) {
102       std::cout << sliceLocations[sliceIndex[i]] << " -> "
103                 << sliceIndex[i] << " / " << i << " => "
104                 << sliceLocations[sliceIndex[i]] - sliceLocations[sliceIndex[i-1]]
105                 << "mm "
106                 << input_files[sliceIndex[i]]
107                 << std::endl;
108     }
109   }
110
111   //===========================================
112   // Analyze slices locations ...
113   double currentDist;
114   double dist=0;
115   double tolerance = args_info.tolerance_arg;
116   double previous = sliceLocations[sliceIndex[0]];
117   for(unsigned int i=1; i<sliceIndex.size(); i++) {
118     currentDist = sliceLocations[sliceIndex[i]]-previous;
119     if (i!=1) {
120       if (fabs(dist-currentDist) > tolerance) {
121         std::cout << "ERROR : " << std::endl
122                   << "Current slice pos is  = " << sliceLocations[sliceIndex[i]] << std::endl
123                   << "Previous slice pos is = " << previous << std::endl
124                   << "Current file is       = " << input_files[sliceIndex[i]] << std::endl
125                   << "Current index is      = " << i << std::endl
126                   << "Current sortindex is  = " << sliceIndex[i] << std::endl
127                   << "Current slice diff    = " << dist << std::endl
128                   << "Current error         = " << fabs(dist-currentDist) << std::endl;
129         exit(1);
130       }
131     } else dist = currentDist;
132     previous = sliceLocations[sliceIndex[i]];
133   }
134
135   //===========================================
136   // Create ordered vector of filenames
137   std::vector<std::string> sorted_files;
138   sorted_files.resize(sliceIndex.size());
139   for(unsigned int i=0; i<sliceIndex.size(); i++)
140     sorted_files[i] = input_files[ sliceIndex[i] ];
141
142   //===========================================
143   // Read write serie
144   vvImageReader::Pointer reader = vvImageReader::New();
145   reader->SetInputFilenames(sorted_files);
146   reader->Update(vvImageReader::DICOM);
147   if (reader->GetLastError().size() != 0) {
148     std::cerr << reader->GetLastError() << std::endl;
149     return 1;
150   }
151   
152   vvImage::Pointer image = reader->GetOutput();
153   vtkImageData* vtk_image = image->GetFirstVTKImageData();
154   vtkImageChangeInformation* modifier = vtkImageChangeInformation::New();
155   if  (args_info.focal_origin_given) {
156     std::vector<double> spacing = image->GetSpacing();
157     std::vector<int> size = image->GetSize();
158     theorigin[0] = -spacing[0]*size[0]/2.0;
159     theorigin[1] = -spacing[1]*size[1]/2.0;
160     modifier->SetInput(vtk_image);
161     modifier->SetOutputOrigin(theorigin[0], theorigin[1], sliceLocations[sliceIndex[0]]);
162     modifier->Update();
163     vvImage::Pointer focal_image = vvImage::New();
164     focal_image->AddVtkImage(modifier->GetOutput());
165     image = focal_image;
166   }
167
168   vvImageWriter::Pointer writer = vvImageWriter::New();
169   writer->SetInput(image);
170   writer->SetOutputFileName(args_info.output_arg);
171   writer->Update();
172
173   modifier->Delete();
174
175   return 0;
176 }