X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=blobdiff_plain;f=src%2FgdcmDocument.cxx;h=4adb7d947cdd844e3130db7fd7f217ce7b449da0;hb=130558c1fc10cbc2d5d58484b310fa86bd20d81b;hp=808bb210d79c6d97dcc298d59c8d0158c4ed04b7;hpb=323dba69fa639a71f1559c8aee8209afc8731bb4;p=gdcm.git diff --git a/src/gdcmDocument.cxx b/src/gdcmDocument.cxx index 808bb210..4adb7d94 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/17 11:03:28 $ - Version: $Revision: 1.192 $ + Date: $Date: 2005/01/18 18:03:16 $ + Version: $Revision: 1.198 $ Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de l'Image). All rights reserved. See Doc/License.txt or @@ -35,9 +35,11 @@ #include // For nthos: -#if defined(_MSC_VER) || defined(__BORLANDC__) +#if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__MINGW32__) #include -#else +#endif + +#ifdef CMAKE_HAVE_NETINET_IN_H #include #endif @@ -137,7 +139,7 @@ Document::Document( std::string const &filename ) : ElementSet(-1) // we switch lineNumber and columnNumber // std::string RecCode; - RecCode = GetEntry(0x0008, 0x0010); // recognition code + RecCode = GetEntry(0x0008, 0x0010); // recognition code (RET) if (RecCode == "ACRNEMA_LIBIDO_1.1" || RecCode == "CANRME_AILIBOD1_1." ) // for brain-damaged softwares // with "little-endian strings" @@ -257,7 +259,7 @@ bool Document::IsReadable() if( TagHT.empty() ) { - gdcmVerboseMacro( "No tags in internal hash table."); + gdcmVerboseMacro( "No tag in internal hash table."); return false; } @@ -412,7 +414,7 @@ bool Document::CloseFile() /** * \brief Writes in a file all the Header Entries (Dicom Elements) - * @param fp file pointer on an already open file + * @param fp file pointer on an already open file (actually: Output File Stream) * @param filetype Type of the File to be written * (ACR-NEMA, ExplicitVR, ImplicitVR) * \return Always true. @@ -511,8 +513,8 @@ ValEntry *Document::ReplaceOrCreate(std::string const &value, * when it exists. Create it with the given value when unexistant. * A copy of the binArea is made to be kept in the Document. * @param binArea (binary) value to be set - * @param Group Group number of the Entry - * @param Elem Element number of the Entry + * @param group Group number of the Entry + * @param elem Element number of the Entry * @param vr V(alue) R(epresentation) of the Entry -if private Entry- * \return pointer to the modified/created Header Entry (NULL when creation * failed). @@ -587,8 +589,8 @@ BinEntry *Document::ReplaceOrCreate(uint8_t *binArea, /* * \brief Modifies the value of a given Header Entry (Dicom Element) * when it exists. Create it when unexistant. - * @param Group Group number of the Entry - * @param Elem Element number of the Entry + * @param group Group number of the Entry + * @param elem Element number of the Entry * \return pointer to the modified/created SeqEntry (NULL when creation * failed). */ @@ -657,13 +659,13 @@ bool Document::ReplaceIfExist(std::string const &value, /** * \brief Checks if a given Dicom Element exists within the H table - * @param group Group number of the searched Dicom Element - * @param element Element number of the searched Dicom Element + * @param group Group number of the searched Dicom Element + * @param elem Element number of the searched Dicom Element * @return true is found */ -bool Document::CheckIfEntryExist(uint16_t group, uint16_t element ) +bool Document::CheckIfEntryExist(uint16_t group, uint16_t elem ) { - const std::string &key = DictEntry::TranslateToKey(group, element ); + const std::string &key = DictEntry::TranslateToKey(group, elem ); return TagHT.count(key) != 0; } @@ -672,14 +674,14 @@ bool Document::CheckIfEntryExist(uint16_t group, uint16_t element ) * \brief Searches within Header Entries (Dicom Elements) parsed with * the public and private dictionaries * for the element value representation of a given tag. - * @param group Group number of the searched tag. - * @param element Element number of the searched tag. + * @param group Group number of the searched tag. + * @param elem Element number of the searched tag. * @return Corresponding element value representation when it exists, * and the string GDCM_UNFOUND ("gdcm::Unfound") otherwise. */ -std::string Document::GetEntry(uint16_t group, uint16_t element) +std::string Document::GetEntry(uint16_t group, uint16_t elem) { - TagKey key = DictEntry::TranslateToKey(group, element); + TagKey key = DictEntry::TranslateToKey(group, elem); if ( !TagHT.count(key)) { return GDCM_UNFOUND; @@ -692,42 +694,41 @@ std::string Document::GetEntry(uint16_t group, uint16_t element) * \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 group Group number of the searched tag. - * @param element Element number of the searched tag. + * @param group Group number of the searched tag. + * @param elem Element number of the searched tag. * @return Corresponding element value representation when it exists, * and the string GDCM_UNFOUND ("gdcm::Unfound") otherwise. */ -std::string Document::GetEntryVR(uint16_t group, uint16_t element) +std::string Document::GetEntryVR(uint16_t group, uint16_t elem) { - DocEntry *elem = GetDocEntry(group, element); - if ( !elem ) + DocEntry *element = GetDocEntry(group, elem); + if ( !element ) { return GDCM_UNFOUND; } - return elem->GetVR(); + return element->GetVR(); } /** * \brief Searches within Header Entries (Dicom Elements) parsed with * the public and private dictionaries * for the value length of a given tag.. - * @param group Group number of the searched tag. - * @param element Element number of the searched tag. + * @param group Group number of the searched tag. + * @param elem Element number of the searched tag. * @return Corresponding element length; -2 if not found */ -int Document::GetEntryLength(uint16_t group, uint16_t element) +int Document::GetEntryLength(uint16_t group, uint16_t elem) { - DocEntry *elem = GetDocEntry(group, element); - if ( !elem ) + DocEntry *element = GetDocEntry(group, elem); + if ( !element ) { return -2; //magic number } - return elem->GetLength(); + return element->GetLength(); } /** @@ -735,13 +736,13 @@ int Document::GetEntryLength(uint16_t group, uint16_t element) * through it's (group, element) and modifies it's content with * the given value. * @param content new value (string) to substitute with - * @param group group number of the Dicom Element to modify - * @param element element number of the Dicom Element to modify + * @param group group number of the Dicom Element to modify + * @param elem element number of the Dicom Element to modify */ bool Document::SetEntry(std::string const& content, - uint16_t group, uint16_t element) + uint16_t group, uint16_t elem) { - ValEntry *entry = GetValEntry(group, element); + ValEntry *entry = GetValEntry(group, elem); if (!entry ) { gdcmVerboseMacro( "No corresponding ValEntry (try promotion first)."); @@ -756,13 +757,13 @@ bool Document::SetEntry(std::string const& content, * the given value. * @param content new value (void* -> uint8_t*) to substitute with * @param lgth new value length - * @param group group number of the Dicom Element to modify - * @param element element number of the Dicom Element to modify + * @param group group number of the Dicom Element to modify + * @param elem element number of the Dicom Element to modify */ bool Document::SetEntry(uint8_t*content, int lgth, - uint16_t group, uint16_t element) + uint16_t group, uint16_t elem) { - BinEntry *entry = GetBinEntry(group, element); + BinEntry *entry = GetBinEntry(group, elem); if (!entry ) { gdcmVerboseMacro( "No corresponding ValEntry (try promotion first)."); @@ -778,7 +779,7 @@ bool Document::SetEntry(uint8_t*content, int lgth, * @param content new value (string) to substitute with * @param entry Entry to be modified */ -bool Document::SetEntry(std::string const &content,ValEntry *entry) +bool Document::SetEntry(std::string const &content, ValEntry *entry) { if(entry) { @@ -793,7 +794,7 @@ bool Document::SetEntry(std::string const &content,ValEntry *entry) * and modifies it's content with the given value. * @param content new value (void* -> uint8_t*) to substitute with * @param entry Entry to be modified - * @param lgth new value length + * @param lgth new value length */ bool Document::SetEntry(uint8_t *content, int lgth, BinEntry *entry) { @@ -860,25 +861,25 @@ void Document::LoadEntryBinArea(uint16_t group, uint16_t elem) /** * \brief Loads (from disk) the element content * when a string is not suitable - * @param element Entry whose binArea is going to be loaded + * @param elem Entry whose binArea is going to be loaded */ -void Document::LoadEntryBinArea(BinEntry *element) +void Document::LoadEntryBinArea(BinEntry *elem) { - if(element->GetBinArea()) + if(elem->GetBinArea()) return; bool openFile = !Fp; if(openFile) OpenFile(); - size_t o =(size_t)element->GetOffset(); + size_t o =(size_t)elem->GetOffset(); Fp->seekg(o, std::ios::beg); - size_t l = element->GetLength(); + size_t l = elem->GetLength(); uint8_t *a = new uint8_t[l]; if( !a ) { - gdcmVerboseMacro( "Cannot allocate a"); + gdcmVerboseMacro( "Cannot allocate BinEntry content"); return; } @@ -890,7 +891,7 @@ void Document::LoadEntryBinArea(BinEntry *element) return; } - element->SetBinArea(a); + elem->SetBinArea(a); if(openFile) CloseFile(); @@ -899,14 +900,14 @@ void Document::LoadEntryBinArea(BinEntry *element) /** * \brief Sets a 'non string' value to a given Dicom Element * @param area area containing the 'non string' value - * @param group Group number of the searched Dicom Element - * @param element Element number of the searched Dicom Element + * @param group Group number of the searched Dicom Element + * @param elem Element number of the searched Dicom Element * @return */ /*bool Document::SetEntryBinArea(uint8_t *area, - uint16_t group, uint16_t element) + uint16_t group, uint16_t elem) { - DocEntry *currentEntry = GetDocEntry(group, element); + DocEntry *currentEntry = GetDocEntry(group, elem); if ( !currentEntry ) { return false; @@ -922,18 +923,14 @@ void Document::LoadEntryBinArea(BinEntry *element) }*/ /** - * \brief retrieves a Dicom Element (the first one) using (group, element) - * \warning (group, element) IS NOT an identifier inside the Dicom Header - * if you think it's NOT UNIQUE, check the count number - * and use iterators to retrieve ALL the Dicoms Elements within - * a given couple (group, element) - * @param group Group number of the searched Dicom Element - * @param element Element number of the searched Dicom Element + * \brief retrieves a Dicom Element using (group, element) + * @param group Group number of the searched Dicom Element + * @param elem Element number of the searched Dicom Element * @return */ -DocEntry *Document::GetDocEntry(uint16_t group, uint16_t element) +DocEntry *Document::GetDocEntry(uint16_t group, uint16_t elem) { - TagKey key = DictEntry::TranslateToKey(group, element); + TagKey key = DictEntry::TranslateToKey(group, elem); if ( !TagHT.count(key)) { return NULL; @@ -945,11 +942,13 @@ DocEntry *Document::GetDocEntry(uint16_t group, uint16_t element) * \brief Same as \ref Document::GetDocEntry except it only * returns a result when the corresponding entry is of type * ValEntry. + * @param group Group number of the searched Dicom Element + * @param elem Element number of the searched Dicom Element * @return When present, the corresponding ValEntry. */ -ValEntry *Document::GetValEntry(uint16_t group, uint16_t element) +ValEntry *Document::GetValEntry(uint16_t group, uint16_t elem) { - DocEntry *currentEntry = GetDocEntry(group, element); + DocEntry *currentEntry = GetDocEntry(group, elem); if ( !currentEntry ) { return 0; @@ -967,11 +966,13 @@ ValEntry *Document::GetValEntry(uint16_t group, uint16_t element) * \brief Same as \ref Document::GetDocEntry except it only * returns a result when the corresponding entry is of type * BinEntry. + * @param group Group number of the searched Dicom Element + * @param elem Element number of the searched Dicom Element * @return When present, the corresponding BinEntry. */ -BinEntry *Document::GetBinEntry(uint16_t group, uint16_t element) +BinEntry *Document::GetBinEntry(uint16_t group, uint16_t elem) { - DocEntry *currentEntry = GetDocEntry(group, element); + DocEntry *currentEntry = GetDocEntry(group, elem); if ( !currentEntry ) { return 0; @@ -986,9 +987,34 @@ BinEntry *Document::GetBinEntry(uint16_t group, uint16_t element) } /** - * \brief Loads the element while preserving the current - * underlying file position indicator as opposed to - * to LoadDocEntry that modifies it. + * \brief Same as \ref Document::GetDocEntry except it only + * returns a result when the corresponding entry is of type + * SeqEntry. + * @param group Group number of the searched Dicom Element + * @param elem Element number of the searched Dicom Element + * @return When present, the corresponding SeqEntry. + */ +SeqEntry *Document::GetSeqEntry(uint16_t group, uint16_t elem) +{ + DocEntry *currentEntry = GetDocEntry(group, elem); + if ( !currentEntry ) + { + return 0; + } + if ( SeqEntry *entry = dynamic_cast(currentEntry) ) + { + return entry; + } + gdcmVerboseMacro( "Unfound SeqEntry."); + + return 0; +} + + +/** + * \brief Loads the element while preserving the current + * underlying file position indicator as opposed to + * LoadDocEntry that modifies it. * @param entry Header Entry whose value will be loaded. * @return */ @@ -1103,7 +1129,7 @@ void Document::ParseDES(DocEntrySet *set, long offset, { if ( newBinEntry ) { - if ( ! Global::GetVR()->IsVROfBinaryRepresentable(vr) ) + if ( Filetype == ExplicitVR && ! Global::GetVR()->IsVROfBinaryRepresentable(vr) ) { ////// Neither ValEntry NOR BinEntry: should mean UNKOWN VR gdcmVerboseMacro( std::hex << newDocEntry->GetGroup() @@ -1115,9 +1141,8 @@ 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 (/*Document *dummy =*/ dynamic_cast< Document* > ( set ) ) + if ( dynamic_cast< Document* > ( set ) ) { - //(void)dummy; newBinEntry->SetKey( newBinEntry->GetKey() ); } // but when "this" is a SQItem, we are inserting this new @@ -1142,9 +1167,8 @@ void Document::ParseDES(DocEntrySet *set, long offset, /////////////////////// ValEntry // When "set" is a Document, then we are at the top of the // hierarchy and the Key is simply of the form ( group, elem )... - if (/*Document *dummy =*/ dynamic_cast< Document* > ( set ) ) + if ( dynamic_cast< Document* > ( set ) ) { - //(void)dummy; newValEntry->SetKey( newValEntry->GetKey() ); } // ...but when "set" is a SQItem, we are inserting this new @@ -1647,6 +1671,9 @@ void Document::FindDocEntryLength( DocEntry *entry ) // on Data elements "Implicit and Explicit VR Data Elements shall // not coexist in a Data Set and Data Sets nested within it".] // Length is on 4 bytes. + + // Well ... group 0002 is always coded in 'Explicit VR Litle Endian' + // even if Transfer Syntax is 'Implicit VR ...' FixDocEntryFoundLength( entry, ReadInt32() ); return; @@ -2288,8 +2315,6 @@ bool Document::CheckSwap() } } - - /** * \brief Change the Byte Swap code. */ @@ -2340,7 +2365,6 @@ void Document::SetMaxSizeLoadEntry(long newSize) */ void Document::SetMaxSizePrintEntry(long newSize) { - //DOH !! This is exactly SetMaxSizeLoadEntry FIXME FIXME if ( newSize < 0 ) { return; @@ -2385,7 +2409,6 @@ void Document::HandleBrokenEndian(uint16_t &group, uint16_t &elem) /** * \brief Accesses the info from 0002,0010 : Transfer Syntax and TS - * else 1. * @return The full Transfer Syntax Name (as opposed to Transfer Syntax UID) */ std::string Document::GetTransferSyntaxName() @@ -2433,6 +2456,13 @@ void Document::HandleOutOfGroup0002(uint16_t &group, uint16_t &elem) return; } + // Group 0002 is always 'Explicit ...' enven when Transfer Syntax says 'Implicit ..." + + if ( Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::ImplicitVRLittleEndian ) + { + Filetype = ImplicitVR; + } + // FIXME Strangely, this works with //'Implicit VR Transfer Syntax (GE Private) if ( Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::ExplicitVRBigEndian ) @@ -2441,7 +2471,7 @@ void Document::HandleOutOfGroup0002(uint16_t &group, uint16_t &elem) << GetTransferSyntaxName() << "]" ); SwitchByteSwapCode(); group = SwapShort(group); - elem = SwapShort(elem); + elem = SwapShort(elem); } } } @@ -2974,10 +3004,7 @@ int Document::ComputeGroup0002Length( FileType filetype ) bool found0002 = false; // for each zero-level Tag in the DCM Header - DocEntry *entry; - - InitTraversal(); - entry = GetNextEntry(); + DocEntry *entry = GetFirstEntry(); while(entry) { gr = entry->GetGroup();