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