2 //-----------------------------------------------------------------------------
3 #include "gdcmDicomDir.h"
7 #include "gdcmDirList.h"
13 #include <sys/types.h>
16 void StartMethod(void * = NULL)
18 std::cout<<"Start parsing"<<std::endl;
21 void EndMethod(void * = NULL)
23 std::cout<<"End parsing"<<std::endl;
26 //-----------------------------------------------------------------------------
27 // For full DICOMDIR description, see:
28 // PS 3.3-2003, pages 731-750
29 //-----------------------------------------------------------------------------
30 // Constructor / Destructor
32 * \ingroup gdcmDicomDir
35 * @param exception_on_error
37 gdcmDicomDir::gdcmDicomDir(const char *FileName, bool parseDir,
38 bool exception_on_error):
39 gdcmParser(FileName,exception_on_error,true)
41 startMethod=StartMethod;
53 if( GetListEntry().begin()==GetListEntry().end() )
55 dbg.Verbose(0, "gdcmDicomDir::gdcmDicomDir : entry list empty");
59 dbg.Verbose(0, "gdcmDicomDir::gdcmDicomDir : Parse directory and create the DicomDir");
68 * \ingroup gdcmDicomDir
69 * \brief Canonical destructor
71 gdcmDicomDir::~gdcmDicomDir()
76 for(ListPatient::iterator cc=patients.begin();cc!=patients.end();++cc)
82 //-----------------------------------------------------------------------------
85 * \ingroup gdcmDicomDir
86 * \brief Canonical Printer
88 void gdcmDicomDir::Print(std::ostream &os)
92 metaElems->SetPrintLevel(printLevel);
96 for(ListPatient::iterator cc=patients.begin();cc!=patients.end();++cc)
98 (*cc)->SetPrintLevel(printLevel);
103 //-----------------------------------------------------------------------------
106 * \ingroup gdcmDicomDir
107 * \brief This predicate, based on hopefully reasonable heuristics,
108 * decides whether or not the current gdcmParser was properly parsed
109 * and contains the mandatory information for being considered as
110 * a well formed and usable DicomDir.
111 * @return true when gdcmParser is the one of a reasonable DicomDir,
114 bool gdcmDicomDir::IsReadable(void)
116 if(!gdcmParser::IsReadable())
120 if(patients.size()<=0)
127 * \ingroup gdcmDicomDir
128 * \brief fills whole the structure
130 void gdcmDicomDir::ParseDirectory(void)
132 NewDicomDir(GetPath());
137 * \ingroup gdcmDicomDir
138 * \brief writes on disc a DICOMDIR
139 * \ warning does NOT add the missing elements in the header :
140 * it's up to the user doing it !
141 * @param fileName file to be written to
142 * @return false only when fail to open
144 bool gdcmDicomDir::Write(std::string fileName)
148 fp1=fopen(fileName.c_str(),"wb");
151 printf("Failed to open(write) File [%s] \n",fileName.c_str());
156 filePreamble=(char*)calloc(128,1);
157 fwrite(filePreamble,128,1,fp1);
158 fwrite("DICM",4,1,fp1);
161 WriteEntries(fp1,DICOMDIR);
168 //-----------------------------------------------------------------------------
171 * \ingroup gdcmDicomDir
172 * \brief create a gdcmDicomDir from a root Directory
173 * @param path entry point of the stree-like structure
175 void gdcmDicomDir::NewDicomDir(std::string path)
179 gdcmDirList fileList(path,1);
180 unsigned int count=0;
187 for(gdcmDirList::iterator it=fileList.begin();
188 it!=fileList.end(); ++it)
190 progress=(float)(count+1)/(float)fileList.size();
191 CallProgressMethod();
195 header=new gdcmHeader(it->c_str());
196 if(header->IsReadable())
197 list.push_back(header);
204 std::sort(list.begin(),list.end(),gdcmDicomDir::HeaderLessThan);
206 std::string tmp=fileList.GetDirName();
207 SetElements(tmp,list);
213 * \ingroup gdcmDicomDir
214 * \brief Get the DicomDir path
217 std::string gdcmDicomDir::GetPath(void)
219 std::string path=GetFileName();
221 int pos1=path.rfind("/");
222 int pos2=path.rfind("\\");
231 void gdcmDicomDir::CallStartMethod(void)
236 startMethod(startArg);
239 void gdcmDicomDir::CallProgressMethod(void)
242 progressMethod(progressArg);
245 void gdcmDicomDir::CallEndMethod(void)
252 //-----------------------------------------------------------------------------
255 * \ingroup gdcmDicomDir
256 * \brief create a 'gdcmDicomDir' from a DICOMDIR gdcmHeader
258 void gdcmDicomDir::CreateDicomDir()
260 // The list is parsed. When a tag is found :
261 // 1 - we save the beginning iterator
262 // 2 - we continue to parse
263 // 3 - we find an other tag
264 // + we create the object for the precedent tag
267 gdcmDicomDirType type=gdcmDicomDir::GDCM_META;
268 ListTag::iterator begin;
269 ListTag::iterator end;
271 begin=listEntries.begin();
273 for(ListTag::iterator i=end;i !=listEntries.end();++i)
275 std::string v=(*i)->GetValue();
279 AddObjectToEnd(type,begin,end);
281 type=gdcmDicomDir::GDCM_PATIENT;
288 AddObjectToEnd(type,begin,end);
290 type=gdcmDicomDir::GDCM_STUDY;
297 AddObjectToEnd(type,begin,end);
299 type=gdcmDicomDir::GDCM_SERIE;
306 AddObjectToEnd(type,begin,end);
308 type=gdcmDicomDir::GDCM_IMAGE;
315 end=GetListEntry().end();
316 AddObjectToEnd(type,begin,end);
320 * \ingroup gdcmDicomDir
326 void gdcmDicomDir::AddObjectToEnd(gdcmDicomDirType type,ListTag::iterator begin,ListTag::iterator end)
333 case gdcmDicomDir::GDCM_META:
334 AddMetaToEnd(begin,end);
336 case gdcmDicomDir::GDCM_PATIENT:
337 AddPatientToEnd(begin,end);
339 case gdcmDicomDir::GDCM_STUDY:
340 AddStudyToEnd(begin,end);
342 case gdcmDicomDir::GDCM_SERIE:
343 AddSerieToEnd(begin,end);
345 case gdcmDicomDir::GDCM_IMAGE:
346 AddImageToEnd(begin,end);
352 * \ingroup gdcmDicomDir
353 * \brief Well ... Not realy to end, there is only one occurence
357 void gdcmDicomDir::AddMetaToEnd(ListTag::iterator begin,ListTag::iterator end)
361 metaElems = new gdcmMeta(begin,end);
365 * \ingroup gdcmDicomDir
370 void gdcmDicomDir::AddPatientToEnd(ListTag::iterator begin,ListTag::iterator end)
372 patients.push_back(new gdcmPatient(begin,end));
376 * \ingroup gdcmDicomDir
381 void gdcmDicomDir::AddStudyToEnd(ListTag::iterator begin,ListTag::iterator end)
383 if(patients.size()>0)
385 ListPatient::iterator itp=patients.end();
387 (*itp)->AddStudy(new gdcmStudy(begin,end));
391 * \ingroup gdcmDicomDir
396 void gdcmDicomDir::AddSerieToEnd(ListTag::iterator begin,ListTag::iterator end)
398 if(patients.size()>0)
400 ListPatient::iterator itp=patients.end();
403 if((*itp)->GetStudies().size()>0)
405 ListStudy::iterator itst=(*itp)->GetStudies().end();
407 (*itst)->AddSerie(new gdcmSerie(begin,end));
413 * \ingroup gdcmDicomDir
418 void gdcmDicomDir::AddImageToEnd(ListTag::iterator begin,ListTag::iterator end)
420 if(patients.size()>0)
422 ListPatient::iterator itp=patients.end();
425 if((*itp)->GetStudies().size()>0)
427 ListStudy::iterator itst=(*itp)->GetStudies().end();
430 if((*itst)->GetSeries().size()>0)
432 ListSerie::iterator its=(*itst)->GetSeries().end();
434 (*its)->AddImage(new gdcmImage(begin,end));
441 * \ingroup gdcmDicomDir
446 void gdcmDicomDir::SetElements(std::string &path,ListHeader &list)
448 std::string patPrevName="", patPrevID="";
449 std::string studPrevInstanceUID="", studPrevID="";
450 std::string serPrevInstanceUID="", serPrevID="";
452 std::string patCurName, patCurID;
453 std::string studCurInstanceUID, studCurID;
454 std::string serCurInstanceUID, serCurID;
456 SetElement(path,GDCM_NONE,NULL);
458 ListTag::iterator debPat=listEntries.begin();
459 for(ListHeader::iterator it=list.begin();it!=list.end();++it)
461 // get the current file characteristics
462 patCurName=(*it)->GetEntryByNumber(0x0010,0x0010);
463 patCurID=(*it)->GetEntryByNumber(0x0010,0x0011);
464 studCurInstanceUID=(*it)->GetEntryByNumber(0x0020,0x000d);
465 studCurID=(*it)->GetEntryByNumber(0x0020,0x0010);
466 serCurInstanceUID=(*it)->GetEntryByNumber(0x0020,0x000e);
467 serCurID=(*it)->GetEntryByNumber(0x0020,0x0011);
469 if(patCurName!=patPrevName || patCurID!=patPrevID)
470 SetElement(path,GDCM_PATIENT,*it);
472 // if new Study Deal with 'STUDY' Elements
473 if(studCurInstanceUID!=studPrevInstanceUID || studCurID!=studPrevID)
474 SetElement(path,GDCM_STUDY,*it);
476 // if new Serie Deal with 'SERIE' Elements
477 if(serCurInstanceUID!=serPrevInstanceUID || serCurID!=serPrevID)
478 SetElement(path,GDCM_SERIE,*it);
480 // Always Deal with 'IMAGE' Elements
481 SetElement(path,GDCM_IMAGE,*it);
483 patPrevName=patCurName;
485 studPrevInstanceUID=studCurInstanceUID;
486 studPrevID=studCurID;
487 serPrevInstanceUID=serCurInstanceUID;
493 * \ingroup gdcmDicomDir
499 void gdcmDicomDir::SetElement(std::string &path,gdcmDicomDirType type,gdcmHeader *header)
501 std::list<gdcmElement> elemList;
502 std::list<gdcmElement>::iterator it;
503 guint16 tmpGr, tmpEl;
504 gdcmDictEntry *dictEntry;
505 gdcmHeaderEntry *entry;
511 elemList=gdcmGlobal::GetDicomDirElements()->GetPatientElements();
514 elemList=gdcmGlobal::GetDicomDirElements()->GetStudyElements();
517 elemList=gdcmGlobal::GetDicomDirElements()->GetSerieElements();
520 elemList=gdcmGlobal::GetDicomDirElements()->GetImageElements();
523 elemList=gdcmGlobal::GetDicomDirElements()->GetMetaElements();
529 for(it=elemList.begin();it!=elemList.end();++it)
534 dictEntry=GetPubDict()->GetDictEntryByNumber(tmpGr,tmpEl);
535 entry=new gdcmHeaderEntry(dictEntry);
536 entry->SetOffset(0); // just to avoid missprinting
539 val=header->GetEntryByNumber(tmpGr,tmpEl);
543 if(val==GDCM_UNFOUND)
545 if((tmpGr==0x0004) &&(tmpEl==0x1130) )
547 // TODO force the *end* File Name(remove path)
550 else if( (tmpGr==0x0004) && (tmpEl==0x1500) ) // Only used for image
552 if(header->GetFileName().substr(0,path.length())!=path)
554 dbg.Verbose(0, "gdcmDicomDir::SetElement : the base path of file name is incorrect");
555 val=header->GetFileName();
558 val=&(header->GetFileName()[path.length()]);
565 entry->SetValue(val);
569 if( (dictEntry->GetVR()=="UL") || (dictEntry->GetVR()=="SL") )
573 else if( (dictEntry->GetVR()=="US") || (dictEntry->GetVR()=="SS") )
577 else if(dictEntry->GetVR()=="SQ")
579 entry->SetLength(0xffffffff);
583 entry->SetLength(entry->GetValue().length());
587 listEntries.push_back(entry);
591 bool gdcmDicomDir::HeaderLessThan(gdcmHeader *header1,gdcmHeader *header2)
593 return(*header1<*header2);
596 //-----------------------------------------------------------------------------