X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=blobdiff_plain;f=src%2FgdcmDocument.cxx;h=62f286563ac8bc275fb601c84a192973ab035df7;hb=224876ca6cbe71952f2a1d66d9853eca7745d3a0;hp=bb7a48e6330a04090c60bd089af320584bdc91b4;hpb=689c1285f6d44a6ea03a8bf2830327a862a26f2d;p=gdcm.git diff --git a/src/gdcmDocument.cxx b/src/gdcmDocument.cxx index bb7a48e6..62f28656 100644 --- a/src/gdcmDocument.cxx +++ b/src/gdcmDocument.cxx @@ -3,8 +3,8 @@ Program: gdcm Module: $RCSfile: gdcmDocument.cxx,v $ Language: C++ - Date: $Date: 2007/10/24 10:38:51 $ - Version: $Revision: 1.374 $ + Date: $Date: 2008/01/07 18:12:02 $ + Version: $Revision: 1.379 $ Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de l'Image). All rights reserved. See Doc/License.txt or @@ -63,6 +63,7 @@ Document::Document() SwapCode = 1234; Filetype = ExplicitVR; CurrentOffsetPosition = 0; + OffsetOfPreviousParseDES =0; // Load will set it to true if sucessfull Group0002Parsed = false; IsDocumentAlreadyLoaded = false; @@ -161,6 +162,7 @@ bool Document::DoTheLoadingDocumentJob( ) // Recursive call. // Loading is done during parsing + OffsetOfPreviousParseDES = beg; ParseDES( this, beg, lgt, false); // delim_mode is first defaulted to false if ( IsEmpty() ) @@ -281,9 +283,10 @@ bool Document::DoTheLoadingDocumentJob( ) // std::string RecCode; RecCode = GetEntryString(0x0008, 0x0010); // recognition code (RET) - if (RecCode == "ACRNEMA_LIBIDO_1.1" || - RecCode == "CANRME_AILIBOD1_1." ) // for brain-damaged softwares - // with "little-endian strings" + + if(RecCode.find("ACRNEMA_LIBIDO") == 0 || // any version + RecCode.find("CANRME_AILIBOD") == 0) // for brain-damaged softwares + // with "little-endian strings" { Filetype = ACR_LIBIDO; std::string rows = GetEntryString(0x0028, 0x0010); @@ -1038,7 +1041,7 @@ int Document::ComputeGroup0002Length( ) // (no SQ, OW, OL, UT in group 0x0002;) if ( vr == "OB" ) { - // explicit VR AND (OB, OW, OL, SQ, UT) : 4 more bytes + // explicit VR AND (OB, OW, OL, SQ, UT, UN) : 4 more bytes groupLength += 4; } groupLength += 2 + 2 + 4 + entry->GetLength(); @@ -1116,14 +1119,14 @@ void Document::ParseDES(DocEntrySet *set, long offset, { ///\todo FIXME : On 64 bits processors, tellg gives unexpected results after a while ? - /// Probabely a bug in gdcm code somwhere (some memory erased ?) + /// Probabely a bug in gdcm code somewhere (some memory erased ?) // Uncomment to track the bug -/* + if( Debug::GetDebugFlag() ) std::cout << std::dec <<"(long)(Fp->tellg()) " << (long)(Fp->tellg()) // in Debug mode << std::hex << " 0x(" <<(long)(Fp->tellg()) << ")" << std::endl; - */ + // if ( !delim_mode && ((long)(Fp->tellg())-offset) >= l_max) // Once per DocEntry if ( !delim_mode ) // 'and then' doesn't exist in C++ :-( @@ -1151,7 +1154,7 @@ void Document::ParseDES(DocEntrySet *set, long offset, if ( !first && newDocEntry->IsItemStarter() ) { // Debug message within the method ! - newDocEntry = Backtrack(newDocEntry); + newDocEntry = Backtrack(newDocEntry, set); } else { @@ -1225,7 +1228,7 @@ void Document::ParseDES(DocEntrySet *set, long offset, { /////////////////////// SeqEntry : VR = "SQ" - unsigned long l = newDocEntry->GetReadLength(); + unsigned long l = newDocEntry->GetReadLength(); if ( l != 0 ) // don't mess the delim_mode for 'zero-length sequence' { if ( l == 0xffffffff ) @@ -1324,7 +1327,9 @@ void Document::ParseDES(DocEntrySet *set, long offset, first = false; if (UnexpectedEOF) // some terminator was missing + { break; + } } // end While gdcmDebugMacro( "Exit from ParseDES, delim-mode " << delim_mode ); } @@ -1382,8 +1387,22 @@ bool Document::ParseSQ( SeqEntry *seqEntry, dlm_mod = false; } + // avoid infinite loop when Bad assumption was made on illegal 'unknown length' UN //JPRx + + if (offsetStartCurrentSQItem <= OffsetOfPreviousParseDES) + { + gdcmWarningMacro("Bad assumption was made on illegal 'unknown length' UN!" << std::endl << + "OffsetOfPreviousParseDES " << std::hex << OffsetOfPreviousParseDES + << " offsetStartCurrentSQItem " << offsetStartCurrentSQItem); + /// \todo when "Bad assumption (SQ) on illegal 'unknown length' UN", Backtrack again + try OB + return false; + } + else + { + OffsetOfPreviousParseDES = offsetStartCurrentSQItem; + } + // fill up the current SQItem, starting at the beginning of fff0,e000 - Fp->seekg(offsetStartCurrentSQItem, std::ios::beg); // Once per SQItem ParseDES(itemSQ, offsetStartCurrentSQItem, l+8, dlm_mod); offsetStartCurrentSQItem = Fp->tellg(); // Once per SQItem @@ -1405,9 +1424,10 @@ bool Document::ParseSQ( SeqEntry *seqEntry, * \brief When a private Sequence + Implicit VR is encountered * we cannot guess it's a Sequence till we find the first * Item Starter. We then backtrack to do the job. - * @param docEntry Item Starter that warned us + * @param docEntry Item Starter that warned us + * @param set DocEntrySet (ElementSet/SQItem) the DocEntry will belong */ -DocEntry *Document::Backtrack(DocEntry *docEntry) +DocEntry *Document::Backtrack(DocEntry *docEntry, DocEntrySet *set) { // delete the Item Starter, built erroneously out of any Sequence // it's not yet in the HTable/chained list @@ -1422,7 +1442,8 @@ DocEntry *Document::Backtrack(DocEntry *docEntry) gdcmDebugMacro( "Backtrack :" << std::hex << group << "|" << elem << " at offset 0x(" <RemoveEntry( PreviousDocEntry ); // forge the Seq Entry DocEntry *newEntry = NewSeqEntry(group, elem); @@ -1432,7 +1453,7 @@ DocEntry *Document::Backtrack(DocEntry *docEntry) // Move back to the beginning of the Sequence Fp->seekg(offset, std::ios::beg); // Only for Shadow Implicit VR SQ - return newEntry; + return newEntry; // It will added where it has to be! } /** @@ -1532,8 +1553,8 @@ void Document::FindDocEntryLength( DocEntry *entry ) // "7.1.2 Data element structure with explicit vr", p 27) must be // skipped before proceeding on reading the length on 4 bytes. - //Fp->seekg( 2L, std::ios::cur); // Once per OB,OW,OL,SQ DocEntry - uint32_t length32 = ReadInt32(); // Once per Ob,OW,OL,SQ DocEntry + //Fp->seekg( 2L, std::ios::cur); // Once per OB,OW,OL,UT,UN,SQ DocEntry + uint32_t length32 = ReadInt32(); // Once per OB,OW,OL,UT,UN,SQ DocEntry CurrentOffsetPosition+=4; if ( (vr == "OB" || vr == "OW" || vr == "OL") && length32 == 0xffffffff ) { @@ -1641,8 +1662,8 @@ uint32_t Document::FindDocEntryLengthOBOrOW() { gdcmWarningMacro( "Neither an Item tag nor a Sequence delimiter tag on :" - << std::hex << group << " , " << elem - << ")" ); + << std::hex << group << "|" << elem << ") Pos. on entry was 0x(" <seekg(positionOnEntry, std::ios::beg); // Once per fragment (if any) of OB,OW DataElements throw FormatUnexpected( @@ -1703,21 +1724,12 @@ VRKey Document::FindDocEntryVR() //if ( !CheckDocEntryVR(vr) ) // avoid useless function call if ( !Global::GetVR()->IsValidVR(vr) ) - { -/* -// std::cout << "================================================================Unknown VR" - << std::hex << "0x(" - << (unsigned int)vr[0] << "|" << (unsigned int)vr[1] - << ")" << "for : " << CurrentGroup - << " at offset : 0x(" << positionOnEntry << ")" - << std::endl; -*/ - gdcmWarningMacro( "Unknown VR " << std::hex << "0x(" - << (unsigned int)vr[0] << "|" << (unsigned int)vr[1] - << ")" - << " at offset : 0x(" << CurrentOffsetPosition-4<< ") for group " << CurrentGroup - ); + { + gdcmWarningMacro( "Unknown VR " << vr.GetHexaRepresentation() << std::hex + << " at offset : 0x(" << CurrentOffsetPosition-4 + << ") for group " << std::hex << CurrentGroup ); + //Fp->seekg(positionOnEntry, std::ios::beg); //JPRx //Fp->seekg((long)-2, std::ios::cur);// only for unrecognized VR (?!?) //see :MR_Philips_Intera_PrivateSequenceExplicitVR.dcm @@ -1756,7 +1768,7 @@ void Document::SkipDocEntry(DocEntry *entry) void Document::SkipToNextDocEntry(DocEntry *currentDocEntry) { long l = currentDocEntry->GetReadLength(); - if ( l == -1 ) // length = 0xffff shouldn't appear here ... + if ( (uint32_t) l == (uint32_t)-1 ) // length = 0xffff shouldn't appear here ... // ... but PMS imagers happen ! return; Fp->seekg((size_t)(currentDocEntry->GetOffset()), std::ios::beg); //FIXME :each DocEntry @@ -1791,10 +1803,12 @@ void Document::FixDocEntryFoundLength(DocEntry *entry, if ( foundLength % 2) { - gdcmWarningMacro( "Warning : Tag with uneven length " << foundLength - << " in x(" << std::hex << gr << "," << elem <<")"); + gdcmWarningMacro( "Warning : Tag (" << std::hex << gr << "|" << elem << ") with uneven length " + << std::dec << foundLength << " 0x(" << std::hex << foundLength << ") " + //<< " at offset x(" << offset << ")" + ); } - + //////// Fix for some naughty General Electric images. // Allthough not recent many such GE corrupted images are still present // on Creatis hard disks. Hence this fix shall remain when such images @@ -2269,7 +2283,7 @@ DocEntry *Document::ReadNextDocEntry() } else if ( CurrentElem == 0x0001) { - realVR = "UL"; // Private Group Length To Eng + realVR = "UL"; // Private Group Length To End } else // check the private dictionary for shadow elements when Implicit VR! { @@ -2300,15 +2314,18 @@ DocEntry *Document::ReadNextDocEntry() DictEntry *dictEntry = GetDictEntry(CurrentGroup,CurrentElem); if ( dictEntry ) { - realVR = dictEntry->GetVR(); + realVR = dictEntry->GetVR(); dictEntry->Unregister(); // GetDictEntry registered it // for VR = "UN", length is always stored on 4 bytes. + // remember this info, in order not to crash later changeFromUN=true; - /// \todo : fixme If inside a supposed to be UN DataElement (but SQ according to a private dictionnary) - /// there is some more supposed to be UN DataElements, it will probabely fail. + /// \todo : fixme If inside a vr = "UN" DataElement (but SQ according to a private dictionnary) + /// there is some more vr = "UN" DataElements, it will probabely fail. /// --> find a -non time consuming- trick to store changeFromUN info at DataElement level, /// not at the Document level. + /// --> ?!? JPR + } } @@ -2337,7 +2354,7 @@ DocEntry *Document::ReadNextDocEntry() int offset = Fp->tellg();//Only when heuristic for Explicit/Implicit was wrong gdcmWarningMacro("Entry (" << newEntry->GetKey() << ") at x(" - << offset << ") should be Explicit VR"); + << std::hex << offset << ") should be Explicit VR"); } } newEntry->SetImplicitVR();