X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=blobdiff_plain;f=src%2FgdcmDocument.cxx;h=0c4507338b017a15dcef0edde0f0c0f42f1a7bb7;hb=9862070436bb6cee0fa3afd04a86d7b5888c8f72;hp=fd3758e0eaa6d336679e9d959083c6392e9c6f60;hpb=579795c872c065c6218899aa8884138ecc613da7;p=gdcm.git diff --git a/src/gdcmDocument.cxx b/src/gdcmDocument.cxx index fd3758e0..0c450733 100644 --- a/src/gdcmDocument.cxx +++ b/src/gdcmDocument.cxx @@ -3,8 +3,8 @@ Program: gdcm Module: $RCSfile: gdcmDocument.cxx,v $ Language: C++ - Date: $Date: 2005/06/24 10:53:46 $ - Version: $Revision: 1.251 $ + Date: $Date: 2005/07/07 13:55:39 $ + Version: $Revision: 1.261 $ Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de l'Image). All rights reserved. See Doc/License.txt or @@ -31,6 +31,8 @@ #include #include #include +#include // for isdigit +#include // for atoi namespace gdcm { @@ -77,7 +79,7 @@ Document::Document( std::string const &fileName ) SwapCode = 1234; Filetype = ExplicitVR; Group0002Parsed = false; - LoadMode = 0x00000000; // Load everything + LoadMode = 0x00000000; // Load everything, later // Load will set it to true if sucessfull IsDocumentAlreadyLoaded = false; @@ -104,16 +106,25 @@ Document::~Document () */ bool Document::Load( std::string const &fileName ) { - // We should clean out anything that already exists. - // Check IsDocumentAlreadyLoaded to be sure. if ( IsDocumentAlreadyLoaded ) { + // time waste hunting + // if ( Filename == fileName ) + // { + // gdcmWarningMacro( "The file was already parsed inside this " + // << "gdcm::Document (its name is: " + // << Filename.c_str() ); + // return true; + // } + gdcmWarningMacro( "A file was already parsed inside this " << "gdcm::Document (previous name was: " << Filename.c_str() << ". New name is :" << fileName ); - // todo : clean out the 'Document' - // Should we call ClearEntry() on the parent object ?!? + // clean out the Entries, if already parsed + // (probabely a mistake from the user) + + ClearEntry(); } Filename = fileName; @@ -151,7 +162,9 @@ bool Document::Load( std::string const &fileName ) lgt -= beg; // remaining length to parse - ParseDES( this, beg, lgt, false); // Loading is done during parsing + // Recursive call. + // Loading is done during parsing + ParseDES( this, beg, lgt, false); // delim_mode is first defaulted to false if ( IsEmpty() ) { @@ -184,7 +197,7 @@ bool Document::Load( std::string const &fileName ) /// altered on PURPOSE but now contains a WRONG value. /// In order to fix things and restore the dictionary to its /// correct value, one needs to decided of the semantics by deciding - /// whether the following tags are either: + /// whether the following tags are either : /// - multivaluated US, and hence loaded as ValEntry, but afterwards /// also used as BinEntry, which requires the proper conversion, /// - OW, and hence loaded as BinEntry, but afterwards also used @@ -224,7 +237,7 @@ bool Document::Load( std::string const &fileName ) // ---------------------------- // Specific code to allow gdcm to read ACR-LibIDO formated images // Note: ACR-LibIDO is an extension of the ACR standard that was - // used at CREATIS. For the time being (say a couple years) + // used at CREATIS. For the time being (say a couple of years) // we keep this kludge to allow CREATIS users // reading their old images. // @@ -852,9 +865,9 @@ void Document::Initialize() /** * \brief Parses a DocEntrySet (Zero-level DocEntries or SQ Item DocEntries) - * @param set DocEntrySet we are going to parse ('zero level' or a SQItem) + * @param set DocEntrySet we are going to parse ('zero level' or a SQItem) * @param offset start of parsing - * @param l_max length to parse + * @param l_max length to parse (meaningless when we are in 'delimitor mode') * @param delim_mode : whether we are in 'delimitor mode' (l=0xffffff) or not */ void Document::ParseDES(DocEntrySet *set, long offset, @@ -866,6 +879,7 @@ void Document::ParseDES(DocEntrySet *set, long offset, SeqEntry *newSeqEntry; VRKey vr; bool used; + bool delim_mode_intern = delim_mode; while (true) { @@ -874,7 +888,6 @@ void Document::ParseDES(DocEntrySet *set, long offset, break; } - used = true; newDocEntry = ReadNextDocEntry( ); if ( !newDocEntry ) @@ -882,15 +895,16 @@ void Document::ParseDES(DocEntrySet *set, long offset, break; } - vr = newDocEntry->GetVR(); + used = true; newValEntry = dynamic_cast(newDocEntry); newBinEntry = dynamic_cast(newDocEntry); - newSeqEntry = dynamic_cast(newDocEntry); - if ( newValEntry || newBinEntry ) + if ( newValEntry || newBinEntry ) { + //////////////////////////// ContentEntry if ( newBinEntry ) { + vr = newDocEntry->GetVR(); if ( Filetype == ExplicitVR && !Global::GetVR()->IsVROfBinaryRepresentable(vr) ) { @@ -902,6 +916,7 @@ void Document::ParseDES(DocEntrySet *set, long offset, } //////////////////// BinEntry or UNKOWN VR: + // When "this" is a Document the Key is simply of the // form ( group, elem )... if ( dynamic_cast< Document* > ( set ) ) @@ -911,20 +926,26 @@ void Document::ParseDES(DocEntrySet *set, long offset, // but when "this" is a SQItem, we are inserting this new // valEntry in a sequence item, and the key has the // generalized form (refer to \ref BaseTagKey): - if (SQItem *parentSQItem = dynamic_cast< SQItem* > ( set ) ) - { - newBinEntry->SetKey( parentSQItem->GetBaseTagKey() - + newBinEntry->GetKey() ); - } - LoadDocEntry( newBinEntry ); + // time waste hunting + //if (SQItem *parentSQItem = dynamic_cast< SQItem* > ( set ) ) + //{ + // newBinEntry->SetKey( parentSQItem->GetBaseTagKey() + // + newBinEntry->GetKey() ); + //} + if ( !set->AddEntry( newBinEntry ) ) { - //Expect big troubles if here - //delete newBinEntry; - used=false; + gdcmWarningMacro( "in ParseDES : cannot add a BinEntry " + << newBinEntry->GetKey() ); + used=false; } - } + else + { + // Load only if we can add (not a duplicate key) + LoadDocEntry( newBinEntry ); + } + } // end BinEntry else { /////////////////////// ValEntry @@ -938,14 +959,13 @@ void Document::ParseDES(DocEntrySet *set, long offset, // ...but when "set" is a SQItem, we are inserting this new // valEntry in a sequence item. Hence the key has the // generalized form (refer to \ref BaseTagKey): - if (SQItem *parentSQItem = dynamic_cast< SQItem* > ( set ) ) - { - newValEntry->SetKey( parentSQItem->GetBaseTagKey() - + newValEntry->GetKey() ); - } - - LoadDocEntry( newValEntry ); - bool delimitor=newValEntry->IsItemDelimitor(); + + // time waste hunting + //if (SQItem *parentSQItem = dynamic_cast< SQItem* > ( set ) ) + //{ + // newValEntry->SetKey( parentSQItem->GetBaseTagKey() + // + newValEntry->GetKey() ); + //} if ( LoadMode & NO_SHADOW ) // User asked to skip, if possible, // shadow groups ( if possible : @@ -970,18 +990,20 @@ void Document::ParseDES(DocEntrySet *set, long offset, if ( !set->AddEntry( newValEntry ) ) { - // If here expect big troubles - // delete newValEntry; //otherwise mem leak + gdcmWarningMacro( "in ParseDES : cannot add a ValEntry " + << newValEntry->GetKey() ); used=false; } - - if (delimitor) + else { - if ( !used ) - delete newDocEntry; - break; + // Load only if we can add (not a duplicate key) + LoadDocEntry( newValEntry ); } - if ( !delim_mode && ((long)(Fp->tellg())-offset) >= l_max ) + + bool delimitor=newValEntry->IsItemDelimitor(); + + if ( delimitor || + (!delim_mode && ((long)(Fp->tellg())-offset) >= l_max) ) { if ( !used ) delete newDocEntry; @@ -994,29 +1016,43 @@ void Document::ParseDES(DocEntrySet *set, long offset, } else { - // VR = "SQ" + /////////////////////// SeqEntry : VR = "SQ" + unsigned long l = newDocEntry->GetReadLength(); - if ( l != 0 ) // don't mess the delim_mode for zero-length sequence + if ( l != 0 ) // don't mess the delim_mode for 'zero-length sequence' { if ( l == 0xffffffff ) { - delim_mode = true; + delim_mode_intern = true; } else { - delim_mode = false; + delim_mode_intern = false; } } - - if ( (LoadMode & NO_SEQ) && ! delim_mode ) // User asked to skip SQ + + if ( (LoadMode & NO_SHADOWSEQ) && ! delim_mode_intern ) + { + // User asked to skip SeQuences *only* if they belong to Shadow Group + if ( newDocEntry->GetGroup()%2 != 0 ) + { + Fp->seekg( l, std::ios::cur); + used = false; + continue; + } + } + if ( (LoadMode & NO_SEQ) && ! delim_mode_intern ) { + // User asked to skip *any* SeQuence Fp->seekg( l, std::ios::cur); used = false; continue; - } + } + // delay the dynamic cast as late as possible + newSeqEntry = dynamic_cast(newDocEntry); - // no other way to create it ... - newSeqEntry->SetDelimitorMode( delim_mode ); + // no other way to create the Delimitor ... + newSeqEntry->SetDelimitorMode( delim_mode_intern ); // At the top of the hierarchy, stands a Document. When "set" // is a Document, then we are building the first depth level. @@ -1030,35 +1066,40 @@ void Document::ParseDES(DocEntrySet *set, long offset, // But when "set" is already a SQItem, we are building a nested // sequence, and hence the depth level of the new SeqEntry // we are building, is one level deeper: + + // time waste hunting if (SQItem *parentSQItem = dynamic_cast< SQItem* > ( set ) ) { newSeqEntry->SetDepthLevel( parentSQItem->GetDepthLevel() + 1 ); - newSeqEntry->SetKey( parentSQItem->GetBaseTagKey() - + newSeqEntry->GetKey() ); + + // newSeqEntry->SetKey( parentSQItem->GetBaseTagKey() + // + newSeqEntry->GetKey() ); } if ( l != 0 ) { // Don't try to parse zero-length sequences ParseSQ( newSeqEntry, newDocEntry->GetOffset(), - l, delim_mode); + l, delim_mode_intern); } if ( !set->AddEntry( newSeqEntry ) ) { + gdcmWarningMacro( "in ParseDES : cannot add a SeqEntry " + << newSeqEntry->GetKey() ); used = false; } - + if ( !delim_mode && ((long)(Fp->tellg())-offset) >= l_max) { if ( !used ) delete newDocEntry; break; } - } + } // end SeqEntry : VR = "SQ" if ( !used ) delete newDocEntry; - } + } // end While } /** @@ -1080,6 +1121,7 @@ void Document::ParseSQ( SeqEntry *seqEntry, if ( !newDocEntry ) { // FIXME Should warn user + gdcmWarningMacro("in ParseSQ : should never get here!"); break; } if ( delim_mode ) @@ -1097,12 +1139,14 @@ void Document::ParseSQ( SeqEntry *seqEntry, } // create the current SQItem SQItem *itemSQ = new SQItem( seqEntry->GetDepthLevel() ); +/* std::ostringstream newBase; newBase << seqEntry->GetKey() << "/" << SQItemNumber << "#"; itemSQ->SetBaseTagKey( newBase.str() ); +*/ unsigned int l = newDocEntry->GetReadLength(); if ( l == 0xffffffff ) @@ -1119,7 +1163,9 @@ void Document::ParseSQ( SeqEntry *seqEntry, delete newDocEntry; Fp->seekg(offsetStartCurrentSQItem, std::ios::beg); // fill up the current SQItem, starting at the beginning of fff0,e000 + ParseDES(itemSQ, offsetStartCurrentSQItem, l+8, dlm_mod); + offsetStartCurrentSQItem = Fp->tellg(); // end try ----------------- @@ -1163,7 +1209,7 @@ void Document::LoadDocEntry(DocEntry *entry) } // The elements whose length is bigger than the specified upper bound - // are not loaded. Instead we leave a short notice of the offset of + // are not loaded. Instead we leave a short notice on the offset of // the element content and it's length. std::ostringstream s; @@ -2015,11 +2061,11 @@ void Document::SetMaxSizeLoadEntry(long newSize) } /** - * \brief Read the next tag but WITHOUT loading it's value + * \brief Read the next tag WITHOUT loading it's value * (read the 'Group Number', the 'Element Number', * gets the Dict Entry * gets the VR, gets the length, gets the offset value) - * @return On succes the newly created DocEntry, NULL on failure. + * @return On succes : the newly created DocEntry, NULL on failure. */ DocEntry *Document::ReadNextDocEntry() { @@ -2078,7 +2124,7 @@ DocEntry *Document::ReadNextDocEntry() { std::string msg; int offset = Fp->tellg(); - msg = Util::Format("Entry (%04x,%04x) at %x should be Explicit VR\n", + msg = Util::Format("Entry (%04x,%04x) at 0x(%x) should be Explicit VR\n", newEntry->GetGroup(), newEntry->GetElement(), offset ); gdcmWarningMacro( msg.c_str() ); } @@ -2104,8 +2150,8 @@ DocEntry *Document::ReadNextDocEntry() /** * \brief Handle broken private tag from Philips NTSCAN - * where the endianess is being switch to BigEndian for no - * apparent reason + * where the endianess is being switched to BigEndian + * for no apparent reason * @return no return */ void Document::HandleBrokenEndian(uint16_t &group, uint16_t &elem)