1 /*=========================================================================
4 Module: $RCSfile: gdcmHeaderHelper.cxx,v $
6 Date: $Date: 2004/06/21 04:18:26 $
7 Version: $Revision: 1.38 $
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 //-----------------------------------------------------------------------------
28 // Constructor / Destructor
29 gdcmSerieHeader::~gdcmSerieHeader(){
31 for (std::list<gdcmHeader*>::iterator it = CoherentGdcmFileList.begin();
32 it != CoherentGdcmFileList.end(); it++)
36 CoherentGdcmFileList.clear();
39 //-----------------------------------------------------------------------------
42 //-----------------------------------------------------------------------------
45 * \brief add a gdcmFile to the list based on file name
46 * @param filename Name of the file to deal with
48 void gdcmSerieHeader::AddFileName(std::string filename) {
49 gdcmHeader *GdcmFile = new gdcmHeader( filename );
50 this->CoherentGdcmFileList.push_back( GdcmFile );
54 * \brief add a gdcmFile to the list
55 * @param file gdcmHeader to add
57 void gdcmSerieHeader::AddGdcmFile(gdcmHeader *file){
58 this->CoherentGdcmFileList.push_back( file );
62 * \brief Sets the Directory
63 * @param dir Name of the directory to deal with
65 void gdcmSerieHeader::SetDirectory(std::string dir){
66 gdcmDirList filenames_list(dir); //OS specific
68 for(gdcmDirList::iterator it = filenames_list.begin();
69 it !=filenames_list.end(); it++)
71 gdcmHeader *file = new gdcmHeader( it->c_str() );
72 this->CoherentGdcmFileList.push_back( file );
77 * \brief Sorts the File List
78 * \warning This could be implemented in a 'Strategy Pattern' approach
79 * But as I don't know how to do it, I leave it this way
80 * BTW, this is also a Strategy, I don't know this is the best approach :)
82 void gdcmSerieHeader::OrderGdcmFileList(){
83 if( ImagePositionPatientOrdering() ) {
86 else if( ImageNumberOrdering() ) {
94 * \brief Gets the *coherent* File List
95 * @return the *coherent* File List
97 std::list<gdcmHeader*> &gdcmSerieHeader::GetGdcmFileList() {
98 return CoherentGdcmFileList;
101 //-----------------------------------------------------------------------------
104 //-----------------------------------------------------------------------------
107 * \ingroup gdcmHeader
108 * \brief sorts the images, according to their Patient Position
109 * We may order, considering :
111 * -# Image Position Patient
113 * @return false only if the header is bugged !
115 bool gdcmSerieHeader::ImagePositionPatientOrdering()
116 //based on Jolinda's algorithm
118 //iop is calculated based on the file file
119 float *cosines = new float[6];
126 std::vector<float> distlist;
128 //!\todo rewrite this for loop.
129 for (std::list<gdcmHeader*>::iterator it = CoherentGdcmFileList.begin();
130 it != CoherentGdcmFileList.end(); it++)
133 (*it)->GetImageOrientationPatient(cosines);
135 //You only have to do this once for all slices in the volume. Next, for
136 //each slice, calculate the distance along the slice normal using the IPP
137 //tag ("dist" is initialized to zero before reading the first slice) :
138 normal[0] = cosines[1]*cosines[5] - cosines[2]*cosines[4];
139 normal[1] = cosines[2]*cosines[3] - cosines[0]*cosines[5];
140 normal[2] = cosines[0]*cosines[4] - cosines[1]*cosines[3];
142 ipp[0] = (*it)->GetXOrigin();
143 ipp[1] = (*it)->GetYOrigin();
144 ipp[2] = (*it)->GetZOrigin();
147 for (int i = 0; i < 3; ++i)
148 dist += normal[i]*ipp[i];
156 distlist.push_back( dist );
162 ipp[0] = (*it)->GetXOrigin();
163 ipp[1] = (*it)->GetYOrigin();
164 ipp[2] = (*it)->GetZOrigin();
167 for (int i = 0; i < 3; ++i)
168 dist += normal[i]*ipp[i];
176 distlist.push_back( dist );
178 min = (min < dist) ? min : dist;
179 max = (max > dist) ? max : dist;
184 //Then I order the slices according to the value "dist". Finally, once
185 //I've read in all the slices, I calculate the z-spacing as the difference
186 //between the "dist" values for the first two slices.
187 std::vector<gdcmHeader*> CoherentGdcmFileVector(n);
188 //CoherentGdcmFileVector.reserve( n );
189 CoherentGdcmFileVector.resize( n );
190 //assert( CoherentGdcmFileVector.capacity() >= n );
192 float step = (max - min)/(n - 1);
196 //VC++ don't understand what scope is !! it -> it2
197 for (std::list<gdcmHeader*>::iterator it2 = CoherentGdcmFileList.begin();
198 it2 != CoherentGdcmFileList.end(); it2++, n++)
201 //Assumption: all files are present (no one missing)
202 pos = (int)( fabs( (distlist[n]-min)/step) + .5 );
204 CoherentGdcmFileVector[pos] = *it2;
207 CoherentGdcmFileList.clear(); //this doesn't delete list's element, node only
209 //VC++ don't understand what scope is !! it -> it3
210 for (std::vector<gdcmHeader*>::iterator it3 = CoherentGdcmFileVector.begin();
211 it3 != CoherentGdcmFileVector.end(); it3++)
213 CoherentGdcmFileList.push_back( *it3 );
217 CoherentGdcmFileVector.clear();
224 * \ingroup gdcmHeader
225 * \brief sorts the images, according to their Image Number
226 * @return false only if the header is bugged !
229 bool gdcmSerieHeader::ImageNumberOrdering() {
231 int n = 0;//CoherentGdcmFileList.size() is a O(N) operation !!
232 unsigned char *partition;
234 std::list<gdcmHeader*>::iterator it = CoherentGdcmFileList.begin();
235 min = max = (*it)->GetImageNumber();
237 for (; it != CoherentGdcmFileList.end(); it++, n++)
239 pos = (*it)->GetImageNumber();
242 min = (min < pos) ? min : pos;
245 //bzeros(partition, n); //Cette fonction est déconseillée, utilisez plutôt memset.
246 partition = new unsigned char[n];
247 memset(partition, 0, n);
249 std::vector<gdcmHeader*> CoherentGdcmFileVector(n);
251 //VC++ don't understand what scope is !! it -> it2
252 for (std::list<gdcmHeader*>::iterator it2 = CoherentGdcmFileList.begin();
253 it2 != CoherentGdcmFileList.end(); it2++)
255 pos = (*it2)->GetImageNumber();
256 CoherentGdcmFileVector[pos - min] = *it2;
257 partition[pos - min]++;
260 unsigned char mult = 1;
261 for(int i=0; i<n ; i++)
263 mult *= partition[i];
266 //VC++ don't understand what scope is !! it -> it3
267 CoherentGdcmFileList.clear(); //this doesn't delete list's element, node only
268 for (std::vector<gdcmHeader*>::iterator it3 = CoherentGdcmFileVector.begin();
269 it3 != CoherentGdcmFileVector.end(); it3++)
271 CoherentGdcmFileList.push_back( *it3 );
273 CoherentGdcmFileVector.clear();
281 * \ingroup gdcmHeader
282 * \brief sorts the images, according to their File Name
283 * @return false only if the header is bugged !
285 bool gdcmSerieHeader::FileNameOrdering() {
287 //sort(CoherentGdcmFileList.begin(), CoherentGdcmFileList.end());
291 //-----------------------------------------------------------------------------