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)
32 if( GetListEntry().begin()==GetListEntry().end() )
34 dbg.Verbose(0, "gdcmDicomDir::gdcmDicomDir : entry list empty");
38 dbg.Verbose(0, "gdcmDicomDir::gdcmDicomDir : Parse directory and create the DicomDir");
47 * \ingroup gdcmDicomDir
48 * \brief Canonical destructor
50 gdcmDicomDir::~gdcmDicomDir()
55 for(ListPatient::iterator cc=patients.begin();cc!=patients.end();++cc)
61 //-----------------------------------------------------------------------------
64 * \ingroup gdcmDicomDir
65 * \brief Canonical Printer
67 void gdcmDicomDir::Print(std::ostream &os)
71 metaElems->SetPrintLevel(printLevel);
75 for(ListPatient::iterator cc=patients.begin();cc!=patients.end();++cc)
77 (*cc)->SetPrintLevel(printLevel);
82 //-----------------------------------------------------------------------------
85 * \ingroup gdcmDicomDir
86 * \brief writes on disc a DICOMDIR
87 * \ warning does NOT add the missing elements in the header :
88 * it's up to the user doing it !
89 * @param fileName file to be written to
90 * @return false only when fail to open
92 bool gdcmDicomDir::Write(std::string fileName)
96 fp1=fopen(fileName.c_str(),"wb");
99 printf("Failed to open(write) File [%s] \n",fileName.c_str());
104 filePreamble=(char*)calloc(128,1);
105 fwrite(filePreamble,128,1,fp1);
106 fwrite("DICM",4,1,fp1);
109 WriteEntries(fp1,DICOMDIR);
117 * \ingroup gdcmDicomDir
118 * \brief fills whole the structure
120 void gdcmDicomDir::ParseDirectory(void)
122 NewDicomDir(GetPath());
126 //-----------------------------------------------------------------------------
129 * \ingroup gdcmDicomDir
130 * \brief create a gdcmDicomDir from a root Directory
131 * @param path entry point of the stree-like structure
133 void gdcmDicomDir::NewDicomDir(std::string path)
135 gdcmDirList fileList(path,1);
142 for(gdcmDirList::iterator it=fileList.begin();
143 it!=fileList.end(); ++it)
145 std::cout<<*it<<std::endl;
146 header=new gdcmHeader(it->c_str());
147 if(header->IsReadable())
148 list.push_back(header);
153 std::sort(list.begin(),list.end(),gdcmDicomDir::HeaderLessThan);
155 std::string tmp=fileList.GetDirName();
156 SetElements(tmp,list);
160 * \ingroup gdcmDicomDir
161 * \brief Get the DicomDir path
164 std::string gdcmDicomDir::GetPath(void)
166 std::string path=GetFileName();
168 int pos1=path.rfind("/");
169 int pos2=path.rfind("\\");
178 //-----------------------------------------------------------------------------
181 * \ingroup gdcmDicomDir
182 * \brief create a 'gdcmDicomDir' from a DICOMDIR gdcmHeader
184 void gdcmDicomDir::CreateDicomDir()
186 // The list is parsed. When a tag is found :
187 // 1 - we save the beginning iterator
188 // 2 - we continue to parse
189 // 3 - we find an other tag
190 // + we create the object for the precedent tag
193 gdcmDicomDirType type=gdcmDicomDir::GDCM_META;
194 ListTag::iterator begin;
195 ListTag::iterator end;
197 begin=listEntries.begin();
199 for(ListTag::iterator i=end;i !=listEntries.end();++i)
201 std::string v=(*i)->GetValue();
205 AddObjectToEnd(type,begin,end);
207 type=gdcmDicomDir::GDCM_PATIENT;
214 AddObjectToEnd(type,begin,end);
216 type=gdcmDicomDir::GDCM_STUDY;
223 AddObjectToEnd(type,begin,end);
225 type=gdcmDicomDir::GDCM_SERIE;
232 AddObjectToEnd(type,begin,end);
234 type=gdcmDicomDir::GDCM_IMAGE;
241 end=GetListEntry().end();
242 AddObjectToEnd(type,begin,end);
246 * \ingroup gdcmDicomDir
252 void gdcmDicomDir::AddObjectToEnd(gdcmDicomDirType type,ListTag::iterator begin,ListTag::iterator end)
259 case gdcmDicomDir::GDCM_META:
260 AddMetaToEnd(begin,end);
262 case gdcmDicomDir::GDCM_PATIENT:
263 AddPatientToEnd(begin,end);
265 case gdcmDicomDir::GDCM_STUDY:
266 AddStudyToEnd(begin,end);
268 case gdcmDicomDir::GDCM_SERIE:
269 AddSerieToEnd(begin,end);
271 case gdcmDicomDir::GDCM_IMAGE:
272 AddImageToEnd(begin,end);
278 * \ingroup gdcmDicomDir
279 * \brief Well ... Not realy to end, there is only one occurence
283 void gdcmDicomDir::AddMetaToEnd(ListTag::iterator begin,ListTag::iterator end)
287 metaElems = new gdcmMeta(begin,end);
291 * \ingroup gdcmDicomDir
296 void gdcmDicomDir::AddPatientToEnd(ListTag::iterator begin,ListTag::iterator end)
298 patients.push_back(new gdcmPatient(begin,end));
302 * \ingroup gdcmDicomDir
307 void gdcmDicomDir::AddStudyToEnd(ListTag::iterator begin,ListTag::iterator end)
309 if(patients.size()>0)
311 ListPatient::iterator itp=patients.end();
313 (*itp)->AddStudy(new gdcmStudy(begin,end));
317 * \ingroup gdcmDicomDir
322 void gdcmDicomDir::AddSerieToEnd(ListTag::iterator begin,ListTag::iterator end)
324 if(patients.size()>0)
326 ListPatient::iterator itp=patients.end();
329 if((*itp)->GetStudies().size()>0)
331 ListStudy::iterator itst=(*itp)->GetStudies().end();
333 (*itst)->AddSerie(new gdcmSerie(begin,end));
339 * \ingroup gdcmDicomDir
344 void gdcmDicomDir::AddImageToEnd(ListTag::iterator begin,ListTag::iterator end)
346 if(patients.size()>0)
348 ListPatient::iterator itp=patients.end();
351 if((*itp)->GetStudies().size()>0)
353 ListStudy::iterator itst=(*itp)->GetStudies().end();
356 if((*itst)->GetSeries().size()>0)
358 ListSerie::iterator its=(*itst)->GetSeries().end();
360 (*its)->AddImage(new gdcmImage(begin,end));
367 * \ingroup gdcmDicomDir
372 void gdcmDicomDir::SetElements(std::string &path,ListHeader &list)
374 std::string patPrevName="", patPrevID="";
375 std::string studPrevInstanceUID="", studPrevID="";
376 std::string serPrevInstanceUID="", serPrevID="";
378 std::string patCurName, patCurID;
379 std::string studCurInstanceUID, studCurID;
380 std::string serCurInstanceUID, serCurID;
382 SetElement(path,GDCM_NONE,NULL);
384 ListTag::iterator debPat=listEntries.begin();
385 for(ListHeader::iterator it=list.begin();it!=list.end();++it)
387 // get the current file characteristics
388 patCurName=(*it)->GetEntryByNumber(0x0010,0x0010);
389 patCurID=(*it)->GetEntryByNumber(0x0010,0x0011);
390 studCurInstanceUID=(*it)->GetEntryByNumber(0x0020,0x000d);
391 studCurID=(*it)->GetEntryByNumber(0x0020,0x0010);
392 serCurInstanceUID=(*it)->GetEntryByNumber(0x0020,0x000e);
393 serCurID=(*it)->GetEntryByNumber(0x0020,0x0011);
395 if(patCurName!=patPrevName || patCurID!=patPrevID)
396 SetElement(path,GDCM_PATIENT,*it);
398 // if new Study Deal with 'STUDY' Elements
399 if(studCurInstanceUID!=studPrevInstanceUID || studCurID!=studPrevID)
400 SetElement(path,GDCM_STUDY,*it);
402 // if new Serie Deal with 'SERIE' Elements
403 if(serCurInstanceUID!=serPrevInstanceUID || serCurID!=serPrevID)
404 SetElement(path,GDCM_SERIE,*it);
406 // Always Deal with 'IMAGE' Elements
407 SetElement(path,GDCM_IMAGE,*it);
409 patPrevName=patCurName;
411 studPrevInstanceUID=studCurInstanceUID;
412 studPrevID=studCurID;
413 serPrevInstanceUID=serCurInstanceUID;
419 * \ingroup gdcmDicomDir
425 void gdcmDicomDir::SetElement(std::string &path,gdcmDicomDirType type,gdcmHeader *header)
427 std::list<gdcmElement> elemList;
428 std::list<gdcmElement>::iterator it;
429 guint16 tmpGr, tmpEl;
430 gdcmDictEntry *dictEntry;
431 gdcmHeaderEntry *entry;
437 elemList=gdcmGlobal::GetDicomDirElements()->GetPatientElements();
440 elemList=gdcmGlobal::GetDicomDirElements()->GetStudyElements();
443 elemList=gdcmGlobal::GetDicomDirElements()->GetSerieElements();
446 elemList=gdcmGlobal::GetDicomDirElements()->GetImageElements();
449 elemList=gdcmGlobal::GetDicomDirElements()->GetMetaElements();
455 for(it=elemList.begin();it!=elemList.end();++it)
460 dictEntry=GetPubDict()->GetDictEntryByNumber(tmpGr,tmpEl);
461 entry=new gdcmHeaderEntry(dictEntry);
462 entry->SetOffset(0); // just to avoid missprinting
465 val=header->GetEntryByNumber(tmpGr,tmpEl);
469 if(val==GDCM_UNFOUND)
471 if((tmpGr==0x0004) &&(tmpEl==0x1130) )
473 // TODO force the *end* File Name(remove path)
476 else if( (tmpGr==0x0004) && (tmpEl==0x1500) ) // Only used for image
478 if(header->GetFileName().substr(0,path.length())!=path)
480 dbg.Verbose(0, "gdcmDicomDir::SetElement : the base path of file name is incorrect");
481 val=header->GetFileName();
484 val=&(header->GetFileName()[path.length()]);
491 entry->SetValue(val);
495 if( (dictEntry->GetVR()=="UL") || (dictEntry->GetVR()=="SL") )
499 else if( (dictEntry->GetVR()=="US") || (dictEntry->GetVR()=="SS") )
503 else if(dictEntry->GetVR()=="SQ")
505 entry->SetLength(0xffffffff);
509 entry->SetLength(entry->GetValue().length());
513 listEntries.push_back(entry);
517 bool gdcmDicomDir::HeaderLessThan(gdcmHeader *header1,gdcmHeader *header2)
519 return(*header1<*header2);
522 //-----------------------------------------------------------------------------