GDCM  2.2.6
gdcmItem.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 
15 #ifndef GDCMITEM_H
16 #define GDCMITEM_H
17 
18 #include "gdcmDataElement.h"
19 #include "gdcmDataSet.h"
20 #include "gdcmParseException.h"
21 #include "gdcmSwapper.h"
22 
23 #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION
24 #include "gdcmByteSwapFilter.h"
25 #endif
26 
27 namespace gdcm
28 {
29 
30 class DataSet;
46 {
47 public:
48  Item() : DataElement(Tag(0xfffe, 0xe000), 0xFFFFFFFF), NestedDataSet() {}
49  friend std::ostream& operator<< (std::ostream &os, const Item &val);
50 
51  void Clear() {
52  this->DataElement::Clear();
53  NestedDataSet.Clear();
54  }
55 
56  template <typename TDE>
57  VL GetLength() const;
58 
59  void InsertDataElement(const DataElement & de) {
60  NestedDataSet.Insert(de);
61  // Update the length
62  if( !IsUndefinedLength() )
63  {
64  assert( 0 && "InsertDataElement" );
65  //ValueLengthField += de.GetLength();
66  }
67  }
68  const DataElement& GetDataElement(const Tag& t) const
69  {
70  return NestedDataSet.GetDataElement(t);
71  }
72 
73  // Completely defines it with the nested dataset
74  // destroy anything present
75  void SetNestedDataSet(const DataSet& nested)
76  {
77  NestedDataSet = nested;
78  }
79  // Return a const ref to the Nested Data Set
80  const DataSet &GetNestedDataSet() const
81  {
82  return NestedDataSet;
83  }
85  {
86  return NestedDataSet;
87  }
88 
89  //Value const & GetValue() const { return *NestedDataSet; }
90 
91  Item(Item const &val):DataElement(val)
92  {
93  NestedDataSet = val.NestedDataSet;
94  }
95 
96  template <typename TDE, typename TSwap>
97  std::istream &Read(std::istream &is) {
98  // Superclass
99  {
100  DataSet &nested = NestedDataSet;
101  nested.Clear();
102  assert( nested.IsEmpty() );
103  }
104  if( !TagField.Read<TSwap>(is) )
105  {
106  throw Exception("Should not happen (item)");
107  return is;
108  }
109 #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION
110  // MR_Philips_Intera_SwitchIndianess_noLgtSQItem_in_trueLgtSeq.dcm
111  if( TagField == Tag(0xfeff, 0x00e0)
112  || TagField == Tag(0xfeff, 0xdde0) )
113  {
114  gdcmWarningMacro( "ByteSwaping Private SQ: " << TagField );
115  // Invert previously read TagField since wrong endianess:
116  TagField = Tag( SwapperDoOp::Swap( TagField.GetGroup() ), SwapperDoOp::Swap( TagField.GetElement() ) );
117  assert ( TagField == Tag(0xfffe, 0xe000)
118  || TagField == Tag(0xfffe, 0xe0dd) );
119 
120  if( !ValueLengthField.Read<SwapperDoOp>(is) )
121  {
122  assert(0 && "Should not happen");
123  return is;
124  }
125  // Self
126  // Some file written by GDCM 1.0 we writting 0xFFFFFFFF instead of 0x0
127  if( TagField == Tag(0xfffe,0xe0dd) )
128  {
129  if( ValueLengthField )
130  {
131  gdcmErrorMacro( "ValueLengthField is not 0" );
132  }
133  }
134  //else if( ValueLengthField == 0 )
135  // {
136  // //assert( TagField == Tag( 0xfffe, 0xe0dd) );
137  // if( TagField != Tag( 0xfffe, 0xe0dd) )
138  // {
139  // gdcmErrorMacro( "SQ: " << TagField << " has a length of 0" );
140  // }
141  // }
142  else if( ValueLengthField.IsUndefined() )
143  {
144  DataSet &nested = NestedDataSet;
145  nested.Clear();
146  assert( nested.IsEmpty() );
147  std::streampos start = is.tellg();
148  try
149  {
150  nested.template ReadNested<TDE,SwapperDoOp>(is);
151  ByteSwapFilter bsf(nested);
152  bsf.ByteSwap();
153  }
154  catch(ParseException &pe)
155  {
156  (void)pe;
157  // MR_Philips_Intera_PrivateSequenceExplicitVR_in_SQ_2001_e05f_item_wrong_lgt_use_NOSHADOWSEQ.dcm
158  // You have to byteswap the length but not the tag...sigh
159  gdcmWarningMacro( "Attempt to read nested Item without byteswapping the Value Length." );
160  start -= is.tellg();
161  assert( start < 0 );
162  is.seekg( start, std::ios::cur );
163  nested.Clear();
164  nested.template ReadNested<TDE,SwapperNoOp>(is);
165  ByteSwapFilter bsf(nested);
166  // Tag are read in big endian, need to byteswap them back...
167  bsf.SetByteSwapTag(true);
168  bsf.ByteSwap();
169  }
170  catch(Exception &e)
171  {
172  // MR_Philips_Intera_No_PrivateSequenceImplicitVR.dcm
173  throw e;
174  }
175  catch(...)
176  {
177  assert(0);
178  }
179  }
180  else /* if( ValueLengthField.IsUndefined() ) */
181  {
182  DataSet &nested = NestedDataSet;
183  nested.Clear();
184  assert( nested.IsEmpty() );
185  nested.template ReadWithLength<TDE,SwapperDoOp>(is, ValueLengthField);
186  ByteSwapFilter bsf(nested);
187  bsf.ByteSwap();
188  }
189  return is;
190  }
191  // http://groups.google.com/group/comp.protocols.dicom/msg/c07efcf5e759fc83
192  // Bug_Philips_ItemTag_3F3F.dcm
193  if( TagField == Tag(0x3f3f, 0x3f00) )
194  {
195  //TagField = Tag(0xfffe, 0xe000);
196  }
197 #endif
198  if( TagField != Tag(0xfffe, 0xe000) && TagField != Tag(0xfffe, 0xe0dd) )
199  {
200  gdcmDebugMacro( "Invalid Item, found tag: " << TagField);
201  throw Exception( "Not a valid Item" );
202  }
203  assert( TagField == Tag(0xfffe, 0xe000) || TagField == Tag(0xfffe, 0xe0dd) );
204 
205  if( !ValueLengthField.Read<TSwap>(is) )
206  {
207  assert(0 && "Should not happen");
208  return is;
209  }
210  // Self
211  if( TagField == Tag(0xfffe,0xe0dd) )
212  {
213  // Some file written by GDCM 1.0 were written with 0xFFFFFFFF instead of 0x0
214  if( ValueLengthField )
215  {
216  gdcmDebugMacro( "ValueLengthField is not 0 but " << ValueLengthField );
217  }
218  }
219  else if( ValueLengthField.IsUndefined() )
220  {
221  DataSet &nested = NestedDataSet;
222  nested.Clear();
223  assert( nested.IsEmpty() );
224  nested.template ReadNested<TDE,TSwap>(is);
225  }
226  else /* if( ValueLengthField.IsUndefined() ) */
227  {
228  assert( !ValueLengthField.IsUndefined() );
229  DataSet &nested = NestedDataSet;
230  nested.Clear();
231  assert( nested.IsEmpty() );
232  nested.template ReadWithLength<TDE,TSwap>(is, ValueLengthField);
233  }
234 
235  return is;
236  }
237 
238  template <typename TDE, typename TSwap>
239  const std::ostream &Write(std::ostream &os) const {
240 #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION
241  if( TagField == Tag(0x3f3f,0x3f00) && false )
242  {
243  Tag t(0xfffe, 0xe000);
244  t.Write<TSwap>(os);
245  }
246  else
247 #endif
248  {
249  assert ( TagField == Tag(0xfffe, 0xe000)
250  || TagField == Tag(0xfffe, 0xe0dd) );
251  // Not sure how this happen
252  if( TagField == Tag(0xfffe, 0xe0dd) )
253  {
254  gdcmWarningMacro( "SegDelItem found in defined length Sequence" );
255  assert( ValueLengthField == 0 );
256  assert( NestedDataSet.Size() == 0 );
257  }
258  if( !TagField.Write<TSwap>(os) )
259  {
260  assert(0 && "Should not happen");
261  return os;
262  }
263  }
264  if( ValueLengthField.IsUndefined() )
265  {
266  if( !ValueLengthField.Write<TSwap>(os) )
267  {
268  assert(0 && "Should not happen");
269  return os;
270  }
271  }
272  else
273  {
274  VL dummy = NestedDataSet.GetLength<TDE>();
275  //assert( ValueLengthField == dummy );
276  if( !dummy.Write<TSwap>(os) )
277  {
278  assert(0 && "Should not happen");
279  return os;
280  }
281  }
282  // Self
283  NestedDataSet.Write<TDE,TSwap>(os);
284  if( ValueLengthField.IsUndefined() )
285  {
286  const Tag itemDelItem(0xfffe,0xe00d);
287  itemDelItem.Write<TSwap>(os);
288  VL zero = 0;
289  zero.Write<TSwap>(os);
290  }
291 
292  return os;
293  }
294 
295 /*
296 There are three special SQ related Data Elements that are not ruled by the VR encoding rules conveyed
297 by the Transfer Syntax. They shall be encoded as Implicit VR. These special Data Elements are Item
298 (FFFE,E000), Item Delimitation Item (FFFE,E00D), and Sequence Delimitation Item (FFFE,E0DD).
299 However, the Data Set within the Value Field of the Data Element Item (FFFE,E000) shall be encoded
300 according to the rules conveyed by the Transfer Syntax.
301 */
302  bool FindDataElement(const Tag &t) const {
303  return NestedDataSet.FindDataElement( t );
304  }
305 
306 private:
307  /* NESTED DATA SET a Data Set contained within a Data Element of an other Data Set.
308  * May be nested recursively.
309  * Only Data Elements with VR = SQ may, themselves, contain Data Sets
310  */
311  DataSet NestedDataSet;
312 };
313 //-----------------------------------------------------------------------------
314 inline std::ostream& operator<<(std::ostream& os, const Item &val)
315 {
316  os << val.TagField;
317  os << "\t" << val.ValueLengthField << "\n";
318  val.NestedDataSet.Print( os, "\t" );
319 
320  return os;
321 }
322 
323 
324 } // end namespace gdcm
325 
326 #include "gdcmItem.txx"
327 
328 #endif //GDCMITEM_H
void Print(std::ostream &os, std::string const &indent="") const
Definition: gdcmDataSet.h:79
Class to represent a Data Set (which contains Data Elements) A Data Set represents an instance of a r...
Definition: gdcmDataSet.h:55
VL GetLength() const
Definition: gdcmVL.h:68
void InsertDataElement(const DataElement &de)
Definition: gdcmItem.h:59
std::istream & Read(std::istream &is)
Definition: gdcmItem.h:97
#define GDCM_EXPORT
Definition: gdcmWin32.h:34
void SetNestedDataSet(const DataSet &nested)
Definition: gdcmItem.h:75
#define gdcmWarningMacro(msg)
Warning.
Definition: gdcmTrace.h:141
Value Length.
Definition: gdcmVL.h:29
#define gdcmDebugMacro(msg)
Debug.
Definition: gdcmTrace.h:119
ParseException Standard exception handling object.
Definition: gdcmParseException.h:26
std::ostream & operator<<(std::ostream &os, const Directory &d)
Definition: gdcmDirectory.h:92
VL ValueLengthField
Definition: gdcmDataElement.h:259
Item(Item const &val)
Definition: gdcmItem.h:91
const std::ostream & Write(std::ostream &os) const
Write a tag in binary rep.
Definition: gdcmTag.h:169
Class to represent a Data Element either Implicit or Explicit.
Definition: gdcmDataElement.h:58
Class to represent an Item A component of the value of a Data Element that is of Value Representation...
Definition: gdcmItem.h:45
const DataElement & GetDataElement(const Tag &t) const
Definition: gdcmItem.h:68
bool FindDataElement(const Tag &t) const
Definition: gdcmItem.h:302
const std::ostream & Write(std::ostream &os) const
Definition: gdcmVL.h:99
void Clear()
Clear Data Element (make Value empty and invalidate Tag &amp; VR)
Definition: gdcmDataElement.h:109
const std::ostream & Write(std::ostream &os) const
Definition: gdcmItem.h:239
ByteSwapFilter In place byte-swapping of a dataset FIXME: FL status ??
Definition: gdcmByteSwapFilter.h:27
void Clear()
Definition: gdcmDataSet.h:70
bool IsEmpty() const
Returns if the dataset is empty.
Definition: gdcmDataSet.h:218
Definition: gdcmSwapper.h:53
DataSet & GetNestedDataSet()
Definition: gdcmItem.h:84
Item()
Definition: gdcmItem.h:48
const DataSet & GetNestedDataSet() const
Definition: gdcmItem.h:80
#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
Tag TagField
Definition: gdcmDataElement.h:257
void Clear()
Definition: gdcmItem.h:51
Exception.
Definition: gdcmException.h:33
static T Swap(T val)

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