GDCM  2.2.6
gdcmDataSet.h
Go to the documentation of this file.
1 /*=========================================================================
2 
3  Program: GDCM (Grassroots DICOM). A DICOM library
4 
5  Copyright (c) 2006-2011 Mathieu Malaterre
6  All rights reserved.
7  See Copyright.txt or http://gdcm.sourceforge.net/Copyright.html for details.
8 
9  This software is distributed WITHOUT ANY WARRANTY; without even
10  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
11  PURPOSE. See the above copyright notice for more information.
12 
13 =========================================================================*/
14 #ifndef GDCMDATASET_H
15 #define GDCMDATASET_H
16 
17 #include "gdcmDataElement.h"
18 #include "gdcmTag.h"
19 #include "gdcmVR.h"
20 #include "gdcmElement.h"
21 #include "gdcmMediaStorage.h"
22 
23 #include <set>
24 #include <iterator>
25 
26 namespace gdcm
27 {
28 class GDCM_EXPORT DataElementException : public std::exception {};
29 
30 class PrivateTag;
56 {
57  friend class CSAHeader;
58 public:
59  typedef std::set<DataElement> DataElementSet;
60  typedef DataElementSet::const_iterator ConstIterator;
61  typedef DataElementSet::iterator Iterator;
62  typedef DataElementSet::size_type SizeType;
63  //typedef typename DataElementSet::iterator iterator;
64  ConstIterator Begin() const { return DES.begin(); }
65  Iterator Begin() { return DES.begin(); }
66  ConstIterator End() const { return DES.end(); }
67  Iterator End() { return DES.end(); }
68  const DataElementSet &GetDES() const { return DES; }
69  DataElementSet &GetDES() { return DES; }
70  void Clear() {
71  DES.clear();
72  assert( DES.empty() );
73  }
74 
75  SizeType Size() const {
76  return DES.size();
77  }
78 
79  void Print(std::ostream &os, std::string const &indent = "") const {
80  // CT_Phillips_JPEG2K_Decompr_Problem.dcm has a SQ of length == 0
81  //int s = DES.size();
82  //assert( s );
83  //std::copy(DES.begin(), DES.end(),
84  // std::ostream_iterator<DataElement>(os, "\n"));
85  ConstIterator it = DES.begin();
86  for( ; it != DES.end(); ++it)
87  {
88  os << indent << *it << "\n";
89  }
90  }
91 
92  template <typename TDE>
93  unsigned int ComputeGroupLength(Tag const &tag) const
94  {
95  assert( tag.GetElement() == 0x0 );
96  const DataElement r(tag);
97  ConstIterator it = DES.find(r);
98  unsigned int res = 0;
99  for( ++it; it != DES.end()
100  && it->GetTag().GetGroup() == tag.GetGroup(); ++it)
101  {
102  assert( it->GetTag().GetElement() != 0x0 );
103  assert( it->GetTag().GetGroup() == tag.GetGroup() );
104  res += it->GetLength<TDE>();
105  }
106  return res;
107  }
108 
109  template <typename TDE>
110  VL GetLength() const {
111  if( DES.empty() ) return 0;
112  assert( !DES.empty() );
113  VL ll = 0;
114  assert( ll == 0 );
115  ConstIterator it = DES.begin();
116  for( ; it != DES.end(); ++it)
117  {
118  assert( !(it->GetLength<TDE>().IsUndefined()) );
119  if ( it->GetTag() != Tag(0xfffe,0xe00d) )
120  {
121  ll += it->GetLength<TDE>();
122  }
123  }
124  return ll;
125  }
128  void Insert(const DataElement& de) {
129  // FIXME: there is a special case where a dataset can have value < 0x8, see:
130  // $ gdcmdump --csa gdcmData/SIEMENS-JPEG-CorruptFrag.dcm
131  if( de.GetTag().GetGroup() >= 0x0008 || de.GetTag().GetGroup() == 0x4 )
132  {
133  // prevent user error:
134  if( de.GetTag() == Tag(0xfffe,0xe00d)
135  || de.GetTag() == Tag(0xfffe,0xe0dd)
136  || de.GetTag() == Tag(0xfffe,0xe000) )
137  {
138  }
139  else
140  {
141  InsertDataElement( de );
142  }
143  }
144  else
145  {
146  gdcmErrorMacro( "Cannot add element with group < 0x0008 and != 0x4 in the dataset: " << de.GetTag() );
147  }
148  }
150  void Replace(const DataElement& de) {
151  if( DES.find(de) != DES.end() ) DES.erase(de);
152  Insert(de);
153  }
155  void ReplaceEmpty(const DataElement& de) {
156  ConstIterator it = DES.find(de);
157  if( it != DES.end() && it->IsEmpty() )
158  DES.erase(de);
159  Insert(de);
160  }
162  SizeType Remove(const Tag& tag) {
163  DataElementSet::size_type count = DES.erase(tag);
164  assert( count == 0 || count == 1 );
165  return count;
166  }
167 
171  //DataElement& GetDataElement(const Tag &t) {
172  // DataElement r(t);
173  // Iterator it = DES.find(r);
174  // if( it != DES.end() )
175  // return *it;
176  // return GetDEEnd();
177  // }
178  const DataElement& GetDataElement(const Tag &t) const {
179  const DataElement r(t);
180  ConstIterator it = DES.find(r);
181  if( it != DES.end() )
182  return *it;
183  return GetDEEnd();
184  }
185  const DataElement& operator[] (const Tag &t) const { return GetDataElement(t); }
186  const DataElement& operator() (uint16_t group, uint16_t element) const { return GetDataElement( Tag(group,element) ); }
187 
189  std::string GetPrivateCreator(const Tag &t) const;
190 
192  bool FindDataElement(const PrivateTag &t) const;
194  const DataElement& GetDataElement(const PrivateTag &t) const;
195 
196  // DUMB: this only search within the level of the current DataSet
197  bool FindDataElement(const Tag &t) const {
198  const DataElement r(t);
199  //ConstIterator it = DES.find(r);
200  if( DES.find(r) != DES.end() )
201  {
202  return true;
203  }
204  return false;
205  }
206 
207  // WARNING:
208  // This only search at the same level as the DataSet is !
209  const DataElement& FindNextDataElement(const Tag &t) const {
210  const DataElement r(t);
211  ConstIterator it = DES.lower_bound(r);
212  if( it != DES.end() )
213  return *it;
214  return GetDEEnd();
215  }
216 
218  bool IsEmpty() const { return DES.empty(); };
219 
220  DataSet& operator=(DataSet const &val)
221  {
222  DES = val.DES;
223  return *this;
224  }
225 
226 /*
227  template <typename TOperation>
228  void ExecuteOperation(TOperation & operation) {
229  assert( !DES.empty() );
230  DataElementSet::iterator it = Begin();
231  for( ; it != End(); ++it)
232  {
233  DataElement &de = (DataElement&)*it;
234  operation( de );
235  }
236  }
237 */
238 
239  template <typename TDE, typename TSwap>
240  std::istream &ReadNested(std::istream &is);
241 
242  template <typename TDE, typename TSwap>
243  std::istream &Read(std::istream &is);
244 
245  template <typename TDE, typename TSwap>
246  std::istream &ReadUpToTag(std::istream &is, const Tag &t, std::set<Tag> const & skiptags);
247 
248  template <typename TDE, typename TSwap>
249  std::istream &ReadUpToTagWithLength(std::istream &is, const Tag &t, std::set<Tag> const & skiptags, VL & length);
250 
251  template <typename TDE, typename TSwap>
252  std::istream &ReadSelectedTags(std::istream &is, const std::set<Tag> & tags, bool readvalues = true);
253  template <typename TDE, typename TSwap>
254  std::istream &ReadSelectedTagsWithLength(std::istream &is, const std::set<Tag> & tags, VL & length, bool readvalues = true);
255 
256  template <typename TDE, typename TSwap>
257  std::istream &ReadSelectedPrivateTags(std::istream &is, const std::set<PrivateTag> & tags, bool readvalues = true);
258  template <typename TDE, typename TSwap>
259  std::istream &ReadSelectedPrivateTagsWithLength(std::istream &is, const std::set<PrivateTag> & tags, VL & length, bool readvalues = true);
260 
261  template <typename TDE, typename TSwap>
262  std::ostream const &Write(std::ostream &os) const;
263 
264  template <typename TDE, typename TSwap>
265  std::istream &ReadWithLength(std::istream &is, VL &length);
266 
267  MediaStorage GetMediaStorage() const;
268 
269 protected:
270  /* GetDEEnd is a Win32 only issue, one cannot use a dllexported
271  * static member data in an inline function, otherwise symbol
272  * will get reported as missing in any dll using the inlined function
273  */
274  const DataElement& GetDEEnd() const;
275 
276  // This function is not safe, it does not check for the value of the tag
277  // so depending whether we are getting called from a dataset or file meta header
278  // the condition is different
279  void InsertDataElement(const DataElement& de) {
280  //if( de.GetTag() == Tag(0xfffe,0xe00d) ) return;
281  //if( de.GetTag() == Tag(0xfffe,0xe0dd) ) return;
282 #ifndef NDEBUG
283  std::pair<Iterator,bool> pr = DES.insert(de);
284  if( pr.second == false )
285  {
286  gdcmWarningMacro( "DataElement: " << de << " was already found, skipping duplicate entry.\n"
287  "Original entry kept is: " << *pr.first );
288  }
289 #else
290  DES.insert(de);
291 #endif
292  assert( de.IsEmpty() || de.GetVL() == de.GetValue().GetLength() );
293  }
294 
295 protected:
296  // Internal function, that will compute the actual Tag (if found) of
297  // a requested Private Tag (XXXX,YY,"PRIVATE")
298  Tag ComputeDataElement(const PrivateTag & t) const;
299 
300 private:
301  DataElementSet DES;
302  static DataElement DEEnd;
303  friend std::ostream& operator<<(std::ostream &_os, const DataSet &val);
304 };
305 //-----------------------------------------------------------------------------
306 inline std::ostream& operator<<(std::ostream &os, const DataSet &val)
307 {
308  val.Print(os);
309  return os;
310 }
311 
312 #if defined(SWIGPYTHON) || defined(SWIGCSHARP) || defined(SWIGJAVA)
313 /*
314  * HACK: I need this temp class to be able to manipulate a std::set from python,
315  * swig does not support wrapping of simple class like std::set...
316  */
317 class SWIGDataSet
318 {
319 public:
320  SWIGDataSet(DataSet &des):Internal(des),it(des.Begin()) {}
321  const DataElement& GetCurrent() const { return *it; }
322  void Start() { it = Internal.Begin(); }
323  bool IsAtEnd() const { return it == Internal.End(); }
324  void Next() { ++it; }
325 private:
326  DataSet & Internal;
328 };
329 #endif /* SWIG */
330 
336 } // end namespace gdcm
337 
338 #include "gdcmDataSet.txx"
339 
340 #endif //GDCMDATASET_H
void Print(std::ostream &os, std::string const &indent="") const
Definition: gdcmDataSet.h:79
bool IsEmpty() const
Check if Data Element is empty.
Definition: gdcmDataElement.h:103
const DataElement & FindNextDataElement(const Tag &t) const
Definition: gdcmDataSet.h:209
Class for CSAHeader.
Definition: gdcmCSAHeader.h:62
Class to represent a Data Set (which contains Data Elements) A Data Set represents an instance of a r...
Definition: gdcmDataSet.h:55
bool FindDataElement(const Tag &t) const
Definition: gdcmDataSet.h:197
const DataElement & GetDataElement(const Tag &t) const
Definition: gdcmDataSet.h:178
const DataElementSet & GetDES() const
Definition: gdcmDataSet.h:68
DataElementSet & GetDES()
Definition: gdcmDataSet.h:69
unsigned int ComputeGroupLength(Tag const &tag) const
Definition: gdcmDataSet.h:93
Class to represent a Private DICOM Data Element (Attribute) Tag (Group, Element, Owner) ...
Definition: gdcmPrivateTag.h:38
const VL & GetVL() const
Get VL.
Definition: gdcmDataElement.h:74
#define GDCM_EXPORT
Definition: gdcmWin32.h:34
#define gdcmWarningMacro(msg)
Warning.
Definition: gdcmTrace.h:141
void ReplaceEmpty(const DataElement &de)
Only replace a DICOM attribute when it is missing or empty.
Definition: gdcmDataSet.h:155
DataElementSet::size_type SizeType
Definition: gdcmDataSet.h:62
Value Length.
Definition: gdcmVL.h:29
uint16_t GetElement() const
Returns the &#39;Element number&#39; of the given Tag.
Definition: gdcmTag.h:57
std::ostream & operator<<(std::ostream &os, const Directory &d)
Definition: gdcmDirectory.h:92
std::set< DataElement > DataElementSet
Definition: gdcmDataSet.h:59
DataElementSet::iterator Iterator
Definition: gdcmDataSet.h:61
Class to represent a Data Element either Implicit or Explicit.
Definition: gdcmDataElement.h:58
void Insert(const DataElement &de)
Definition: gdcmDataSet.h:128
Definition: gdcmDataSet.h:28
Value const & GetValue() const
Set/Get Value (bytes array, SQ of items, SQ of fragments):
Definition: gdcmDataElement.h:94
SizeType Size() const
Definition: gdcmDataSet.h:75
void InsertDataElement(const DataElement &de)
Definition: gdcmDataSet.h:279
void Clear()
Definition: gdcmDataSet.h:70
bool IsEmpty() const
Returns if the dataset is empty.
Definition: gdcmDataSet.h:218
virtual VL GetLength() const =0
const Tag & GetTag() const
Get Tag.
Definition: gdcmDataElement.h:67
Iterator End()
Definition: gdcmDataSet.h:67
DataElementSet::const_iterator ConstIterator
Definition: gdcmDataSet.h:60
DataSet & operator=(DataSet const &val)
Definition: gdcmDataSet.h:220
#define gdcmErrorMacro(msg)
Error this is pretty bad, more than just warning It could mean lost of data, something not handle...
Definition: gdcmTrace.h:163
Class to represent a DICOM Data Element (Attribute) Tag (Group, Element). Basically an uint32_t which...
Definition: gdcmTag.h:38
uint16_t GetGroup() const
Returns the &#39;Group number&#39; of the given Tag.
Definition: gdcmTag.h:55
void Replace(const DataElement &de)
Replace a dataelement with another one.
Definition: gdcmDataSet.h:150
Iterator Begin()
Definition: gdcmDataSet.h:65
VL GetLength() const
Definition: gdcmDataSet.h:110
ConstIterator Begin() const
Definition: gdcmDataSet.h:64
ConstIterator End() const
Definition: gdcmDataSet.h:66
MediaStorage.
Definition: gdcmMediaStorage.h:41
SizeType Remove(const Tag &tag)
Completely remove a dataelement from the dataset.
Definition: gdcmDataSet.h:162

Generated on Sat Dec 21 2013 05:56:16 for GDCM by doxygen 1.8.5
SourceForge.net Logo