Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | 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: 2005/02/07 14:48:34 $
00007   Version:   $Revision: 1.130 $
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 "gdcmDicomDirStudy.h"
00025 #include "gdcmDicomDirSerie.h"
00026 #include "gdcmDicomDirImage.h"
00027 #include "gdcmDicomDirPatient.h"
00028 #include "gdcmDicomDirMeta.h"
00029 #include "gdcmDicomDirElement.h"
00030 #include "gdcmDirList.h"
00031 #include "gdcmUtil.h"
00032 #include "gdcmDebug.h"
00033 #include "gdcmGlobal.h"
00034 #include "gdcmFile.h"
00035 #include "gdcmSeqEntry.h"
00036 #include "gdcmSQItem.h"
00037 #include "gdcmValEntry.h"
00038 
00039 #include <fstream>
00040 #include <string>
00041 #include <algorithm>
00042 #include <sys/types.h>
00043 
00044 #ifdef _MSC_VER
00045 #   define getcwd _getcwd
00046 #endif
00047 
00048 #if defined(_MSC_VER) || defined(__BORLANDC__)
00049 #   include <direct.h>
00050 #else
00051 #   include <unistd.h>
00052 #endif
00053 // ----------------------------------------------------------------------------
00054 //         Note for future developpers
00055 // ----------------------------------------------------------------------------
00056 //
00057 //  Dicom PS 3.3 describes the relationship between Directory Records, as follow
00058 //
00059 //  Directory Record Type      Directory Record Types which may be included
00060 //                                in the next lower-člevel directory Entity
00061 //
00062 // (Root directory Entity)     PATIENT
00063 //
00064 // PATIENT                     STUDY
00065 //
00066 // STUDY                       SERIES, VISIT, RESULTS, STUDY COMPONENT
00067 //
00068 // SERIES                      IMAGE, OVERLAYS, MODALITY LUT, VOI LUT,
00069 //                             CURVE, STORED PRINT, RT DOSE, RT STRUCTURE SET
00070 //                             RT PLAN, RT TREAT RECORD, PRESENTATION, WAVEFORM,
00071 //                             SR DOCUMENT, KEY OBJECT DOC, SPECTROSCOPY,
00072 //                             RAW DATA, REGISTRATION, FIDUCIAL
00073 // IMAGE
00074 // OVERLAY
00075 // MODALITY LUT
00076 // VOI LUT
00077 // CURVE
00078 // STORED PRINT
00079 // RT DOSE
00080 // RT STRUCTURE SET
00081 // RT PLAN
00082 // RT TREAT RECORD
00083 // PRESENTATION
00084 // WAVEFORM
00085 // SR DOCUMENT
00086 // KEY OBJECT DOC
00087 // SPECTROSCOPY
00088 // RAW DATA
00089 // REGISTRATION
00090 // FIDUCIAL
00091 // 
00092 // ----------------------
00093 // The current gdcm version only deals with :
00094 //
00095 // (Root directory Entity)     PATIENT
00096 // PATIENT                     STUDY
00097 // STUDY                       SERIES 
00098 // SERIES                      IMAGE
00099 // IMAGE                       /
00100 //
00101 // DicomDir::CreateDicomDir will have to be completed
00102 // Treelike structure management will have to be upgraded
00103 // ----------------------------------------------------------------------------
00104     
00105 namespace gdcm 
00106 {
00107 //-----------------------------------------------------------------------------
00108 // Constructor / Destructor
00112 DicomDir::DicomDir()
00113          :Document( )
00114 {
00115    Initialize();  // sets all private fields to NULL
00116    NewMeta();
00117 }
00118 
00131 DicomDir::DicomDir(std::string const &fileName, bool parseDir ):
00132    Document( fileName )
00133 {
00134    // At this step, Document constructor is already executed,
00135    // whatever user passed (a root directory or a DICOMDIR)
00136    // and whatever the value of parseDir was.
00137    // (nothing is cheked in Document constructor, to avoid overhead)
00138 
00139    Initialize();  // sets all private fields to NULL
00140 
00141    // if user passed a root directory, sure we didn't get anything
00142 
00143    if ( GetFirstEntry() == 0 ) // when user passed a Directory to parse
00144    {
00145       if (!parseDir)
00146          gdcmWarningMacro( "Entry HT empty for file: "<<fileName);
00147 
00148    // Only if user passed a root directory
00149    // ------------------------------------
00150       if ( fileName == "." )
00151       {
00152          // user passed '.' as Name
00153          // we get current directory name
00154          char dummy[1000];
00155          getcwd(dummy, (size_t)1000);
00156          SetFileName( dummy ); // will be converted into a string
00157       }
00158 
00159       if ( parseDir ) // user asked for a recursive parsing of a root directory
00160       {
00161          NewMeta();
00162 
00163          gdcmWarningMacro( "Parse directory and create the DicomDir");
00164          ParseDirectory();
00165       }
00166       else
00167       {
00169          // NO ! user may just call ParseDirectory() *after* constructor
00170       }
00171    }
00172    // Only if user passed a DICOMDIR
00173    // ------------------------------
00174    else 
00175    {
00176       // Directory record sequence
00177       DocEntry *e = GetDocEntry(0x0004, 0x1220);
00178       if ( !e )
00179       {
00180          gdcmWarningMacro( "NO 'Directory record sequence' (0x0004,0x1220)"
00181                           << " in file " << fileName);
00184       }
00185       else
00186          CreateDicomDir();
00187    }
00188 }
00189 
00193 DicomDir::~DicomDir() 
00194 {
00195    SetStartMethod(NULL);
00196    SetProgressMethod(NULL);
00197    SetEndMethod(NULL);
00198 
00199    ClearPatient();
00200    if ( MetaElems )
00201    {
00202       delete MetaElems;
00203    }
00204 }
00205 
00206 //-----------------------------------------------------------------------------
00207 // Public
00216 bool DicomDir::IsReadable()
00217 {
00218    if( Filetype == Unknown)
00219    {
00220       gdcmWarningMacro( "Wrong filetype");
00221       return false;
00222    }
00223    if( !MetaElems )
00224    {
00225       gdcmWarningMacro( "Meta Elements missing in DicomDir");
00226       return false;
00227    }
00228    if( Patients.size() <= 0 )
00229    {
00230       gdcmWarningMacro( "NO Patient in DicomDir");
00231       return false;
00232    }
00233 
00234    return true;
00235 }
00236 
00240 DicomDirMeta *DicomDir::NewMeta()
00241 {
00242    if( MetaElems )
00243       delete MetaElems;
00244 
00245    DocEntry *entry = GetFirstEntry();
00246    if( entry )
00247    { 
00248       MetaElems = new DicomDirMeta(true);
00249 
00250       entry = GetFirstEntry();
00251       while( entry )
00252       {
00253          if( dynamic_cast<SeqEntry *>(entry) )
00254             break;
00255 
00256          RemoveEntryNoDestroy(entry);
00257          MetaElems->AddEntry(entry);
00258 
00259          entry = GetFirstEntry();
00260       }
00261    }
00262    else  // after root directory parsing
00263    {
00264       MetaElems = new DicomDirMeta(false);
00265    }
00266    MetaElems->SetSQItemNumber(0); // To avoid further missprinting
00267    return MetaElems;  
00268 }
00269 
00274 DicomDirPatient *DicomDir::NewPatient()
00275 {
00276    DicomDirPatient *p = new DicomDirPatient();
00277    AddPatientToEnd( p );
00278    return p;
00279 }
00280 
00284 void DicomDir::ClearPatient()
00285 {
00286    for(ListDicomDirPatient::iterator cc = Patients.begin();
00287                                      cc!= Patients.end();
00288                                    ++cc)
00289    {
00290       delete *cc;
00291    }
00292    Patients.clear();
00293 }
00294 
00299 DicomDirPatient *DicomDir::GetFirstPatient()
00300 {
00301    ItPatient = Patients.begin();
00302    if ( ItPatient != Patients.end() )
00303       return *ItPatient;
00304    return NULL;
00305 }
00306 
00312 DicomDirPatient *DicomDir::GetNextPatient()
00313 {
00314    gdcmAssertMacro (ItPatient != Patients.end());
00315 
00316    ++ItPatient;
00317    if ( ItPatient != Patients.end() )
00318       return *ItPatient;
00319    return NULL;
00320 }
00321 
00325 void DicomDir::ParseDirectory()
00326 {
00327    CreateDicomDirChainedList( GetFileName() );
00328    CreateDicomDir();
00329 }
00330 
00339 void DicomDir::SetStartMethod( DicomDir::Method *method, void *arg, 
00340                                DicomDir::Method *argDelete )
00341 {
00342    if( StartArg && StartMethodArgDelete )
00343    {
00344       StartMethodArgDelete( StartArg );
00345    }
00346 
00347    StartMethod          = method;
00348    StartArg             = arg;
00349    StartMethodArgDelete = argDelete;
00350 }
00351 
00360 void DicomDir::SetProgressMethod( DicomDir::Method *method, void *arg, 
00361                                   DicomDir::Method *argDelete )
00362 {
00363    if( ProgressArg && ProgressMethodArgDelete )
00364    {
00365       ProgressMethodArgDelete( ProgressArg );
00366    }
00367 
00368    ProgressMethod          = method;
00369    ProgressArg             = arg;
00370    ProgressMethodArgDelete = argDelete;
00371 }
00372 
00380 void DicomDir::SetEndMethod( DicomDir::Method *method, void *arg, 
00381                              DicomDir::Method *argDelete )
00382 {
00383    if( EndArg && EndMethodArgDelete )
00384    {
00385       EndMethodArgDelete( EndArg );
00386    }
00387 
00388    EndMethod          = method;
00389    EndArg             = arg;
00390    EndMethodArgDelete = argDelete;
00391 }
00392 
00399 void DicomDir::SetStartMethodArgDelete( DicomDir::Method *method ) 
00400 {
00401    StartMethodArgDelete = method;
00402 }
00403 
00410 void DicomDir::SetProgressMethodArgDelete( DicomDir::Method *method )
00411 {
00412    ProgressMethodArgDelete = method;
00413 }
00414 
00421 void DicomDir::SetEndMethodArgDelete( DicomDir::Method *method )
00422 {
00423    EndMethodArgDelete = method;
00424 }
00425 
00437 bool DicomDir::WriteDicomDir(std::string const &fileName) 
00438 {  
00439    int i;
00440    uint16_t sq[4] = { 0x0004, 0x1220, 0xffff, 0xffff };
00441    uint16_t sqt[4]= { 0xfffe, 0xe0dd, 0xffff, 0xffff };
00442 
00443    std::ofstream *fp = new std::ofstream(fileName.c_str(),  
00444                                          std::ios::out | std::ios::binary);
00445    if( !fp ) 
00446    {
00447       gdcmWarningMacro("Failed to open(write) File: " << fileName.c_str());
00448       return false;
00449    }
00450 
00451    char filePreamble[128];
00452    memset(filePreamble, 0, 128);
00453    fp->write(filePreamble, 128); //FIXME
00454    binary_write( *fp, "DICM");
00455  
00456    DicomDirMeta *ptrMeta = GetMeta();
00457    ptrMeta->WriteContent(fp, ExplicitVR);
00458    
00459    // force writing 0004|1220 [SQ ], that CANNOT exist within DicomDirMeta
00460    for(i=0;i<4;++i)
00461    {
00462       binary_write(*fp, sq[i]);
00463    }
00464         
00465    for(ListDicomDirPatient::iterator cc  = Patients.begin();
00466                                      cc != Patients.end();
00467                                    ++cc )
00468    {
00469       (*cc)->WriteContent( fp, ExplicitVR );
00470    }
00471    
00472    // force writing Sequence Delimitation Item
00473    for(i=0;i<4;++i)
00474    {
00475       binary_write(*fp, sqt[i]);  // fffe e0dd ffff ffff 
00476    }
00477 
00478    fp->close();
00479    delete fp;
00480 
00481    return true;
00482 }
00483 
00484 //-----------------------------------------------------------------------------
00485 // Protected
00490 void DicomDir::CreateDicomDirChainedList(std::string const &path)
00491 {
00492    CallStartMethod();
00493    DirList dirList(path,1); // gets recursively the file list
00494    unsigned int count = 0;
00495    VectDocument list;
00496    File *header;
00497 
00498    DirListType fileList = dirList.GetFilenames();
00499 
00500    for( DirListType::iterator it  = fileList.begin();
00501                               it != fileList.end();
00502                               ++it )
00503    {
00504       Progress = (float)(count+1)/(float)fileList.size();
00505       CallProgressMethod();
00506       if( Abort )
00507       {
00508          break;
00509       }
00510 
00511       header = new File( it->c_str() );
00512       if( !header )
00513       {
00514          gdcmWarningMacro( "Failure in new gdcm::File " << it->c_str() );
00515          continue;
00516       }
00517       
00518       if( header->IsReadable() )
00519       {
00520          // Add the file to the chained list:
00521          list.push_back(header);
00522          gdcmWarningMacro( "Readable " << it->c_str() );
00523        }
00524        else
00525        {
00526           delete header;
00527        }
00528        count++;
00529    }
00530    // sorts Patient/Study/Serie/
00531    std::sort(list.begin(), list.end(), DicomDir::HeaderLessThan );
00532    
00533    std::string tmp = dirList.GetDirName();      
00534    //for each File of the chained list, add/update the Patient/Study/Serie/Image info
00535    SetElements(tmp, list);
00536    CallEndMethod();
00537 
00538    for(VectDocument::iterator itDoc=list.begin();
00539        itDoc!=list.end();
00540        ++itDoc)
00541    {
00542       delete dynamic_cast<File *>(*itDoc);
00543    }
00544 }
00545 
00549 void DicomDir::CallStartMethod()
00550 {
00551    Progress = 0.0f;
00552    Abort    = false;
00553    if( StartMethod )
00554    {
00555       StartMethod( StartArg );
00556    }
00557 }
00558 
00562 void DicomDir::CallProgressMethod()
00563 {
00564    if( ProgressMethod )
00565    {
00566       ProgressMethod( ProgressArg );
00567    }
00568 }
00569 
00573 void DicomDir::CallEndMethod()
00574 {
00575    Progress = 1.0f;
00576    if( EndMethod )
00577    {
00578       EndMethod( EndArg );
00579    }
00580 }
00581 
00582 //-----------------------------------------------------------------------------
00583 // Private
00587 void DicomDir::Initialize()
00588 {
00589    StartMethod             = NULL;
00590    ProgressMethod          = NULL;
00591    EndMethod               = NULL;
00592    StartMethodArgDelete    = NULL;
00593    ProgressMethodArgDelete = NULL;
00594    EndMethodArgDelete      = NULL;
00595    StartArg                = NULL;
00596    ProgressArg             = NULL;
00597    EndArg                  = NULL;
00598 
00599    Progress = 0.0;
00600    Abort = false;
00601 
00602    MetaElems = NULL;   
00603 }
00604 
00608 void DicomDir::CreateDicomDir()
00609 {
00610    // The SeqEntries of "Directory Record Sequence" are parsed. 
00611    //  When a DicomDir tag ("PATIENT", "STUDY", "SERIE", "IMAGE") is found :
00612    //  1 - we save the beginning iterator
00613    //  2 - we continue to parse
00614    //  3 - we find an other tag
00615    //       + we create the object for the precedent tag
00616    //       + loop to 1 -
00617 
00618    // Directory record sequence
00619    DocEntry *e = GetDocEntry(0x0004, 0x1220);
00620    if ( !e )
00621    {
00622       gdcmWarningMacro( "No Directory Record Sequence (0004,1220) found");
00624       return;         
00625    }
00626    
00627    SeqEntry *s = dynamic_cast<SeqEntry *>(e);
00628    if ( !s )
00629    {
00630       gdcmWarningMacro( "Element (0004,1220) is not a Sequence ?!?");
00631       return;
00632    }
00633 
00634    NewMeta();
00635    
00636    DocEntry *d;
00637    std::string v;
00638    SQItem *si;
00639 
00640    SQItem *tmpSI=s->GetFirstSQItem();
00641    while(tmpSI)
00642    {
00643       d = tmpSI->GetDocEntry(0x0004, 0x1430); // Directory Record Type
00644       if ( ValEntry* valEntry = dynamic_cast<ValEntry *>(d) )
00645       {
00646          v = valEntry->GetValue();
00647       }
00648       else
00649       {
00650          gdcmWarningMacro( "Not a ValEntry.");
00651          continue;
00652       }
00653 
00654       if( v == "PATIENT " )
00655       {
00656          si = new DicomDirPatient(true);
00657          if( !AddPatientToEnd( static_cast<DicomDirPatient *>(si)) )
00658          {
00659             delete si;
00660             si = NULL;
00661             gdcmErrorMacro( "Add PatientToEnd failed");
00662          }
00663       }
00664       else if( v == "STUDY " )
00665       {
00666          si = new DicomDirStudy(true);
00667          if( !AddStudyToEnd( static_cast<DicomDirStudy *>(si)) )
00668          {
00669             delete si;
00670             si = NULL;
00671             gdcmErrorMacro( "Add AddStudyToEnd failed");
00672          }
00673       }
00674       else if( v == "SERIES" )
00675       {
00676          si = new DicomDirSerie(true);
00677          if( !AddSerieToEnd( static_cast<DicomDirSerie *>(si)) )
00678          {
00679             delete si;
00680             si = NULL;
00681             gdcmErrorMacro( "Add AddSerieToEnd failed");
00682          }
00683       }
00684       else if( v == "IMAGE " ) 
00685       {
00686          si = new DicomDirImage(true);
00687          if( !AddImageToEnd( static_cast<DicomDirImage *>(si)) )
00688          {
00689             delete si;
00690             si = NULL;
00691             gdcmErrorMacro( "Add AddImageToEnd failed");
00692          }
00693       }
00694       else
00695       {
00696          // It was not a 'PATIENT', nor a 'STUDY', nor a 'SERIE',
00697          // neither an 'IMAGE' SQItem. Skip to next item.
00698          continue;
00699       }
00700       if( si )
00701          MoveSQItem(si,tmpSI);
00702 
00703       tmpSI=s->GetNextSQItem();
00704    }
00705    ClearEntry();
00706 }
00707 
00712 bool DicomDir::AddPatientToEnd(DicomDirPatient *dd)
00713 {
00714    Patients.push_back(dd);
00715    return true;
00716 }
00717 
00722 bool DicomDir::AddStudyToEnd(DicomDirStudy *dd)
00723 {
00724    if( Patients.size() > 0 )
00725    {
00726       ListDicomDirPatient::iterator itp = Patients.end();
00727       itp--;
00728       (*itp)->AddStudy(dd);
00729       return true;
00730    }
00731    return false;
00732 }
00733 
00738 bool DicomDir::AddSerieToEnd(DicomDirSerie *dd)
00739 {
00740    if( Patients.size() > 0 )
00741    {
00742       ListDicomDirPatient::iterator itp = Patients.end();
00743       itp--;
00744 
00745       DicomDirStudy *study = (*itp)->GetLastStudy();
00746       if( study )
00747       {
00748          study->AddSerie(dd);
00749          return true;
00750       }
00751    }
00752    return false;
00753 }
00754 
00759 bool DicomDir::AddImageToEnd(DicomDirImage *dd)
00760 {
00761    if( Patients.size() > 0 )
00762    {
00763       ListDicomDirPatient::iterator itp = Patients.end();
00764       itp--;
00765 
00766       DicomDirStudy *study = (*itp)->GetLastStudy();
00767       if( study )
00768       {
00769          DicomDirSerie *serie = study->GetLastSerie();
00770          if( serie )
00771          {
00772             serie->AddImage(dd);
00773             return true;
00774          }
00775       }
00776    }
00777    return false;
00778 }
00779 
00786 void DicomDir::SetElements(std::string const &path, VectDocument const &list)
00787 {
00788    ClearEntry();
00789    ClearPatient();
00790 
00791    std::string patPrevName         = "", patPrevID  = "";
00792    std::string studPrevInstanceUID = "", studPrevID = "";
00793    std::string serPrevInstanceUID  = "", serPrevID  = "";
00794 
00795    std::string patCurName,         patCurID;
00796    std::string studCurInstanceUID, studCurID;
00797    std::string serCurInstanceUID,  serCurID;
00798 
00799    bool first = true;
00800    for( VectDocument::const_iterator it = list.begin();
00801                                      it != list.end(); 
00802                                    ++it )
00803    {
00804       // get the current file characteristics
00805       patCurName         = (*it)->GetEntryValue(0x0010,0x0010);
00806       patCurID           = (*it)->GetEntryValue(0x0010,0x0011);
00807       studCurInstanceUID = (*it)->GetEntryValue(0x0020,0x000d);
00808       studCurID          = (*it)->GetEntryValue(0x0020,0x0010);
00809       serCurInstanceUID  = (*it)->GetEntryValue(0x0020,0x000e);
00810       serCurID           = (*it)->GetEntryValue(0x0020,0x0011);
00811 
00812       if( patCurName != patPrevName || patCurID != patPrevID || first )
00813       {
00814          SetElement(path, GDCM_DICOMDIR_PATIENT, *it);
00815          first = true;
00816       }
00817 
00818       // if new Study Deal with 'STUDY' Elements   
00819       if( studCurInstanceUID != studPrevInstanceUID || studCurID != studPrevID 
00820          || first )
00821       {
00822          SetElement(path, GDCM_DICOMDIR_STUDY, *it);
00823          first = true;
00824       }
00825 
00826       // if new Serie Deal with 'SERIE' Elements   
00827       if( serCurInstanceUID != serPrevInstanceUID || serCurID != serPrevID
00828          || first )
00829       {
00830          SetElement(path, GDCM_DICOMDIR_SERIE, *it);
00831          first = true;
00832       }
00833       
00834       // Always Deal with 'IMAGE' Elements  
00835       SetElement(path, GDCM_DICOMDIR_IMAGE, *it);
00836 
00837       patPrevName         = patCurName;
00838       patPrevID           = patCurID;
00839       studPrevInstanceUID = studCurInstanceUID;
00840       studPrevID          = studCurID;
00841       serPrevInstanceUID  = serCurInstanceUID;
00842       serPrevID           = serCurID;
00843       first = false;
00844    }
00845 }
00846 
00855 void DicomDir::SetElement(std::string const &path, DicomDirType type,
00856                           Document *header)
00857 {
00858    ListDicomDirElem elemList; //FIXME this is going to be a by copy operation
00859    ListDicomDirElem::const_iterator it;
00860    uint16_t tmpGr, tmpEl;
00861    DictEntry *dictEntry;
00862    ValEntry *entry;
00863    std::string val;
00864    SQItem *si;
00865 
00866    switch( type )
00867    {
00868       case GDCM_DICOMDIR_IMAGE:
00869          elemList = Global::GetDicomDirElements()->GetDicomDirImageElements();
00870          si = new DicomDirImage(true);
00871          if( !AddImageToEnd(static_cast<DicomDirImage *>(si)) )
00872          {
00873             delete si;
00874             gdcmErrorMacro( "Add ImageToEnd failed");
00875          }
00876          break;
00877       case GDCM_DICOMDIR_SERIE:
00878          elemList = Global::GetDicomDirElements()->GetDicomDirSerieElements();
00879          si = new DicomDirSerie(true);
00880          if( !AddSerieToEnd(static_cast<DicomDirSerie *>(si)) )
00881          {
00882             delete si;
00883             gdcmErrorMacro( "Add SerieToEnd failed");
00884          }
00885          break;
00886       case GDCM_DICOMDIR_STUDY:
00887          elemList = Global::GetDicomDirElements()->GetDicomDirStudyElements();
00888          si = new DicomDirStudy(true);
00889          if( !AddStudyToEnd(static_cast<DicomDirStudy *>(si)) )
00890          {
00891             delete si;
00892             gdcmErrorMacro( "Add StudyToEnd failed");
00893          }
00894          break;
00895       case GDCM_DICOMDIR_PATIENT:
00896          elemList = Global::GetDicomDirElements()->GetDicomDirPatientElements();
00897          si = new DicomDirPatient(true);
00898          if( !AddPatientToEnd(static_cast<DicomDirPatient *>(si)) )
00899          {
00900             delete si;
00901             gdcmErrorMacro( "Add PatientToEnd failed");
00902          }
00903          break;
00904       case GDCM_DICOMDIR_META:
00905          elemList = Global::GetDicomDirElements()->GetDicomDirMetaElements();
00906          si = new DicomDirMeta(true);
00907          if( MetaElems )
00908          {
00909             delete MetaElems;
00910             gdcmErrorMacro( "MetaElements already exist, they will be destroyed");
00911          }
00912          MetaElems = static_cast<DicomDirMeta *>(si);
00913          break;
00914       default:
00915          return;
00916    }
00917    // removed all the seems-to-be-useless stuff about Referenced Image Sequence
00918    // to avoid further troubles
00919    // imageElem 0008 1140 "" // Referenced Image Sequence
00920    // imageElem fffe e000 "" // 'no length' item : length to be set to 0xffffffff later
00921    // imageElem 0008 1150 "" // Referenced SOP Class UID    : to be set/forged later
00922    // imageElem 0008 1155 "" // Referenced SOP Instance UID : to be set/forged later
00923    // imageElem fffe e00d "" // Item delimitation : length to be set to ZERO later
00924  
00925    // FIXME : troubles found when it's a SeqEntry
00926 
00927    // for all the relevant elements found in their own spot of the DicomDir.dic
00928    for( it = elemList.begin(); it != elemList.end(); ++it)
00929    {
00930       tmpGr     = it->Group;
00931       tmpEl     = it->Elem;
00932       dictEntry = GetPubDict()->GetEntry(tmpGr, tmpEl);
00933 
00934       entry     = new ValEntry( dictEntry ); // Be sure it's never a BinEntry !
00935 
00936       entry->SetOffset(0); // just to avoid further missprinting
00937 
00938       if( header )
00939       {
00940          // NULL when we Build Up (ex nihilo) a DICOMDIR
00941          //   or when we add the META elems
00942          val = header->GetEntryValue(tmpGr, tmpEl);
00943       }
00944       else
00945       {
00946          val = GDCM_UNFOUND;
00947       }
00948 
00949       if( val == GDCM_UNFOUND) 
00950       {
00951          if( tmpGr == 0x0004 && tmpEl == 0x1130 ) // File-set ID
00952          {
00953            // force to the *end* File Name
00954            val = Util::GetName( path );
00955          }
00956          else if( tmpGr == 0x0004 && tmpEl == 0x1500 ) // Only used for image
00957          {
00958             if( header->GetFileName().substr(0, path.length()) != path )
00959             {
00960                gdcmWarningMacro( "The base path of file name is incorrect");
00961                val = header->GetFileName();
00962             }
00963             else
00964             {
00965                val = &(header->GetFileName().c_str()[path.length()]);
00966             }
00967          }
00968          else
00969          {
00970             val = it->Value;
00971          }
00972       }
00973       else
00974       {
00975          if ( header->GetEntryLength(tmpGr,tmpEl) == 0 )
00976             val = it->Value;
00977       }
00978 
00979       entry->SetValue( val ); // troubles expected when vr=SQ ...
00980 
00981       if ( type == GDCM_DICOMDIR_META ) // fusible : should never print !
00982       {
00983          gdcmWarningMacro("GDCM_DICOMDIR_META ?!? should never print that");
00984       }
00985       si->AddEntry(entry);
00986    }
00987 }
00988 
00995 void DicomDir::MoveSQItem(DocEntrySet *dst,DocEntrySet *src)
00996 {
00997    DocEntry *entry;
00998 
00999    entry = src->GetFirstEntry();
01000    while(entry)
01001    {
01002       src->RemoveEntryNoDestroy(entry);
01003       dst->AddEntry(entry);
01004       // we destroyed -> the current iterator is not longer valid
01005       entry = src->GetFirstEntry();
01006    }
01007 }
01008 
01012 bool DicomDir::HeaderLessThan(Document *header1, Document *header2)
01013 {
01014    return *header1 < *header2;
01015 }
01016 
01017 //-----------------------------------------------------------------------------
01018 // Print
01024 void DicomDir::Print(std::ostream &os, std::string const & )
01025 {
01026    if( MetaElems )
01027    {
01028       MetaElems->SetPrintLevel(PrintLevel);
01029       MetaElems->Print(os);   
01030    }   
01031    for(ListDicomDirPatient::iterator cc  = Patients.begin();
01032                                      cc != Patients.end();
01033                                    ++cc)
01034    {
01035      (*cc)->SetPrintLevel(PrintLevel);
01036      (*cc)->Print(os);
01037    }
01038 }
01039 
01040 //-----------------------------------------------------------------------------
01041 } // end namespace gdcm

Generated on Thu Feb 10 22:17:56 2005 for gdcm by doxygen 1.3.6