X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=blobdiff_plain;f=src%2FgdcmDocument.cxx;h=24777f51729a1ecef83fea09ed7850b9b00059a9;hb=0f2a60bf2a0d1ddab03f0ed30e2e382da2bc3f79;hp=8937fa3ea97638ab36e1d647d066bc983c8867fd;hpb=827d0d72b115d9e54aac8f0b054856dffff862ca;p=gdcm.git diff --git a/src/gdcmDocument.cxx b/src/gdcmDocument.cxx index 8937fa3e..24777f51 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/11 00:21:48 $ - Version: $Revision: 1.172 $ + Date: $Date: 2005/01/11 22:46:22 $ + Version: $Revision: 1.179 $ Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de l'Image). All rights reserved. See Doc/License.txt or @@ -43,41 +43,6 @@ namespace gdcm { -//----------------------------------------------------------------------------- -static const char *TransferSyntaxStrings[] = { - // Implicit VR Little Endian - "1.2.840.10008.1.2", - // 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", - // Deflated Explicit VR Little Endian - "1.2.840.10008.1.2.1.99", - // Explicit VR Big Endian - "1.2.840.10008.1.2.2", - // JPEG Baseline (Process 1) - "1.2.840.10008.1.2.4.50", - // JPEG Extended (Process 2 & 4) - "1.2.840.10008.1.2.4.51", - // JPEG Extended (Process 3 & 5) - "1.2.840.10008.1.2.4.52", - // JPEG Spectral Selection, Non-Hierarchical (Process 6 & 8) - "1.2.840.10008.1.2.4.53", - // JPEG Full Progression, Non-Hierarchical (Process 10 & 12) - "1.2.840.10008.1.2.4.55", - // JPEG Lossless, Non-Hierarchical (Process 14) - "1.2.840.10008.1.2.4.57", - // JPEG Lossless, Hierarchical, First-Order Prediction (Process 14, [Selection Value 1]) - "1.2.840.10008.1.2.4.70", - // JPEG 2000 Lossless - "1.2.840.10008.1.2.4.90", - // JPEG 2000 - "1.2.840.10008.1.2.4.91", - // RLE Lossless - "1.2.840.10008.1.2.5", - // Unknown - "Unknown Transfer Syntax" -}; //----------------------------------------------------------------------------- // Refer to Document::CheckSwap() @@ -106,8 +71,10 @@ Document::Document( std::string const &filename ) : ElementSet(-1) return; } + Group0002Parsed = false; + gdcmVerboseMacro( "Starting parsing of file: " << Filename.c_str()); - Fp->seekg( 0, std::ios::beg); + // Fp->seekg( 0, std::ios::beg); Fp->seekg(0, std::ios::end); long lgt = Fp->tellg(); @@ -193,8 +160,9 @@ Document::Document() : ElementSet(-1) SetMaxSizeLoadEntry(MAX_SIZE_LOAD_ELEMENT_VALUE); Initialise(); - SwapCode = 0; + SwapCode = 1234; Filetype = ExplicitVR; + Group0002Parsed = false; } /** @@ -301,12 +269,12 @@ bool Document::IsReadable() * value from disk when only parsing occured). * @return The encountered Transfer Syntax of the current document. */ -TransferSyntaxType Document::GetTransferSyntax() +std::string Document::GetTransferSyntax() { DocEntry *entry = GetDocEntry(0x0002, 0x0010); if ( !entry ) { - return UnknownTS; + return GDCM_UNKNOWN; } // The entry might be present but not loaded (parsing and loading @@ -321,68 +289,15 @@ TransferSyntaxType Document::GetTransferSyntax() if ( transfer.length() == 0 ) { // for brain damaged headers - return UnknownTS; + return GDCM_UNKNOWN; } while ( !isdigit((unsigned char)transfer[transfer.length()-1]) ) { transfer.erase(transfer.length()-1, 1); } - for (int i = 0; TransferSyntaxStrings[i] != NULL; i++) - { - if ( TransferSyntaxStrings[i] == transfer ) - { - return TransferSyntaxType(i); - } - } + return transfer; } - return UnknownTS; -} - -bool Document::IsJPEGLossless() -{ - TransferSyntaxType r = GetTransferSyntax(); - return r == JPEGFullProgressionProcess10_12 - || r == JPEGLosslessProcess14 - || r == JPEGLosslessProcess14_1; -} - -/** - * \brief Determines if the Transfer Syntax was already encountered - * and if it corresponds to a JPEG2000 one - * @return True when JPEG2000 (Lossly or LossLess) found. False in all - * other cases. - */ -bool Document::IsJPEG2000() -{ - TransferSyntaxType r = GetTransferSyntax(); - return r == JPEG2000Lossless || r == JPEG2000; -} - -/** - * \brief Determines if the Transfer Syntax corresponds to any form - * of Jpeg encoded Pixel data. - * @return True when any form of JPEG found. False otherwise. - */ -bool Document::IsJPEG() -{ - TransferSyntaxType r = GetTransferSyntax(); - return r == JPEGBaselineProcess1 - || r == JPEGExtendedProcess2_4 - || r == JPEGExtendedProcess3_5 - || r == JPEGSpectralSelectionProcess6_8 - || IsJPEGLossless() - || IsJPEG2000(); -} - -/** - * \brief Determines if the Transfer Syntax corresponds to encapsulated - * of encoded Pixel Data (as opposed to native). - * @return True when encapsulated. False when native. - */ -bool Document::IsEncapsulate() -{ - TransferSyntaxType r = GetTransferSyntax(); - return IsJPEG() || r == RLELossless; + return GDCM_UNKNOWN; } /** @@ -391,7 +306,7 @@ bool Document::IsEncapsulate() */ bool Document::IsDicomV3() { - // Checking if Transfert Syntax exists is enough + // Checking if Transfer Syntax exists is enough // 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 !) @@ -415,6 +330,8 @@ FileType Document::GetFileType() */ std::ifstream *Document::OpenFile() { + + HasDCMPreamble = false; if (Filename.length() == 0) { return 0; @@ -422,7 +339,7 @@ std::ifstream *Document::OpenFile() if(Fp) { - gdcmVerboseMacro( "Is already opened when opening: " << Filename.c_str()); + gdcmVerboseMacro( "File already open: " << Filename.c_str()); } Fp = new std::ifstream(Filename.c_str(), std::ios::in | std::ios::binary); @@ -466,6 +383,7 @@ std::ifstream *Document::OpenFile() } if( memcmp(dicm, "DICM", 4) == 0 ) { + HasDCMPreamble = true; return Fp; } @@ -733,11 +651,6 @@ bool Document::ReplaceIfExist(std::string const &value, return true; } -std::string Document::GetTransferSyntaxValue(TransferSyntaxType type) -{ - return TransferSyntaxStrings[type]; -} - //----------------------------------------------------------------------------- // Protected @@ -1097,7 +1010,7 @@ uint32_t Document::SwapLong(uint32_t a) { switch (SwapCode) { - case 0 : + case 1234 : break; case 4321 : a=( ((a<<24) & 0xff000000) | ((a<<8) & 0x00ff0000) | @@ -1267,15 +1180,15 @@ void Document::ParseDES(DocEntrySet *set, long offset, if ( ( newDocEntry->GetGroup() == 0x7fe0 ) && ( newDocEntry->GetElement() == 0x0010 ) ) { - TransferSyntaxType ts = GetTransferSyntax(); - if ( ts == RLELossless ) + std::string ts = GetTransferSyntax(); + if ( Global::GetTS()->IsRLELossless(ts) ) { long positionOnEntry = Fp->tellg(); Fp->seekg( newDocEntry->GetOffset(), std::ios::beg ); ComputeRLEInfo(); Fp->seekg( positionOnEntry, std::ios::beg ); } - else if ( IsJPEG() ) + else if ( Global::GetTS()->IsJPEG(ts) ) { long positionOnEntry = Fp->tellg(); Fp->seekg( newDocEntry->GetOffset(), std::ios::beg ); @@ -1663,15 +1576,16 @@ void Document::FindDocEntryLength( DocEntry *entry ) // big endian and proceed... if ( element == 0x0000 && length16 == 0x0400 ) { - TransferSyntaxType ts = GetTransferSyntax(); - if ( ts != ExplicitVRBigEndian ) + std::string ts = GetTransferSyntax(); + if ( Global::GetTS()->GetSpecialTransferSyntax(ts) + != TS::ExplicitVRBigEndian ) { throw FormatError( "Document::FindDocEntryLength()", " not explicit VR." ); return; } length16 = 4; - SwitchSwapToBigEndian(); + SwitchByteSwapCode(); // Restore the unproperly loaded values i.e. the group, the element // and the dictionary entry depending on them. @@ -2222,7 +2136,7 @@ bool Document::CheckSwap() // FIXME : FIXME: // Sometimes (see : gdcmData/icone.dcm) group 0x0002 *is* Explicit VR, - // but elem 0002,0010 (Transfert Syntax) tells us the file is + // but elem 0002,0010 (Transfer Syntax) tells us the file is // *Implicit* VR. -and it is !- if( memcmp(entCur, "UL", (size_t)2) == 0 || @@ -2250,7 +2164,7 @@ bool Document::CheckSwap() } else { - SwapCode = 0; + SwapCode = 1234; gdcmVerboseMacro( "HostByteOrder = NetworkByteOrder"); } @@ -2293,7 +2207,7 @@ bool Document::CheckSwap() Filetype = ACR; return true; case 0x00000004 : - SwapCode = 0; + SwapCode = 1234; Filetype = ACR; return true; default : @@ -2324,7 +2238,7 @@ bool Document::CheckSwap() case 0x0006 : case 0x0007 : case 0x0008 : - SwapCode = 0; + SwapCode = 1234; Filetype = ACR; return true; case 0x0100 : @@ -2345,7 +2259,7 @@ bool Document::CheckSwap() } // Then the only info we have is the net2host one. //if (! net2host ) - // SwapCode = 0; + // SwapCode = 1234; //else // SwapCode = 4321; //return; @@ -2355,19 +2269,18 @@ bool Document::CheckSwap() /** - * \brief Restore the unproperly loaded values i.e. the group, the element - * and the dictionary entry depending on them. + * \brief Change the Byte Swap code. */ -void Document::SwitchSwapToBigEndian() +void Document::SwitchByteSwapCode() { - gdcmVerboseMacro( "Switching to BigEndian mode."); - if ( SwapCode == 0 ) + gdcmVerboseMacro( "Switching Byte Swap code."); + if ( SwapCode == 1234 ) { SwapCode = 4321; } else if ( SwapCode == 4321 ) { - SwapCode = 0; + SwapCode = 1234; } else if ( SwapCode == 3412 ) { @@ -2426,7 +2339,7 @@ void Document::SetMaxSizePrintEntry(long newSize) * apparent reason * @return no return */ -void Document::HandleBrokenEndian(uint16_t group, uint16_t elem) +void Document::HandleBrokenEndian(uint16_t &group, uint16_t &elem) { // Endian reversion. Some files contain groups of tags with reversed endianess. static int reversedEndian = 0; @@ -2435,7 +2348,7 @@ void Document::HandleBrokenEndian(uint16_t group, uint16_t elem) { // start endian swap mark for group found reversedEndian++; - SwitchSwapToBigEndian(); + SwitchByteSwapCode(); // fix the tag group = 0xfffe; elem = 0xe000; @@ -2444,14 +2357,47 @@ void Document::HandleBrokenEndian(uint16_t group, uint16_t elem) { // end of reversed endian group reversedEndian--; - SwitchSwapToBigEndian(); + SwitchByteSwapCode(); + } +} + +/** + * \brief Group 0002 is always coded Little Endian + * whatever Transfer Syntax is + * @return no return + */ +void Document::HandleOutOfGroup0002(uint16_t group) +{ + // Endian reversion. Some files contain groups of tags with reversed endianess. + if ( !Group0002Parsed && group != 0x0002) + { + Group0002Parsed = true; + // we just came out of group 0002 + // if Transfer syntax is Big Endian we have to change CheckSwap + + TagKey key = DictEntry::TranslateToKey(0x0002, 0x0010); + if ( !TagHT.count(key)) + { + gdcmVerboseMacro("True DICOM File, with NO Tansfer Syntax ?!?"); + return; + } + + // FIXME Strangely, this works with + //'Implicit VR Transfer Syntax (GE Private) + + if ( ((ValEntry *)TagHT.find(key)->second)->GetValue() + == "Explicit VR - Big Endian" ) + { + gdcmVerboseMacro("Tansfer Syntax = Explicit VR - Big Endian"); + SwitchByteSwapCode(); + } } } /** * \brief Read the next tag but WITHOUT loading it's value * (read the 'Group Number', the 'Element Number', - * gets the Dict Entry + * gets the Dict Entry * gets the VR, gets the length, gets the offset value) * @return On succes the newly created DocEntry, NULL on failure. */ @@ -2473,7 +2419,13 @@ DocEntry *Document::ReadNextDocEntry() return 0; } + // Sometimes file contains groups of tags with reversed endianess. HandleBrokenEndian(group, elem); + +// In 'true DICOM' files Group 0002 is allways little endian + if ( HasDCMPreamble ) + HandleOutOfGroup0002(group); + std::string vr = FindDocEntryVR(); std::string realVR = vr; @@ -2582,8 +2534,8 @@ bool Document::ReadTag(uint16_t testGroup, uint16_t testElement) << std::hex << testGroup << "," << testElement << ")" << std::endl << " but instead we encountered tag (" << std::hex << itemTagGroup << "," << itemTagElement << ")" - << std::dec - << " at address: " << (unsigned int)currentPosition ); + << " at address: " << " 0x(" << (unsigned int)currentPosition << ")" + ) ; Fp->seekg(positionOnEntry, std::ios::beg); return false; @@ -2621,7 +2573,7 @@ uint32_t Document::ReadTagLength(uint16_t testGroup, uint16_t testElement) { gdcmVerboseMacro( "Basic Item Length is: " << itemLength << std::endl - << " at address: " << (unsigned int)currentPosition); + << " at address: " << std::hex << (unsigned int)currentPosition); } return itemLength; } @@ -2667,8 +2619,8 @@ void Document::ReadAndSkipEncapsulatedBasicOffsetTable() */ void Document::ComputeRLEInfo() { - TransferSyntaxType ts = GetTransferSyntax(); - if ( ts != RLELossless ) + std::string ts = GetTransferSyntax(); + if ( !Global::GetTS()->IsRLELossless(ts) ) { return; } @@ -2765,7 +2717,8 @@ void Document::ComputeRLEInfo() void Document::ComputeJPEGFragmentInfo() { // If you need to, look for comments of ComputeRLEInfo(). - if ( ! IsJPEG() ) + std::string ts = GetTransferSyntax(); + if ( ! Global::GetTS()->IsJPEG(ts) ) { return; }