Main Page | File List | Related Pages

gdcmDicomDir.cxx

00001 // gdcmDicomDir.cxx
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 // Constructor / Destructor
00018 /*
00019  * \ingroup gdcmDicomDir
00020  * \brief   Constructor
00021  * @param   Filename
00022  * @param   exception_on_error
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  * \ingroup gdcmDicomDir
00044  * \brief   
00045  * @param   exception_on_error
00046  */
00047 /*gdcmDicomDir::gdcmDicomDir(ListTag *l,
00048                            bool exception_on_error):                           
00049    gdcmParser(exception_on_error )  
00050 {    
00051    listEntries=*l;
00052    CreateDicomDir();
00053 }*/
00054 
00055 /*
00056  * \ingroup gdcmDicomDir
00057  * \brief  Canonical destructor 
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 // Print
00069 /*
00070  * \ingroup gdcmDicomDir
00071  * \brief  Canonical Printer 
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 // Public
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  * \ingroup gdcmDicomDir
00118  * \brief  fills whole the structure
00119  */
00120 void gdcmDicomDir::ParseDirectory(void)
00121 {
00122    NewDicomDir(GetPath());
00123    CreateDicomDir();
00124 }
00125 
00126 //-----------------------------------------------------------------------------
00127 // Protected
00128 /*
00129  * \ingroup gdcmDicomDir
00130  * \brief   
00131  * @param path entry point of the stree-like structure
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  * \ingroup gdcmDicomDir
00160  * \brief   Get the dicom dir path
00161  * @param   
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 // Private
00179 /*
00180  * \ingroup gdcmDicomDir
00181  * \brief   
00182  * @param   
00183  */
00184 void gdcmDicomDir::CreateDicomDir()
00185 {
00186    // The list is parsed. When a tag is found :
00187    //  1 - we save the beginning iterator
00188    //  2 - we continue to parse
00189    //  3 - we find an other tag
00190    //       + we create the object for the precedent tag
00191    //       + loop to 1 -
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  * \ingroup gdcmDicomDir
00244  * \brief   
00245  * @param   type
00246  * @param   begin
00247  * @param   end
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  * \ingroup gdcmDicomDir
00273  * \brief   
00274  * @param   begin
00275  * @param   end
00276 */
00277 void gdcmDicomDir::AddPatientToEnd(ListTag::iterator begin,ListTag::iterator end)
00278 {
00279    patients.push_back(new gdcmPatient(begin,end));
00280 }
00281 
00282 /*
00283  * \ingroup gdcmDicomDir
00284  * \brief   
00285  * @param   begin
00286  * @param   end
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  * \ingroup gdcmDicomDir
00299  * \brief   
00300  * @param   begin
00301  * @param   end
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  * \ingroup gdcmDicomDir
00321  * @param   begin
00322  * @param   end
00323  * @param   
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  * \ingroup gdcmDicomDir
00349  * \brief   
00350  * @param   path
00351  * @param   list
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       // get the current file characteristics
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       // if new Study Deal with 'STUDY' Elements   
00380       if(studCurInstanceUID!=studPrevInstanceUID || studCurID!=studPrevID) 
00381          SetElement(path,GDCM_STUDY,*it);
00382 
00383       // if new Serie Deal with 'SERIE' Elements   
00384       if(serCurInstanceUID!=serPrevInstanceUID || serCurID!=serPrevID) 
00385       {
00386          SetElement(path,GDCM_SERIE,*it);
00387       } 
00388       
00389       // Always Deal with 'IMAGE' Elements  
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  * \ingroup gdcmDicomDir
00403  * \brief   
00404  * @param   path
00405  * @param   type
00406  * @param   header
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); // just to avoid missprinting
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             // TODO force the *end* File Name(remove path)
00457             val=path;
00458          }
00459          else if( (tmpGr==0x0004) && (tmpEl==0x1500) ) // Only used for image
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 //-----------------------------------------------------------------------------

Generated on Mon Feb 14 16:13:43 2005 for gdcm by doxygen 1.3.6