2 //-----------------------------------------------------------------------------
3 #include "gdcmDicomDir.h"
7 #include "gdcmDirList.h"
13 #include <sys/types.h>
15 //-----------------------------------------------------------------------------
16 // For full DICOMDIR description, see:
17 // PS 3.3-2003, pages 731-750
18 //-----------------------------------------------------------------------------
19 // Constructor / Destructor
21 * \ingroup gdcmDicomDir
24 * @param exception_on_error
26 gdcmDicomDir::gdcmDicomDir(const char *FileName, bool parseDir,
27 bool exception_on_error):
28 gdcmParser(FileName,exception_on_error,true)
30 if( GetListEntry().begin()==GetListEntry().end() )
32 dbg.Verbose(0, "gdcmDicomDir::gdcmDicomDir : entry list empty");
36 dbg.Verbose(0, "gdcmDicomDir::gdcmDicomDir : Parse directory and create the DicomDir");
45 * \ingroup gdcmDicomDir
47 * @param exception_on_error
49 /*gdcmDicomDir::gdcmDicomDir(ListTag *l,
50 bool exception_on_error):
51 gdcmParser(exception_on_error )
58 * \ingroup gdcmDicomDir
59 * \brief Canonical destructor
61 gdcmDicomDir::~gdcmDicomDir()
65 for(ListPatient::iterator cc=patients.begin();cc!=patients.end();++cc)
71 //-----------------------------------------------------------------------------
74 * \ingroup gdcmDicomDir
75 * \brief Canonical Printer
77 void gdcmDicomDir::Print(std::ostream &os)
79 (*metaelems).SetPrintLevel(printLevel);
80 (*metaelems).Print(os);
82 for(ListPatient::iterator cc=patients.begin();cc!=patients.end();++cc)
84 (*cc)->SetPrintLevel(printLevel);
89 //-----------------------------------------------------------------------------
92 * \ingroup gdcmDicomDir
93 * \brief writes on disc a DICOMDIR
94 * \ warning does NOT add the missing elements in the header :
95 * it's up to the user doing it !
96 * @param fileName file to be written to
97 * @return false only when fail to open
99 bool gdcmDicomDir::Write(std::string fileName)
103 fp1=fopen(fileName.c_str(),"wb");
106 printf("Failed to open(write) File [%s] \n",fileName.c_str());
111 filePreamble=(char*)calloc(128,1);
112 fwrite(filePreamble,128,1,fp1);
113 fwrite("DICM",4,1,fp1);
116 WriteEntries(fp1,DICOMDIR);
124 * \ingroup gdcmDicomDir
125 * \brief fills whole the structure
127 void gdcmDicomDir::ParseDirectory(void)
129 NewDicomDir(GetPath());
133 //-----------------------------------------------------------------------------
136 * \ingroup gdcmDicomDir
137 * \brief create a gdcmDicomDir from a root Directory
138 * @param path entry point of the stree-like structure
140 void gdcmDicomDir::NewDicomDir(std::string path)
142 gdcmDirList fileList(path,1);
149 for(gdcmDirList::iterator it=fileList.begin();
150 it!=fileList.end(); ++it)
152 header=new gdcmHeader(it->c_str());
153 if(header->IsReadable())
154 list.push_back(header);
159 std::sort(list.begin(),list.end(),gdcmDicomDir::HeaderLessThan);
161 std::string tmp=fileList.GetDirName();
162 SetElements(tmp,list);
166 * \ingroup gdcmDicomDir
167 * \brief Get the DicomDir path
170 std::string gdcmDicomDir::GetPath(void)
172 std::string path=GetFileName();
174 int pos1=path.rfind("/");
175 int pos2=path.rfind("\\");
184 //-----------------------------------------------------------------------------
187 * \ingroup gdcmDicomDir
188 * \brief create a 'gdcmDicomDir' from a DICOMDIR gdcmHeader
190 void gdcmDicomDir::CreateDicomDir()
192 // The list is parsed. When a tag is found :
193 // 1 - we save the beginning iterator
194 // 2 - we continue to parse
195 // 3 - we find an other tag
196 // + we create the object for the precedent tag
199 gdcmDicomDirType type=gdcmDicomDir::GDCM_NONE;
200 ListTag::iterator begin;
201 ListTag::iterator end;
204 begin=listEntries.begin();
207 for(ListTag::iterator j=begin;j !=listEntries.end();++j)
209 if((*j)->GetValue()=="PATIENT ") {
214 AddObjectToEnd(gdcmDicomDir::GDCM_META,begin,k);
216 for(ListTag::iterator i=k;i !=listEntries.end();++i)
218 std::string v=(*i)->GetValue();
222 AddObjectToEnd(type,begin,end);
224 type=gdcmDicomDir::GDCM_PATIENT;
231 AddObjectToEnd(type,begin,end);
233 type=gdcmDicomDir::GDCM_STUDY;
240 AddObjectToEnd(type,begin,end);
242 type=gdcmDicomDir::GDCM_SERIE;
249 AddObjectToEnd(type,begin,end);
251 type=gdcmDicomDir::GDCM_IMAGE;
256 end=GetListEntry().end();
257 AddObjectToEnd(type,begin,end);
260 * \ingroup gdcmDicomDir
266 void gdcmDicomDir::AddObjectToEnd(gdcmDicomDirType type,ListTag::iterator begin,ListTag::iterator end)
273 case gdcmDicomDir::GDCM_META:
274 AddMetaToEnd(begin,end);
276 case gdcmDicomDir::GDCM_PATIENT:
277 AddPatientToEnd(begin,end);
279 case gdcmDicomDir::GDCM_STUDY:
280 AddStudyToEnd(begin,end);
282 case gdcmDicomDir::GDCM_SERIE:
283 AddSerieToEnd(begin,end);
285 case gdcmDicomDir::GDCM_IMAGE:
286 AddImageToEnd(begin,end);
293 * \ingroup gdcmDicomDir
294 * \brief Well ... Not realy to end, there is only one occurence
298 void gdcmDicomDir::AddMetaToEnd(ListTag::iterator begin,ListTag::iterator end)
300 metaelems = new gdcmMeta(begin,end);
304 * \ingroup gdcmDicomDir
309 void gdcmDicomDir::AddPatientToEnd(ListTag::iterator begin,ListTag::iterator end)
311 patients.push_back(new gdcmPatient(begin,end));
315 * \ingroup gdcmDicomDir
320 void gdcmDicomDir::AddStudyToEnd(ListTag::iterator begin,ListTag::iterator end)
322 if(patients.size()>0)
324 ListPatient::iterator itp=patients.end();
326 (*itp)->AddStudy(new gdcmStudy(begin,end));
330 * \ingroup gdcmDicomDir
335 void gdcmDicomDir::AddSerieToEnd(ListTag::iterator begin,ListTag::iterator end)
337 if(patients.size()>0)
339 ListPatient::iterator itp=patients.end();
342 if((*itp)->GetStudies().size()>0)
344 ListStudy::iterator itst=(*itp)->GetStudies().end();
346 (*itst)->AddSerie(new gdcmSerie(begin,end));
352 * \ingroup gdcmDicomDir
357 void gdcmDicomDir::AddImageToEnd(ListTag::iterator begin,ListTag::iterator end)
359 if(patients.size()>0)
361 ListPatient::iterator itp=patients.end();
364 if((*itp)->GetStudies().size()>0)
366 ListStudy::iterator itst=(*itp)->GetStudies().end();
369 if((*itst)->GetSeries().size()>0)
371 ListSerie::iterator its=(*itst)->GetSeries().end();
373 (*its)->AddImage(new gdcmImage(begin,end));
380 * \ingroup gdcmDicomDir
385 void gdcmDicomDir::SetElements(std::string &path,ListHeader &list)
387 std::string patPrevName="", patPrevID="";
388 std::string studPrevInstanceUID="", studPrevID="";
389 std::string serPrevInstanceUID="", serPrevID="";
391 std::string patCurName, patCurID;
392 std::string studCurInstanceUID, studCurID;
393 std::string serCurInstanceUID, serCurID;
395 SetElement(path,GDCM_NONE,NULL);
397 ListTag::iterator debPat=listEntries.begin();
398 for(ListHeader::iterator it=list.begin();it!=list.end();++it)
400 // get the current file characteristics
401 patCurName=(*it)->GetEntryByNumber(0x0010,0x0010);
402 patCurID=(*it)->GetEntryByNumber(0x0010,0x0011);
403 studCurInstanceUID=(*it)->GetEntryByNumber(0x0020,0x000d);
404 studCurID=(*it)->GetEntryByNumber(0x0020,0x0010);
405 serCurInstanceUID=(*it)->GetEntryByNumber(0x0020,0x000e);
406 serCurID=(*it)->GetEntryByNumber(0x0020,0x0011);
408 if(patCurName!=patPrevName || patCurID!=patPrevID)
409 SetElement(path,GDCM_PATIENT,*it);
411 // if new Study Deal with 'STUDY' Elements
412 if(studCurInstanceUID!=studPrevInstanceUID || studCurID!=studPrevID)
413 SetElement(path,GDCM_STUDY,*it);
415 // if new Serie Deal with 'SERIE' Elements
416 if(serCurInstanceUID!=serPrevInstanceUID || serCurID!=serPrevID)
417 SetElement(path,GDCM_SERIE,*it);
419 // Always Deal with 'IMAGE' Elements
420 SetElement(path,GDCM_IMAGE,*it);
422 patPrevName=patCurName;
424 studPrevInstanceUID=studCurInstanceUID;
425 studPrevID=studCurID;
426 serPrevInstanceUID=serCurInstanceUID;
432 * \ingroup gdcmDicomDir
438 void gdcmDicomDir::SetElement(std::string &path,gdcmDicomDirType type,gdcmHeader *header)
440 std::list<gdcmElement> elemList;
441 std::list<gdcmElement>::iterator it;
442 guint16 tmpGr, tmpEl;
443 gdcmDictEntry *dictEntry;
444 gdcmHeaderEntry *entry;
450 elemList=gdcmGlobal::GetDicomDirElements()->GetPatientElements();
453 elemList=gdcmGlobal::GetDicomDirElements()->GetStudyElements();
456 elemList=gdcmGlobal::GetDicomDirElements()->GetSerieElements();
459 elemList=gdcmGlobal::GetDicomDirElements()->GetImageElements();
462 elemList=gdcmGlobal::GetDicomDirElements()->GetMetaElements();
468 for(it=elemList.begin();it!=elemList.end();++it)
473 dictEntry=GetPubDict()->GetDictEntryByNumber(tmpGr,tmpEl);
474 entry=new gdcmHeaderEntry(dictEntry);
475 entry->SetOffset(0); // just to avoid missprinting
478 val=header->GetEntryByNumber(tmpGr,tmpEl);
482 if(val==GDCM_UNFOUND)
484 if((tmpGr==0x0004) &&(tmpEl==0x1130) )
486 // TODO force the *end* File Name(remove path)
489 else if( (tmpGr==0x0004) && (tmpEl==0x1500) ) // Only used for image
491 if(header->GetFileName().substr(0,path.length())!=path)
493 dbg.Verbose(0, "gdcmDicomDir::SetElement : the base path of file name is incorrect");
494 val=header->GetFileName();
497 val=&(header->GetFileName()[path.length()]);
504 entry->SetValue(val);
508 if( (dictEntry->GetVR()=="UL") || (dictEntry->GetVR()=="SL") )
512 else if( (dictEntry->GetVR()=="US") || (dictEntry->GetVR()=="SS") )
516 else if(dictEntry->GetVR()=="SQ")
518 entry->SetLength(0xffffffff);
522 entry->SetLength(entry->GetValue().length());
526 listEntries.push_back(entry);
530 bool gdcmDicomDir::HeaderLessThan(gdcmHeader *header1,gdcmHeader *header2)
532 return(*header1<*header2);
535 //-----------------------------------------------------------------------------