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