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