X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=blobdiff_plain;f=src%2FgdcmDicomDir.cxx;h=5b1b6e4904841fd0e34e5634e8649239c93cd62a;hb=b59e9f16e06afc854372454e8d816bdb8ec72ccf;hp=14b5b41b1e1d2dda067458315e52fb77f7a1ecb2;hpb=adbbd930989c6e6fc8e1b76bfd7bdfe5cbcb430e;p=gdcm.git diff --git a/src/gdcmDicomDir.cxx b/src/gdcmDicomDir.cxx index 14b5b41b..5b1b6e49 100644 --- a/src/gdcmDicomDir.cxx +++ b/src/gdcmDicomDir.cxx @@ -1,43 +1,54 @@ // gdcmDicomDir.cxx //----------------------------------------------------------------------------- +#include +#include +#include +#include + +#ifdef _MSC_VER + #include +#else + #include +#endif + #include "gdcmDicomDir.h" #include "gdcmDicomDirStudy.h" #include "gdcmDicomDirSerie.h" #include "gdcmDicomDirImage.h" #include "gdcmDirList.h" #include "gdcmUtil.h" - -#include -#include - -#include -#include +#include "gdcmDebug.h" +#include "gdcmGlobal.h" //----------------------------------------------------------------------------- // For full DICOMDIR description, see: // PS 3.3-2003, pages 731-750 //----------------------------------------------------------------------------- + + // Constructor / Destructor -/* - * \ingroup gdcmDicomDir - * \brief Constructor : Parses recursively the directory and creates the DicomDir - * \ or uses an already built DICOMDIR, depending on 'parseDir' value - * @param Name name of the root directory (parseDir = true) - * name of the DICOMDIR (parseDir = false) - * @param parseDir - true if user passed an entry point + +/** + * \brief Constructor Parses recursively the directory and creates the DicomDir + * or uses an already built DICOMDIR, depending on 'parseDir' value. + * @param FileName name + * - of the root directory (parseDir = true) + * - of the DICOMDIR (parseDir = false) + * @param parseDir boolean + * - true if user passed an entry point * and wants to explore recursively the directories - * - false if user passed an already built DICOMDIR file + * - false if user passed an already built DICOMDIR file * and wants to use it - * @param exception_on_error whether we want to throw an exception or not + * @param exception_on_error whether we want to throw an exception or not */ -gdcmDicomDir::gdcmDicomDir(const char *Name, bool parseDir, +gdcmDicomDir::gdcmDicomDir(const char *FileName, bool parseDir, bool exception_on_error): - gdcmParser(Name,exception_on_error,true) // true : enable SeQuences + gdcmParser(FileName,exception_on_error,true) // true : enable SeQuences { // que l'on ai passe un root directory ou un DICOMDIR // et quelle que soit la valeur de parseDir, - // on a lance gdcmParser - + // on a lance gdcmParser + startMethod= NULL; progressMethod= NULL; endMethod= NULL; @@ -53,24 +64,38 @@ gdcmDicomDir::gdcmDicomDir(const char *Name, bool parseDir, metaElems=NULL; -// Si on passe un root directory, on est assuré de n'avoir rien ramené +// gdcmParser already executed +// if user passed a root directory, sure we didn't get anything if( GetListEntry().begin()==GetListEntry().end() ) { - // Si, en plus, parseDir == false, ca devrait etre une erreur + // if parseDir == false, it should be tagged as an error dbg.Verbose(0, "gdcmDicomDir::gdcmDicomDir : entry list empty"); + if(strlen(FileName)==1 && FileName[0]=='.') { // user passed '.' as Name + // we get current directory name + char* dummy= new char[1000]; + getcwd(dummy, (size_t)1000); + SetFileName(dummy); // will be converted into a string + delete[] dummy; // no longer needed + } + if(parseDir) { - dbg.Verbose(0, "gdcmDicomDir::gdcmDicomDir : Parse directory and create the DicomDir"); + dbg.Verbose(0, "gdcmDicomDir::gdcmDicomDir : Parse directory" + " and create the DicomDir"); ParseDirectory(); } } - else + else { CreateDicomDir(); + CheckBoundaries(); // to maintain consistency between + // home-made gdcmDicomDir + // and the ones comming from a DICOMDIR file + } } -/* +/** * \ingroup gdcmDicomDir * \brief Constructor : creates an empty gdcmDicomDir * @param exception_on_error whether we want to throw an exception or not @@ -97,7 +122,7 @@ gdcmDicomDir::gdcmDicomDir(bool exception_on_error): } -/* +/** * \ingroup gdcmDicomDir * \brief Canonical destructor */ @@ -118,7 +143,7 @@ gdcmDicomDir::~gdcmDicomDir() //----------------------------------------------------------------------------- // Print -/* +/** * \ingroup gdcmDicomDir * \brief Canonical Printer */ @@ -138,10 +163,10 @@ void gdcmDicomDir::Print(std::ostream &os) //----------------------------------------------------------------------------- // Public -/* +/** * \ingroup gdcmDicomDir * \brief This predicate, based on hopefully reasonable heuristics, - * decides whether or not the current gdcmParser was properly parsed + * decides whether or not the current header was properly parsed * and contains the mandatory information for being considered as * a well formed and usable DicomDir. * @return true when gdcmParser is the one of a reasonable DicomDir, @@ -159,21 +184,22 @@ bool gdcmDicomDir::IsReadable(void) return(true); } -/* +/** * \ingroup gdcmDicomDir - * \brief fills whole the structure + * \brief fills the whole structure, starting from a root Directory */ void gdcmDicomDir::ParseDirectory(void) { - CreateDicomDirChainedList(GetPath()); + CreateDicomDirChainedList(GetFileName()); CreateDicomDir(); } -/* +/** * \ingroup gdcmDicomDir * \brief Set the start method to call when the parsing of the directory starts * @param method Method to call * @param arg Argument to pass to the method + * @param argDelete Argument * \warning In python : the arg parameter isn't considered */ void gdcmDicomDir::SetStartMethod(gdcmMethod *method,void *arg,gdcmMethod *argDelete) @@ -186,11 +212,11 @@ void gdcmDicomDir::SetStartMethod(gdcmMethod *method,void *arg,gdcmMethod *argDe startMethodArgDelete=argDelete; } -/* +/** * \ingroup gdcmDicomDir * \brief Set the method to delete the argument - * The argument is destroyed when the method is changed or when the class - * is destroyed + * The argument is destroyed when the method is changed or when the + * class is destroyed * @param method Method to call to delete the argument */ void gdcmDicomDir::SetStartMethodArgDelete(gdcmMethod *method) @@ -198,11 +224,12 @@ void gdcmDicomDir::SetStartMethodArgDelete(gdcmMethod *method) startMethodArgDelete=method; } -/* +/** * \ingroup gdcmDicomDir * \brief Set the progress method to call when the parsing of the directory progress * @param method Method to call * @param arg Argument to pass to the method + * @param argDelete Argument * \warning In python : the arg parameter isn't considered */ void gdcmDicomDir::SetProgressMethod(gdcmMethod *method,void *arg,gdcmMethod *argDelete) @@ -215,11 +242,11 @@ void gdcmDicomDir::SetProgressMethod(gdcmMethod *method,void *arg,gdcmMethod *ar progressMethodArgDelete=argDelete; } -/* +/** * \ingroup gdcmDicomDir * \brief Set the method to delete the argument - * The argument is destroyed when the method is changed or when the class - * is destroyed + * The argument is destroyed when the method is changed or when the + * class is destroyed * @param method Method to call to delete the argument */ void gdcmDicomDir::SetProgressMethodArgDelete(gdcmMethod *method) @@ -227,14 +254,15 @@ void gdcmDicomDir::SetProgressMethodArgDelete(gdcmMethod *method) progressMethodArgDelete=method; } -/* +/** * \ingroup gdcmDicomDir * \brief Set the end method to call when the parsing of the directory ends * @param method Method to call * @param arg Argument to pass to the method + * @param argDelete Argument * \warning In python : the arg parameter isn't considered */ -void gdcmDicomDir::SetEndMethod(gdcmMethod *method,void *arg,gdcmMethod *argDelete) +void gdcmDicomDir::SetEndMethod(gdcmMethod *method, void *arg, gdcmMethod *argDelete) { if((endArg)&&(endMethodArgDelete)) endMethodArgDelete(endArg); @@ -244,7 +272,7 @@ void gdcmDicomDir::SetEndMethod(gdcmMethod *method,void *arg,gdcmMethod *argDele endMethodArgDelete=argDelete; } -/* +/** * \ingroup gdcmDicomDir * \brief Set the method to delete the argument * The argument is destroyed when the method is changed or when the class @@ -279,29 +307,23 @@ bool gdcmDicomDir::Write(std::string fileName) return(false); } - char * filePreamble; - filePreamble=(char*)calloc(128,1); + char * filePreamble = new char[128]; fwrite(filePreamble,128,1,fp1); fwrite("DICM",4,1,fp1); - free(filePreamble); - //UpdateDirectoryRecordSequenceLength(); // a reecrire en utilisant - // la structure arborescente JPR - WriteDicomDirEntries(fp1); + delete[] filePreamble; + UpdateDirectoryRecordSequenceLength(); + WriteEntries(fp1); fclose(fp1); - return true; } /** - * \ingroup gdcmParser - * \brief writes on disc according to the DICOMDIR format - * using the Chained List - * \todo a reecrire en utilisant la structure arborescente + * \brief Writes in a file using the tree-like structure. * @param _fp already open file pointer */ -void gdcmDicomDir::WriteDicomDirEntries(FILE *_fp) +void gdcmDicomDir::WriteEntries(FILE *_fp) { // TODO (?) tester les echecs en ecriture // (apres chaque fwrite, dans le WriteEntry) @@ -315,28 +337,28 @@ void gdcmDicomDir::WriteDicomDirEntries(FILE *_fp) ptrMeta= GetDicomDirMeta(); for(i=ptrMeta->debut();i!=ptrMeta->fin();++i) { - WriteEntry(*i,_fp,DICOMDIR); + WriteEntry(*i,_fp, ExplicitVR); } itPatient = GetDicomDirPatients().begin(); while ( itPatient != GetDicomDirPatients().end() ) { for(i=(*itPatient)->debut();i!=(*itPatient)->fin();++i) { - WriteEntry(*i,_fp,DICOMDIR); + WriteEntry(*i,_fp, ExplicitVR); } itStudy = ((*itPatient)->GetDicomDirStudies()).begin(); while (itStudy != (*itPatient)->GetDicomDirStudies().end() ) { for(i=(*itStudy)->debut();i!=(*itStudy)->fin();++i) { - WriteEntry(*i,_fp,DICOMDIR); + WriteEntry(*i,_fp, ExplicitVR); } itSerie = ((*itStudy)->GetDicomDirSeries()).begin(); while (itSerie != (*itStudy)->GetDicomDirSeries().end() ) { for(i=(*itSerie)->debut();i!=(*itSerie)->fin();++i) { - WriteEntry(*i,_fp,DICOMDIR); + WriteEntry(*i,_fp, ExplicitVR); } itImage = ((*itSerie)->GetDicomDirImages()).begin(); while (itImage != (*itSerie)->GetDicomDirImages().end() ) { for(i=(*itImage)->debut();i!=(*itImage)->fin();++i) { - WriteEntry(*i,_fp,DICOMDIR); + WriteEntry(*i,_fp, ExplicitVR); } ++itImage; } @@ -351,7 +373,7 @@ void gdcmDicomDir::WriteDicomDirEntries(FILE *_fp) //----------------------------------------------------------------------------- // Protected -/* +/** * \ingroup gdcmDicomDir * \brief create a gdcmHeader-like chained list from a root Directory * @param path entry point of the tree-like structure @@ -369,7 +391,8 @@ void gdcmDicomDir::CreateDicomDirChainedList(std::string path) patients.clear(); for(gdcmDirList::iterator it=fileList.begin(); - it!=fileList.end(); ++it) + it!=fileList.end(); + ++it) { progress=(float)(count+1)/(float)fileList.size(); CallProgressMethod(); @@ -388,13 +411,52 @@ void gdcmDicomDir::CreateDicomDirChainedList(std::string path) std::sort(list.begin(),list.end(),gdcmDicomDir::HeaderLessThan); std::string tmp=fileList.GetDirName(); + //for each Header of the chained list, add/update the Patient/Study/Serie/Image info SetElements(tmp,list); - + CallEndMethod(); } -/* +/** + * \ingroup gdcmDicomDir + * \brief modifies the limits of a gdcmObject, created from a DICOMDIR file + */ + +void gdcmDicomDir::CheckBoundaries() +{ + ListDicomDirPatient::iterator itPatient; + ListDicomDirStudy::iterator itStudy; + ListDicomDirSerie::iterator itSerie; + ListDicomDirImage::iterator itImage; + ListTag::iterator i,j; + + GetDicomDirMeta()->ResetBoundaries(0); + + itPatient = GetDicomDirPatients().begin(); + while ( itPatient != GetDicomDirPatients().end() ) { + (*itPatient)->ResetBoundaries(1); + itStudy = ((*itPatient)->GetDicomDirStudies()).begin(); + while (itStudy != (*itPatient)->GetDicomDirStudies().end() ) { + (*itStudy)->ResetBoundaries(1); + itSerie = ((*itStudy)->GetDicomDirSeries()).begin(); + while (itSerie != (*itStudy)->GetDicomDirSeries().end() ) { + (*itSerie)->ResetBoundaries(1); + itImage = ((*itSerie)->GetDicomDirImages()).begin(); + while (itImage != (*itSerie)->GetDicomDirImages().end() ) { + (*itImage)->ResetBoundaries(1); + ++itImage; + } + ++itSerie; + } + ++itStudy; + } + ++itPatient; + } +} + + +/** * \ingroup gdcmDicomDir * \brief adds a new Patient to a partially created DICOMDIR */ @@ -407,8 +469,7 @@ gdcmDicomDirPatient * gdcmDicomDir::NewPatient(void) { elemList=gdcmGlobal::GetDicomDirElements()->GetDicomDirPatientElements(); std::list::iterator debInsertion, finInsertion, i,j; - - + debInsertion = metaElems->fin(); ++debInsertion; finInsertion=debInsertion; @@ -424,9 +485,9 @@ gdcmDicomDirPatient * gdcmDicomDir::NewPatient(void) { entry->SetValue(it->value); if(dictEntry->GetGroup()==0xfffe) - { - entry->SetLength(entry->GetValue().length()); - } + { + entry->SetLength(entry->GetValue().length()); + } else if( (dictEntry->GetVR()=="UL") || (dictEntry->GetVR()=="SL") ) { entry->SetLength(4); @@ -458,24 +519,7 @@ gdcmDicomDirPatient * gdcmDicomDir::NewPatient(void) { return p; } -/* - * \ingroup gdcmDicomDir - * \brief Get the DicomDir path - */ -std::string gdcmDicomDir::GetPath(void) -{ - std::string path=GetFileName(); - - int pos1=path.rfind("/"); - int pos2=path.rfind("\\"); - if(pos1>pos2) - path.resize(pos1); - else - path.resize(pos2); - - return(path); -} -/* +/** * \ingroup gdcmDicomDir * \brief CallStartMethod */ @@ -486,7 +530,7 @@ void gdcmDicomDir::CallStartMethod(void) if(startMethod) startMethod(startArg); } -/* +/** * \ingroup gdcmDicomDir * \brief CallProgressMethod */ @@ -495,7 +539,7 @@ void gdcmDicomDir::CallProgressMethod(void) if(progressMethod) progressMethod(progressArg); } -/* +/** * \ingroup gdcmDicomDir * \brief CallEndMethod */ @@ -508,7 +552,7 @@ void gdcmDicomDir::CallEndMethod(void) //----------------------------------------------------------------------------- // Private -/* +/** * \ingroup gdcmDicomDir * \brief create a 'gdcmDicomDir' from a DICOMDIR gdcmHeader */ @@ -568,12 +612,12 @@ void gdcmDicomDir::CreateDicomDir() if(begin!=end) AddObjectToEnd(type,begin,--end2); } -/* +/** * \ingroup gdcmDicomDir * \brief AddObjectToEnd * @param type - * @param begin - * @param end + * @param begin iterator on the first HeaderEntry within the chained List + * @param end iterator on the last HeaderEntry within the chained List */ void gdcmDicomDir::AddObjectToEnd(gdcmDicomDirType type,ListTag::iterator begin,ListTag::iterator end) { @@ -597,14 +641,17 @@ void gdcmDicomDir::AddObjectToEnd(gdcmDicomDirType type,ListTag::iterator begin, case gdcmDicomDir::GDCM_DICOMDIR_IMAGE: AddDicomDirImageToEnd(begin,end); break; + case gdcmDicomDir::GDCM_DICOMDIR_NONE: + AddDicomDirImageToEnd(begin,end); //FIXME + break; } } -/* +/** * \ingroup gdcmDicomDir * \brief Well ... Not realy to end, there is only one occurence - * @param begin - * @param end + * @param begin iterator on the first HeaderEntry within the chained List + * @param end iterator on the last HeaderEntry within the chained List */ void gdcmDicomDir::AddDicomDirMetaToEnd(ListTag::iterator begin,ListTag::iterator end) { @@ -613,22 +660,22 @@ void gdcmDicomDir::AddDicomDirMetaToEnd(ListTag::iterator begin,ListTag::iterato metaElems = new gdcmDicomDirMeta(begin,end,&tagHT,&listEntries); } -/* +/** * \ingroup gdcmDicomDir * \brief AddDicomDirPatientToEnd - * @param begin - * @param end + * @param begin iterator on the first HeaderEntry within the chained List + * @param end iterator on the last HeaderEntry within the chained List */ void gdcmDicomDir::AddDicomDirPatientToEnd(ListTag::iterator begin,ListTag::iterator end) { patients.push_back(new gdcmDicomDirPatient(begin,end,&tagHT, &listEntries)); } -/* +/** * \ingroup gdcmDicomDir * \brief AddDicomDirStudyToEnd - * @param begin - * @param end + * @param begin iterator on the first HeaderEntry within the chained List + * @param end iterator on the last HeaderEntry within the chained List */ void gdcmDicomDir::AddDicomDirStudyToEnd(ListTag::iterator begin,ListTag::iterator end) { @@ -639,11 +686,11 @@ void gdcmDicomDir::AddDicomDirPatientToEnd(ListTag::iterator begin,ListTag::iter (*itp)->AddDicomDirStudy(new gdcmDicomDirStudy(begin,end,&tagHT, &listEntries)); } } -/* +/** * \ingroup gdcmDicomDir * \brief AddDicomDirSerieToEnd - * @param begin - * @param end + * @param begin iterator on the first HeaderEntry within the chained List + * @param end iterator on the last HeaderEntry within the chained List */ void gdcmDicomDir::AddDicomDirSerieToEnd(ListTag::iterator begin,ListTag::iterator end) { @@ -661,11 +708,11 @@ void gdcmDicomDir::AddDicomDirSerieToEnd(ListTag::iterator begin,ListTag::iterat } } -/* +/** * \ingroup gdcmDicomDir * \brief AddDicomDirImageToEnd - * @param begin - * @param end + * @param begin iterator on the first HeaderEntry within the chained List + * @param end iterator on the last HeaderEntry within the chained List */ void gdcmDicomDir::AddDicomDirImageToEnd(ListTag::iterator begin,ListTag::iterator end) { @@ -689,11 +736,11 @@ void gdcmDicomDir::AddDicomDirSerieToEnd(ListTag::iterator begin,ListTag::iterat } } -/* +/** * \ingroup gdcmDicomDir * \brief for each Header of the chained list, add/update the Patient/Study/Serie/Image info - * @param path - * @param list + * @param path path of the root directory + * @param list chained list of Headers */ void gdcmDicomDir::SetElements(std::string &path, ListHeader &list) { @@ -741,11 +788,11 @@ void gdcmDicomDir::SetElements(std::string &path, ListHeader &list) } } -/* +/** * \ingroup gdcmDicomDir * \brief adds to the HTable and at the end of the Chained List * the gdcmEntries (Dicom Elements) corresponding to the given type - * @param path file Path (only used when type = GDCM_DICOMDIR_IMAGE + * @param path full path file name(only used when type = GDCM_DICOMDIR_IMAGE * @param type gdcmObject type to create (GDCM_DICOMDIR_PATIENT, GDCM_DICOMDIR_STUDY, GDCM_DICOMDIR_SERIE ...) * @param header gdcmHeader of the current file */ @@ -783,7 +830,6 @@ void gdcmDicomDir::SetElement(std::string &path,gdcmDicomDirType type,gdcmHeader { tmpGr=it->group; tmpEl=it->elem; - dictEntry=GetPubDict()->GetDictEntryByNumber(tmpGr,tmpEl); entry=new gdcmHeaderEntry(dictEntry); entry->SetOffset(0); // just to avoid missprinting @@ -795,10 +841,10 @@ void gdcmDicomDir::SetElement(std::string &path,gdcmDicomDirType type,gdcmHeader if(val==GDCM_UNFOUND) { - if((tmpGr==0x0004) &&(tmpEl==0x1130) ) - { - // TODO force the *end* File Name(remove path) - val=path; + if((tmpGr==0x0004) &&(tmpEl==0x1130) ) // File-set ID + { + // force to the *end* File Name + val=GetName(path); } else if( (tmpGr==0x0004) && (tmpEl==0x1500) ) // Only used for image { @@ -807,8 +853,9 @@ void gdcmDicomDir::SetElement(std::string &path,gdcmDicomDirType type,gdcmHeader dbg.Verbose(0, "gdcmDicomDir::SetElement : the base path of file name is incorrect"); val=header->GetFileName(); } - else - val=&(header->GetFileName()[path.length()]); + else { + val=&(header->GetFileName().c_str()[path.length()]); + } } else { @@ -827,7 +874,7 @@ void gdcmDicomDir::SetElement(std::string &path,gdcmDicomDirType type,gdcmHeader { if(dictEntry->GetGroup()==0xfffe) { - entry->SetLength(entry->GetValue().length()); //JPR + entry->SetLength(entry->GetValue().length()); } else if( (dictEntry->GetVR()=="UL") || (dictEntry->GetVR()=="SL") ) { @@ -852,13 +899,19 @@ void gdcmDicomDir::SetElement(std::string &path,gdcmDicomDirType type,gdcmHeader //wasUpdated = 1; // is private } } - +/** + * \ingroup gdcmDicomDir + * \brief compares two dgcmHeaders + */ bool gdcmDicomDir::HeaderLessThan(gdcmHeader *header1,gdcmHeader *header2) { return(*header1<*header2); } - +/** + * \ingroup gdcmDicomDir + * \brief Sets the accurate value for the (0x0004,0x1220) element of a DICOMDIR + */ void gdcmDicomDir::UpdateDirectoryRecordSequenceLength() { int offset = 0; @@ -878,7 +931,8 @@ void gdcmDicomDir::UpdateDirectoryRecordSequenceLength() { offset += 4; // delimiters don't have a value. } } - bool res=SetEntryLengthByNumber(offset, 0x0004, 0x1220); // Hope there is no dupps. + //bool res=SetEntryLengthByNumber(offset, 0x0004, 0x1220); // Hope there is no dupps. + SetEntryLengthByNumber(offset, 0x0004, 0x1220); // Hope there is no dupps. return; }