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