X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=blobdiff_plain;f=src%2FgdcmElementSet.cxx;h=0f332f77b49c7ecc984fc84fefbae66a1342fc96;hb=ecac4d36edf15736ae8f516ef3f9d8a6396ed54c;hp=33325c3fda8ba30b71857eac771eaf988534e90b;hpb=0b36f4932e894a1dde4a80e614755816b4b29218;p=gdcm.git diff --git a/src/gdcmElementSet.cxx b/src/gdcmElementSet.cxx index 33325c3f..0f332f77 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/07/19 03:34:12 $ + Version: $Revision: 1.16 $ + + 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.htm 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,9 @@ * \ingroup gdcmElementSet * \brief Constructor from a given gdcmElementSet */ -gdcmDocEntrySet::gdcmDocEntrySet() { - +gdcmElementSet::gdcmElementSet(int depthLevel) + : gdcmDocEntrySet(depthLevel) +{ } /** @@ -21,11 +39,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 +55,87 @@ 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); + bool PrintEndLine = true; + if ( gdcmSeqEntry* seqEntry = dynamic_cast(entry) ) + { + (void)seqEntry; //not used + PrintEndLine = false; + } + if( PrintEndLine ) + { + 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()) ) - { - 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(); +bool gdcmElementSet::AddEntry( gdcmDocEntry *newEntry) +{ + gdcmTagKey key = newEntry->GetKey(); - if ( (vr == "OB") && (length32 == 0xffffffff) ) - { - Entry->SetLength(FindHeaderEntryLengthOB()); - return; - } - FixHeaderEntryFoundLength(Entry, length32); - return; - } + if( TagHT.count(key) == 1 ) + { + 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; - } - else +/** + * \brief Clear the hash table from given entry. + * @param EntryToRemove Entry to remove. + */ +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."); + return true; } + + dbg.Verbose(0, "gdcmElementSet::RemoveEntry: key not present: "); + return false ; }