]> Creatis software - gdcm.git/blob - src/gdcmHeaderHelper.cxx
* corrected directory parsing under Win32
[gdcm.git] / src / gdcmHeaderHelper.cxx
1 // $Header: /cvs/public/gdcm/src/Attic/gdcmHeaderHelper.cxx,v 1.4 2003/09/17 17:46:35 malaterre Exp $
2
3 //This is needed when compiling in debug mode
4 #ifdef _MSC_VER
5 #pragma warning ( disable : 4800 )
6 // 'identifier' : class 'type' needs to have dll-interface to be used by
7 // clients of class 'type2'
8 #pragma warning ( disable : 4251 )
9 // 'identifier' : identifier was truncated to 'number' characters in the
10 // debug information
11 #pragma warning ( disable : 4786 )
12 #endif //_MSC_VER
13
14 #include "gdcmHeaderHelper.h"
15 #include "gdcmUtil.h" //for debug
16 #include <math.h>
17 #include <algorithm>
18 #include <string.h> //for bzero
19 using namespace std;
20
21 //directory manipulation (os indep).
22 //cygwin ???? -> _WIN32 ??
23 #ifdef _MSC_VER 
24 #include <windows.h> 
25 int GetDir(string dPath, list<string> &filenames)
26 {
27   //For now dPath should have an ending "\"
28   WIN32_FIND_DATA FileData; 
29   HANDLE hFile; 
30   hFile = FindFirstFile((dPath+"*").c_str(), &FileData); 
31   if ( hFile == INVALID_HANDLE_VALUE ) 
32   { 
33     //No files !
34     return false; 
35   } 
36   
37   if( strncmp(FileData.cFileName, ".", 1) != 0 )
38     filenames.push_back( dPath+FileData.cFileName );
39   while( FindNextFile(hFile, &FileData ) != 0)
40   { 
41     if( strncmp(FileData.cFileName, ".", 1) != 0 )
42       filenames.push_back( dPath+FileData.cFileName );
43   }
44   return true;
45 }
46
47 #else
48 #include <dirent.h>
49
50 int GetDir(string dPath, list<string> &filenames)
51 {
52  DIR *dir = opendir( dPath.c_str() );
53  struct dirent *entry;
54  while((entry = readdir(dir)) != NULL)
55  {
56 //   if( strncmp(entry->d_name, ".", 1) != 0 && strncmp(entry->d_name, "..", 2) != 0)
57    if( strncmp(entry->d_name, ".", 1) != 0 )
58    {
59       filenames.push_back( dPath + "/" + entry->d_name );
60    }
61  }
62  closedir(dir);
63  return true;
64 }
65
66 #endif
67
68 //----------------------------------------------------------------------------
69 /**
70  * \ingroup gdcmHeaderHelper
71  * \brief   cstor
72  */
73 gdcmHeaderHelper::gdcmHeaderHelper() : gdcmHeader( )
74 {
75 }
76 //----------------------------------------------------------------------------
77 /**
78  * \ingroup gdcmHeaderHelper
79  * \brief   cstor
80  */
81 gdcmHeaderHelper::gdcmHeaderHelper(const char *InFilename, 
82     bool exception_on_error) : gdcmHeader( InFilename , exception_on_error)
83 {
84 }
85 //----------------------------------------------------------------------------
86 /**
87  * \ingroup gdcmHeaderHelper
88  * \brief   Return the size (in bytes) of a single pixel of data.
89  * @return  The size in bytes of a single pixel of data.
90  *
91  */
92 int gdcmHeaderHelper::GetPixelSize() {
93    string PixelType = GetPixelType();
94    if (PixelType == "8U"  || PixelType == "8S")
95       return 1;
96    if (PixelType == "16U" || PixelType == "16S")
97       return 2;
98    if (PixelType == "32U" || PixelType == "32S")
99       return 4;
100    dbg.Verbose(0, "gdcmHeader::GetPixelSize: Unknown pixel type");
101    return 0;
102 }
103 //----------------------------------------------------------------------------
104 /**
105  * \ingroup gdcmHeaderHelper
106  * \brief   Build the Pixel Type of the image.
107  *          Possible values are:
108  *          - 8U  unsigned  8 bit,
109  *          - 8S    signed  8 bit,
110  *          - 16U unsigned 16 bit,
111  *          - 16S   signed 16 bit,
112  *          - 32U unsigned 32 bit,
113  *          - 32S   signed 32 bit,
114  * \warning 12 bit images appear as 16 bit.
115  * @return  
116  */
117 string gdcmHeaderHelper::GetPixelType() {
118    string BitsAlloc;
119    BitsAlloc = GetElValByName("Bits Allocated");
120    if (BitsAlloc == "gdcm::Unfound") {
121       dbg.Verbose(0, "gdcmHeader::GetPixelType: unfound Bits Allocated");
122       BitsAlloc = string("16");
123    }
124    if (BitsAlloc == "12")
125       BitsAlloc = string("16");
126
127    string Signed;
128    Signed = GetElValByName("Pixel Representation");
129    if (Signed == "gdcm::Unfound") {
130       dbg.Verbose(0, "gdcmHeader::GetPixelType: unfound Pixel Representation");
131       BitsAlloc = string("0");
132    }
133    if (Signed == "0")
134       Signed = string("U");
135    else
136       Signed = string("S");
137
138    return( BitsAlloc + Signed);
139 }
140 //----------------------------------------------------------------------------
141 /**
142   * \ingroup gdcmHeaderHelper
143   * \brief gets the info from 0028,0030 : Pixel Spacing
144   * \           else 1.
145   * @return X dimension of a pixel
146   */
147 float gdcmHeaderHelper::GetXSpacing() {
148     float xspacing, yspacing;
149     string StrSpacing = GetPubElValByNumber(0x0028,0x0030);
150
151     if (StrSpacing == "gdcm::Unfound") {
152        dbg.Verbose(0, "gdcmHeader::GetXSpacing: unfound Pixel Spacing (0028,0030)");
153        return 1.;
154      }
155    if( sscanf( StrSpacing.c_str(), "%f\\%f", &xspacing, &yspacing) != 2)
156      return 0.;
157    //else
158    return xspacing;
159 }
160 //----------------------------------------------------------------------------
161 /**
162   * \ingroup gdcmHeaderHelper
163   * \brief gets the info from 0028,0030 : Pixel Spacing
164   * \           else 1.
165   * @return Y dimension of a pixel
166   */
167 float gdcmHeaderHelper::GetYSpacing() {
168    float xspacing, yspacing;
169    string StrSpacing = GetPubElValByNumber(0x0028,0x0030);
170   
171    if (StrSpacing == "gdcm::Unfound") {
172       dbg.Verbose(0, "gdcmHeader::GetYSpacing: unfound Pixel Spacing (0028,0030)");
173       return 1.;
174     }
175   if( sscanf( StrSpacing.c_str(), "%f\\%f", &xspacing, &yspacing) != 2)
176     return 0.;
177   if (yspacing == 0.) {
178     dbg.Verbose(0, "gdcmHeader::GetYSpacing: gdcmData/CT-MONO2-8-abdo.dcm problem");
179     // seems to be a bug in the header ...
180     sscanf( StrSpacing.c_str(), "%f\\0\\%f", &xspacing, &yspacing);
181   }
182   return yspacing;
183
184
185 //----------------------------------------------------------------------------
186 /**
187   *\ingroup gdcmHeaderHelper
188   *\brief gets the info from 0018,0088 : Space Between Slices
189   *\               else from 0018,0050 : Slice Thickness
190   *\               else 1.
191   * @return Z dimension of a voxel-to be
192   */
193 float gdcmHeaderHelper::GetZSpacing() {
194    // TODO : translate into English
195    // Spacing Between Slices : distance entre le milieu de chaque coupe
196    // Les coupes peuvent etre :
197    //   jointives     (Spacing between Slices = Slice Thickness)
198    //   chevauchantes (Spacing between Slices < Slice Thickness)
199    //   disjointes    (Spacing between Slices > Slice Thickness)
200    // Slice Thickness : epaisseur de tissus sur laquelle est acquis le signal
201    //   ca interesse le physicien de l'IRM, pas le visualisateur de volumes ...
202    //   Si le Spacing Between Slices est absent, 
203    //   on suppose que les coupes sont jointives
204    
205    string StrSpacingBSlices = GetPubElValByNumber(0x0018,0x0088);
206
207    if (StrSpacingBSlices == "gdcm::Unfound") {
208       dbg.Verbose(0, "gdcmHeader::GetZSpacing: unfound StrSpacingBSlices");
209       string StrSliceThickness = GetPubElValByNumber(0x0018,0x0050);       
210       if (StrSliceThickness == "gdcm::Unfound")
211          return 1.;
212       else
213          // if no 'Spacing Between Slices' is found, 
214          // we assume slices join together
215          // (no overlapping, no interslice gap)
216          // if they don't, we're fucked up
217          return atof(StrSliceThickness.c_str());  
218    } else {
219       return atof(StrSpacingBSlices.c_str());
220    }
221 }
222
223 //----------------------------------------------------------------------------
224 //
225 // Image Position Patient                              (0020,0032):
226 // If not found (ACR_NEMA) we try Image Position       (0020,0030)
227 // If not found (ACR-NEMA), we consider Slice Location (0020,1041)
228 //                                   or Location       (0020,0050) 
229 // as the Z coordinate, 
230 // 0. for all the coordinates if nothing is found
231
232 // TODO : find a way to inform the caller nothing was found
233 // TODO : How to tell the caller a wrong number of values was found?
234
235 /**
236   * \ingroup gdcmHeaderHelper
237   * \brief gets the info from 0020,0032 : Image Position Patient
238   *\                else from 0020,0030 : Image Position (RET)
239   *\                else 0.
240   * @return up-left image corner position
241   */
242 float gdcmHeaderHelper::GetXOrigin() {
243     float xImPos, yImPos, zImPos;  
244     string StrImPos = GetPubElValByNumber(0x0020,0x0032);
245
246     if (StrImPos == "gdcm::Unfound") {
247        dbg.Verbose(0, "gdcmHeader::GetXImagePosition: unfound Image Position Patient (0020,0032)");
248        StrImPos = GetPubElValByNumber(0x0020,0x0030); // For ACR-NEMA images
249        if (StrImPos == "gdcm::Unfound") {
250           dbg.Verbose(0, "gdcmHeader::GetXImagePosition: unfound Image Position (RET) (0020,0030)");
251           // How to tell the caller nothing was found ?
252          return 0.;
253        }  
254      }
255    if( sscanf( StrImPos.c_str(), "%f\\%f\\%f", &xImPos, &yImPos, &zImPos) != 3)
256      return 0.;
257    return xImPos;
258 }
259 //----------------------------------------------------------------------------
260 /**
261   * \ingroup gdcmHeaderHelper
262   * \brief gets the info from 0020,0032 : Image Position Patient
263   * \               else from 0020,0030 : Image Position (RET)
264   * \               else 0.
265   * @return up-left image corner position
266   */
267 float gdcmHeaderHelper::GetYOrigin() {
268     float xImPos, yImPos, zImPos;
269     string StrImPos = GetPubElValByNumber(0x0020,0x0032);
270
271     if (StrImPos == "gdcm::Unfound") {
272        dbg.Verbose(0, "gdcmHeader::GetYImagePosition: unfound Image Position Patient (0020,0032)");
273        StrImPos = GetPubElValByNumber(0x0020,0x0030); // For ACR-NEMA images
274        if (StrImPos == "gdcm::Unfound") {
275           dbg.Verbose(0, "gdcmHeader::GetYImagePosition: unfound Image Position (RET) (0020,0030)");
276           // How to tell the caller nothing was found ?
277            return 0.;
278        }  
279      }
280    if( sscanf( StrImPos.c_str(), "%f\\%f\\%f", &xImPos, &yImPos, &zImPos) != 3)
281      return 0.;
282    return yImPos;
283 }
284 //----------------------------------------------------------------------------
285 /**
286   * \ingroup gdcmHeaderHelper
287   * \brief gets the info from 0020,0032 : Image Position Patient
288   * \               else from 0020,0030 : Image Position (RET)
289   * \               else from 0020,1041 : Slice Location
290   * \               else from 0020,0050 : Location
291   * \               else 0.
292   * @return up-left image corner position
293   */
294 float gdcmHeaderHelper::GetZOrigin() {
295    float xImPos, yImPos, zImPos; 
296    string StrImPos = GetPubElValByNumber(0x0020,0x0032);
297    if (StrImPos != "gdcm::Unfound") {
298       if( sscanf( StrImPos.c_str(), "%f\\%f\\%f", &xImPos, &yImPos, &zImPos) != 3) {
299          dbg.Verbose(0, "gdcmHeader::GetZImagePosition: wrong Image Position Patient (0020,0032)");
300          return 0.;  // bug in the element 0x0020,0x0032
301       } else {
302          return zImPos;
303       }    
304    }  
305    StrImPos = GetPubElValByNumber(0x0020,0x0030); // For ACR-NEMA images
306    if (StrImPos != "gdcm::Unfound") {
307       if( sscanf( StrImPos.c_str(), "%f\\%f\\%f", &xImPos, &yImPos, &zImPos) != 3) {
308          dbg.Verbose(0, "gdcmHeader::GetZImagePosition: wrong Image Position (RET) (0020,0030)");
309          return 0.;  // bug in the element 0x0020,0x0032
310       } else {
311          return zImPos;
312       }    
313    }                
314    string StrSliceLocation = GetPubElValByNumber(0x0020,0x1041);// for *very* old ACR-NEMA images
315    if (StrSliceLocation != "gdcm::Unfound") {
316       if( sscanf( StrSliceLocation.c_str(), "%f", &zImPos) !=1) {
317          dbg.Verbose(0, "gdcmHeader::GetZImagePosition: wrong Slice Location (0020,1041)");
318          return 0.;  // bug in the element 0x0020,0x1041
319       } else {
320          return zImPos;
321       }
322    }   
323    dbg.Verbose(0, "gdcmHeader::GetZImagePosition: unfound Slice Location (0020,1041)");
324    string StrLocation = GetPubElValByNumber(0x0020,0x0050);
325    if (StrLocation != "gdcm::Unfound") {
326       if( sscanf( StrLocation.c_str(), "%f", &zImPos) !=1) {
327          dbg.Verbose(0, "gdcmHeader::GetZImagePosition: wrong Location (0020,0050)");
328          return 0.;  // bug in the element 0x0020,0x0050
329       } else {
330          return zImPos;
331       }
332    }
333    dbg.Verbose(0, "gdcmHeader::GetYImagePosition: unfound Location (0020,0050)");  
334    return 0.; // Hopeless
335 }
336 //----------------------------------------------------------------------------
337 /**
338   * \ingroup gdcmHeaderHelper
339   * \brief gets the info from 0020,0013 : Image Number
340   * \               else 0.
341   * @return image number
342   */
343 int gdcmHeaderHelper::GetImageNumber() {
344   //The function i atoi() takes the address of an area of memory as parameter and converts 
345   //the string stored at that location to an integer using the external decimal to internal
346   //binary conversion rules. This may be preferable to sscanf() since atoi() is a much smaller,
347   // simpler and faster function. sscanf() can do all possible conversions whereas atoi() can 
348   //only do single decimal integer conversions.
349   string StrImNumber = GetPubElValByNumber(0x0020,0x0013); //0020 0013 IS REL Image Number
350   if (StrImNumber != "gdcm::Unfound") {
351     return atoi( StrImNumber.c_str() );
352   }
353   return 0;   //Hopeless
354 }
355 //----------------------------------------------------------------------------
356 /**
357   * \ingroup gdcmHeaderHelper
358   * \brief gets the info from 0008,0060 : Modality
359   * @return ModalityType
360   */
361 ModalityType gdcmHeaderHelper::GetModality(void) {
362   string StrModality = GetPubElValByNumber(0x0008,0x0060); //0008 0060 CS ID Modality
363   if (StrModality != "gdcm::Unfound") {
364          if ( StrModality.find("AU") < StrModality.length()) return AU;
365     else if ( StrModality.find("AS") < StrModality.length()) return AS;
366     else if ( StrModality.find("BI") < StrModality.length()) return BI;
367     else if ( StrModality.find("CF") < StrModality.length()) return CF;
368     else if ( StrModality.find("CP") < StrModality.length()) return CP;
369     else if ( StrModality.find("CR") < StrModality.length()) return CR;
370     else if ( StrModality.find("CT") < StrModality.length()) return CT;
371     else if ( StrModality.find("CS") < StrModality.length()) return CS;
372     else if ( StrModality.find("DD") < StrModality.length()) return DD;
373     else if ( StrModality.find("DF") < StrModality.length()) return DF;
374     else if ( StrModality.find("DG") < StrModality.length()) return DG;
375     else if ( StrModality.find("DM") < StrModality.length()) return DM;
376     else if ( StrModality.find("DS") < StrModality.length()) return DS;
377     else if ( StrModality.find("DX") < StrModality.length()) return DX;
378     else if ( StrModality.find("ECG") < StrModality.length()) return ECG;
379     else if ( StrModality.find("EPS") < StrModality.length()) return EPS;
380     else if ( StrModality.find("FA") < StrModality.length()) return FA;
381     else if ( StrModality.find("FS") < StrModality.length()) return FS;
382     else if ( StrModality.find("HC") < StrModality.length()) return HC;
383     else if ( StrModality.find("HD") < StrModality.length()) return HD;
384     else if ( StrModality.find("LP") < StrModality.length()) return LP;
385     else if ( StrModality.find("LS") < StrModality.length()) return LS;
386     else if ( StrModality.find("MA") < StrModality.length()) return MA;
387     else if ( StrModality.find("MR") < StrModality.length()) return MR;
388     else if ( StrModality.find("NM") < StrModality.length()) return NM;
389     else if ( StrModality.find("OT") < StrModality.length()) return OT;
390     else if ( StrModality.find("PT") < StrModality.length()) return PT;
391     else if ( StrModality.find("RF") < StrModality.length()) return RF;
392     else if ( StrModality.find("RG") < StrModality.length()) return RG;
393     else if ( StrModality.find("RTDOSE")   < StrModality.length()) return RTDOSE;
394     else if ( StrModality.find("RTIMAGE")  < StrModality.length()) return RTIMAGE;
395     else if ( StrModality.find("RTPLAN")   < StrModality.length()) return RTPLAN;
396     else if ( StrModality.find("RTSTRUCT") < StrModality.length()) return RTSTRUCT;
397     else if ( StrModality.find("SM") < StrModality.length()) return SM;
398     else if ( StrModality.find("ST") < StrModality.length()) return ST;
399     else if ( StrModality.find("TG") < StrModality.length()) return TG;
400     else if ( StrModality.find("US") < StrModality.length()) return US;
401     else if ( StrModality.find("VF") < StrModality.length()) return VF;
402     else if ( StrModality.find("XA") < StrModality.length()) return XA;
403     else if ( StrModality.find("XC") < StrModality.length()) return XC;
404
405     else
406     {
407       //throw error return value ???
408       // specified <> unknow in our database
409       return Unknow;
410     }
411   }
412   return Unknow;
413 }
414
415 //----------------------------------------------------------------------------
416 string gdcmHeaderHelper::GetStudyUID()
417 {
418   return GetPubElValByNumber(0x0020,0x000d); //!0020 000d UI REL Study Instance UID
419 }
420 //----------------------------------------------------------------------------
421 string gdcmHeaderHelper::GetSeriesUID()
422 {
423   return GetPubElValByNumber(0x0020,0x000e); //!0020 000e UI REL Series Instance UID
424 }
425 //----------------------------------------------------------------------------
426 string gdcmHeaderHelper::GetClassUID()
427 {
428   return GetPubElValByNumber(0x0008,0x0016); //!0008 0016 UI ID SOP Class UID
429 }
430 //----------------------------------------------------------------------------
431 string gdcmHeaderHelper::GetInstanceUID()
432 {
433   return GetPubElValByNumber(0x0008,0x0018); //!0008 0018 UI ID SOP Instance UID
434 }
435
436
437
438
439
440
441
442
443
444 gdcmSerieHeaderHelper::~gdcmSerieHeaderHelper()
445 {
446   //! \todo
447   for (list<gdcmHeaderHelper*>::iterator it  = CoherentGdcmFileList.begin();
448         it != CoherentGdcmFileList.end(); it++)
449   {
450     delete *it;
451   }
452   CoherentGdcmFileList.clear();
453 }
454 //----------------------------------------------------------------------------
455 /**
456   * \ingroup gdcmHeaderHelper
457   * \brief gets the info from 0020,0037 : Image Orientation Patient
458   * @return cosines of image orientation patient
459   */
460 void gdcmHeaderHelper::GetImageOrientationPatient( float* iop ) {
461
462   //iop is supposed to be float[6]
463   iop[0] = iop[1] = iop[2] = iop[3] = iop[4] = iop[5] = 0;
464   
465   string StrImOriPat = GetPubElValByNumber(0x0020,0x0037); // 0020 0037 DS REL Image Orientation (Patient)
466   if (StrImOriPat != "gdcm::Unfound") {
467     if( sscanf( StrImOriPat.c_str(), "%f\\%f\\%f\\%f\\%f\\%f", 
468             &iop[0], &iop[1], &iop[2], &iop[3], &iop[4], &iop[5]) != 6) {
469          dbg.Verbose(0, "gdcmHeader::GetImageOrientationPatient: wrong Image Orientation Patient (0020,0037)");
470          return ;  // bug in the element 0x0020,0x0037
471     } 
472     else
473       return ;
474   }
475   
476   //For ACR-NEMA
477   StrImOriPat = GetPubElValByNumber(0x0020,0x0035); //0020 0035 DS REL Image Orientation (RET)
478   if (StrImOriPat != "gdcm::Unfound") {
479     if( sscanf( StrImOriPat.c_str(), "%f\\%f\\%f\\%f\\%f\\%f", 
480             &iop[0], &iop[1], &iop[2], &iop[3], &iop[4], &iop[5]) != 6) {
481          dbg.Verbose(0, "gdcmHeader::GetImageOrientationPatient: wrong Image Orientation Patient (0020,0035)");
482          return ;  // bug in the element 0x0020,0x0035
483     } 
484     else
485       return ;
486   }
487 }
488
489 //----------------------------------------------------------------------------
490 /**
491   * \ingroup gdcmHeaderHelper
492   * \brief add a gdcmFile to the list based on file name
493   */
494 void gdcmSerieHeaderHelper::AddFileName(string filename)
495 {
496   gdcmHeaderHelper *GdcmFile = new gdcmHeaderHelper( filename.c_str() );
497   this->CoherentGdcmFileList.push_back( GdcmFile );
498 }
499 //----------------------------------------------------------------------------
500 /**
501   * \ingroup gdcmHeaderHelper
502   * \brief add a gdcmFile to the list
503   */
504 void gdcmSerieHeaderHelper::AddGdcmFile(gdcmHeaderHelper *file)
505 {
506   this->CoherentGdcmFileList.push_back( file );
507 }
508 //----------------------------------------------------------------------------
509 /**
510   * \ingroup gdcmHeaderHelper
511   * \brief \todo
512   */
513 void gdcmSerieHeaderHelper::SetDirectory(string dir)
514 {
515   list<string> filenames_list;
516   GetDir(dir, filenames_list);  //OS specific
517   
518   for(list<string>::iterator it = filenames_list.begin(); it !=
519   filenames_list.end(); it++)
520   {
521     gdcmHeaderHelper *file = new gdcmHeaderHelper( it->c_str() );
522     this->CoherentGdcmFileList.push_back( file );
523   }
524 }
525 //----------------------------------------------------------------------------
526 //This could be implemented in a 'Strategy Pattern' approach
527 //But as I don't know how to do it, I leave it this way
528 //BTW, this is also a Strategy, I don't know this is the best approcah :)
529 void gdcmSerieHeaderHelper::OrderGdcmFileList()
530 {
531   if( ImagePositionPatientOrdering() )
532   {
533     return ;
534   }
535   else if( ImageNumberOrdering() )
536   {
537     return ;
538   }
539   else
540   {
541     FileNameOrdering();
542   }
543 }
544 //----------------------------------------------------------------------------
545 /**
546   * \ingroup gdcmHeaderHelper
547   * \brief 
548     We may order, considering :
549       -# Image Number
550       -# Image Position Patient
551       -# More to come :)
552 */
553 //based on Jolinda's algorithm
554 bool gdcmSerieHeaderHelper::ImagePositionPatientOrdering()
555 {
556   //iop is calculated based on the file file
557   float *cosines = new float[6];
558   float normal[3];
559   float ipp[3];
560   float dist;
561   float min, max;
562   bool first = true;
563   int n=0;
564   vector<float> distlist;
565
566   //!\todo rewrite this for loop.
567   for (list<gdcmHeaderHelper*>::iterator it  = CoherentGdcmFileList.begin();
568         it != CoherentGdcmFileList.end(); it++)
569   {
570     if(first) {
571       (*it)->GetImageOrientationPatient(cosines);
572       
573       //You only have to do this once for all slices in the volume. Next, for
574       //each slice, calculate the distance along the slice normal using the IPP
575       //tag ("dist" is initialized to zero before reading the first slice) :
576       normal[0] = cosines[1]*cosines[5] - cosines[2]*cosines[4];
577       normal[1] = cosines[2]*cosines[3] - cosines[0]*cosines[5];
578       normal[2] = cosines[0]*cosines[4] - cosines[1]*cosines[3];
579   
580       ipp[0] = (*it)->GetXOrigin();
581       ipp[1] = (*it)->GetYOrigin();
582       ipp[2] = (*it)->GetZOrigin();
583
584       dist = 0;
585       for (int i = 0; i < 3; ++i)
586           dist += normal[i]*ipp[i];
587     
588       if( dist == 0 )
589       {
590         delete[] cosines;
591         return false;
592       }
593
594       distlist.push_back( dist );
595
596       max = min = dist;
597       first = false;
598     }
599     else {
600       ipp[0] = (*it)->GetXOrigin();
601       ipp[1] = (*it)->GetYOrigin();
602       ipp[2] = (*it)->GetZOrigin();
603   
604       dist = 0;
605       for (int i = 0; i < 3; ++i)
606           dist += normal[i]*ipp[i];
607
608       if( dist == 0 )
609       {
610         delete[] cosines;
611         return false;
612       }
613
614       
615       distlist.push_back( dist );
616
617       min = (min < dist) ? min : dist;
618       max = (max > dist) ? max : dist;
619     }
620     n++;
621   }
622
623     //Then I order the slices according to the value "dist". Finally, once
624     //I've read in all the slices, I calculate the z-spacing as the difference
625     //between the "dist" values for the first two slices.
626     vector<gdcmHeaderHelper*> CoherentGdcmFileVector(n);
627     //CoherentGdcmFileVector.reserve( n );
628     CoherentGdcmFileVector.resize( n );
629     //assert( CoherentGdcmFileVector.capacity() >= n );
630
631     float step = (max - min)/(n - 1);
632     int pos;
633     n = 0;
634     
635     //VC++ don't understand what scope is !! it -> it2
636     for (list<gdcmHeaderHelper*>::iterator it2  = CoherentGdcmFileList.begin();
637         it2 != CoherentGdcmFileList.end(); it2++, n++)
638     {
639       //2*n sort algo !!
640       //Assumption: all files are present (no one missing)
641       pos = (int)( fabs( (distlist[n]-min)/step) + .5 );
642             
643       CoherentGdcmFileVector[pos] = *it2;
644     }
645
646   CoherentGdcmFileList.clear();  //this doesn't delete list's element, node only
647   
648   //VC++ don't understand what scope is !! it -> it3
649   for (vector<gdcmHeaderHelper*>::iterator it3  = CoherentGdcmFileVector.begin();
650         it3 != CoherentGdcmFileVector.end(); it3++)
651   {
652     CoherentGdcmFileList.push_back( *it3 );
653   }
654
655   distlist.clear();
656   CoherentGdcmFileVector.clear();
657   delete[] cosines;
658   
659   return true;
660 }
661 //----------------------------------------------------------------------------
662 //Based on Image Number
663 bool gdcmSerieHeaderHelper::ImageNumberOrdering()
664 {
665   int min, max, pos;
666   int n = 0;//CoherentGdcmFileList.size(); //O(N) operation !!
667   unsigned char *partition;
668   
669   list<gdcmHeaderHelper*>::iterator it  = CoherentGdcmFileList.begin();
670   min = max = (*it)->GetImageNumber();
671
672   for (; it != CoherentGdcmFileList.end(); it++, n++)
673   {
674     pos = (*it)->GetImageNumber();
675
676     //else
677     min = (min < pos) ? min : pos;
678   }
679
680   //bzeros(partition, n); //Cette fonction est déconseillée, utilisez plutôt memset.
681   partition = new unsigned char[n];
682   memset(partition, 0, n);
683
684   vector<gdcmHeaderHelper*> CoherentGdcmFileVector(n);
685
686   //VC++ don't understand what scope is !! it -> it2
687   for (list<gdcmHeaderHelper*>::iterator it2  = CoherentGdcmFileList.begin();
688         it2 != CoherentGdcmFileList.end(); it2++)
689   {
690     pos = (*it2)->GetImageNumber();
691     CoherentGdcmFileVector[pos - min] = *it2;
692     partition[pos - min]++;
693   }
694   
695   unsigned char mult;
696   for(int i=0; i<n ; i++)
697   {
698     mult *= partition[i];
699   }
700
701   //VC++ don't understand what scope is !! it -> it3
702   CoherentGdcmFileList.clear();  //this doesn't delete list's element, node only
703   for (vector<gdcmHeaderHelper*>::iterator it3  = CoherentGdcmFileVector.begin();
704         it3 != CoherentGdcmFileVector.end(); it3++)
705   {
706     CoherentGdcmFileList.push_back( *it3 );
707   }
708   CoherentGdcmFileVector.clear();
709   
710   delete[] partition;
711   return mult;
712 }
713 //----------------------------------------------------------------------------
714 bool gdcmSerieHeaderHelper::FileNameOrdering()
715 {
716   //using the sort
717   //sort(CoherentGdcmFileList.begin(), CoherentGdcmFileList.end());
718   return true;
719 }
720 //----------------------------------------------------------------------------
721 list<gdcmHeaderHelper*> &gdcmSerieHeaderHelper::GetGdcmFileList()
722 {
723   return CoherentGdcmFileList;
724 }
725 //----------------------------------------------------------------------------