]> Creatis software - gdcm.git/blob - src/gdcmDicomDir.cxx
* FIX : amelioration of code
[gdcm.git] / src / gdcmDicomDir.cxx
1 // gdcmDicomDir.cxx
2 //-----------------------------------------------------------------------------
3 #include "gdcmDicomDir.h"
4 #include "gdcmStudy.h"
5 #include "gdcmSerie.h"
6 #include "gdcmImage.h"
7 #include "gdcmDirList.h"
8 #include "gdcmUtil.h"
9
10 #include <string>
11
12 #include <sys/types.h>
13 #include <errno.h>
14
15 //-----------------------------------------------------------------------------
16 // Constructor / Destructor
17 /*
18  * \ingroup gdcmDicomDir
19  * \brief   
20  * @param   Filename
21  * @param   exception_on_error
22  */
23 gdcmDicomDir::gdcmDicomDir(const char *FileName, bool parseDir,
24                            bool exception_on_error):
25    gdcmParser(FileName,exception_on_error,true)
26 {
27    if( GetListEntry().begin()==GetListEntry().end() ) 
28    {
29       dbg.Verbose(0, "gdcmDicomDir::gdcmDicomDir : entry list empty");
30
31       if(parseDir)
32       {
33          dbg.Verbose(0, "gdcmDicomDir::gdcmDicomDir : Parse directory and create the DicomDir");
34          ParseDirectory();
35       }
36    }
37    else
38       CreateDicomDir();
39 }
40
41 /*
42  * \ingroup gdcmDicomDir
43  * \brief   
44  * @param   exception_on_error
45  */
46 /*gdcmDicomDir::gdcmDicomDir(ListTag *l,
47                            bool exception_on_error):                           
48    gdcmParser(exception_on_error )  
49 {    
50    listEntries=*l;
51    CreateDicomDir();
52 }*/
53
54 /*
55  * \ingroup gdcmDicomDir
56  * \brief  Canonical destructor 
57  */
58 gdcmDicomDir::~gdcmDicomDir() 
59 {
60    for(ListPatient::iterator cc=patients.begin();cc!=patients.end();++cc)
61    {
62       delete *cc;
63    }
64 }
65
66 //-----------------------------------------------------------------------------
67 // Print
68 void gdcmDicomDir::Print(std::ostream &os)
69 {
70    for(ListPatient::iterator cc=patients.begin();cc!=patients.end();++cc)
71    {
72      (*cc)->SetPrintLevel(printLevel);
73      (*cc)->Print(os);
74    }
75 }
76
77 //-----------------------------------------------------------------------------
78 // Public
79 /**
80  * \ingroup gdcmDicomDir
81  * \brief   writes on disc a DICOMDIR
82  * \ warning does NOT add the missing elements in the header :
83  * \         it's up to the user doing it !
84  * @param  fileName file to be written to 
85  * @return
86  */
87 bool gdcmDicomDir::Write(std::string fileName) 
88 {
89    FILE * fp1;
90
91    fp1=fopen(fileName.c_str(),"wb");
92    if(fp1==NULL) 
93    {
94       printf("Failed to open(write) File [%s] \n",fileName.c_str());
95       return(false);
96    }
97
98    char * filePreamble;
99    filePreamble=(char*)calloc(128,1);
100    fwrite(filePreamble,128,1,fp1);
101    fwrite("DICM",4,1,fp1);
102    free(filePreamble);
103
104    WriteEntries(fp1,DICOMDIR);
105
106    fclose(fp1);
107
108    return true;
109 }
110
111 void gdcmDicomDir::ParseDirectory(void)
112 {
113    NewDicomDir(GetPath());
114    CreateDicomDir();
115 }
116
117 //-----------------------------------------------------------------------------
118 // Protected
119 /*
120  * \ingroup gdcmDicomDir
121  * \brief   
122  * @param   
123  */
124 void gdcmDicomDir::NewDicomDir(std::string path)
125 {
126    gdcmDirList fileList(path,1);
127    ListHeader list;
128    gdcmHeader *header;
129
130    listEntries.clear();
131    patients.clear();
132
133    for(gdcmDirList::iterator it=fileList.begin(); 
134        it!=fileList.end(); ++it) 
135    {
136 //      std::cout<<*it<<std::endl;
137       header=new gdcmHeader(it->c_str());
138       if(header->IsReadable())
139          list.push_back(header);
140       else
141          delete header;
142    }
143
144    SetElements(path,list);
145 }
146
147 /*
148  * \ingroup gdcmDicomDir
149  * \brief   Get the dicom dir path
150  * @param   
151  */
152 std::string gdcmDicomDir::GetPath(void)
153 {
154    std::string path=GetFileName();
155
156    int pos1=path.rfind("/");
157    int pos2=path.rfind("\\");
158    if(pos1>pos2)
159       path.resize(pos1);
160    else
161       path.resize(pos2);
162
163    return(path);
164 }
165
166 //-----------------------------------------------------------------------------
167 // Private
168 /*
169  * \ingroup gdcmDicomDir
170  * \brief   
171  * @param   
172  */
173 void gdcmDicomDir::CreateDicomDir()
174 {
175    // The list is parsed. When a tag is found :
176    //  1 - we save the beginning iterator
177    //  2 - we continue to parse
178    //  3 - we find an other tag
179    //       + we create the object for the precedent tag
180    //       + loop to 1 -
181
182    gdcmDicomDirType type=gdcmDicomDir::GDCM_NONE;
183    ListTag::iterator begin;
184    ListTag::iterator end;
185
186    begin=listEntries.begin();
187    end=begin;
188    for(ListTag::iterator i=listEntries.begin();i !=listEntries.end();++i) 
189    {
190       // std::cout << std::hex <<(*i)->GetGroup() << 
191       //                  " " <<(*i)->GetElement() << endl;
192
193       std::string v=(*i)->GetValue();
194       if(v=="PATIENT ") 
195       {
196        //  std::cout<<"PATIENT"<<std::endl;
197          end=i;
198          AddObjectToEnd(type,begin,end);
199
200          type=gdcmDicomDir::GDCM_PATIENT;
201          begin=end;
202       } 
203
204       if(v=="STUDY ")
205       {
206        //  std::cout<<"STUDY"<<std::endl;
207          end=i;
208          AddObjectToEnd(type,begin,end);
209
210          type=gdcmDicomDir::GDCM_STUDY;
211          begin=end;
212       }
213
214       if(v=="SERIES") 
215       {
216        //  std::cout<<"SERIES"<<std::endl;
217          end=i;
218          AddObjectToEnd(type,begin,end);
219
220          type=gdcmDicomDir::GDCM_SERIE;
221          begin=end;
222       }
223
224       if(v=="IMAGE ") 
225       {
226        //  std::cout<<"IMAGE"<<std::endl;
227          end=i;
228          AddObjectToEnd(type,begin,end);
229
230          type=gdcmDicomDir::GDCM_IMAGE;
231          begin=end;
232       }
233    }
234
235    end=GetListEntry().end();
236    AddObjectToEnd(type,begin,end);
237 }
238 /*
239  * \ingroup gdcmDicomDir
240  * \brief   
241  * @param   
242  */
243 void gdcmDicomDir::AddObjectToEnd(gdcmDicomDirType type,ListTag::iterator begin,ListTag::iterator end)
244 {
245    if(begin==end)
246       return;
247
248    switch(type)
249    {
250       case gdcmDicomDir::GDCM_PATIENT:
251          AddPatientToEnd(begin,end);
252          break;
253       case gdcmDicomDir::GDCM_STUDY:
254          AddStudyToEnd(begin,end);
255          break;
256       case gdcmDicomDir::GDCM_SERIE:
257          AddSerieToEnd(begin,end);
258          break;
259       case gdcmDicomDir::GDCM_IMAGE:
260          AddImageToEnd(begin,end);
261          break;
262    }
263 }
264
265 /*
266  * \ingroup gdcmDicomDir
267  * \brief   
268  * @param   
269  */
270 void gdcmDicomDir::AddPatientToEnd(ListTag::iterator begin,ListTag::iterator end)
271 {
272    patients.push_back(new gdcmPatient(begin,end));
273 }
274
275 /*
276  * \ingroup gdcmDicomDir
277  * \brief   
278  * @param   
279  */
280  void gdcmDicomDir::AddStudyToEnd(ListTag::iterator begin,ListTag::iterator end)
281 {
282    if(patients.size()>0)
283    {
284       ListPatient::iterator itp=patients.end();
285       itp--;
286      (*itp)->AddStudy(new gdcmStudy(begin,end));
287    }
288 }
289 /*
290  * \ingroup gdcmDicomDir
291  * \brief   
292  * @param   
293  */
294 void gdcmDicomDir::AddSerieToEnd(ListTag::iterator begin,ListTag::iterator end)
295 {
296    if(patients.size()>0)
297    {
298       ListPatient::iterator itp=patients.end();
299       itp--;
300
301       if((*itp)->GetStudies().size()>0)
302       {
303          ListStudy::iterator itst=(*itp)->GetStudies().end();
304          itst--;
305         (*itst)->AddSerie(new gdcmSerie(begin,end));
306       }
307    }
308 }
309
310 /*
311  * \ingroup gdcmDicomDir
312  * \brief   
313  * @param   
314  */
315  void gdcmDicomDir::AddImageToEnd(ListTag::iterator begin,ListTag::iterator end)
316 {
317    if(patients.size()>0)
318    {
319       ListPatient::iterator itp=patients.end();
320       itp--;
321
322       if((*itp)->GetStudies().size()>0)
323       {
324          ListStudy::iterator itst=(*itp)->GetStudies().end();
325          itst--;
326
327          if((*itst)->GetSeries().size()>0)
328          {
329             ListSerie::iterator its=(*itst)->GetSeries().end();
330             its--;
331            (*its)->AddImage(new gdcmImage(begin,end));
332          }
333       }
334    }
335 }
336
337 /*
338  * \ingroup gdcmDicomDir
339  * \brief   
340  * @param   
341  */
342 void gdcmDicomDir::SetElements(std::string &path,ListHeader &list)
343 {
344    std::string patPrevName="", patPrevID="";
345    std::string studPrevInstanceUID="", studPrevID="";
346    std::string serPrevInstanceUID="", serPrevID="";
347
348    std::string patCurName, patCurID;
349    std::string studCurInstanceUID, studCurID;
350    std::string serCurInstanceUID, serCurID;
351
352    SetElement(path,GDCM_NONE,NULL);
353
354    ListTag::iterator debPat=listEntries.begin();
355    for(ListHeader::iterator it=list.begin();it!=list.end();++it) 
356    {
357      // get the current file characteristics
358       patCurName=(*it)->GetEntryByNumber(0x0010,0x0010); 
359       patCurID=(*it)->GetEntryByNumber(0x0010,0x0011); 
360       studCurInstanceUID=(*it)->GetEntryByNumber(0x0020,0x000d);            
361       studCurID=(*it)->GetEntryByNumber(0x0020,0x0010);            
362       serCurInstanceUID=(*it)->GetEntryByNumber(0x0020,0x000e);            
363       serCurID=(*it)->GetEntryByNumber(0x0020,0x0011);
364
365       if(patCurName!=patPrevName || patCurID!=patPrevID) 
366          SetElement(path,GDCM_PATIENT,*it);
367
368       // if new Study Deal with 'STUDY' Elements   
369       if(studCurInstanceUID!=studPrevInstanceUID || studCurID!=studPrevID) 
370          SetElement(path,GDCM_STUDY,*it);
371
372       // if new Serie Deal with 'SERIE' Elements   
373       if(serCurInstanceUID!=serPrevInstanceUID || serCurID!=serPrevID) 
374       {
375          SetElement(path,GDCM_SERIE,*it);
376       } 
377       
378       // Always Deal with 'IMAGE' Elements  
379       SetElement(path,GDCM_IMAGE,*it);
380
381       patPrevName=patCurName;
382       patPrevID=patCurID;
383       studPrevInstanceUID=studCurInstanceUID;
384       studPrevID=studCurID;
385       serPrevInstanceUID=serCurInstanceUID;
386       serPrevID=serCurID;
387    }
388 }
389
390 /*
391  * \ingroup gdcmDicomDir
392  * \brief   
393  * @param   
394  */
395 void gdcmDicomDir::SetElement(std::string &path,gdcmDicomDirType type,gdcmHeader *header)
396 {
397    std::list<gdcmElement> elemList;
398    std::list<gdcmElement>::iterator it;
399    guint16 tmpGr, tmpEl;
400    gdcmDictEntry *dictEntry;
401    gdcmHeaderEntry *entry;
402    std::string val;
403
404    switch(type)
405    {
406       case GDCM_PATIENT:
407          elemList=gdcmGlobal::GetDicomDirElements()->GetPatientElements();
408          break;
409       case GDCM_STUDY:
410          elemList=gdcmGlobal::GetDicomDirElements()->GetStudyElements();
411          break;
412       case GDCM_SERIE:
413          elemList=gdcmGlobal::GetDicomDirElements()->GetSerieElements();
414          break;
415       case GDCM_IMAGE:
416          elemList=gdcmGlobal::GetDicomDirElements()->GetImageElements();
417          break;
418       case GDCM_NONE:
419          elemList=gdcmGlobal::GetDicomDirElements()->GetMetaElements();
420          break;
421       default:
422          return;
423    }
424
425    for(it=elemList.begin();it!=elemList.end();++it)
426    {
427       tmpGr=it->group;
428       tmpEl=it->elem;
429
430       dictEntry=GetPubDict()->GetDictEntryByNumber(tmpGr,tmpEl);
431       entry=new gdcmHeaderEntry(dictEntry);
432       entry->SetOffset(0); // just to avoid missprinting
433
434       if(header)
435          val=header->GetEntryByNumber(tmpGr,tmpEl);
436       else
437          val=GDCM_UNFOUND;
438
439       if(val==GDCM_UNFOUND) 
440       {
441          if((tmpGr==0x0004) &&(tmpEl==0x1130) )
442          {
443             // TODO force the *end* File Name(remove path)
444             val=path;
445          }
446          else if( (tmpGr==0x0004) && (tmpEl==0x1500) ) // Only used for image
447          {
448             if(header->GetFileName().substr(0,path.length())!=path)
449             {
450                dbg.Verbose(0, "gdcmDicomDir::SetElement : the base path of file name is incorrect");
451                val=header->GetFileName();
452             }
453             else
454                val=&(header->GetFileName()[path.length()]);
455          }
456          else
457          {
458             val=it->value;
459          }
460       }
461       entry->SetValue(val);
462
463       if(dictEntry)
464       {
465          if( (dictEntry->GetVR()=="UL") || (dictEntry->GetVR()=="SL") ) 
466          {
467             entry->SetLength(4);
468          } 
469          else if( (dictEntry->GetVR()=="US") || (dictEntry->GetVR()=="SS") ) 
470          {
471             entry->SetLength(2); 
472          } 
473          else if(dictEntry->GetVR()=="SQ") 
474          {
475             entry->SetLength(0xffffffff);
476          }
477          else
478          {
479             entry->SetLength(entry->GetValue().length());        
480          }
481       }
482
483       listEntries.push_back(entry);
484    }     
485 }
486
487 //-----------------------------------------------------------------------------