]> Creatis software - gdcm.git/blob - src/gdcmElementSet.cxx
re indent
[gdcm.git] / src / gdcmElementSet.cxx
1 /*=========================================================================
2                                                                                 
3   Program:   gdcm
4   Module:    $RCSfile: gdcmElementSet.cxx,v $
5   Language:  C++
6   Date:      $Date: 2008/05/19 09:25:42 $
7   Version:   $Revision: 1.80 $
8                                                                                 
9   Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
10   l'Image). All rights reserved. See Doc/License.txt or
11   http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
12                                                                                 
13      This software is distributed WITHOUT ANY WARRANTY; without even
14      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15      PURPOSE.  See the above copyright notices for more information.
16                                                                                 
17 =========================================================================*/
18
19 #include "gdcmElementSet.h"
20 #include "gdcmDebug.h"
21 #include "gdcmSeqEntry.h"
22 #include "gdcmDataEntry.h"
23
24 namespace GDCM_NAME_SPACE 
25 {
26 //-----------------------------------------------------------------------------
27 // Constructor / Destructor
28 /**
29  * \brief   Constructor for a given ElementSet
30  */
31 ElementSet::ElementSet() 
32           : DocEntrySet()
33 {
34 }
35
36 /**
37  * \brief   Canonical destructor.
38  */
39 ElementSet::~ElementSet() 
40 {
41    ClearEntry();
42 }
43
44 //-----------------------------------------------------------------------------
45 // Public
46 /**
47   * \brief   Writes the Header Entries (Dicom Elements)
48   *          from the H Table
49   * @param fp ofstream to write to  
50   * @param filetype    ExplicitVR/ImplicitVR/ACR/ACR_LIBIDO/JPEG/JPEG2000/...
51   */ 
52 void ElementSet::WriteContent(std::ofstream *fp, FileType filetype, bool dummy, bool dummy2)
53 {
54    bool insideMetaElements     = false;
55    bool yetOutsideMetaElements = false;
56    (void)dummy2;(void)dummy;
57    
58    for (TagDocEntryHT::const_iterator i = TagHT.begin(); 
59                                      i != TagHT.end(); 
60                                     ++i)
61    {
62         int group = (i->second)->GetGroup();
63        
64        if (yetOutsideMetaElements==false && group == 0x0002)
65           insideMetaElements = true;
66     
67        if (insideMetaElements == true && group != 0x0002)
68        {
69           yetOutsideMetaElements = true;
70           insideMetaElements     = false;
71        }
72    
73        // depending on the gdcm::Document type 
74        // (gdcm::File; gdcm::DicomDir, (more to come ?)
75        // some groups *cannot* be present.
76        // We hereby protect gdcm for writting stupid things
77        // if they were found in the original document. 
78        if ( !MayIWrite( group ) )
79           continue;
80   
81       // Skip 'Group Length' element, since it may be wrong.
82       //       except for Group 0x0002
83       // ( keep it as well for Group 0x0008 of ACR Files, 
84       //  since some ACR readers *need* it )
85       
86        if ( (i->second)->GetElement() != 0x0000 
87            || 
88             (  (i->second)->GetGroup() == 0x0002 
89              ||( (filetype == ACR || filetype == ACR_LIBIDO ) && (i->second)->GetGroup() == 0x0008 ) )
90         )
91        {           
92              // There are DocEntries, written recursively
93              // false : we are outside any Sequence
94              i->second->WriteContent(fp, filetype, insideMetaElements, false );
95        }             
96    } 
97 }
98
99 /**
100  * \brief   add a new Dicom Element pointer to the H Table
101  * @param   newEntry entry to add
102  */
103 bool ElementSet::AddEntry(DocEntry *newEntry)
104 {
105    const TagKey &key = newEntry->GetKey();
106
107    if ( TagHT.count(key) == 1 )
108    {
109       gdcmWarningMacro( "Key already present: " << key );
110       return false;
111    }
112    else
113    {
114       TagHT.insert(TagDocEntryHT::value_type(newEntry->GetKey(), newEntry));
115       newEntry->Register();
116       return true;
117    }
118 }
119
120 /**
121  * \brief   Clear the hash table from given entry AND delete the entry.
122  * @param   entryToRemove Entry to remove AND delete.
123  */
124 bool ElementSet::RemoveEntry( DocEntry *entryToRemove)
125 {
126    const TagKey &key = entryToRemove->GetKey();
127    if ( TagHT.count(key) == 1 )
128    {
129       TagHT.erase(key);
130       entryToRemove->Unregister();
131       return true;
132    }
133
134    gdcmWarningMacro( "Key not present : " << key);
135    return false ;
136 }
137
138 /**
139  * \brief   delete all entries in the ElementSet
140  */
141 void ElementSet::ClearEntry()
142 {
143    for(TagDocEntryHT::iterator cc = TagHT.begin();cc != TagHT.end(); ++cc)
144    {
145       if ( cc->second )
146       {
147          cc->second->Unregister();
148       }
149    }
150    TagHT.clear();
151 }
152
153 /**
154  * \brief   Get the first entry while visiting *the* 'zero level' DocEntrySet
155  *              (DocEntries out of any Sequence)
156  * \return  The first DocEntry if found, otherwhise NULL
157  */
158 DocEntry *ElementSet::GetFirstEntry()
159 {
160    ItTagHT = TagHT.begin();
161    if (ItTagHT != TagHT.end())
162       return  ItTagHT->second;
163    return NULL;
164 }
165
166 /**
167  * \brief   Get the next entry while visiting *the* 'zero level' DocEntrySet
168  *              (DocEntries out of any Sequence) 
169  * \note : meaningfull only if GetFirstEntry already called 
170  * \return  The next DocEntry if found, otherwhise NULL
171  */
172 DocEntry *ElementSet::GetNextEntry()
173 {
174    gdcmAssertMacro (ItTagHT != TagHT.end());
175
176    ++ItTagHT;
177    if (ItTagHT != TagHT.end())
178       return  ItTagHT->second;
179    return NULL;
180 }
181
182 /**
183  * \brief  retrieves a Dicom Element using (group, element)
184  * @param   group  Group number of the searched Dicom Element 
185  * @param   elem Element number of the searched Dicom Element 
186  * @return  
187  */
188 DocEntry *ElementSet::GetDocEntry(uint16_t group, uint16_t elem) 
189 {
190    TagKey key = DictEntry::TranslateToKey(group, elem);
191    TagDocEntryHT::iterator it = TagHT.find(key);
192
193    if ( it!=TagHT.end() )
194       return it->second;
195    return NULL;
196 }
197
198 /**
199  * \brief Copies all the attributes from an other DocEntrySet 
200  * @param set entry to copy from
201  * @remarks The contained DocEntries a not copied, only referenced
202  */
203 void ElementSet::Copy(DocEntrySet *set)
204 {
205    // Remove all previous entries
206    ClearEntry();
207
208    DocEntrySet::Copy(set);
209
210    ElementSet *eltSet = dynamic_cast<ElementSet *>(set);
211    if( eltSet )
212    {
213       TagHT = eltSet->TagHT;
214       for(ItTagHT = TagHT.begin();ItTagHT != TagHT.end();++ItTagHT)
215       {
216          (ItTagHT->second)->Register();
217       }
218    }
219 }
220
221 /**
222  * \brief Checks whether *all* the DataEntries of the group have all
223  *        the same type for VR (ImplicitVR or ExplicitVR) 
224  * @param group group number to be checked
225  * @return 1:ImplicitVR 2:ExplicitVR -1:NotCoherent 
226  */
227 int ElementSet::IsVRCoherent( uint16_t group )
228 {
229    uint16_t currentGroup;
230    int codeVR = -1;
231    int currentCodeVR;
232    for(TagDocEntryHT::iterator cc = TagHT.begin();cc != TagHT.end(); ++cc)
233    {
234       currentGroup = cc->second->GetGroup();
235
236       if ( currentGroup < group )
237          continue;   
238       if ( currentGroup > group )
239          break;
240       // currentGroup == group
241       if (codeVR == -1)
242       {
243          if (cc->second->IsImplicitVR() )
244             codeVR = 1;
245          else 
246             codeVR = 2;
247          continue;
248       }
249       else
250       {
251          if (cc->second->IsImplicitVR() )
252             currentCodeVR = 1; //Implicit
253          else 
254             currentCodeVR = 2; // Explicit  
255   
256          if ( currentCodeVR == codeVR )
257            continue;
258          else
259             return -1;    // -1 : not coherent 
260       }
261    }   
262    return codeVR;
263 }
264
265
266 //-----------------------------------------------------------------------------
267 // Protected
268
269 //-----------------------------------------------------------------------------
270 // Private
271
272 //-----------------------------------------------------------------------------
273 // Print
274 /**
275   * \brief   Prints the Header Entries (Dicom Elements) from the H Table
276   * @param os ostream to write to  
277   * @param indent Indentation string to be prepended during printing
278   */ 
279 void ElementSet::Print(std::ostream &os, std::string const & )
280 {
281    // Let's change the 'warning value' for Pixel Data,
282    // to avoid human reader to be confused by 'gdcm::NotLoaded'.   
283    DataEntry *pixelElement = GetDataEntry(0x7fe0,0x0010);
284    if ( pixelElement != 0 )
285    {
286       pixelElement->SetFlag( DataEntry::FLAG_PIXELDATA );
287    }
288
289    for( TagDocEntryHT::const_iterator i = TagHT.begin(); i != TagHT.end(); ++i)
290    {
291       DocEntry *entry = i->second;
292
293       entry->SetPrintLevel(PrintLevel);
294       entry->Print(os);   
295
296       if ( dynamic_cast<SeqEntry*>(entry) )
297       {
298          // Avoid the newline for a sequence:
299          continue;
300       }
301       os << std::endl;
302    }
303 }
304
305 //-----------------------------------------------------------------------------
306 } // end namespace gdcm