1 /*=========================================================================
4 Module: $RCSfile: gdcmHeaderHelper.cxx,v $
6 Date: $Date: 2004/06/25 20:48:25 $
7 Version: $Revision: 1.40 $
9 Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
10 l'Image). All rights reserved. See Doc/License.txt or
11 http://www.creatis.insa-lyon.fr/Public/Gdcm/License.htm for details.
13 This software is distributed WITHOUT ANY WARRANTY; without even
14 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 PURPOSE. See the above copyright notices for more information.
17 =========================================================================*/
19 #include "gdcmHeaderHelper.h"
20 #include "gdcmDirList.h"
22 #include "gdcmDebug.h"
27 typedef std::vector<gdcmHeader* > GdcmHeaderVector;
28 //-----------------------------------------------------------------------------
29 // Constructor / Destructor
30 gdcmSerieHeader::gdcmSerieHeader()
32 CoherentGdcmFileList.clear();
35 gdcmSerieHeader::~gdcmSerieHeader()
38 for ( GdcmHeaderList::const_iterator it = CoherentGdcmFileList.begin();
39 it != CoherentGdcmFileList.end(); ++it)
43 CoherentGdcmFileList.clear();
46 //-----------------------------------------------------------------------------
49 //-----------------------------------------------------------------------------
52 * \brief add a gdcmFile to the list based on file name
53 * @param filename Name of the file to deal with
55 void gdcmSerieHeader::AddFileName(std::string const & filename)
57 gdcmHeader *header = new gdcmHeader( filename );
58 this->CoherentGdcmFileList.push_back( header );
62 * \brief add a gdcmFile to the list
63 * @param file gdcmHeader to add
65 void gdcmSerieHeader::AddGdcmFile(gdcmHeader *file)
67 this->CoherentGdcmFileList.push_back( file );
71 * \brief Sets the Directory
72 * @param dir Name of the directory to deal with
74 void gdcmSerieHeader::SetDirectory(std::string const & dir)
76 gdcmDirList filenames_list(dir); //OS specific
78 for( gdcmDirList::const_iterator it = filenames_list.begin();
79 it != filenames_list.end(); ++it)
81 //use string and not const char*:
82 gdcmHeader *header = new gdcmHeader( *it );
83 this->CoherentGdcmFileList.push_back( header );
88 * \brief Sorts the File List
89 * \warning This could be implemented in a 'Strategy Pattern' approach
90 * But as I don't know how to do it, I leave it this way
91 * BTW, this is also a Strategy, I don't know this is the best approach :)
93 void gdcmSerieHeader::OrderGdcmFileList()
95 if( ImagePositionPatientOrdering() )
99 else if( ImageNumberOrdering() )
109 //-----------------------------------------------------------------------------
112 //-----------------------------------------------------------------------------
115 * \ingroup gdcmHeader
116 * \brief sorts the images, according to their Patient Position
117 * We may order, considering :
119 * -# Image Position Patient
121 * @return false only if the header is bugged !
123 bool gdcmSerieHeader::ImagePositionPatientOrdering()
124 //based on Jolinda's algorithm
126 //iop is calculated based on the file file
127 float *cosines = new float[6];
131 float min = 0, max = 0;
134 std::vector<float> distlist;
136 //!\todo rewrite this for loop.
137 for ( GdcmHeaderList::const_iterator
138 it = CoherentGdcmFileList.begin();
139 it != CoherentGdcmFileList.end(); ++it )
143 (*it)->GetImageOrientationPatient( cosines );
145 //You only have to do this once for all slices in the volume. Next,
146 // for each slice, calculate the distance along the slice normal
147 // using the IPP tag ("dist" is initialized to zero before reading
148 // the first slice) :
149 normal[0] = cosines[1]*cosines[5] - cosines[2]*cosines[4];
150 normal[1] = cosines[2]*cosines[3] - cosines[0]*cosines[5];
151 normal[2] = cosines[0]*cosines[4] - cosines[1]*cosines[3];
153 ipp[0] = (*it)->GetXOrigin();
154 ipp[1] = (*it)->GetYOrigin();
155 ipp[2] = (*it)->GetZOrigin();
158 for ( int i = 0; i < 3; ++i )
160 dist += normal[i]*ipp[i];
169 distlist.push_back( dist );
176 ipp[0] = (*it)->GetXOrigin();
177 ipp[1] = (*it)->GetYOrigin();
178 ipp[2] = (*it)->GetZOrigin();
181 for ( int i = 0; i < 3; ++i )
183 dist += normal[i]*ipp[i];
192 distlist.push_back( dist );
194 min = (min < dist) ? min : dist;
195 max = (max > dist) ? max : dist;
200 // Then I order the slices according to the value "dist". Finally, once
201 // I've read in all the slices, I calculate the z-spacing as the difference
202 // between the "dist" values for the first two slices.
203 GdcmHeaderVector CoherentGdcmFileVector(n);
204 // CoherentGdcmFileVector.reserve( n );
205 CoherentGdcmFileVector.resize( n );
206 // assert( CoherentGdcmFileVector.capacity() >= n );
208 float step = (max - min)/(n - 1);
212 //VC++ don't understand what scope is !! it -> it2
213 for (GdcmHeaderList::const_iterator it2 = CoherentGdcmFileList.begin();
214 it2 != CoherentGdcmFileList.end(); ++it2, ++n)
217 //Assumption: all files are present (no one missing)
218 pos = (int)( fabs( (distlist[n]-min)/step) + .5 );
220 CoherentGdcmFileVector[pos] = *it2;
223 CoherentGdcmFileList.clear(); //this doesn't delete list's element, node only
225 //VC++ don't understand what scope is !! it -> it3
226 for (GdcmHeaderVector::const_iterator it3 = CoherentGdcmFileVector.begin();
227 it3 != CoherentGdcmFileVector.end(); ++it3)
229 CoherentGdcmFileList.push_back( *it3 );
233 CoherentGdcmFileVector.clear();
240 * \ingroup gdcmHeader
241 * \brief sorts the images, according to their Image Number
242 * @return false only if the header is bugged !
245 bool gdcmSerieHeader::ImageNumberOrdering()
248 int n = 0;//CoherentGdcmFileList.size() is a O(N) operation !!
249 unsigned char *partition;
251 GdcmHeaderList::const_iterator it = CoherentGdcmFileList.begin();
252 min = max = (*it)->GetImageNumber();
254 for (; it != CoherentGdcmFileList.end(); ++it, ++n)
256 pos = (*it)->GetImageNumber();
259 min = (min < pos) ? min : pos;
262 //bzeros(partition, n); //Cette fonction est déconseillée, utilisez plutôt memset.
263 partition = new unsigned char[n];
264 memset(partition, 0, n);
266 GdcmHeaderVector CoherentGdcmFileVector(n);
268 //VC++ don't understand what scope is !! it -> it2
269 for (GdcmHeaderList::const_iterator it2 = CoherentGdcmFileList.begin();
270 it2 != CoherentGdcmFileList.end(); ++it2)
272 pos = (*it2)->GetImageNumber();
273 CoherentGdcmFileVector[pos - min] = *it2;
274 partition[pos - min]++;
277 unsigned char mult = 1;
278 for( int i=0; i<n ; i++ )
280 mult *= partition[i];
283 //VC++ don't understand what scope is !! it -> it3
284 CoherentGdcmFileList.clear(); //this doesn't delete list's element, node only
285 for ( GdcmHeaderVector::const_iterator it3 = CoherentGdcmFileVector.begin();
286 it3 != CoherentGdcmFileVector.end(); ++it3 )
288 CoherentGdcmFileList.push_back( *it3 );
290 CoherentGdcmFileVector.clear();
299 * \ingroup gdcmHeader
300 * \brief sorts the images, according to their File Name
301 * @return false only if the header is bugged !
303 bool gdcmSerieHeader::FileNameOrdering()
306 //sort(CoherentGdcmFileList.begin(), CoherentGdcmFileList.end());
310 //-----------------------------------------------------------------------------