2 //-----------------------------------------------------------------------------
3 #include "gdcmDicomDir.h"
7 #include "gdcmDirList.h"
13 #include <sys/types.h>
16 //-----------------------------------------------------------------------------
17 // Constructor / Destructor
19 * \ingroup gdcmDicomDir
22 * @param exception_on_error
24 gdcmDicomDir::gdcmDicomDir(const char *FileName, bool parseDir,
25 bool exception_on_error):
26 gdcmParser(FileName,exception_on_error,true)
28 if( GetListEntry().begin()==GetListEntry().end() )
30 dbg.Verbose(0, "gdcmDicomDir::gdcmDicomDir : entry list empty");
34 dbg.Verbose(0, "gdcmDicomDir::gdcmDicomDir : Parse directory and create the DicomDir");
43 * \ingroup gdcmDicomDir
45 * @param exception_on_error
47 /*gdcmDicomDir::gdcmDicomDir(ListTag *l,
48 bool exception_on_error):
49 gdcmParser(exception_on_error )
56 * \ingroup gdcmDicomDir
57 * \brief Canonical destructor
59 gdcmDicomDir::~gdcmDicomDir()
63 for(ListPatient::iterator cc=patients.begin();cc!=patients.end();++cc)
69 //-----------------------------------------------------------------------------
72 * \ingroup gdcmDicomDir
73 * \brief Canonical Printer
75 void gdcmDicomDir::Print(std::ostream &os)
77 (*metaelems).SetPrintLevel(printLevel);
78 (*metaelems).Print(os);
80 for(ListPatient::iterator cc=patients.begin();cc!=patients.end();++cc)
82 (*cc)->SetPrintLevel(printLevel);
87 //-----------------------------------------------------------------------------
90 * \ingroup gdcmDicomDir
91 * \brief writes on disc a DICOMDIR
92 * \ warning does NOT add the missing elements in the header :
93 * it's up to the user doing it !
94 * @param fileName file to be written to
95 * @return false only when fail to open
97 bool gdcmDicomDir::Write(std::string fileName)
101 fp1=fopen(fileName.c_str(),"wb");
104 printf("Failed to open(write) File [%s] \n",fileName.c_str());
109 filePreamble=(char*)calloc(128,1);
110 fwrite(filePreamble,128,1,fp1);
111 fwrite("DICM",4,1,fp1);
114 WriteEntries(fp1,DICOMDIR);
122 * \ingroup gdcmDicomDir
123 * \brief fills whole the structure
125 void gdcmDicomDir::ParseDirectory(void)
127 NewDicomDir(GetPath());
131 //-----------------------------------------------------------------------------
134 * \ingroup gdcmDicomDir
135 * \brief create a gdcmDicomDir from a root Directory
136 * @param path entry point of the stree-like structure
138 void gdcmDicomDir::NewDicomDir(std::string path)
140 gdcmDirList fileList(path,1);
147 for(gdcmDirList::iterator it=fileList.begin();
148 it!=fileList.end(); ++it)
150 header=new gdcmHeader(it->c_str());
151 if(header->IsReadable())
152 list.push_back(header);
157 std::sort(list.begin(),list.end(),gdcmDicomDir::HeaderLessThan);
159 std::string tmp=fileList.GetDirName();
160 SetElements(tmp,list);
164 * \ingroup gdcmDicomDir
165 * \brief Get the DicomDir path
168 std::string gdcmDicomDir::GetPath(void)
170 std::string path=GetFileName();
172 int pos1=path.rfind("/");
173 int pos2=path.rfind("\\");
182 //-----------------------------------------------------------------------------
185 * \ingroup gdcmDicomDir
186 * \brief create a 'gdcmDicomDir' from a DICOMDIR gdcmHeader
188 void gdcmDicomDir::CreateDicomDir()
190 // The list is parsed. When a tag is found :
191 // 1 - we save the beginning iterator
192 // 2 - we continue to parse
193 // 3 - we find an other tag
194 // + we create the object for the precedent tag
197 gdcmDicomDirType type=gdcmDicomDir::GDCM_NONE;
198 ListTag::iterator begin;
199 ListTag::iterator end;
202 begin=listEntries.begin();
205 for(ListTag::iterator j=listEntries.begin();j !=listEntries.end();++j)
207 if((*j)->GetValue()=="PATIENT ") {
211 AddObjectToEnd(gdcmDicomDir::GDCM_META,begin,j);
214 // for(ListTag::iterator i=listEntries.begin();i !=listEntries.end();++i)
215 for(ListTag::iterator i=k;i !=listEntries.end();++i)
217 std::string v=(*i)->GetValue();
221 AddObjectToEnd(type,begin,end);
223 type=gdcmDicomDir::GDCM_PATIENT;
230 AddObjectToEnd(type,begin,end);
232 type=gdcmDicomDir::GDCM_STUDY;
239 AddObjectToEnd(type,begin,end);
241 type=gdcmDicomDir::GDCM_SERIE;
248 AddObjectToEnd(type,begin,end);
250 type=gdcmDicomDir::GDCM_IMAGE;
255 end=GetListEntry().end();
256 AddObjectToEnd(type,begin,end);
259 * \ingroup gdcmDicomDir
265 void gdcmDicomDir::AddObjectToEnd(gdcmDicomDirType type,ListTag::iterator begin,ListTag::iterator end)
272 case gdcmDicomDir::GDCM_META:
273 AddMetaToEnd(begin,end);
275 case gdcmDicomDir::GDCM_PATIENT:
276 AddPatientToEnd(begin,end);
278 case gdcmDicomDir::GDCM_STUDY:
279 AddStudyToEnd(begin,end);
281 case gdcmDicomDir::GDCM_SERIE:
282 AddSerieToEnd(begin,end);
284 case gdcmDicomDir::GDCM_IMAGE:
285 AddImageToEnd(begin,end);
292 * \ingroup gdcmDicomDir
293 * \brief Well ... Not realy to end, there is only one occurence
297 void gdcmDicomDir::AddMetaToEnd(ListTag::iterator begin,ListTag::iterator end)
299 metaelems = new gdcmMeta(begin,end);
303 * \ingroup gdcmDicomDir
308 void gdcmDicomDir::AddPatientToEnd(ListTag::iterator begin,ListTag::iterator end)
310 patients.push_back(new gdcmPatient(begin,end));
314 * \ingroup gdcmDicomDir
319 void gdcmDicomDir::AddStudyToEnd(ListTag::iterator begin,ListTag::iterator end)
321 if(patients.size()>0)
323 ListPatient::iterator itp=patients.end();
325 (*itp)->AddStudy(new gdcmStudy(begin,end));
329 * \ingroup gdcmDicomDir
334 void gdcmDicomDir::AddSerieToEnd(ListTag::iterator begin,ListTag::iterator end)
336 if(patients.size()>0)
338 ListPatient::iterator itp=patients.end();
341 if((*itp)->GetStudies().size()>0)
343 ListStudy::iterator itst=(*itp)->GetStudies().end();
345 (*itst)->AddSerie(new gdcmSerie(begin,end));
351 * \ingroup gdcmDicomDir
356 void gdcmDicomDir::AddImageToEnd(ListTag::iterator begin,ListTag::iterator end)
358 if(patients.size()>0)
360 ListPatient::iterator itp=patients.end();
363 if((*itp)->GetStudies().size()>0)
365 ListStudy::iterator itst=(*itp)->GetStudies().end();
368 if((*itst)->GetSeries().size()>0)
370 ListSerie::iterator its=(*itst)->GetSeries().end();
372 (*its)->AddImage(new gdcmImage(begin,end));
379 * \ingroup gdcmDicomDir
384 void gdcmDicomDir::SetElements(std::string &path,ListHeader &list)
386 std::string patPrevName="", patPrevID="";
387 std::string studPrevInstanceUID="", studPrevID="";
388 std::string serPrevInstanceUID="", serPrevID="";
390 std::string patCurName, patCurID;
391 std::string studCurInstanceUID, studCurID;
392 std::string serCurInstanceUID, serCurID;
394 SetElement(path,GDCM_NONE,NULL);
396 ListTag::iterator debPat=listEntries.begin();
397 for(ListHeader::iterator it=list.begin();it!=list.end();++it)
399 // get the current file characteristics
400 patCurName=(*it)->GetEntryByNumber(0x0010,0x0010);
401 patCurID=(*it)->GetEntryByNumber(0x0010,0x0011);
402 studCurInstanceUID=(*it)->GetEntryByNumber(0x0020,0x000d);
403 studCurID=(*it)->GetEntryByNumber(0x0020,0x0010);
404 serCurInstanceUID=(*it)->GetEntryByNumber(0x0020,0x000e);
405 serCurID=(*it)->GetEntryByNumber(0x0020,0x0011);
407 if(patCurName!=patPrevName || patCurID!=patPrevID)
408 SetElement(path,GDCM_PATIENT,*it);
410 // if new Study Deal with 'STUDY' Elements
411 if(studCurInstanceUID!=studPrevInstanceUID || studCurID!=studPrevID)
412 SetElement(path,GDCM_STUDY,*it);
414 // if new Serie Deal with 'SERIE' Elements
415 if(serCurInstanceUID!=serPrevInstanceUID || serCurID!=serPrevID)
416 SetElement(path,GDCM_SERIE,*it);
418 // Always Deal with 'IMAGE' Elements
419 SetElement(path,GDCM_IMAGE,*it);
421 patPrevName=patCurName;
423 studPrevInstanceUID=studCurInstanceUID;
424 studPrevID=studCurID;
425 serPrevInstanceUID=serCurInstanceUID;
431 * \ingroup gdcmDicomDir
437 void gdcmDicomDir::SetElement(std::string &path,gdcmDicomDirType type,gdcmHeader *header)
439 std::list<gdcmElement> elemList;
440 std::list<gdcmElement>::iterator it;
441 guint16 tmpGr, tmpEl;
442 gdcmDictEntry *dictEntry;
443 gdcmHeaderEntry *entry;
449 elemList=gdcmGlobal::GetDicomDirElements()->GetPatientElements();
452 elemList=gdcmGlobal::GetDicomDirElements()->GetStudyElements();
455 elemList=gdcmGlobal::GetDicomDirElements()->GetSerieElements();
458 elemList=gdcmGlobal::GetDicomDirElements()->GetImageElements();
461 elemList=gdcmGlobal::GetDicomDirElements()->GetMetaElements();
467 for(it=elemList.begin();it!=elemList.end();++it)
472 dictEntry=GetPubDict()->GetDictEntryByNumber(tmpGr,tmpEl);
473 entry=new gdcmHeaderEntry(dictEntry);
474 entry->SetOffset(0); // just to avoid missprinting
477 val=header->GetEntryByNumber(tmpGr,tmpEl);
481 if(val==GDCM_UNFOUND)
483 if((tmpGr==0x0004) &&(tmpEl==0x1130) )
485 // TODO force the *end* File Name(remove path)
488 else if( (tmpGr==0x0004) && (tmpEl==0x1500) ) // Only used for image
490 if(header->GetFileName().substr(0,path.length())!=path)
492 dbg.Verbose(0, "gdcmDicomDir::SetElement : the base path of file name is incorrect");
493 val=header->GetFileName();
496 val=&(header->GetFileName()[path.length()]);
503 entry->SetValue(val);
507 if( (dictEntry->GetVR()=="UL") || (dictEntry->GetVR()=="SL") )
511 else if( (dictEntry->GetVR()=="US") || (dictEntry->GetVR()=="SS") )
515 else if(dictEntry->GetVR()=="SQ")
517 entry->SetLength(0xffffffff);
521 entry->SetLength(entry->GetValue().length());
525 listEntries.push_back(entry);
529 bool gdcmDicomDir::HeaderLessThan(gdcmHeader *header1,gdcmHeader *header2)
531 return(*header1<*header2);
534 //-----------------------------------------------------------------------------