Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

gdcmDicomDir.cxx

Go to the documentation of this file.
00001 /*=========================================================================
00002   
00003   Program:   gdcm
00004   Module:    $RCSfile: gdcmDicomDir.cxx,v $
00005   Language:  C++
00006   Date:      $Date: 2006/01/18 10:17:40 $
00007   Version:   $Revision: 1.184 $
00008   
00009   Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
00010   l'Image). All rights reserved. See Doc/License.txt or
00011   http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
00012   
00013      This software is distributed WITHOUT ANY WARRANTY; without even
00014      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
00015      PURPOSE.  See the above copyright notices for more information.
00016   
00017 =========================================================================*/
00018 
00019 //-----------------------------------------------------------------------------
00020 //  For full DICOMDIR description, see:
00021 //  PS 3.3-2003, pages 731-750
00022 //-----------------------------------------------------------------------------
00023 #include "gdcmDicomDir.h"
00024 #include "gdcmDicomDirObject.h"
00025 #include "gdcmDicomDirStudy.h"
00026 #include "gdcmDicomDirSerie.h"
00027 #include "gdcmDicomDirVisit.h"
00028 #include "gdcmDicomDirImage.h"
00029 #include "gdcmDicomDirPatient.h"
00030 #include "gdcmDicomDirMeta.h"
00031 #include "gdcmDicomDirElement.h"
00032 #include "gdcmDirList.h"
00033 #include "gdcmUtil.h"
00034 #include "gdcmDebug.h"
00035 #include "gdcmGlobal.h"
00036 #include "gdcmFile.h"
00037 #include "gdcmSeqEntry.h"
00038 #include "gdcmSQItem.h"
00039 #include "gdcmDataEntry.h"
00040 #include "gdcmCommandManager.h"
00041 
00042 #include <fstream>
00043 #include <string>
00044 #include <algorithm>
00045 #include <sys/types.h>
00046 
00047 #ifdef _MSC_VER
00048 #   define getcwd _getcwd
00049 #endif
00050 
00051 #if defined(_MSC_VER) || defined(__BORLANDC__)
00052 #   include <direct.h>
00053 #else
00054 #   include <unistd.h>
00055 #endif
00056 // ----------------------------------------------------------------------------
00057 //         Note for future developpers
00058 // ----------------------------------------------------------------------------
00059 //
00060 //  Dicom PS 3.3 describes the relationship between Directory Records, as follow
00061 //    (see also PS 4.3, 2004, page 50 for Entity-Relationship model)
00062 //
00063 //  Directory Record Type      Directory Record Types which may be included
00064 //                                in the next lower-level directory Entity
00065 //
00066 // (Root directory Entity)     PATIENT, TOPIC, PRIVATE
00067 //
00068 // PATIENT                     STUDY, PRIVATE
00069 //
00070 // STUDY                       SERIES, VISIT, RESULTS, STUDY COMPONENT, PRIVATE
00071 //
00072 // SERIES                      IMAGE, OVERLAYS, MODALITY LUT, VOI LUT,
00073 //                             CURVE, STORED PRINT, RT DOSE, RT STRUCTURE SET
00074 //                             RT PLAN, RT TREAT RECORD, PRESENTATION, WAVEFORM,
00075 //                             SR DOCUMENT, KEY OBJECT DOC, SPECTROSCOPY,
00076 //                             RAW DATA, REGISTRATION, FIDUCIAL, PRIVATE,
00077 //                             ENCAP DOC
00078 // IMAGE
00079 // OVERLAY
00080 // MODALITY LUT
00081 // VOI LUT
00082 // CURVE
00083 // STORED PRINT
00084 // RT DOSE
00085 // RT STRUCTURE SET
00086 // RT PLAN
00087 // RT TREAT RECORD
00088 // PRESENTATION
00089 // WAVEFORM
00090 // SR DOCUMENT
00091 // KEY OBJECT DOC
00092 // SPECTROSCOPY
00093 // RAW DATA
00094 // REGISTRATION
00095 // FIDUCIAL
00096 // PRIVATE
00097 // ENCAP DOC
00098 // 
00099 // ----------------------
00100 // The current gdcm version only deals with :
00101 //
00102 // (Root directory Entity)     PATIENT
00103 // PATIENT                     STUDY
00104 // STUDY                       SERIES
00105 // STUDY                       VISIT 
00106 // SERIES                      IMAGE
00107 // IMAGE                       /
00108 //
00109 // DicomDir::CreateDicomDir will have to be completed
00110 // Treelike structure management will have to be upgraded
00111 // ----------------------------------------------------------------------------
00112     
00113 namespace gdcm 
00114 {
00115 //-----------------------------------------------------------------------------
00116 // Constructor / Destructor
00120 DicomDir::DicomDir()
00121 {
00122    Initialize();  // sets all private fields to NULL
00123    ParseDir = false;
00124    NewMeta();
00125 }
00126 
00130 DicomDir::~DicomDir() 
00131 {
00132    ClearPatient();
00133    if ( MetaElems )
00134    {
00135       MetaElems->Delete();
00136    }
00137 }
00138 
00139 //-----------------------------------------------------------------------------
00140 // Public
00141 
00148 bool DicomDir::Load( ) 
00149 {
00150    if (!ParseDir)
00151    {
00152       if ( ! this->Document::Load( ) )
00153          return false;
00154    }
00155    return DoTheLoadingJob( );   
00156 }
00157 
00163 bool DicomDir::DoTheLoadingJob( ) 
00164 {
00165    Progress = 0.0f;
00166    Abort = false;
00167 
00168    if (!ParseDir)
00169    {
00170    // Only if user passed a DICOMDIR
00171    // ------------------------------
00172       Fp = 0;
00173       if (!Document::Load() )
00174       {
00175          return false;
00176       }
00177 
00178       if ( GetFirstEntry() == 0 ) // when user passed a Directory to parse
00179       {
00180          gdcmWarningMacro( "Entry HT empty for file: "<< GetFileName());
00181          return false;
00182       }
00183       // Directory record sequence
00184       DocEntry *e = GetDocEntry(0x0004, 0x1220);
00185       if ( !e )
00186       {
00187          gdcmWarningMacro( "NO 'Directory record sequence' (0x0004,0x1220)"
00188                           << " in file " << GetFileName());
00189          return false;
00190       }
00191       else
00192          CreateDicomDir();
00193    }
00194    else
00195    {
00196    // Only if user passed a root directory
00197    // ------------------------------------
00198       if ( GetFileName() == "." )
00199       {
00200          // user passed '.' as Name
00201          // we get current directory name
00202          char buf[2048];
00203          const char *cwd = getcwd(buf, 2048);
00204          if( cwd )
00205          {
00206            SetFileName( buf ); // will be converted into a string
00207          }
00208          else
00209          {
00210            gdcmErrorMacro( "Path was too long to fit on 2048 bytes" );
00211          }
00212       }
00213       NewMeta();
00214       gdcmDebugMacro( "Parse directory and create the DicomDir : " 
00215                          << GetFileName() );
00216       ParseDirectory();
00217    }
00218    return true;
00219 }
00220 
00229 bool DicomDir::IsReadable()
00230 {
00231    if ( Filetype == Unknown )
00232    {
00233       gdcmErrorMacro( "Wrong filetype for " << GetFileName());
00234       return false;
00235    }
00236    if ( !MetaElems )
00237    {
00238       gdcmWarningMacro( "Meta Elements missing in DicomDir");
00239       return false;
00240    }
00241    if ( Patients.size() <= 0 )
00242    {
00243       gdcmWarningMacro( "NO Patient in DicomDir");
00244       return false;
00245    }
00246 
00247    return true;
00248 }
00249 
00253 DicomDirMeta *DicomDir::NewMeta()
00254 {
00255    if ( MetaElems )
00256       MetaElems->Delete();
00257 
00258    DocEntry *entry = GetFirstEntry();
00259    if ( entry )
00260    { 
00261       MetaElems = DicomDirMeta::New(true); // true = empty
00262 
00263       entry = GetFirstEntry();
00264       while( entry )
00265       {
00266          if ( dynamic_cast<SeqEntry *>(entry) )
00267             break;
00268 
00269          MetaElems->AddEntry(entry);
00270          RemoveEntry(entry);
00271 
00272          entry = GetFirstEntry();
00273       }
00274    }
00275    else  // after root directory parsing
00276    {
00277       MetaElems = DicomDirMeta::New(false); // false = not empty
00278    }
00279    MetaElems->SetSQItemNumber(0); // To avoid further missprinting
00280    return MetaElems;  
00281 }
00282 
00287 DicomDirPatient *DicomDir::NewPatient()
00288 {
00289    DicomDirPatient *dd = DicomDirPatient::New();
00290    AddPatientToEnd( dd );
00291    return dd;
00292 }
00293 
00297 void DicomDir::ClearPatient()
00298 {
00299    for(ListDicomDirPatient::iterator cc = Patients.begin();
00300                                      cc!= Patients.end();
00301                                    ++cc)
00302    {
00303       (*cc)->Unregister();
00304    }
00305    Patients.clear();
00306 }
00307 
00312 DicomDirPatient *DicomDir::GetFirstPatient()
00313 {
00314    ItPatient = Patients.begin();
00315    if ( ItPatient != Patients.end() )
00316       return *ItPatient;
00317    return NULL;
00318 }
00319 
00325 DicomDirPatient *DicomDir::GetNextPatient()
00326 {
00327    gdcmAssertMacro (ItPatient != Patients.end());
00328 
00329    ++ItPatient;
00330    if ( ItPatient != Patients.end() )
00331       return *ItPatient;
00332    return NULL;
00333 }
00334 
00338 void DicomDir::ParseDirectory()
00339 {
00340    CreateDicomDirChainedList( GetFileName() );
00341    CreateDicomDir();
00342 }
00343 
00352 bool DicomDir::Write(std::string const &fileName) 
00353 {  
00354    int i;
00355    uint16_t sq[6] = { 0x0004, 0x1220, 0x5153, 0x0000, 0xffff, 0xffff };
00356    uint16_t sqt[4]= { 0xfffe, 0xe0dd, 0x0000, 0x0000 };
00357 
00358    std::ofstream *fp = new std::ofstream(fileName.c_str(),  
00359                                          std::ios::out | std::ios::binary);
00360    if ( !fp ) 
00361    {
00362       gdcmWarningMacro("Failed to open(write) File: " << fileName.c_str());
00363       return false;
00364    }
00365 
00366    char filePreamble[128];
00367    memset(filePreamble, 0, 128);
00368    fp->write(filePreamble, 128);
00369    binary_write( *fp, "DICM");
00370  
00371    DicomDirMeta *ptrMeta = GetMeta();
00372    ptrMeta->WriteContent(fp, ExplicitVR);
00373    
00374    // force writing 0004|1220 [SQ ], that CANNOT exist within DicomDirMeta
00375    for(i=0;i<6;++i)
00376    {
00377       binary_write(*fp, sq[i]);
00378    }
00379         
00380    for(ListDicomDirPatient::iterator cc  = Patients.begin();
00381                                      cc != Patients.end();
00382                                    ++cc )
00383    {
00384       (*cc)->WriteContent( fp, ExplicitVR );
00385    }
00386    
00387    // force writing Sequence Delimitation Item
00388    for(i=0;i<4;++i)
00389    {
00390       binary_write(*fp, sqt[i]);  // fffe e0dd 0000 0000 
00391    }
00392 
00393    fp->close();
00394    delete fp;
00395 
00396    return true;
00397 }
00398 
00404 bool DicomDir::Anonymize() 
00405 {
00406    DataEntry *v;
00407    // Something clever to be found to forge the Patient names
00408    std::ostringstream s;
00409    int i = 1;
00410    for(ListDicomDirPatient::iterator cc = Patients.begin();
00411                                      cc!= Patients.end();
00412                                    ++cc)
00413    {
00414       s << i;
00415       v = (*cc)->GetDataEntry(0x0010, 0x0010) ; // Patient's Name
00416       if (v)
00417       {
00418          v->SetString(s.str());
00419       }
00420 
00421       v = (*cc)->GetDataEntry(0x0010, 0x0020) ; // Patient ID
00422       if (v)
00423       {
00424          v->SetString(" ");
00425       }
00426 
00427       v = (*cc)->GetDataEntry(0x0010, 0x0030) ; // Patient's BirthDate
00428       if (v)
00429       {
00430          v->SetString(" ");
00431       }
00432       s << "";
00433       i++;
00434    }
00435    return true;
00436 }
00437 
00443 void DicomDir::Copy(DocEntrySet *set)
00444 {
00445    // Remove all previous childs
00446    ClearPatient();
00447 
00448    Document::Copy(set);
00449 
00450    DicomDir *dd = dynamic_cast<DicomDir *>(set);
00451    if( dd )
00452    {
00453       if(MetaElems)
00454          MetaElems->Unregister();
00455       MetaElems = dd->MetaElems;
00456       if(MetaElems)
00457          MetaElems->Register();
00458 
00459       Patients = dd->Patients;
00460       for(ItPatient = Patients.begin();ItPatient != Patients.end();++ItPatient)
00461          (*ItPatient)->Register();
00462    }
00463 }
00464 
00465 //-----------------------------------------------------------------------------
00466 // Protected
00471 void DicomDir::CreateDicomDirChainedList(std::string const &path)
00472 {
00473    CallStartMethod();
00474    DirList dirList(path,1); // gets recursively the file list
00475    unsigned int count = 0;
00476    VectDocument list;
00477    File *f;
00478 
00479    DirListType fileList = dirList.GetFilenames();
00480    unsigned int nbFile = fileList.size();
00481    for( DirListType::iterator it  = fileList.begin();
00482                               it != fileList.end();
00483                               ++it )
00484    {
00485       Progress = (float)(count+1)/(float)nbFile;
00486       CallProgressMethod();
00487       if ( Abort )
00488       {
00489          break;
00490       }
00491 
00492       f = File::New( );
00493       f->SetLoadMode(LoadMode); // we allow user not to load Sequences, 
00494                                 //        or Shadow groups, or ......
00495       f->SetFileName( it->c_str() );
00496       f->Load( );
00497 
00498       if ( f->IsReadable() )
00499       {
00500          // Add the file to the chained list:
00501          list.push_back(f);
00502          gdcmDebugMacro( "Readable " << it->c_str() );
00503        }
00504        else
00505        {
00506           f->Delete();
00507        }
00508        count++;
00509    }
00510    // sorts Patient/Study/Serie/
00511    std::sort(list.begin(), list.end(), DicomDir::HeaderLessThan );
00512    
00513    std::string tmp = dirList.GetDirName();      
00514    //for each File of the chained list, add/update the Patient/Study/Serie/Image info
00515    SetElements(tmp, list);
00516    CallEndMethod();
00517 
00518    for(VectDocument::iterator itDoc=list.begin();
00519        itDoc!=list.end();
00520        ++itDoc)
00521    {
00522       dynamic_cast<File *>(*itDoc)->Delete();
00523    }
00524 }
00525 
00526 
00527 //-----------------------------------------------------------------------------
00528 // Private
00532 void DicomDir::Initialize()
00533 {
00534    Progress = 0.0;
00535    Abort = false;
00536 
00537    MetaElems = NULL;   
00538 }
00539 
00543 void DicomDir::CreateDicomDir()
00544 {
00545    // The SeqEntries of "Directory Record Sequence" are parsed. 
00546    //  When a DicomDir tag ("PATIENT", "STUDY", "SERIE", "IMAGE") is found :
00547    //  1 - we save the beginning iterator
00548    //  2 - we continue to parse
00549    //  3 - we find an other tag
00550    //       + we create the object for the precedent tag
00551    //       + loop to 1 -
00552    gdcmDebugMacro("Create DicomDir");
00553 
00554    // Directory record sequence
00555    DocEntry *e = GetDocEntry(0x0004, 0x1220);
00556    if ( !e )
00557    {
00558       gdcmWarningMacro( "No Directory Record Sequence (0004,1220) found");
00559       return;         
00560    }
00561    
00562    SeqEntry *s = dynamic_cast<SeqEntry *>(e);
00563    if ( !s )
00564    {
00565       gdcmWarningMacro( "Element (0004,1220) is not a Sequence ?!?");
00566       return;
00567    }
00568 
00569    NewMeta();
00570    
00571    DocEntry *d;
00572    std::string v;
00573    SQItem *si;
00574 
00575    SQItem *tmpSI=s->GetFirstSQItem();
00576    while(tmpSI)
00577    {
00578       d = tmpSI->GetDocEntry(0x0004, 0x1430); // Directory Record Type
00579       if ( DataEntry *dataEntry = dynamic_cast<DataEntry *>(d) )
00580       {
00581          v = dataEntry->GetString();
00582       }
00583       else
00584       {
00585          gdcmWarningMacro( "(0004,1430) not a DataEntry ?!?");
00586          continue;
00587       }
00588 
00589       // A decent DICOMDIR has much more images than series,
00590       // more series than studies, and so on.
00591       // This is the right order to perform the tests
00592 
00593       if ( v == "IMAGE " ) 
00594       {
00595          si = DicomDirImage::New(true);
00596          if ( !AddImageToEnd( static_cast<DicomDirImage *>(si)) )
00597          {
00598             si->Delete();
00599             si = NULL;
00600             gdcmErrorMacro( "Add AddImageToEnd failed");
00601          }
00602       }
00603       else if ( v == "SERIES" )
00604       {
00605          si = DicomDirSerie::New(true);
00606          if ( !AddSerieToEnd( static_cast<DicomDirSerie *>(si)) )
00607          {
00608             si->Delete();
00609             si = NULL;
00610             gdcmErrorMacro( "Add AddSerieToEnd failed");
00611          }
00612       }
00613       else if ( v == "VISIT " )
00614       {
00615          si = DicomDirVisit::New(true);
00616          if ( !AddVisitToEnd( static_cast<DicomDirVisit *>(si)) )
00617          {
00618             si->Delete();
00619             si = NULL;
00620             gdcmErrorMacro( "Add AddVisitToEnd failed");
00621          }
00622       }
00623       else if ( v == "STUDY " )
00624       {
00625          si = DicomDirStudy::New(true);
00626          if ( !AddStudyToEnd( static_cast<DicomDirStudy *>(si)) )
00627          {
00628             si->Delete();
00629             si = NULL;
00630             gdcmErrorMacro( "Add AddStudyToEnd failed");
00631          }
00632       }
00633       else if ( v == "PATIENT " )
00634       {
00635          si = DicomDirPatient::New(true);
00636          if ( !AddPatientToEnd( static_cast<DicomDirPatient *>(si)) )
00637          {
00638             si->Delete();
00639             si = NULL;
00640             gdcmErrorMacro( "Add PatientToEnd failed");
00641          }
00642       }
00643       else
00644       {
00645          // It was neither a 'PATIENT', nor a 'STUDY', nor a 'SERIE',
00646          // nor an 'IMAGE' SQItem. Skip to next item.
00647          gdcmDebugMacro( " -------------------------------------------"
00648          << "a non PATIENT/STUDY/SERIE/IMAGE SQItem was found : "
00649          << v);
00650 
00651         // FIXME : deal with other item types !
00652         tmpSI=s->GetNextSQItem(); // To avoid infinite loop
00653         continue;
00654       }
00655       if ( si )
00656          si->Copy(tmpSI);
00657 
00658       tmpSI=s->GetNextSQItem();
00659    }
00660    ClearEntry();
00661 }
00662 
00667 bool DicomDir::AddPatientToEnd(DicomDirPatient *dd)
00668 {
00669    Patients.push_back(dd);
00670    return true;
00671 }
00672 
00677 bool DicomDir::AddStudyToEnd(DicomDirStudy *dd)
00678 {
00679    if ( Patients.size() > 0 )
00680    {
00681       ListDicomDirPatient::iterator itp = Patients.end();
00682       itp--;
00683       (*itp)->AddStudy(dd);
00684       return true;
00685    }
00686    return false;
00687 }
00688 
00693 bool DicomDir::AddSerieToEnd(DicomDirSerie *dd)
00694 {
00695    if ( Patients.size() > 0 )
00696    {
00697       ListDicomDirPatient::iterator itp = Patients.end();
00698       itp--;
00699 
00700       DicomDirStudy *study = (*itp)->GetLastStudy();
00701       if ( study )
00702       {
00703          study->AddSerie(dd);
00704          return true;
00705       }
00706    }
00707    return false;
00708 }
00709 
00714 bool DicomDir::AddVisitToEnd(DicomDirVisit *dd)
00715 {
00716    if ( Patients.size() > 0 )
00717    {
00718       ListDicomDirPatient::iterator itp = Patients.end();
00719       itp--;
00720 
00721       DicomDirStudy *study = (*itp)->GetLastStudy();
00722       if ( study )
00723       {
00724          study->AddVisit(dd);
00725          return true;
00726       }
00727    }
00728    return false;
00729 }
00734 bool DicomDir::AddImageToEnd(DicomDirImage *dd)
00735 {
00736    if ( Patients.size() > 0 )
00737    {
00738       ListDicomDirPatient::iterator itp = Patients.end();
00739       itp--;
00740 
00741       DicomDirStudy *study = (*itp)->GetLastStudy();
00742       if ( study )
00743       {
00744          DicomDirSerie *serie = study->GetLastSerie();
00745          if ( serie )
00746          {
00747             serie->AddImage(dd);
00748             return true;
00749          }
00750       }
00751    }
00752    return false;
00753 }
00754 
00761 void DicomDir::SetElements(std::string const &path, VectDocument const &list)
00762 {
00763    ClearEntry();
00764    ClearPatient();
00765 
00766    std::string patPrevName         = "", patPrevID  = "";
00767    std::string studPrevInstanceUID = "", studPrevID = "";
00768    std::string serPrevInstanceUID  = "", serPrevID  = "";
00769 
00770    std::string patCurName,         patCurID;
00771    std::string studCurInstanceUID, studCurID;
00772    std::string serCurInstanceUID,  serCurID;
00773 
00774    bool first = true;
00775    for( VectDocument::const_iterator it = list.begin();
00776                                      it != list.end(); 
00777                                    ++it )
00778    {
00779       // get the current file characteristics
00780       patCurName         = (*it)->GetEntryString(0x0010,0x0010);
00781       patCurID           = (*it)->GetEntryString(0x0010,0x0011);
00782       studCurInstanceUID = (*it)->GetEntryString(0x0020,0x000d);
00783       studCurID          = (*it)->GetEntryString(0x0020,0x0010);
00784       serCurInstanceUID  = (*it)->GetEntryString(0x0020,0x000e);
00785       serCurID           = (*it)->GetEntryString(0x0020,0x0011);
00786 
00787       if ( patCurName != patPrevName || patCurID != patPrevID || first )
00788       {
00789          SetElement(path, GDCM_DICOMDIR_PATIENT, *it);
00790          first = true;
00791       }
00792 
00793       // if new Study, deal with 'STUDY' Elements   
00794       if ( studCurInstanceUID != studPrevInstanceUID || studCurID != studPrevID 
00795          || first )
00796       {
00797          SetElement(path, GDCM_DICOMDIR_STUDY, *it);
00798          first = true;
00799       }
00800 
00801       // if new Serie, deal with 'SERIE' Elements   
00802       if ( serCurInstanceUID != serPrevInstanceUID || serCurID != serPrevID
00803          || first )
00804       {
00805          SetElement(path, GDCM_DICOMDIR_SERIE, *it);
00806       }
00807       
00808       // Always Deal with 'IMAGE' Elements  
00809       SetElement(path, GDCM_DICOMDIR_IMAGE, *it);
00810 
00811       patPrevName         = patCurName;
00812       patPrevID           = patCurID;
00813       studPrevInstanceUID = studCurInstanceUID;
00814       studPrevID          = studCurID;
00815       serPrevInstanceUID  = serCurInstanceUID;
00816       serPrevID           = serCurID;
00817       first = false;
00818    }
00819 }
00820 
00829 void DicomDir::SetElement(std::string const &path, DicomDirType type,
00830                           Document *header)
00831 {
00832    ListDicomDirElem elemList;
00833    ListDicomDirElem::const_iterator it;
00834    uint16_t tmpGr, tmpEl;
00835    DictEntry *dictEntry;
00836    DataEntry *entry;
00837    std::string val;
00838    SQItem *si;
00839 
00840    switch( type )
00841    {
00842       case GDCM_DICOMDIR_IMAGE:
00843          elemList = Global::GetDicomDirElements()->GetDicomDirImageElements();
00844          si = DicomDirImage::New(true);
00845          if ( !AddImageToEnd(static_cast<DicomDirImage *>(si)) )
00846          {
00847             si->Delete();
00848             gdcmErrorMacro( "Add ImageToEnd failed");
00849          }
00850          break;
00851       case GDCM_DICOMDIR_SERIE:
00852          elemList = Global::GetDicomDirElements()->GetDicomDirSerieElements();
00853          si = DicomDirSerie::New(true);
00854          if ( !AddSerieToEnd(static_cast<DicomDirSerie *>(si)) )
00855          {
00856             si->Delete();
00857             gdcmErrorMacro( "Add SerieToEnd failed");
00858          }
00859          break;
00860       case GDCM_DICOMDIR_STUDY:
00861          elemList = Global::GetDicomDirElements()->GetDicomDirStudyElements();
00862          si = DicomDirStudy::New(true);
00863          if ( !AddStudyToEnd(static_cast<DicomDirStudy *>(si)) )
00864          {
00865             si->Delete();
00866             gdcmErrorMacro( "Add StudyToEnd failed");
00867          }
00868          break;
00869       case GDCM_DICOMDIR_PATIENT:
00870          elemList = Global::GetDicomDirElements()->GetDicomDirPatientElements();
00871          si = DicomDirPatient::New(true);
00872          if ( !AddPatientToEnd(static_cast<DicomDirPatient *>(si)) )
00873          {
00874             si->Delete();
00875             gdcmErrorMacro( "Add PatientToEnd failed");
00876          }
00877          break;
00878       case GDCM_DICOMDIR_META:
00879          if ( MetaElems )
00880          {
00881             MetaElems->Delete();
00882             gdcmErrorMacro( "MetaElements already exist, they will be destroyed");
00883          }
00884          elemList = Global::GetDicomDirElements()->GetDicomDirMetaElements();
00885          MetaElems = DicomDirMeta::New(true);
00886          si = MetaElems;
00887          break;
00888       default:
00889          return;
00890    }
00891    
00892    // FIXME : troubles found when it's a SeqEntry
00893       
00894    // removed all the seems-to-be-useless stuff about Referenced Image Sequence
00895    // to avoid further troubles
00896    // imageElem 0008 1140 "" // Referenced Image Sequence
00897    // imageElem fffe e000 "" // 'no length' item : length to be set to 0xffffffff later
00898    // imageElem 0008 1150 "" // Referenced SOP Class UID    : to be set/forged later
00899    // imageElem 0008 1155 "" // Referenced SOP Instance UID : to be set/forged later
00900    // imageElem fffe e00d "" // Item delimitation : length to be set to ZERO later
00901  
00902    std::string referencedVal;
00903    // for all the relevant elements found in their own spot of the DicomDir.dic
00904    for( it = elemList.begin(); it != elemList.end(); ++it)
00905    {
00906       tmpGr     = it->Group;
00907       tmpEl     = it->Elem;
00908       dictEntry = GetPubDict()->GetEntry(tmpGr, tmpEl);
00909 
00910       entry     = DataEntry::New( dictEntry ); 
00911       entry->SetOffset(0); // just to avoid further missprinting
00912 
00913       if ( header )
00914       {
00915          // NULL when we Build Up (ex nihilo) a DICOMDIR
00916          //   or when we add the META elems
00917  
00918             val = header->GetEntryString(tmpGr, tmpEl); 
00919       }
00920       else
00921       {
00922          val = GDCM_UNFOUND;
00923       }
00924 
00925       if ( val == GDCM_UNFOUND) 
00926       {       
00927          if ( tmpGr == 0x0004 ) // never present in File !     
00928          {
00929             switch (tmpEl)
00930             {
00931             case 0x1130: // File-set ID
00932                // force to the *end* File Name
00933                val = Util::GetName( path );
00934                break;
00935       
00936             case 0x1500: // Only used for image    
00937                if ( header->GetFileName().substr(0, path.length()) != path )
00938                { 
00939                  gdcmWarningMacro( "The base path of file name is incorrect");
00940                  val = header->GetFileName();
00941                }
00942                else
00943                { 
00944                  // avoid the first '/' in File name !
00945                  if ( header->GetFileName().c_str()[path.length()] 
00946                                                       == GDCM_FILESEPARATOR )
00947                     val = &(header->GetFileName().c_str()[path.length()+1]);
00948                  else  
00949                     val = &(header->GetFileName().c_str()[path.length()]);   
00950                }
00951                break;
00952     
00953              case 0x1510:  // Referenced SOP Class UID in File
00954                referencedVal = header->GetEntryString(0x0008, 0x0016);
00955                // FIXME : probabely something to check
00956                val = referencedVal;
00957                break;
00958        
00959              case 0x1511: // Referenced SOP Instance UID in File
00960                referencedVal = header->GetEntryString(0x0008, 0x0018);
00961                // FIXME : probabely something to check
00962                val = referencedVal;
00963                break;
00964     
00965             case 0x1512: // Referenced Transfer Syntax UID in File
00966                referencedVal = header->GetEntryString(0x0002, 0x0010);
00967                // FIXME : probabely something to check
00968                val = referencedVal;
00969                break;
00970     
00971             default :
00972                val = it->Value;   
00973             } 
00974          }
00975          else
00976          {
00977             // If the entry is not found in the Header, don't write its 'value' in the DICOMDIR !
00978             entry->Delete();
00979             continue;
00980           }
00981       }
00982       else
00983       {
00984          if ( header->GetEntryLength(tmpGr,tmpEl) == 0 )
00985          {
00986             val = it->Value;
00987             // Don't polute the DICOMDIR with empty fields
00988             if (val == "")
00989             {
00990                entry->Delete();
00991                continue;
00992             }  
00993          }    
00994       }
00995 
00996 /* FIX later the pb of creating the 'Implementation Version Name'!
00997 
00998       if (val == GDCM_UNFOUND)
00999          val = "";
01000 
01001       if ( tmpGr == 0x0002 && tmpEl == 0x0013)
01002       { 
01003          // 'Implementation Version Name'
01004          std::string val = "GDCM ";
01005          val += Util::GetVersion();
01006       }
01007 */ 
01008 
01009       entry->SetString( val ); // troubles expected when vr=SQ ...
01010 
01011       if ( type == GDCM_DICOMDIR_META ) // fusible : should never print !
01012       {
01013          gdcmDebugMacro("GDCM_DICOMDIR_META ?!? should never print that");
01014       }
01015       
01016       si->AddEntry(entry);
01017       entry->Delete();
01018    }
01019 }
01020 
01027 void DicomDir::MoveSQItem(DocEntrySet *dst, DocEntrySet *src)
01028 { 
01029    DocEntry *entry;
01030 // todo : rewrite the whole stuff, without using RemoveEntry an AddEntry,
01031 //        to save time
01032    entry = src->GetFirstEntry();
01033    while(entry)
01034    {
01035       dst->AddEntry(entry);  // use it, *before* removing it!
01036       src->RemoveEntry(entry);
01037       // we destroyed -> the current iterator is not longer valid
01038       entry = src->GetFirstEntry();
01039    }
01040 }
01041 
01045 bool DicomDir::HeaderLessThan(Document *header1, Document *header2)
01046 {
01047    return *header1 < *header2;
01048 }
01049 
01050 //-----------------------------------------------------------------------------
01051 // Print
01057 void DicomDir::Print(std::ostream &os, std::string const & )
01058 {
01059    if ( MetaElems )
01060    {
01061       MetaElems->SetPrintLevel(PrintLevel);
01062       MetaElems->Print(os);   
01063    }   
01064    for(ListDicomDirPatient::iterator cc  = Patients.begin();
01065                                      cc != Patients.end();
01066                                    ++cc)
01067    {
01068      (*cc)->SetPrintLevel(PrintLevel);
01069      (*cc)->Print(os);
01070    }
01071 }
01072 
01073 //-----------------------------------------------------------------------------
01074 } // end namespace gdcm

Generated on Fri Jan 20 10:14:24 2006 for gdcm by  doxygen 1.4.4