X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=blobdiff_plain;f=src%2FgdcmElementSet.cxx;h=d071067ca02daf98552b910b5bfcb3f24069e691;hb=8ac4df8c7543a827c7b89fc9bbcf86625f3c1afe;hp=33325c3fda8ba30b71857eac771eaf988534e90b;hpb=0b36f4932e894a1dde4a80e614755816b4b29218;p=gdcm.git diff --git a/src/gdcmElementSet.cxx b/src/gdcmElementSet.cxx index 33325c3f..d071067c 100644 --- a/src/gdcmElementSet.cxx +++ b/src/gdcmElementSet.cxx @@ -1,9 +1,26 @@ -// gdcmElementSet.cxx -//----------------------------------------------------------------------------- -// -#include "gdcmElementSet.h" -#include "gdcmTS.h" +/*========================================================================= + + Program: gdcm + Module: $RCSfile: gdcmElementSet.cxx,v $ + Language: C++ + Date: $Date: 2004/09/27 08:39:07 $ + Version: $Revision: 1.23 $ + + Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de + l'Image). All rights reserved. See Doc/License.txt or + http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#include "gdcmElementSet.h" +#include "gdcmDebug.h" +#include "gdcmValEntry.h" +#include "gdcmBinEntry.h" +#include "gdcmSeqEntry.h" //----------------------------------------------------------------------------- // Constructor / Destructor @@ -11,8 +28,11 @@ * \ingroup gdcmElementSet * \brief Constructor from a given gdcmElementSet */ -gdcmDocEntrySet::gdcmDocEntrySet() { - +//BOZ depthLevel is not usefull anymore +gdcmElementSet::gdcmElementSet(int depthLevel) + : gdcmDocEntrySet() +{ + (void)depthLevel; } /** @@ -21,11 +41,15 @@ gdcmDocEntrySet::gdcmDocEntrySet() { */ gdcmElementSet::~gdcmElementSet() { -/* for(tous les DocEntry) + for(TagDocEntryHT::iterator cc = TagHT.begin();cc != TagHT.end(); ++cc) { - delete *cc; + gdcmDocEntry* entryToDelete = cc->second; + if ( entryToDelete ) + { + delete entryToDelete; + } } - */ + TagHT.clear(); } @@ -33,120 +57,103 @@ gdcmElementSet::~gdcmElementSet() // Public +//----------------------------------------------------------------------------- +// Print +/** + * \brief Prints the Header Entries (Dicom Elements) + * from the H Table + * @return + */ +void gdcmElementSet::Print(std::ostream& os) +{ + for( TagDocEntryHT::const_iterator i = TagHT.begin(); i != TagHT.end(); ++i) + { + gdcmDocEntry* entry = i->second; + entry->Print(os); + if ( gdcmSeqEntry* seqEntry = dynamic_cast(entry) ) + { + (void)seqEntry; + // Avoid the newline for a sequence: + continue; + } + os << std::endl; + } +} + +/** + * \brief Writes the Header Entries (Dicom Elements) + * from the H Table + * @return + */ +void gdcmElementSet::Write(FILE* fp, FileType filetype) +{ + for (TagDocEntryHT::const_iterator i = TagHT.begin(); i != TagHT.end(); ++i) + { + i->second->Write(fp, filetype); + } +} //----------------------------------------------------------------------------- // Protected +//----------------------------------------------------------------------------- + //----------------------------------------------------------------------------- // Private /** - * \brief Find the value Length of the passed Header Entry - * @param Entry Header Entry whose length of the value shall be loaded. + * \brief add a new Dicom Element pointer to the H Table + * @param newEntry entry to add */ - void gdcmElementSet::FindDocEntryLength (gdcmDocEntry *Entry) { - guint16 element = Entry->GetElement(); - //guint16 group = Entry->GetGroup(); //FIXME - std::string vr = Entry->GetVR(); - guint16 length16; - - - if ( (filetype == ExplicitVR) && (! Entry->IsImplicitVR()) ) +bool gdcmElementSet::AddEntry( gdcmDocEntry* newEntry) +{ + gdcmTagKey key = newEntry->GetKey(); + + if( TagHT.count(key) == 1 ) { - if ( (vr=="OB") || (vr=="OW") || (vr=="SQ") || (vr=="UN") ) - { - // The following reserved two bytes (see PS 3.5-2001, section - // 7.1.2 Data element structure with explicit vr p27) must be - // skipped before proceeding on reading the length on 4 bytes. - fseek(fp, 2L, SEEK_CUR); - guint32 length32 = ReadInt32(); - - if ( (vr == "OB") && (length32 == 0xffffffff) ) - { - Entry->SetLength(FindHeaderEntryLengthOB()); - return; - } - FixHeaderEntryFoundLength(Entry, length32); - return; - } + dbg.Verbose(1, "gdcmElementSet::AddEntry key already present: ", + key.c_str()); + return(false); + } + else + { + TagHT[newEntry->GetKey()] = newEntry; + return true; + } +} - // Length is encoded on 2 bytes. - length16 = ReadInt16(); - - // We can tell the current file is encoded in big endian (like - // Data/US-RGB-8-epicard) when we find the "Transfer Syntax" tag - // and it's value is the one of the encoding of a big endian file. - // In order to deal with such big endian encoded files, we have - // (at least) two strategies: - // * when we load the "Transfer Syntax" tag with value of big endian - // encoding, we raise the proper flags. Then we wait for the end - // of the META group (0x0002) among which is "Transfer Syntax", - // before switching the swap code to big endian. We have to postpone - // the switching of the swap code since the META group is fully encoded - // in little endian, and big endian coding only starts at the next - // group. The corresponding code can be hard to analyse and adds - // many additional unnecessary tests for regular tags. - // * the second strategy consists in waiting for trouble, that shall - // appear when we find the first group with big endian encoding. This - // is easy to detect since the length of a "Group Length" tag (the - // ones with zero as element number) has to be of 4 (0x0004). When we - // encounter 1024 (0x0400) chances are the encoding changed and we - // found a group with big endian encoding. - // We shall use this second strategy. In order to make sure that we - // can interpret the presence of an apparently big endian encoded - // length of a "Group Length" without committing a big mistake, we - // add an additional check: we look in the already parsed elements - // for the presence of a "Transfer Syntax" whose value has to be "big - // endian encoding". When this is the case, chances are we have got our - // hands on a big endian encoded file: we switch the swap code to - // big endian and proceed... - if ( (element == 0x0000) && (length16 == 0x0400) ) - { - if ( ! IsExplicitVRBigEndianTransferSyntax() ) - { - dbg.Verbose(0, "gdcmDocument::FindLength", "not explicit VR"); - errno = 1; - return; - } - length16 = 4; - SwitchSwapToBigEndian(); - // Restore the unproperly loaded values i.e. the group, the element - // and the dictionary entry depending on them. - guint16 CorrectGroup = SwapShort(Entry->GetGroup()); - guint16 CorrectElem = SwapShort(Entry->GetElement()); - gdcmDictEntry * NewTag = GetDictEntryByNumber(CorrectGroup, - CorrectElem); - if (!NewTag) - { - // This correct tag is not in the dictionary. Create a new one. - NewTag = NewVirtualDictEntry(CorrectGroup, CorrectElem); - } - // FIXME this can create a memory leaks on the old entry that be - // left unreferenced. - Entry->SetDictEntry(NewTag); - } - - // Heuristic: well some files are really ill-formed. - if ( length16 == 0xffff) - { - length16 = 0; - //dbg.Verbose(0, "gdcmDocument::FindLength", - // "Erroneous element length fixed."); - // Actually, length= 0xffff means that we deal with - // Unknown Sequence Length - } - FixHeaderEntryFoundLength(Entry, (guint32)length16); - return; +/** + * \brief Clear the hash table from given entry BUT keep the entry. + * @param entryToRemove Entry to remove. + */ +bool gdcmElementSet::RemoveEntryNoDestroy( gdcmDocEntry* entryToRemove) +{ + gdcmTagKey key = entryToRemove->GetKey(); + if( TagHT.count(key) == 1 ) + { + TagHT.erase(key); + dbg.Verbose(0, "gdcmElementSet::RemoveEntry: one element erased."); + return true; } - else + + dbg.Verbose(0, "gdcmElementSet::RemoveEntry: key not present: "); + return false ; +} + +/** + * \brief Clear the hash table from given entry AND delete the entry. + * @param entryToRemove Entry to remove AND delete. + */ +bool gdcmElementSet::RemoveEntry( gdcmDocEntry* entryToRemove) +{ + gdcmTagKey key = entryToRemove->GetKey(); + if( TagHT.count(key) == 1 ) { - // Either implicit VR or a non DICOM conformal (see note below) explicit - // VR that ommited the VR of (at least) this element. Farts happen. - // [Note: according to the part 5, PS 3.5-2001, section 7.1 p25 - // 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. - - FixHeaderEntryFoundLength(Entry, ReadInt32()); - return; + TagHT.erase(key); + dbg.Verbose(0, "gdcmElementSet::RemoveEntry: one element erased."); + delete entryToRemove; + return true; } + + dbg.Verbose(0, "gdcmElementSet::RemoveEntry: key not present: "); + return false ; }