X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=blobdiff_plain;f=src%2FgdcmDocument.cxx;h=d89207dd94097aea20b18bc77ec6e7a595b783cf;hb=7059f7f1ad9d1466d7b752a40cfeb95ba81aa3d8;hp=2c705af22df48a1ece6ea8bedfeec4c28ea465ff;hpb=327dfe7647e3720b0f3125f9b19397cb9afc0ed3;p=gdcm.git diff --git a/src/gdcmDocument.cxx b/src/gdcmDocument.cxx index 2c705af2..d89207dd 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/01/06 20:03:27 $ - Version: $Revision: 1.161 $ + Date: $Date: 2005/01/10 17:17:52 $ + Version: $Revision: 1.171 $ Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de l'Image). All rights reserved. See Doc/License.txt or @@ -47,7 +47,7 @@ namespace gdcm static const char *TransferSyntaxStrings[] = { // Implicit VR Little Endian "1.2.840.10008.1.2", - // Implicit VR Big Endian DLX G.E? + // Implicit VR Big Endian DLX (G.E Private) "1.2.840.113619.5.2", // Explicit VR Little Endian "1.2.840.10008.1.2.1", @@ -106,8 +106,7 @@ Document::Document( std::string const &filename ) : ElementSet(-1) return; } - dbg.Verbose(0, "Document::Document: starting parsing of file: ", - Filename.c_str()); + gdcmVerboseMacro( "Starting parsing of file: " << Filename.c_str()); Fp->seekg( 0, std::ios::beg); Fp->seekg(0, std::ios::end); @@ -124,7 +123,7 @@ Document::Document( std::string const &filename ) : ElementSet(-1) // Load 'non string' values - std::string PhotometricInterpretation = GetEntryByNumber(0x0028,0x0004); + std::string PhotometricInterpretation = GetEntry(0x0028,0x0004); if( PhotometricInterpretation == "PALETTE COLOR " ) { LoadEntryBinArea(0x0028,0x1200); // gray LUT @@ -170,16 +169,16 @@ Document::Document( std::string const &filename ) : ElementSet(-1) // we switch lineNumber and columnNumber // std::string RecCode; - RecCode = GetEntryByNumber(0x0008, 0x0010); // recognition code + RecCode = GetEntry(0x0008, 0x0010); // recognition code if (RecCode == "ACRNEMA_LIBIDO_1.1" || RecCode == "CANRME_AILIBOD1_1." ) // for brain-damaged softwares // with "little-endian strings" { Filetype = ACR_LIBIDO; - std::string rows = GetEntryByNumber(0x0028, 0x0010); - std::string columns = GetEntryByNumber(0x0028, 0x0011); - SetEntryByNumber(columns, 0x0028, 0x0010); - SetEntryByNumber(rows , 0x0028, 0x0011); + std::string rows = GetEntry(0x0028, 0x0010); + std::string columns = GetEntry(0x0028, 0x0011); + SetEntry(columns, 0x0028, 0x0010); + SetEntry(rows , 0x0028, 0x0011); } // ----------------- End of ACR-LibIDO kludge ------------------ } @@ -283,14 +282,13 @@ bool Document::IsReadable() { if( Filetype == Unknown) { - dbg.Verbose(0, "Document::IsReadable: wrong filetype"); + gdcmVerboseMacro( "Wrong filetype"); return false; } if( TagHT.empty() ) { - dbg.Verbose(0, "Document::IsReadable: no tags in internal" - " hash table."); + gdcmVerboseMacro( "No tags in internal hash table."); return false; } @@ -305,7 +303,7 @@ bool Document::IsReadable() */ TransferSyntaxType Document::GetTransferSyntax() { - DocEntry *entry = GetDocEntryByNumber(0x0002, 0x0010); + DocEntry *entry = GetDocEntry(0x0002, 0x0010); if ( !entry ) { return UnknownTS; @@ -397,7 +395,7 @@ bool Document::IsDicomV3() // Anyway, it's to late check if the 'Preamble' was found ... // And ... would it be a rich idea to check ? // (some 'no Preamble' DICOM images exist !) - return GetDocEntryByNumber(0x0002, 0x0010) != NULL; + return GetDocEntry(0x0002, 0x0010) != NULL; } /** @@ -424,17 +422,13 @@ std::ifstream *Document::OpenFile() if(Fp) { - dbg.Verbose( 0, - "Document::OpenFile is already opened when opening: ", - Filename.c_str()); + gdcmVerboseMacro( "Is already opened when opening: " << Filename.c_str()); } Fp = new std::ifstream(Filename.c_str(), std::ios::in | std::ios::binary); if( ! *Fp ) { - dbg.Verbose( 0, - "Document::OpenFile cannot open file: ", - Filename.c_str()); + gdcmVerboseMacro( "Cannot open file: " << Filename.c_str()); delete Fp; Fp = 0; return 0; @@ -455,6 +449,9 @@ std::ifstream *Document::OpenFile() zero == 0x0005 || zero == 0x0500 || zero == 0x0006 || zero == 0x0600 || zero == 0x0007 || zero == 0x0700 || zero == 0x0008 || zero == 0x0800 ) { + std::string msg + = Util::Format("ACR/DICOM with no preamble: (%04x)\n", zero); + gdcmVerboseMacro( msg.c_str() ); return Fp; } @@ -473,9 +470,7 @@ std::ifstream *Document::OpenFile() } CloseFile(); - dbg.Verbose( 0, - "Document::OpenFile not DICOM/ACR (missing preamble)", - Filename.c_str()); + gdcmVerboseMacro( "Not DICOM/ACR (missing preamble)" << Filename.c_str()); return 0; } @@ -544,13 +539,13 @@ void Document::WriteContent(std::ofstream *fp, FileType filetype) * \return pointer to the modified/created Header Entry (NULL when creation * failed). */ -ValEntry *Document::ReplaceOrCreateByNumber(std::string const &value, - uint16_t group, - uint16_t elem, - TagName const &vr ) +ValEntry *Document::ReplaceOrCreate(std::string const &value, + uint16_t group, + uint16_t elem, + TagName const &vr ) { ValEntry *valEntry = 0; - DocEntry *currentEntry = GetDocEntryByNumber( group, elem); + DocEntry *currentEntry = GetDocEntry( group, elem); if (currentEntry) { @@ -566,8 +561,7 @@ ValEntry *Document::ReplaceOrCreateByNumber(std::string const &value, { if (!RemoveEntry(currentEntry)) { - dbg.Verbose(0, "Document::ReplaceOrCreateByNumber: removal" - " of previous DocEntry failed."); + gdcmVerboseMacro( "Removal of previous DocEntry failed."); return NULL; } @@ -577,12 +571,11 @@ ValEntry *Document::ReplaceOrCreateByNumber(std::string const &value, // Create a new valEntry if necessary if (!valEntry) { - valEntry = NewValEntryByNumber(group, elem, vr); + valEntry = NewValEntry(group, elem, vr); if ( !AddEntry(valEntry)) { - dbg.Verbose(0, "Document::ReplaceOrCreateByNumber: AddEntry" - " failed allthough this is a creation."); + gdcmVerboseMacro("AddEntry failed although this is a creation."); delete valEntry; return NULL; @@ -605,14 +598,14 @@ ValEntry *Document::ReplaceOrCreateByNumber(std::string const &value, * \return pointer to the modified/created Header Entry (NULL when creation * failed). */ -BinEntry *Document::ReplaceOrCreateByNumber(uint8_t *binArea, - int lgth, - uint16_t group, - uint16_t elem, - TagName const &vr ) +BinEntry *Document::ReplaceOrCreate(uint8_t *binArea, + int lgth, + uint16_t group, + uint16_t elem, + TagName const &vr ) { BinEntry *binEntry = 0; - DocEntry *currentEntry = GetDocEntryByNumber( group, elem); + DocEntry *currentEntry = GetDocEntry( group, elem); // Verify the currentEntry if (currentEntry) @@ -629,8 +622,7 @@ BinEntry *Document::ReplaceOrCreateByNumber(uint8_t *binArea, { if (!RemoveEntry(currentEntry)) { - dbg.Verbose(0, "Document::ReplaceOrCreateByNumber: removal" - " of previous DocEntry failed."); + gdcmVerboseMacro( "Removal of previous DocEntry failed."); return NULL; } @@ -640,12 +632,11 @@ BinEntry *Document::ReplaceOrCreateByNumber(uint8_t *binArea, // Create a new binEntry if necessary if (!binEntry) { - binEntry = NewBinEntryByNumber(group, elem, vr); + binEntry = NewBinEntry(group, elem, vr); if ( !AddEntry(binEntry)) { - dbg.Verbose(0, "Document::ReplaceOrCreateByNumber: AddEntry" - " failed allthough this is a creation."); + gdcmVerboseMacro( "AddEntry failed allthough this is a creation."); delete binEntry; return NULL; @@ -682,10 +673,10 @@ BinEntry *Document::ReplaceOrCreateByNumber(uint8_t *binArea, * \return pointer to the modified/created SeqEntry (NULL when creation * failed). */ -SeqEntry *Document::ReplaceOrCreateByNumber( uint16_t group, uint16_t elem) +SeqEntry *Document::ReplaceOrCreate( uint16_t group, uint16_t elem) { SeqEntry *seqEntry = 0; - DocEntry *currentEntry = GetDocEntryByNumber( group, elem); + DocEntry *currentEntry = GetDocEntry( group, elem); // Verify the currentEntry if (currentEntry) @@ -702,8 +693,7 @@ SeqEntry *Document::ReplaceOrCreateByNumber( uint16_t group, uint16_t elem) { if (!RemoveEntry(currentEntry)) { - dbg.Verbose(0, "Document::ReplaceOrCreateByNumber: removal" - " of previous DocEntry failed."); + gdcmVerboseMacro( "Removal of previous DocEntry failed."); return NULL; } @@ -713,12 +703,11 @@ SeqEntry *Document::ReplaceOrCreateByNumber( uint16_t group, uint16_t elem) // Create a new seqEntry if necessary if (!seqEntry) { - seqEntry = NewSeqEntryByNumber(group, elem); + seqEntry = NewSeqEntry(group, elem); if ( !AddEntry(seqEntry)) { - dbg.Verbose(0, "Document::ReplaceOrCreateByNumber: AddEntry" - " failed allthough this is a creation."); + gdcmVerboseMacro( "AddEntry failed allthough this is a creation."); delete seqEntry; return NULL; @@ -736,10 +725,10 @@ SeqEntry *Document::ReplaceOrCreateByNumber( uint16_t group, uint16_t elem) * @param elem element number of the Entry * \return boolean */ -bool Document::ReplaceIfExistByNumber(std::string const &value, - uint16_t group, uint16_t elem ) +bool Document::ReplaceIfExist(std::string const &value, + uint16_t group, uint16_t elem ) { - SetEntryByNumber(value, group, elem); + SetEntry(value, group, elem); return true; } @@ -758,57 +747,12 @@ std::string Document::GetTransferSyntaxValue(TransferSyntaxType type) * @param element Element number of the searched Dicom Element * @return true is found */ -bool Document::CheckIfEntryExistByNumber(uint16_t group, uint16_t element ) +bool Document::CheckIfEntryExist(uint16_t group, uint16_t element ) { const std::string &key = DictEntry::TranslateToKey(group, element ); return TagHT.count(key) != 0; } -/** - * \brief Searches within Header Entries (Dicom Elements) parsed with - * the public and private dictionaries - * for the element value of a given tag. - * \warning Don't use any longer : use GetPubEntryByName - * @param tagName name of the searched element. - * @return Corresponding element value when it exists, - * and the string GDCM_UNFOUND ("gdcm::Unfound") otherwise. - */ -std::string Document::GetEntryByName(TagName const &tagName) -{ - DictEntry *dictEntry = RefPubDict->GetDictEntryByName(tagName); - if( !dictEntry ) - { - return GDCM_UNFOUND; - } - - return GetEntryByNumber(dictEntry->GetGroup(),dictEntry->GetElement()); -} - -/** - * \brief Searches within Header Entries (Dicom Elements) parsed with - * the public and private dictionaries - * for the element value representation of a given tag. - * - * Obtaining the VR (Value Representation) might be needed by caller - * to convert the string typed content to caller's native type - * (think of C++ vs Python). The VR is actually of a higher level - * of semantics than just the native C++ type. - * @param tagName name of the searched element. - * @return Corresponding element value representation when it exists, - * and the string GDCM_UNFOUND ("gdcm::Unfound") otherwise. - */ -std::string Document::GetEntryVRByName(TagName const& tagName) -{ - DictEntry *dictEntry = RefPubDict->GetDictEntryByName(tagName); - if( dictEntry == NULL) - { - return GDCM_UNFOUND; - } - - DocEntry *elem = GetDocEntryByNumber(dictEntry->GetGroup(), - dictEntry->GetElement()); - return elem->GetVR(); -} /** * \brief Searches within Header Entries (Dicom Elements) parsed with @@ -819,7 +763,7 @@ std::string Document::GetEntryVRByName(TagName const& tagName) * @return Corresponding element value representation when it exists, * and the string GDCM_UNFOUND ("gdcm::Unfound") otherwise. */ -std::string Document::GetEntryByNumber(uint16_t group, uint16_t element) +std::string Document::GetEntry(uint16_t group, uint16_t element) { TagKey key = DictEntry::TranslateToKey(group, element); if ( !TagHT.count(key)) @@ -844,9 +788,9 @@ std::string Document::GetEntryByNumber(uint16_t group, uint16_t element) * @return Corresponding element value representation when it exists, * and the string GDCM_UNFOUND ("gdcm::Unfound") otherwise. */ -std::string Document::GetEntryVRByNumber(uint16_t group, uint16_t element) +std::string Document::GetEntryVR(uint16_t group, uint16_t element) { - DocEntry *elem = GetDocEntryByNumber(group, element); + DocEntry *elem = GetDocEntry(group, element); if ( !elem ) { return GDCM_UNFOUND; @@ -862,33 +806,15 @@ std::string Document::GetEntryVRByNumber(uint16_t group, uint16_t element) * @param element Element number of the searched tag. * @return Corresponding element length; -2 if not found */ -int Document::GetEntryLengthByNumber(uint16_t group, uint16_t element) +int Document::GetEntryLength(uint16_t group, uint16_t element) { - DocEntry *elem = GetDocEntryByNumber(group, element); + DocEntry *elem = GetDocEntry(group, element); if ( !elem ) { return -2; //magic number } return elem->GetLength(); } -/** - * \brief Sets the value (string) of the Header Entry (Dicom Element) - * @param content string value of the Dicom Element - * @param tagName name of the searched Dicom Element. - * @return true when found - */ -bool Document::SetEntryByName( std::string const &content, - TagName const &tagName) -{ - DictEntry *dictEntry = RefPubDict->GetDictEntryByName(tagName); - if( !dictEntry ) - { - return false; - } - - return SetEntryByNumber(content,dictEntry->GetGroup(), - dictEntry->GetElement()); -} /** * \brief Accesses an existing DocEntry (i.e. a Dicom Element) @@ -898,14 +824,13 @@ bool Document::SetEntryByName( std::string const &content, * @param group group number of the Dicom Element to modify * @param element element number of the Dicom Element to modify */ -bool Document::SetEntryByNumber(std::string const& content, - uint16_t group, uint16_t element) +bool Document::SetEntry(std::string const& content, + uint16_t group, uint16_t element) { - ValEntry *entry = GetValEntryByNumber(group, element); + ValEntry *entry = GetValEntry(group, element); if (!entry ) { - dbg.Verbose(0, "Document::SetEntryByNumber: no corresponding", - " ValEntry (try promotion first)."); + gdcmVerboseMacro( "No corresponding ValEntry (try promotion first)."); return false; } return SetEntry(content,entry); @@ -920,14 +845,13 @@ bool Document::SetEntryByNumber(std::string const& content, * @param group group number of the Dicom Element to modify * @param element element number of the Dicom Element to modify */ -bool Document::SetEntryByNumber(uint8_t*content, int lgth, - uint16_t group, uint16_t element) +bool Document::SetEntry(uint8_t*content, int lgth, + uint16_t group, uint16_t element) { - BinEntry *entry = GetBinEntryByNumber(group, element); + BinEntry *entry = GetBinEntry(group, element); if (!entry ) { - dbg.Verbose(0, "Document::SetEntryByNumber: no corresponding", - " ValEntry (try promotion first)."); + gdcmVerboseMacro( "No corresponding ValEntry (try promotion first)."); return false; } @@ -983,12 +907,12 @@ bool Document::SetEntry(uint8_t *content, int lgth, BinEntry *entry) * @param elem element number of the Entry * @return Pointer to the 'non string' area */ -void *Document::GetEntryBinAreaByNumber(uint16_t group, uint16_t elem) +void *Document::GetEntryBinArea(uint16_t group, uint16_t elem) { - DocEntry *entry = GetDocEntryByNumber(group, elem); + DocEntry *entry = GetDocEntry(group, elem); if (!entry) { - dbg.Verbose(1, "Document::GetDocEntryByNumber: no entry"); + gdcmVerboseMacro( "No entry"); return 0; } if ( BinEntry *binEntry = dynamic_cast(entry) ) @@ -1008,7 +932,7 @@ void *Document::GetEntryBinAreaByNumber(uint16_t group, uint16_t elem) void Document::LoadEntryBinArea(uint16_t group, uint16_t elem) { // Search the corresponding DocEntry - DocEntry *docElement = GetDocEntryByNumber(group, elem); + DocEntry *docElement = GetDocEntry(group, elem); if ( !docElement ) return; @@ -1040,7 +964,7 @@ void Document::LoadEntryBinArea(BinEntry *element) uint8_t *a = new uint8_t[l]; if( !a ) { - dbg.Verbose(0, "Document::LoadEntryBinArea cannot allocate a"); + gdcmVerboseMacro( "Cannot allocate a"); return; } @@ -1065,10 +989,10 @@ void Document::LoadEntryBinArea(BinEntry *element) * @param element Element number of the searched Dicom Element * @return */ -/*bool Document::SetEntryBinAreaByNumber(uint8_t *area, - uint16_t group, uint16_t element) +/*bool Document::SetEntryBinArea(uint8_t *area, + uint16_t group, uint16_t element) { - DocEntry *currentEntry = GetDocEntryByNumber(group, element); + DocEntry *currentEntry = GetDocEntry(group, element); if ( !currentEntry ) { return false; @@ -1083,24 +1007,6 @@ void Document::LoadEntryBinArea(BinEntry *element) return false; }*/ -/** - * \brief Searches within the Header Entries for a Dicom Element of - * a given tag. - * @param tagName name of the searched Dicom Element. - * @return Corresponding Dicom Element when it exists, and NULL - * otherwise. - */ -DocEntry *Document::GetDocEntryByName(TagName const &tagName) -{ - DictEntry *dictEntry = RefPubDict->GetDictEntryByName(tagName); - if( !dictEntry ) - { - return NULL; - } - - return GetDocEntryByNumber(dictEntry->GetGroup(),dictEntry->GetElement()); -} - /** * \brief retrieves a Dicom Element (the first one) using (group, element) * \warning (group, element) IS NOT an identifier inside the Dicom Header @@ -1111,7 +1017,7 @@ DocEntry *Document::GetDocEntryByName(TagName const &tagName) * @param element Element number of the searched Dicom Element * @return */ -DocEntry *Document::GetDocEntryByNumber(uint16_t group, uint16_t element) +DocEntry *Document::GetDocEntry(uint16_t group, uint16_t element) { TagKey key = DictEntry::TranslateToKey(group, element); if ( !TagHT.count(key)) @@ -1122,14 +1028,14 @@ DocEntry *Document::GetDocEntryByNumber(uint16_t group, uint16_t element) } /** - * \brief Same as \ref Document::GetDocEntryByNumber except it only + * \brief Same as \ref Document::GetDocEntry except it only * returns a result when the corresponding entry is of type * ValEntry. * @return When present, the corresponding ValEntry. */ -ValEntry *Document::GetValEntryByNumber(uint16_t group, uint16_t element) +ValEntry *Document::GetValEntry(uint16_t group, uint16_t element) { - DocEntry *currentEntry = GetDocEntryByNumber(group, element); + DocEntry *currentEntry = GetDocEntry(group, element); if ( !currentEntry ) { return 0; @@ -1138,20 +1044,20 @@ ValEntry *Document::GetValEntryByNumber(uint16_t group, uint16_t element) { return entry; } - dbg.Verbose(0, "Document::GetValEntryByNumber: unfound ValEntry."); + gdcmVerboseMacro( "Unfound ValEntry."); return 0; } /** - * \brief Same as \ref Document::GetDocEntryByNumber except it only + * \brief Same as \ref Document::GetDocEntry except it only * returns a result when the corresponding entry is of type * BinEntry. * @return When present, the corresponding BinEntry. */ -BinEntry *Document::GetBinEntryByNumber(uint16_t group, uint16_t element) +BinEntry *Document::GetBinEntry(uint16_t group, uint16_t element) { - DocEntry *currentEntry = GetDocEntryByNumber(group, element); + DocEntry *currentEntry = GetDocEntry(group, element); if ( !currentEntry ) { return 0; @@ -1160,7 +1066,7 @@ BinEntry *Document::GetBinEntryByNumber(uint16_t group, uint16_t element) { return entry; } - dbg.Verbose(0, "Document::GetBinEntryByNumber: unfound BinEntry."); + gdcmVerboseMacro( "Unfound BinEntry."); return 0; } @@ -1207,7 +1113,7 @@ uint32_t Document::SwapLong(uint32_t a) break; default : //std::cout << "swapCode= " << SwapCode << std::endl; - dbg.Error(" Document::SwapLong : unset swap code"); + gdcmErrorMacro( "Unset swap code"); a = 0; } return a; @@ -1261,7 +1167,6 @@ void Document::ParseDES(DocEntrySet *set, long offset, SeqEntry *newSeqEntry; VRKey vr; bool used=false; - long offsetEntry,readEntry; while (true) { @@ -1284,16 +1189,13 @@ void Document::ParseDES(DocEntrySet *set, long offset, if ( newValEntry || newBinEntry ) { - offsetEntry=newDocEntry->GetOffset(); - readEntry=newDocEntry->GetReadLength(); - if ( newBinEntry ) { if ( ! Global::GetVR()->IsVROfBinaryRepresentable(vr) ) { ////// Neither ValEntry NOR BinEntry: should mean UNKOWN VR - dbg.Verbose(0, "Document::ParseDES: neither Valentry, " - "nor BinEntry. Probably unknown VR."); + gdcmVerboseMacro( "Neither Valentry, nor BinEntry." + "Probably unknown VR."); } //////////////////// BinEntry or UNKOWN VR: @@ -1382,9 +1284,9 @@ void Document::ParseDES(DocEntrySet *set, long offset, Fp->seekg( positionOnEntry, std::ios::beg ); } } - + // Just to make sure we are at the beginning of next entry. - SkipToNextDocEntry(offsetEntry,readEntry); + SkipToNextDocEntry(newDocEntry); } else { @@ -1581,7 +1483,7 @@ void Document::LoadDocEntry(DocEntry *entry) LoadEntryBinArea(binEntryPtr); // last one, not to erase length ! return; } - + /// \todo Any compacter code suggested (?) if ( IsDocEntryAnInteger(entry) ) { @@ -1640,10 +1542,10 @@ void Document::LoadDocEntry(DocEntry *entry) if( length % 2 ) { newValue = Util::DicomString(str, length+1); - //dbg.Verbose(0, "Warning: bad length: ", length ); - dbg.Verbose(0, "For string :", newValue.c_str()); + gdcmVerboseMacro("Warning: bad length: " << length ); + gdcmVerboseMacro("For string :" << newValue.c_str()); // Since we change the length of string update it length - entry->SetReadLength(length+1); + //entry->SetReadLength(length+1); } else { @@ -1655,8 +1557,7 @@ void Document::LoadDocEntry(DocEntry *entry) { if ( Fp->fail() || Fp->eof())//Fp->gcount() == 1 { - dbg.Verbose(1, "Document::LoadDocEntry", - "unread element value"); + gdcmVerboseMacro( "Unread element value"); valEntry->SetValue(GDCM_UNREAD); return; } @@ -1673,8 +1574,7 @@ void Document::LoadDocEntry(DocEntry *entry) } else { - dbg.Error(true, "Document::LoadDocEntry" - "Should have a ValEntry, here !"); + gdcmErrorMacro( "Should have a ValEntry, here !"); } } @@ -1705,9 +1605,7 @@ void Document::FindDocEntryLength( DocEntry *entry ) uint32_t lengthOB; try { - /// \todo rename that to FindDocEntryLengthOBOrOW since - /// the above test is on both OB and OW... - lengthOB = FindDocEntryLengthOB(); + lengthOB = FindDocEntryLengthOBOrOW(); } catch ( FormatUnexpected ) { @@ -1718,11 +1616,15 @@ void Document::FindDocEntryLength( DocEntry *entry ) // the length and proceed. long currentPosition = Fp->tellg(); Fp->seekg(0L,std::ios::end); + long lengthUntilEOF = (long)(Fp->tellg())-currentPosition; Fp->seekg(currentPosition, std::ios::beg); + + entry->SetReadLength(lengthUntilEOF); entry->SetLength(lengthUntilEOF); return; } + entry->SetReadLength(lengthOB); entry->SetLength(lengthOB); return; } @@ -1771,11 +1673,12 @@ void Document::FindDocEntryLength( DocEntry *entry ) } length16 = 4; SwitchSwapToBigEndian(); + // Restore the unproperly loaded values i.e. the group, the element // and the dictionary entry depending on them. uint16_t correctGroup = SwapShort( entry->GetGroup() ); uint16_t correctElem = SwapShort( entry->GetElement() ); - DictEntry *newTag = GetDictEntryByNumber( correctGroup, + DictEntry *newTag = GetDictEntry( correctGroup, correctElem ); if ( !newTag ) { @@ -2003,14 +1906,12 @@ void Document::SkipDocEntry(DocEntry *entry) /** * \brief Skips to the begining of the next Header Entry * \warning NOT end user intended method ! - * @param offset start of skipping - * @param readLgth length to skip - + * @param currentDocEntry entry to skip */ -void Document::SkipToNextDocEntry(long offset,long readLgth) +void Document::SkipToNextDocEntry(DocEntry *currentDocEntry) { - Fp->seekg((long)(offset), std::ios::beg); - Fp->seekg( (long)(readLgth), std::ios::cur); + Fp->seekg((long)(currentDocEntry->GetOffset()), std::ios::beg); + Fp->seekg( (long)(currentDocEntry->GetReadLength()),std::ios::cur); } /** @@ -2018,7 +1919,7 @@ void Document::SkipToNextDocEntry(long offset,long readLgth) * the parser went Jabberwocky) one can hope improving things by * applying some heuristics. * @param entry entry to check - * @param foundLength fist assumption about length + * @param foundLength first assumption about length */ void Document::FixDocEntryFoundLength(DocEntry *entry, uint32_t foundLength) @@ -2029,30 +1930,25 @@ void Document::FixDocEntryFoundLength(DocEntry *entry, foundLength = 0; } - uint16_t gr = entry->GetGroup(); - uint16_t el = entry->GetElement(); + uint16_t gr = entry->GetGroup(); + uint16_t elem = entry->GetElement(); if ( foundLength % 2) { - std::ostringstream s; - s << "Warning : Tag with uneven length " - << foundLength - << " in x(" << std::hex << gr << "," << el <<")" << std::dec; - dbg.Verbose(0, s.str().c_str()); + gdcmVerboseMacro( "Warning : Tag with uneven length " << foundLength + << " in x(" << std::hex << gr << "," << elem <<")"); } //////// 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 - // are no longer in user (we are talking a few years, here)... + // are no longer in use (we are talking a few years, here)... // Note: XMedCom probably uses such a trick since it is able to read // those pesky GE images ... if ( foundLength == 13) { // Only happens for this length ! - if ( entry->GetGroup() != 0x0008 - || ( entry->GetElement() != 0x0070 - && entry->GetElement() != 0x0080 ) ) + if ( gr != 0x0008 || ( elem != 0x0070 && elem != 0x0080 ) ) { foundLength = 10; entry->SetReadLength(10); /// \todo a bug is to be fixed !? @@ -2063,9 +1959,7 @@ void Document::FixDocEntryFoundLength(DocEntry *entry, // Occurence of such images is quite low (unless one leaves close to a // 'Leonardo' source. Hence, one might consider commenting out the // following fix on efficiency reasons. - else if ( entry->GetGroup() == 0x0009 - && ( entry->GetElement() == 0x1113 - || entry->GetElement() == 0x1114 ) ) + else if ( gr == 0x0009 && ( elem == 0x1113 || elem == 0x1114 ) ) { foundLength = 4; entry->SetReadLength(4); /// \todo a bug is to be fixed !? @@ -2079,7 +1973,7 @@ void Document::FixDocEntryFoundLength(DocEntry *entry, //////// We encountered a 'delimiter' element i.e. a tag of the form // "fffe|xxxx" which is just a marker. Delimiters length should not be // taken into account. - else if( entry->GetGroup() == 0xfffe ) + else if( gr == 0xfffe ) { // According to the norm, fffe|0000 shouldn't exist. BUT the Philips // image gdcmData/gdcm-MR-PHILIPS-16-Multi-Seq.dcm happens to @@ -2090,7 +1984,7 @@ void Document::FixDocEntryFoundLength(DocEntry *entry, } } - entry->SetUsableLength(foundLength); + entry->SetLength(foundLength); } /** @@ -2101,7 +1995,7 @@ void Document::FixDocEntryFoundLength(DocEntry *entry, */ bool Document::IsDocEntryAnInteger(DocEntry *entry) { - uint16_t element = entry->GetElement(); + uint16_t elem = entry->GetElement(); uint16_t group = entry->GetGroup(); const std::string &vr = entry->GetVR(); uint32_t length = entry->GetLength(); @@ -2109,7 +2003,7 @@ bool Document::IsDocEntryAnInteger(DocEntry *entry) // When we have some semantics on the element we just read, and if we // a priori know we are dealing with an integer, then we shall be // able to swap it's element value properly. - if ( element == 0 ) // This is the group length of the group + if ( elem == 0 ) // This is the group length of the group { if ( length == 4 ) { @@ -2124,13 +2018,11 @@ bool Document::IsDocEntryAnInteger(DocEntry *entry) // test is useless (and might even look a bit paranoid), when we // encounter such an ill-formed image, we simply display a warning // message and proceed on parsing (while crossing fingers). - std::ostringstream s; long filePosition = Fp->tellg(); - s << "Erroneous Group Length element length on : (" \ - << std::hex << group << " , " << element + gdcmVerboseMacro( "Erroneous Group Length element length on : (" + << std::hex << group << " , " << elem << ") -before- position x(" << filePosition << ")" - << "lgt : " << length; - dbg.Verbose(0, "Document::IsDocEntryAnInteger", s.str().c_str() ); + << "lgt : " << length ); } } @@ -2147,7 +2039,7 @@ bool Document::IsDocEntryAnInteger(DocEntry *entry) * @return */ -uint32_t Document::FindDocEntryLengthOB() +uint32_t Document::FindDocEntryLengthOBOrOW() throw( FormatUnexpected ) { // See PS 3.5-2001, section A.4 p. 49 on encapsulation of encoded pixel data. @@ -2166,8 +2058,8 @@ uint32_t Document::FindDocEntryLengthOB() } catch ( FormatError ) { - throw FormatError("Document::FindDocEntryLengthOB()", - " group or element not present."); + throw FormatError("Unexpected end of file encountered during ", + "Document::FindDocEntryLengthOBOrOW()"); } // We have to decount the group and element we just read @@ -2175,12 +2067,13 @@ uint32_t Document::FindDocEntryLengthOB() if ( group != 0xfffe || ( ( elem != 0xe0dd ) && ( elem != 0xe000 ) ) ) { - dbg.Verbose(1, "Document::FindDocEntryLengthOB: neither an Item " - "tag nor a Sequence delimiter tag."); + long filePosition = Fp->tellg(); + gdcmVerboseMacro( "Neither an Item tag nor a Sequence delimiter tag on :" + << std::hex << group << " , " << elem + << ") -before- position x(" << filePosition << ")" ); + Fp->seekg(positionOnEntry, std::ios::beg); - throw FormatUnexpected("Document::FindDocEntryLengthOB()", - "Neither an Item tag nor a Sequence " - "delimiter tag."); + throw FormatUnexpected( "Neither an Item tag nor a Sequence delimiter tag."); } if ( elem == 0xe0dd ) @@ -2310,7 +2203,7 @@ bool Document::CheckSwap() char *entCur = deb + 128; if( memcmp(entCur, "DICM", (size_t)4) == 0 ) { - dbg.Verbose(1, "Document::CheckSwap:", "looks like DICOM Version3"); + gdcmVerboseMacro( "Looks like DICOM Version3" ); // Next, determine the value representation (VR). Let's skip to the // first element (0002, 0000) and check there if we find "UL" @@ -2344,27 +2237,23 @@ bool Document::CheckSwap() // instead of just checking for UL, OB and UI !? group 0000 { Filetype = ExplicitVR; - dbg.Verbose(1, "Document::CheckSwap:", - "explicit Value Representation"); + gdcmVerboseMacro( "Explicit Value Representation"); } else { Filetype = ImplicitVR; - dbg.Verbose(1, "Document::CheckSwap:", - "not an explicit Value Representation"); + gdcmVerboseMacro( "Not an explicit Value Representation"); } if ( net2host ) { SwapCode = 4321; - dbg.Verbose(1, "Document::CheckSwap:", - "HostByteOrder != NetworkByteOrder"); + gdcmVerboseMacro( "HostByteOrder != NetworkByteOrder"); } else { SwapCode = 0; - dbg.Verbose(1, "Document::CheckSwap:", - "HostByteOrder = NetworkByteOrder"); + gdcmVerboseMacro( "HostByteOrder = NetworkByteOrder"); } // Position the file position indicator at first tag (i.e. @@ -2377,7 +2266,7 @@ bool Document::CheckSwap() // Alas, this is not a DicomV3 file and whatever happens there is no file // preamble. We can reset the file position indicator to where the data // is (i.e. the beginning of the file). - dbg.Verbose(1, "Document::CheckSwap:", "not a DICOM Version3 file"); + gdcmVerboseMacro( "Not a DICOM Version3 file"); Fp->seekg(0, std::ios::beg); // Our next best chance would be to be considering a 'clean' ACR/NEMA file. @@ -2452,8 +2341,7 @@ bool Document::CheckSwap() Filetype = ACR; return true; default : - dbg.Verbose(0, "Document::CheckSwap:", - "ACR/NEMA unfound swap info (Really hopeless !)"); + gdcmVerboseMacro( "ACR/NEMA unfound swap info (Really hopeless !)"); Filetype = Unknown; return false; } @@ -2474,8 +2362,7 @@ bool Document::CheckSwap() */ void Document::SwitchSwapToBigEndian() { - dbg.Verbose(1, "Document::SwitchSwapToBigEndian", - "Switching to BigEndian mode."); + gdcmVerboseMacro( "Switching to BigEndian mode."); if ( SwapCode == 0 ) { SwapCode = 4321; @@ -2555,7 +2442,7 @@ void Document::HandleBrokenEndian(uint16_t group, uint16_t elem) group = 0xfffe; elem = 0xe000; } - else if ((group == 0xfffe) && (elem == 0xe00d) && reversedEndian) + else if (group == 0xfffe && elem == 0xe00d && reversedEndian) { // end of reversed endian group reversedEndian--; @@ -2594,18 +2481,18 @@ DocEntry *Document::ReadNextDocEntry() if( vr == GDCM_UNKNOWN) { - DictEntry *dictEntry = GetDictEntryByNumber(group,elem); + DictEntry *dictEntry = GetDictEntry(group,elem); if( dictEntry ) realVR = dictEntry->GetVR(); } DocEntry *newEntry; if( Global::GetVR()->IsVROfSequence(realVR) ) - newEntry = NewSeqEntryByNumber(group, elem); + newEntry = NewSeqEntry(group, elem); else if( Global::GetVR()->IsVROfStringRepresentable(realVR) ) - newEntry = NewValEntryByNumber(group, elem,vr); + newEntry = NewValEntry(group, elem,vr); else - newEntry = NewBinEntryByNumber(group, elem,vr); + newEntry = NewBinEntry(group, elem,vr); if( vr == GDCM_UNKNOWN ) { @@ -2616,7 +2503,7 @@ DocEntry *Document::ReadNextDocEntry() std::string msg; msg = Util::Format("Falsely explicit vr file (%04x,%04x)\n", newEntry->GetGroup(), newEntry->GetElement()); - dbg.Verbose(1, "Document::FindVR: ", msg.c_str()); + gdcmVerboseMacro( msg.c_str() ); } newEntry->SetImplicitVR(); } @@ -2692,15 +2579,13 @@ bool Document::ReadTag(uint16_t testGroup, uint16_t testElement) } if ( itemTagGroup != testGroup || itemTagElement != testElement ) { - std::ostringstream s; - s << " We should have found tag ("; - s << std::hex << testGroup << "," << testElement << ")" << std::endl; - s << " but instead we encountered tag ("; - s << std::hex << itemTagGroup << "," << itemTagElement << ")" - << std::endl; - s << " at address: " << (unsigned)currentPosition << std::endl; - dbg.Verbose(0, "Document::ReadItemTagLength: wrong Item Tag found:"); - dbg.Verbose(0, s.str().c_str()); + gdcmVerboseMacro( "Wrong Item Tag found:" + << " We should have found tag (" + << std::hex << testGroup << "," << testElement << ")" << std::endl + << " but instead we encountered tag (" + << std::hex << itemTagGroup << "," << itemTagElement << ")" + << std::dec + << " at address: " << (unsigned int)currentPosition ); Fp->seekg(positionOnEntry, std::ios::beg); return false; @@ -2736,11 +2621,9 @@ uint32_t Document::ReadTagLength(uint16_t testGroup, uint16_t testElement) long currentPosition = Fp->tellg(); uint32_t itemLength = ReadInt32(); { - std::ostringstream s; - s << "Basic Item Length is: " - << itemLength << std::endl; - s << " at address: " << (unsigned)currentPosition << std::endl; - dbg.Verbose(0, "Document::ReadItemTagLength: ", s.str().c_str()); + gdcmVerboseMacro( "Basic Item Length is: " + << itemLength << std::endl + << " at address: " << (unsigned int)currentPosition); } return itemLength; } @@ -2770,12 +2653,8 @@ void Document::ReadAndSkipEncapsulatedBasicOffsetTable() { uint32_t individualLength = str2num( &basicOffsetTableItemValue[i], uint32_t); - std::ostringstream s; - s << " Read one length: "; - s << std::hex << individualLength << std::endl; - dbg.Verbose(0, - "Document::ReadAndSkipEncapsulatedBasicOffsetTable: ", - s.str().c_str()); + gdcmVerboseMacro( "Read one length: " << + std::hex << individualLength ); } #endif //GDCM_DEBUG @@ -2832,7 +2711,7 @@ void Document::ComputeRLEInfo() if ( nbRleSegments > 16 ) { // There should be at most 15 segments (refer to RLEFrame class) - dbg.Verbose(0, "Document::ComputeRLEInfo: too many segments."); + gdcmVerboseMacro( "Too many segments."); } uint32_t rleSegmentOffsetTable[16]; @@ -2875,8 +2754,7 @@ void Document::ComputeRLEInfo() // Delimiter Item': if ( !ReadTag(0xfffe, 0xe0dd) ) { - dbg.Verbose(0, "Document::ComputeRLEInfo: no sequence delimiter "); - dbg.Verbose(0, " item at end of RLE item sequence"); + gdcmVerboseMacro( "No sequence delimiter item at end of RLE item sequence"); } } @@ -2916,8 +2794,7 @@ void Document::ComputeJPEGFragmentInfo() // Delimiter Item': if ( !ReadTag(0xfffe, 0xe0dd) ) { - dbg.Verbose(0, "Document::ComputeRLEInfo: no sequence delimiter "); - dbg.Verbose(0, " item at end of JPEG item sequence"); + gdcmVerboseMacro( "No sequence delimiter item at end of JPEG item sequence"); } } @@ -3024,8 +2901,8 @@ TagDocEntryHT *Document::BuildFlatHashTable() bool Document::operator<(Document &document) { // Patient Name - std::string s1 = GetEntryByNumber(0x0010,0x0010); - std::string s2 = document.GetEntryByNumber(0x0010,0x0010); + std::string s1 = GetEntry(0x0010,0x0010); + std::string s2 = document.GetEntry(0x0010,0x0010); if(s1 < s2) { return true; @@ -3037,8 +2914,8 @@ bool Document::operator<(Document &document) else { // Patient ID - s1 = GetEntryByNumber(0x0010,0x0020); - s2 = document.GetEntryByNumber(0x0010,0x0020); + s1 = GetEntry(0x0010,0x0020); + s2 = document.GetEntry(0x0010,0x0020); if ( s1 < s2 ) { return true; @@ -3050,8 +2927,8 @@ bool Document::operator<(Document &document) else { // Study Instance UID - s1 = GetEntryByNumber(0x0020,0x000d); - s2 = document.GetEntryByNumber(0x0020,0x000d); + s1 = GetEntry(0x0020,0x000d); + s2 = document.GetEntry(0x0020,0x000d); if ( s1 < s2 ) { return true; @@ -3063,8 +2940,8 @@ bool Document::operator<(Document &document) else { // Serie Instance UID - s1 = GetEntryByNumber(0x0020,0x000e); - s2 = document.GetEntryByNumber(0x0020,0x000e); + s1 = GetEntry(0x0020,0x000e); + s2 = document.GetEntry(0x0020,0x000e); if ( s1 < s2 ) { return true;