00001 
00002 
00003 #include "gdcmDicomDir.h"
00004 #include "gdcmStudy.h"
00005 #include "gdcmSerie.h"
00006 #include "gdcmImage.h"
00007 #include "gdcmDirList.h"
00008 #include "gdcmUtil.h"
00009 
00010 #include <string>
00011 #include <algorithm>
00012 
00013 #include <sys/types.h>
00014 #include <errno.h>
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 gdcmDicomDir::gdcmDicomDir(const char *FileName, bool parseDir,
00025                            bool exception_on_error):
00026    gdcmParser(FileName,exception_on_error,true)
00027 {
00028    if( GetListEntry().begin()==GetListEntry().end() ) 
00029    {
00030       dbg.Verbose(0, "gdcmDicomDir::gdcmDicomDir : entry list empty");
00031 
00032       if(parseDir)
00033       {
00034          dbg.Verbose(0, "gdcmDicomDir::gdcmDicomDir : Parse directory and create the DicomDir");
00035          ParseDirectory();
00036       }
00037    }
00038    else
00039       CreateDicomDir();
00040 }
00041 
00042 
00043 
00044 
00045 
00046 
00047 
00048 
00049 
00050 
00051 
00052 
00053 
00054 
00055 
00056 
00057 
00058 
00059 gdcmDicomDir::~gdcmDicomDir() 
00060 {
00061    for(ListPatient::iterator cc=patients.begin();cc!=patients.end();++cc)
00062    {
00063       delete *cc;
00064    }
00065 }
00066 
00067 
00068 
00069 
00070 
00071 
00072 
00073 void gdcmDicomDir::Print(std::ostream &os)
00074 {
00075    for(ListPatient::iterator cc=patients.begin();cc!=patients.end();++cc)
00076    {
00077      (*cc)->SetPrintLevel(printLevel);
00078      (*cc)->Print(os);
00079    }
00080 }
00081 
00082 
00083 
00092 bool gdcmDicomDir::Write(std::string fileName) 
00093 {
00094    FILE * fp1;
00095 
00096    fp1=fopen(fileName.c_str(),"wb");
00097    if(fp1==NULL) 
00098    {
00099       printf("Failed to open(write) File [%s] \n",fileName.c_str());
00100       return(false);
00101    }
00102 
00103    char * filePreamble;
00104    filePreamble=(char*)calloc(128,1);
00105    fwrite(filePreamble,128,1,fp1);
00106    fwrite("DICM",4,1,fp1);
00107    free(filePreamble);
00108 
00109    WriteEntries(fp1,DICOMDIR);
00110 
00111    fclose(fp1);
00112 
00113    return true;
00114 }
00115 
00116 
00117 
00118 
00119 
00120 void gdcmDicomDir::ParseDirectory(void)
00121 {
00122    NewDicomDir(GetPath());
00123    CreateDicomDir();
00124 }
00125 
00126 
00127 
00128 
00129 
00130 
00131 
00132 
00133 void gdcmDicomDir::NewDicomDir(std::string path)
00134 {
00135    gdcmDirList fileList(path,1);
00136    ListHeader list;
00137    gdcmHeader *header;
00138 
00139    listEntries.clear();
00140    patients.clear();
00141 
00142    for(gdcmDirList::iterator it=fileList.begin(); 
00143        it!=fileList.end(); ++it) 
00144    {
00145       header=new gdcmHeader(it->c_str());
00146       if(header->IsReadable())
00147          list.push_back(header);
00148       else
00149          delete header;
00150    }
00151 
00152    std::sort(list.begin(),list.end(),gdcmDicomDir::HeaderLessThan);
00153 
00154    std::string tmp=fileList.GetDirName();
00155    SetElements(tmp,list);
00156 }
00157 
00158 
00159 
00160 
00161 
00162 
00163 std::string gdcmDicomDir::GetPath(void)
00164 {
00165    std::string path=GetFileName();
00166 
00167    int pos1=path.rfind("/");
00168    int pos2=path.rfind("\\");
00169    if(pos1>pos2)
00170       path.resize(pos1);
00171    else
00172       path.resize(pos2);
00173 
00174    return(path);
00175 }
00176 
00177 
00178 
00179 
00180 
00181 
00182 
00183 
00184 void gdcmDicomDir::CreateDicomDir()
00185 {
00186    
00187    
00188    
00189    
00190    
00191    
00192 
00193    gdcmDicomDirType type=gdcmDicomDir::GDCM_NONE;
00194    ListTag::iterator begin;
00195    ListTag::iterator end;
00196 
00197    begin=listEntries.begin();
00198    end=begin;
00199    for(ListTag::iterator i=listEntries.begin();i !=listEntries.end();++i) 
00200    {
00201       std::string v=(*i)->GetValue();
00202       if(v=="PATIENT ") 
00203       {
00204          end=i;
00205          AddObjectToEnd(type,begin,end);
00206 
00207          type=gdcmDicomDir::GDCM_PATIENT;
00208          begin=end;
00209       } 
00210 
00211       if(v=="STUDY ")
00212       {
00213          end=i;
00214          AddObjectToEnd(type,begin,end);
00215 
00216          type=gdcmDicomDir::GDCM_STUDY;
00217          begin=end;
00218       }
00219 
00220       if(v=="SERIES") 
00221       {
00222          end=i;
00223          AddObjectToEnd(type,begin,end);
00224 
00225          type=gdcmDicomDir::GDCM_SERIE;
00226          begin=end;
00227       }
00228 
00229       if(v=="IMAGE ") 
00230       {
00231          end=i;
00232          AddObjectToEnd(type,begin,end);
00233 
00234          type=gdcmDicomDir::GDCM_IMAGE;
00235          begin=end;
00236       }
00237    }
00238 
00239    end=GetListEntry().end();
00240    AddObjectToEnd(type,begin,end);
00241 }
00242 
00243 
00244 
00245 
00246 
00247 
00248 
00249 void gdcmDicomDir::AddObjectToEnd(gdcmDicomDirType type,ListTag::iterator begin,ListTag::iterator end)
00250 {
00251    if(begin==end)
00252       return;
00253 
00254    switch(type)
00255    {
00256       case gdcmDicomDir::GDCM_PATIENT:
00257          AddPatientToEnd(begin,end);
00258          break;
00259       case gdcmDicomDir::GDCM_STUDY:
00260          AddStudyToEnd(begin,end);
00261          break;
00262       case gdcmDicomDir::GDCM_SERIE:
00263          AddSerieToEnd(begin,end);
00264          break;
00265       case gdcmDicomDir::GDCM_IMAGE:
00266          AddImageToEnd(begin,end);
00267          break;
00268    }
00269 }
00270 
00271 
00272 
00273 
00274 
00275 
00276 
00277 void gdcmDicomDir::AddPatientToEnd(ListTag::iterator begin,ListTag::iterator end)
00278 {
00279    patients.push_back(new gdcmPatient(begin,end));
00280 }
00281 
00282 
00283 
00284 
00285 
00286 
00287 
00288  void gdcmDicomDir::AddStudyToEnd(ListTag::iterator begin,ListTag::iterator end)
00289 {
00290    if(patients.size()>0)
00291    {
00292       ListPatient::iterator itp=patients.end();
00293       itp--;
00294      (*itp)->AddStudy(new gdcmStudy(begin,end));
00295    }
00296 }
00297 
00298 
00299 
00300 
00301 
00302 
00303 void gdcmDicomDir::AddSerieToEnd(ListTag::iterator begin,ListTag::iterator end)
00304 {
00305    if(patients.size()>0)
00306    {
00307       ListPatient::iterator itp=patients.end();
00308       itp--;
00309 
00310       if((*itp)->GetStudies().size()>0)
00311       {
00312          ListStudy::iterator itst=(*itp)->GetStudies().end();
00313          itst--;
00314         (*itst)->AddSerie(new gdcmSerie(begin,end));
00315       }
00316    }
00317 }
00318 
00319 
00320 
00321 
00322 
00323 
00324 
00325  void gdcmDicomDir::AddImageToEnd(ListTag::iterator begin,ListTag::iterator end)
00326 {
00327    if(patients.size()>0)
00328    {
00329       ListPatient::iterator itp=patients.end();
00330       itp--;
00331 
00332       if((*itp)->GetStudies().size()>0)
00333       {
00334          ListStudy::iterator itst=(*itp)->GetStudies().end();
00335          itst--;
00336 
00337          if((*itst)->GetSeries().size()>0)
00338          {
00339             ListSerie::iterator its=(*itst)->GetSeries().end();
00340             its--;
00341            (*its)->AddImage(new gdcmImage(begin,end));
00342          }
00343       }
00344    }
00345 }
00346 
00347 
00348 
00349 
00350 
00351 
00352 
00353 void gdcmDicomDir::SetElements(std::string &path,ListHeader &list)
00354 {
00355    std::string patPrevName="", patPrevID="";
00356    std::string studPrevInstanceUID="", studPrevID="";
00357    std::string serPrevInstanceUID="", serPrevID="";
00358 
00359    std::string patCurName, patCurID;
00360    std::string studCurInstanceUID, studCurID;
00361    std::string serCurInstanceUID, serCurID;
00362 
00363    SetElement(path,GDCM_NONE,NULL);
00364 
00365    ListTag::iterator debPat=listEntries.begin();
00366    for(ListHeader::iterator it=list.begin();it!=list.end();++it) 
00367    {
00368       
00369       patCurName=(*it)->GetEntryByNumber(0x0010,0x0010); 
00370       patCurID=(*it)->GetEntryByNumber(0x0010,0x0011); 
00371       studCurInstanceUID=(*it)->GetEntryByNumber(0x0020,0x000d);            
00372       studCurID=(*it)->GetEntryByNumber(0x0020,0x0010);            
00373       serCurInstanceUID=(*it)->GetEntryByNumber(0x0020,0x000e);            
00374       serCurID=(*it)->GetEntryByNumber(0x0020,0x0011);
00375 
00376       if(patCurName!=patPrevName || patCurID!=patPrevID) 
00377          SetElement(path,GDCM_PATIENT,*it);
00378 
00379       
00380       if(studCurInstanceUID!=studPrevInstanceUID || studCurID!=studPrevID) 
00381          SetElement(path,GDCM_STUDY,*it);
00382 
00383       
00384       if(serCurInstanceUID!=serPrevInstanceUID || serCurID!=serPrevID) 
00385       {
00386          SetElement(path,GDCM_SERIE,*it);
00387       } 
00388       
00389       
00390       SetElement(path,GDCM_IMAGE,*it);
00391 
00392       patPrevName=patCurName;
00393       patPrevID=patCurID;
00394       studPrevInstanceUID=studCurInstanceUID;
00395       studPrevID=studCurID;
00396       serPrevInstanceUID=serCurInstanceUID;
00397       serPrevID=serCurID;
00398    }
00399 }
00400 
00401 
00402 
00403 
00404 
00405 
00406 
00407 
00408 void gdcmDicomDir::SetElement(std::string &path,gdcmDicomDirType type,gdcmHeader *header)
00409 {
00410    std::list<gdcmElement> elemList;
00411    std::list<gdcmElement>::iterator it;
00412    guint16 tmpGr, tmpEl;
00413    gdcmDictEntry *dictEntry;
00414    gdcmHeaderEntry *entry;
00415    std::string val;
00416 
00417    switch(type)
00418    {
00419       case GDCM_PATIENT:
00420          elemList=gdcmGlobal::GetDicomDirElements()->GetPatientElements();
00421          break;
00422       case GDCM_STUDY:
00423          elemList=gdcmGlobal::GetDicomDirElements()->GetStudyElements();
00424          break;
00425       case GDCM_SERIE:
00426          elemList=gdcmGlobal::GetDicomDirElements()->GetSerieElements();
00427          break;
00428       case GDCM_IMAGE:
00429          elemList=gdcmGlobal::GetDicomDirElements()->GetImageElements();
00430          break;
00431       case GDCM_NONE:
00432          elemList=gdcmGlobal::GetDicomDirElements()->GetMetaElements();
00433          break;
00434       default:
00435          return;
00436    }
00437 
00438    for(it=elemList.begin();it!=elemList.end();++it)
00439    {
00440       tmpGr=it->group;
00441       tmpEl=it->elem;
00442 
00443       dictEntry=GetPubDict()->GetDictEntryByNumber(tmpGr,tmpEl);
00444       entry=new gdcmHeaderEntry(dictEntry);
00445       entry->SetOffset(0); 
00446 
00447       if(header)
00448          val=header->GetEntryByNumber(tmpGr,tmpEl);
00449       else
00450          val=GDCM_UNFOUND;
00451 
00452       if(val==GDCM_UNFOUND) 
00453       {
00454          if((tmpGr==0x0004) &&(tmpEl==0x1130) )
00455          {
00456             
00457             val=path;
00458          }
00459          else if( (tmpGr==0x0004) && (tmpEl==0x1500) ) 
00460          {
00461             if(header->GetFileName().substr(0,path.length())!=path)
00462             {
00463                dbg.Verbose(0, "gdcmDicomDir::SetElement : the base path of file name is incorrect");
00464                val=header->GetFileName();
00465             }
00466             else
00467                val=&(header->GetFileName()[path.length()]);
00468          }
00469          else
00470          {
00471             val=it->value;
00472          }
00473       }
00474       entry->SetValue(val);
00475 
00476       if(dictEntry)
00477       {
00478          if( (dictEntry->GetVR()=="UL") || (dictEntry->GetVR()=="SL") ) 
00479          {
00480             entry->SetLength(4);
00481          } 
00482          else if( (dictEntry->GetVR()=="US") || (dictEntry->GetVR()=="SS") ) 
00483          {
00484             entry->SetLength(2); 
00485          } 
00486          else if(dictEntry->GetVR()=="SQ") 
00487          {
00488             entry->SetLength(0xffffffff);
00489          }
00490          else
00491          {
00492             entry->SetLength(entry->GetValue().length());        
00493          }
00494       }
00495 
00496       listEntries.push_back(entry);
00497    }     
00498 }
00499 
00500 bool gdcmDicomDir::HeaderLessThan(gdcmHeader *header1,gdcmHeader *header2)
00501 {
00502    return(*header1<*header2);
00503 }
00504 
00505