2 //-----------------------------------------------------------------------------
3 #include "gdcmDicomDir.h"
4 #include "gdcmDicomDirStudy.h"
5 #include "gdcmDicomDirSerie.h"
6 #include "gdcmDicomDirImage.h"
7 #include "gdcmDirList.h"
13 #include <sys/types.h>
22 //-----------------------------------------------------------------------------
23 // For full DICOMDIR description, see:
24 // PS 3.3-2003, pages 731-750
25 //-----------------------------------------------------------------------------
26 // Constructor / Destructor
28 * \ingroup gdcmDicomDir
29 * \brief Constructor : Parses recursively the directory and creates the DicomDir
30 * \ or uses an already built DICOMDIR, depending on 'parseDir' value
31 * @param Name name of the root directory (parseDir = true)
32 * name of the DICOMDIR (parseDir = false)
33 * @param parseDir - true if user passed an entry point
34 * and wants to explore recursively the directories
35 * - false if user passed an already built DICOMDIR file
37 * @param exception_on_error whether we want to throw an exception or not
39 gdcmDicomDir::gdcmDicomDir(const char *Name, bool parseDir,
40 bool exception_on_error):
41 gdcmParser(Name,exception_on_error,true) // true : enable SeQuences
43 // que l'on ai passe un root directory ou un DICOMDIR
44 // et quelle que soit la valeur de parseDir,
45 // on a lance gdcmParser
50 startMethodArgDelete= NULL;
51 progressMethodArgDelete=NULL;
52 endMethodArgDelete= NULL;
62 // gdcmParser already executed
63 // if user passed a root directory, sure we didn't get anything
65 if( GetListEntry().begin()==GetListEntry().end() )
67 // if parseDir == false, it should be tagged as an error
68 dbg.Verbose(0, "gdcmDicomDir::gdcmDicomDir : entry list empty");
70 if(strlen(Name)==1 && Name[0]=='.') { // user passed '.' as Name
71 // we get current directory name
72 char*dummy=(char*) malloc(1000); // TODO : check with Windoze // JPR
74 _getcwd(dummy,(size_t)1000);
76 getcwd(dummy,(size_t)1000);
78 SetFileName(dummy); // will be converted into a string
79 free(dummy); // no longer needed
84 dbg.Verbose(0, "gdcmDicomDir::gdcmDicomDir : Parse directory and create the DicomDir");
90 CheckBoundaries(); // to maintain consistency between
91 // home-made gdcmDicomDir
92 // and the ones comming from a DICOMDIR file
97 * \ingroup gdcmDicomDir
98 * \brief Constructor : creates an empty gdcmDicomDir
99 * @param exception_on_error whether we want to throw an exception or not
101 gdcmDicomDir::gdcmDicomDir(bool exception_on_error):
102 gdcmParser(exception_on_error)
105 progressMethod= NULL;
107 startMethodArgDelete= NULL;
108 progressMethodArgDelete=NULL;
109 endMethodArgDelete= NULL;
116 std::string pathBidon = ""; // Sorry, NULL not allowed ...
117 SetElement(pathBidon, GDCM_DICOMDIR_META, NULL); // Set the META elements
119 AddDicomDirMetaToEnd(listEntries.begin(),--listEntries.end());
124 * \ingroup gdcmDicomDir
125 * \brief Canonical destructor
127 gdcmDicomDir::~gdcmDicomDir()
129 SetStartMethod(NULL);
130 SetProgressMethod(NULL);
136 for(ListDicomDirPatient::iterator cc=patients.begin();cc!=patients.end();++cc)
142 //-----------------------------------------------------------------------------
145 * \ingroup gdcmDicomDir
146 * \brief Canonical Printer
148 void gdcmDicomDir::Print(std::ostream &os)
152 metaElems->SetPrintLevel(printLevel);
153 metaElems->Print(os);
155 for(ListDicomDirPatient::iterator cc=patients.begin();cc!=patients.end();++cc)
157 (*cc)->SetPrintLevel(printLevel);
162 //-----------------------------------------------------------------------------
165 * \ingroup gdcmDicomDir
166 * \brief This predicate, based on hopefully reasonable heuristics,
167 * decides whether or not the current header was properly parsed
168 * and contains the mandatory information for being considered as
169 * a well formed and usable DicomDir.
170 * @return true when gdcmParser is the one of a reasonable DicomDir,
173 bool gdcmDicomDir::IsReadable(void)
175 if(!gdcmParser::IsReadable())
179 if(patients.size()<=0)
186 * \ingroup gdcmDicomDir
187 * \brief fills the whole structure, starting from a root Directory
189 void gdcmDicomDir::ParseDirectory(void)
191 CreateDicomDirChainedList(GetFileName());
196 * \ingroup gdcmDicomDir
197 * \brief Set the start method to call when the parsing of the directory starts
198 * @param method Method to call
199 * @param arg Argument to pass to the method
200 * \warning In python : the arg parameter isn't considered
202 void gdcmDicomDir::SetStartMethod(gdcmMethod *method,void *arg,gdcmMethod *argDelete)
204 if((startArg)&&(startMethodArgDelete))
205 startMethodArgDelete(startArg);
209 startMethodArgDelete=argDelete;
213 * \ingroup gdcmDicomDir
214 * \brief Set the method to delete the argument
215 * The argument is destroyed when the method is changed or when the
217 * @param method Method to call to delete the argument
219 void gdcmDicomDir::SetStartMethodArgDelete(gdcmMethod *method)
221 startMethodArgDelete=method;
225 * \ingroup gdcmDicomDir
226 * \brief Set the progress method to call when the parsing of the directory progress
227 * @param method Method to call
228 * @param arg Argument to pass to the method
229 * \warning In python : the arg parameter isn't considered
231 void gdcmDicomDir::SetProgressMethod(gdcmMethod *method,void *arg,gdcmMethod *argDelete)
233 if((progressArg)&&(progressMethodArgDelete))
234 progressMethodArgDelete(progressArg);
236 progressMethod=method;
238 progressMethodArgDelete=argDelete;
242 * \ingroup gdcmDicomDir
243 * \brief Set the method to delete the argument
244 * The argument is destroyed when the method is changed or when the
246 * @param method Method to call to delete the argument
248 void gdcmDicomDir::SetProgressMethodArgDelete(gdcmMethod *method)
250 progressMethodArgDelete=method;
254 * \ingroup gdcmDicomDir
255 * \brief Set the end method to call when the parsing of the directory ends
256 * @param method Method to call
257 * @param arg Argument to pass to the method
258 * \warning In python : the arg parameter isn't considered
260 void gdcmDicomDir::SetEndMethod(gdcmMethod *method,void *arg,gdcmMethod *argDelete)
262 if((endArg)&&(endMethodArgDelete))
263 endMethodArgDelete(endArg);
267 endMethodArgDelete=argDelete;
271 * \ingroup gdcmDicomDir
272 * \brief Set the method to delete the argument
273 * The argument is destroyed when the method is changed or when the class
275 * @param method Method to call to delete the argument
277 void gdcmDicomDir::SetEndMethodArgDelete(gdcmMethod *method)
279 endMethodArgDelete=method;
283 * \ingroup gdcmDicomDir
284 * \brief writes on disc a DICOMDIR
285 * \ warning does NOT add the missing elements in the header :
286 * it's up to the user doing it !
287 * \todo : to be re-written using the DICOMDIR tree-like structure
288 * *not* the chained list
289 * (does NOT exist if the DICOMDIR is user-forged !)
290 * @param fileName file to be written to
291 * @return false only when fail to open
294 bool gdcmDicomDir::Write(std::string fileName)
298 fp1=fopen(fileName.c_str(),"wb");
301 printf("Failed to open(write) File [%s] \n",fileName.c_str());
306 filePreamble=(char*)calloc(128,1);
307 fwrite(filePreamble,128,1,fp1);
308 fwrite("DICM",4,1,fp1);
310 //UpdateDirectoryRecordSequenceLength(); // a reecrire en utilisant JPR
311 // la structure arborescente JPR
312 WriteDicomDirEntries(fp1);
319 * \ingroup gdcmParser
320 * \brief writes on disc according to the DICOMDIR format
321 * using the tree-like structure
322 * @param _fp already open file pointer
325 void gdcmDicomDir::WriteDicomDirEntries(FILE *_fp)
327 // TODO (?) tester les echecs en ecriture
328 // (apres chaque fwrite, dans le WriteEntry)
330 gdcmDicomDirMeta *ptrMeta;
331 ListDicomDirPatient::iterator itPatient;
332 ListDicomDirStudy::iterator itStudy;
333 ListDicomDirSerie::iterator itSerie;
334 ListDicomDirImage::iterator itImage;
337 ptrMeta= GetDicomDirMeta();
338 for(i=ptrMeta->debut();i!=ptrMeta->fin();++i) {
339 WriteEntry(*i,_fp,DICOMDIR);
342 itPatient = GetDicomDirPatients().begin();
343 while ( itPatient != GetDicomDirPatients().end() ) {
344 for(i=(*itPatient)->debut();i!=(*itPatient)->fin();++i) {
345 WriteEntry(*i,_fp,DICOMDIR);
347 itStudy = ((*itPatient)->GetDicomDirStudies()).begin();
348 while (itStudy != (*itPatient)->GetDicomDirStudies().end() ) {
349 for(i=(*itStudy)->debut();i!=(*itStudy)->fin();++i) {
350 WriteEntry(*i,_fp,DICOMDIR);
352 itSerie = ((*itStudy)->GetDicomDirSeries()).begin();
353 while (itSerie != (*itStudy)->GetDicomDirSeries().end() ) {
354 for(i=(*itSerie)->debut();i!=(*itSerie)->fin();++i) {
355 WriteEntry(*i,_fp,DICOMDIR);
357 itImage = ((*itSerie)->GetDicomDirImages()).begin();
358 while (itImage != (*itSerie)->GetDicomDirImages().end() ) {
359 for(i=(*itImage)->debut();i!=(*itImage)->fin();++i) {
360 WriteEntry(*i,_fp,DICOMDIR);
372 //-----------------------------------------------------------------------------
376 * \ingroup gdcmDicomDir
377 * \brief create a gdcmHeader-like chained list from a root Directory
378 * @param path entry point of the tree-like structure
380 void gdcmDicomDir::CreateDicomDirChainedList(std::string path)
384 gdcmDirList fileList(path,1); // gets recursively the file list
385 unsigned int count=0;
392 for(gdcmDirList::iterator it=fileList.begin();
396 progress=(float)(count+1)/(float)fileList.size();
397 CallProgressMethod();
401 header=new gdcmHeader(it->c_str());
402 if(header->IsReadable())
403 list.push_back(header); // adds the file header to the chained list
409 // sorts Patient/Study/Serie/
410 std::sort(list.begin(),list.end(),gdcmDicomDir::HeaderLessThan);
412 std::string tmp=fileList.GetDirName();
414 //for each Header of the chained list, add/update the Patient/Study/Serie/Image info
415 SetElements(tmp,list);
422 void gdcmDicomDir::CheckBoundaries()
424 ListDicomDirPatient::iterator itPatient;
425 ListDicomDirStudy::iterator itStudy;
426 ListDicomDirSerie::iterator itSerie;
427 ListDicomDirImage::iterator itImage;
428 ListTag::iterator i,j;
430 GetDicomDirMeta()->ResetBoundaries(0);
432 itPatient = GetDicomDirPatients().begin();
433 while ( itPatient != GetDicomDirPatients().end() ) {
434 (*itPatient)->ResetBoundaries(1);
435 itStudy = ((*itPatient)->GetDicomDirStudies()).begin();
436 while (itStudy != (*itPatient)->GetDicomDirStudies().end() ) {
437 (*itStudy)->ResetBoundaries(1);
438 itSerie = ((*itStudy)->GetDicomDirSeries()).begin();
439 while (itSerie != (*itStudy)->GetDicomDirSeries().end() ) {
440 (*itSerie)->ResetBoundaries(1);
441 itImage = ((*itSerie)->GetDicomDirImages()).begin();
442 while (itImage != (*itSerie)->GetDicomDirImages().end() ) {
443 (*itImage)->ResetBoundaries(1);
456 * \ingroup gdcmDicomDir
457 * \brief adds a new Patient to a partially created DICOMDIR
459 gdcmDicomDirPatient * gdcmDicomDir::NewPatient(void) {
460 std::list<gdcmElement> elemList;
461 std::list<gdcmElement>::iterator it;
463 gdcmDictEntry *dictEntry;
464 gdcmHeaderEntry *entry;
466 elemList=gdcmGlobal::GetDicomDirElements()->GetDicomDirPatientElements();
467 std::list<gdcmHeaderEntry *>::iterator debInsertion, finInsertion, i,j;
469 debInsertion = metaElems->fin();
471 finInsertion=debInsertion;
473 // for all the DicomDirPatient Elements
474 for(it=elemList.begin();it!=elemList.end();++it)
478 dictEntry=GetPubDict()->GetDictEntryByNumber(tmpGr,tmpEl);
479 entry=new gdcmHeaderEntry(dictEntry);
480 entry->SetOffset(0); // just to avoid missprinting
481 entry->SetValue(it->value);
483 if(dictEntry->GetGroup()==0xfffe)
485 entry->SetLength(entry->GetValue().length());
487 else if( (dictEntry->GetVR()=="UL") || (dictEntry->GetVR()=="SL") )
491 else if( (dictEntry->GetVR()=="US") || (dictEntry->GetVR()=="SS") )
495 else if(dictEntry->GetVR()=="SQ")
497 entry->SetLength(0xffffffff);
501 entry->SetLength(entry->GetValue().length());
504 tagHT.insert( PairHT(entry->GetKey(),entry) ); // add in the (multimap) H Table
505 listEntries.insert(debInsertion ,entry); // en tete de liste des Patients
512 gdcmDicomDirPatient *p = new gdcmDicomDirPatient(i, --debInsertion,
513 &tagHT, &listEntries);
514 patients.push_front(p);
519 * \ingroup gdcmDicomDir
520 * \brief CallStartMethod
522 void gdcmDicomDir::CallStartMethod(void)
527 startMethod(startArg);
530 * \ingroup gdcmDicomDir
531 * \brief CallProgressMethod
533 void gdcmDicomDir::CallProgressMethod(void)
536 progressMethod(progressArg);
539 * \ingroup gdcmDicomDir
540 * \brief CallEndMethod
542 void gdcmDicomDir::CallEndMethod(void)
549 //-----------------------------------------------------------------------------
552 * \ingroup gdcmDicomDir
553 * \brief create a 'gdcmDicomDir' from a DICOMDIR gdcmHeader
555 void gdcmDicomDir::CreateDicomDir()
557 // The list is parsed.
558 // When a DicomDir tag ("PATIENT", "STUDY", "SERIE", "IMAGE") is found :
559 // 1 - we save the beginning iterator
560 // 2 - we continue to parse
561 // 3 - we find an other tag
562 // + we create the object for the precedent tag
565 gdcmDicomDirType type=gdcmDicomDir::GDCM_DICOMDIR_META;
566 ListTag::iterator begin;
567 ListTag::iterator end, end2;
569 begin=listEntries.begin();
571 for(ListTag::iterator i=end;i !=listEntries.end();++i)
573 std::string v=(*i)->GetValue();
577 AddObjectToEnd(type,begin,--end2);
578 type=gdcmDicomDir::GDCM_DICOMDIR_PATIENT;
585 AddObjectToEnd(type,begin,--end2);
586 type=gdcmDicomDir::GDCM_DICOMDIR_STUDY;
593 AddObjectToEnd(type,begin,--end2);
594 type=gdcmDicomDir::GDCM_DICOMDIR_SERIE;
601 AddObjectToEnd(type,begin,--end2);
602 type=gdcmDicomDir::GDCM_DICOMDIR_IMAGE;
607 end=end2=listEntries.end();
609 AddObjectToEnd(type,begin,--end2);
612 * \ingroup gdcmDicomDir
613 * \brief AddObjectToEnd
618 void gdcmDicomDir::AddObjectToEnd(gdcmDicomDirType type,ListTag::iterator begin,ListTag::iterator end)
625 case gdcmDicomDir::GDCM_DICOMDIR_META:
626 AddDicomDirMetaToEnd(begin,end);
628 case gdcmDicomDir::GDCM_DICOMDIR_PATIENT:
629 AddDicomDirPatientToEnd(begin,end);
631 case gdcmDicomDir::GDCM_DICOMDIR_STUDY:
632 AddDicomDirStudyToEnd(begin,end);
634 case gdcmDicomDir::GDCM_DICOMDIR_SERIE:
635 AddDicomDirSerieToEnd(begin,end);
637 case gdcmDicomDir::GDCM_DICOMDIR_IMAGE:
638 AddDicomDirImageToEnd(begin,end);
644 * \ingroup gdcmDicomDir
645 * \brief Well ... Not realy to end, there is only one occurence
649 void gdcmDicomDir::AddDicomDirMetaToEnd(ListTag::iterator begin,ListTag::iterator end)
653 metaElems = new gdcmDicomDirMeta(begin,end,&tagHT,&listEntries);
657 * \ingroup gdcmDicomDir
658 * \brief AddDicomDirPatientToEnd
662 void gdcmDicomDir::AddDicomDirPatientToEnd(ListTag::iterator begin,ListTag::iterator end)
664 patients.push_back(new gdcmDicomDirPatient(begin,end,&tagHT, &listEntries));
668 * \ingroup gdcmDicomDir
669 * \brief AddDicomDirStudyToEnd
673 void gdcmDicomDir::AddDicomDirStudyToEnd(ListTag::iterator begin,ListTag::iterator end)
675 if(patients.size()>0)
677 ListDicomDirPatient::iterator itp=patients.end();
679 (*itp)->AddDicomDirStudy(new gdcmDicomDirStudy(begin,end,&tagHT, &listEntries));
683 * \ingroup gdcmDicomDir
684 * \brief AddDicomDirSerieToEnd
688 void gdcmDicomDir::AddDicomDirSerieToEnd(ListTag::iterator begin,ListTag::iterator end)
690 if(patients.size()>0)
692 ListDicomDirPatient::iterator itp=patients.end();
695 if((*itp)->GetDicomDirStudies().size()>0)
697 ListDicomDirStudy::iterator itst=(*itp)->GetDicomDirStudies().end();
699 (*itst)->AddDicomDirSerie(new gdcmDicomDirSerie(begin,end,&tagHT, &listEntries));
705 * \ingroup gdcmDicomDir
706 * \brief AddDicomDirImageToEnd
710 void gdcmDicomDir::AddDicomDirImageToEnd(ListTag::iterator begin,ListTag::iterator end)
712 if(patients.size()>0)
714 ListDicomDirPatient::iterator itp=patients.end();
717 if((*itp)->GetDicomDirStudies().size()>0)
719 ListDicomDirStudy::iterator itst=(*itp)->GetDicomDirStudies().end();
722 if((*itst)->GetDicomDirSeries().size()>0)
724 ListDicomDirSerie::iterator its=(*itst)->GetDicomDirSeries().end();
726 (*its)->AddDicomDirImage(new gdcmDicomDirImage(begin,end,&tagHT, &listEntries));
733 * \ingroup gdcmDicomDir
734 * \brief for each Header of the chained list, add/update the Patient/Study/Serie/Image info
735 * @param path path of the root directory
736 * @param list chained list of Headers
738 void gdcmDicomDir::SetElements(std::string &path, ListHeader &list)
740 std::string patPrevName="", patPrevID="";
741 std::string studPrevInstanceUID="", studPrevID="";
742 std::string serPrevInstanceUID="", serPrevID="";
744 std::string patCurName, patCurID;
745 std::string studCurInstanceUID, studCurID;
746 std::string serCurInstanceUID, serCurID;
748 SetElement(path,GDCM_DICOMDIR_META,NULL);
750 ListTag::iterator debPat=listEntries.begin();
751 for(ListHeader::iterator it=list.begin();it!=list.end();++it)
753 // get the current file characteristics
754 patCurName= (*it)->GetEntryByNumber(0x0010,0x0010);
755 patCurID= (*it)->GetEntryByNumber(0x0010,0x0011);
756 studCurInstanceUID=(*it)->GetEntryByNumber(0x0020,0x000d);
757 studCurID= (*it)->GetEntryByNumber(0x0020,0x0010);
758 serCurInstanceUID= (*it)->GetEntryByNumber(0x0020,0x000e);
759 serCurID= (*it)->GetEntryByNumber(0x0020,0x0011);
761 if(patCurName!=patPrevName || patCurID!=patPrevID)
762 SetElement(path,GDCM_DICOMDIR_PATIENT,*it);
764 // if new Study Deal with 'STUDY' Elements
765 if(studCurInstanceUID!=studPrevInstanceUID || studCurID!=studPrevID)
766 SetElement(path,GDCM_DICOMDIR_STUDY,*it);
768 // if new Serie Deal with 'SERIE' Elements
769 if(serCurInstanceUID!=serPrevInstanceUID || serCurID!=serPrevID)
770 SetElement(path,GDCM_DICOMDIR_SERIE,*it);
772 // Always Deal with 'IMAGE' Elements
773 SetElement(path,GDCM_DICOMDIR_IMAGE,*it);
775 patPrevName= patCurName;
777 studPrevInstanceUID=studCurInstanceUID;
778 studPrevID= studCurID;
779 serPrevInstanceUID= serCurInstanceUID;
785 * \ingroup gdcmDicomDir
786 * \brief adds to the HTable and at the end of the Chained List
787 * the gdcmEntries (Dicom Elements) corresponding to the given type
788 * @param path full path file name(only used when type = GDCM_DICOMDIR_IMAGE
789 * @param type gdcmObject type to create (GDCM_DICOMDIR_PATIENT, GDCM_DICOMDIR_STUDY, GDCM_DICOMDIR_SERIE ...)
790 * @param header gdcmHeader of the current file
792 void gdcmDicomDir::SetElement(std::string &path,gdcmDicomDirType type,gdcmHeader *header)
794 std::list<gdcmElement> elemList;
795 std::list<gdcmElement>::iterator it;
796 guint16 tmpGr, tmpEl;
797 gdcmDictEntry *dictEntry;
798 gdcmHeaderEntry *entry;
803 case GDCM_DICOMDIR_PATIENT:
804 elemList=gdcmGlobal::GetDicomDirElements()->GetDicomDirPatientElements();
806 case GDCM_DICOMDIR_STUDY:
807 elemList=gdcmGlobal::GetDicomDirElements()->GetDicomDirStudyElements();
809 case GDCM_DICOMDIR_SERIE:
810 elemList=gdcmGlobal::GetDicomDirElements()->GetDicomDirSerieElements();
812 case GDCM_DICOMDIR_IMAGE:
813 elemList=gdcmGlobal::GetDicomDirElements()->GetDicomDirImageElements();
815 case GDCM_DICOMDIR_META:
816 elemList=gdcmGlobal::GetDicomDirElements()->GetDicomDirMetaElements();
822 for(it=elemList.begin();it!=elemList.end();++it)
826 dictEntry=GetPubDict()->GetDictEntryByNumber(tmpGr,tmpEl);
827 entry=new gdcmHeaderEntry(dictEntry);
828 entry->SetOffset(0); // just to avoid missprinting
831 val=header->GetEntryByNumber(tmpGr,tmpEl);
835 if(val==GDCM_UNFOUND)
837 if((tmpGr==0x0004) &&(tmpEl==0x1130) ) // File-set ID
839 // force to the *end* File Name
842 else if( (tmpGr==0x0004) && (tmpEl==0x1500) ) // Only used for image
844 if(header->GetFileName().substr(0,path.length())!=path)
846 dbg.Verbose(0, "gdcmDicomDir::SetElement : the base path of file name is incorrect");
847 val=header->GetFileName();
850 val=&(header->GetFileName().c_str()[path.length()]);
860 if (header->GetEntryLengthByNumber(tmpGr,tmpEl)== 0)
864 entry->SetValue(val);
868 if(dictEntry->GetGroup()==0xfffe)
870 entry->SetLength(entry->GetValue().length());
872 else if( (dictEntry->GetVR()=="UL") || (dictEntry->GetVR()=="SL") )
876 else if( (dictEntry->GetVR()=="US") || (dictEntry->GetVR()=="SS") )
880 else if(dictEntry->GetVR()=="SQ")
882 entry->SetLength(0xffffffff);
886 entry->SetLength(entry->GetValue().length());
889 //AddHeaderEntry(entry); // both in H Table and in chained list
890 tagHT.insert( PairHT( entry->GetKey(),entry) );
891 listEntries.push_back(entry);
892 //wasUpdated = 1; // is private
896 bool gdcmDicomDir::HeaderLessThan(gdcmHeader *header1,gdcmHeader *header2)
898 return(*header1<*header2);
903 void gdcmDicomDir::UpdateDirectoryRecordSequenceLength() {
905 ListTag::iterator it;
908 for(it=listEntries.begin();it!=listEntries.end();++it) {
909 gr = (*it)->GetGroup();
910 el = (*it)->GetElement();
913 if ( (vr == "OB") || (vr == "OW") || (vr == "SQ") ) {
914 offset += 4; // explicit VR AND OB, OW, SQ : 4 more bytes
916 offset += 2 + 2 + 4 + (*it)->GetLength();
918 offset += 4; // delimiters don't have a value.
921 bool res=SetEntryLengthByNumber(offset, 0x0004, 0x1220); // Hope there is no dupps.
925 //-----------------------------------------------------------------------------