GDCM  2.4.5
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_ns
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 endianness:
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  const VL dummy = NestedDataSet.GetLength<TDE>();
275  assert( dummy % 2 == 0 );
276  //assert( ValueLengthField == dummy );
277  if( !dummy.Write<TSwap>(os) )
278  {
279  assert(0 && "Should not happen");
280  return os;
281  }
282  }
283  // Self
284  NestedDataSet.Write<TDE,TSwap>(os);
285  if( ValueLengthField.IsUndefined() )
286  {
287  const Tag itemDelItem(0xfffe,0xe00d);
288  itemDelItem.Write<TSwap>(os);
289  VL zero = 0;
290  zero.Write<TSwap>(os);
291  }
292 
293  return os;
294  }
295 
296 /*
297 There are three special SQ related Data Elements that are not ruled by the VR encoding rules conveyed
298 by the Transfer Syntax. They shall be encoded as Implicit VR. These special Data Elements are Item
299 (FFFE,E000), Item Delimitation Item (FFFE,E00D), and Sequence Delimitation Item (FFFE,E0DD).
300 However, the Data Set within the Value Field of the Data Element Item (FFFE,E000) shall be encoded
301 according to the rules conveyed by the Transfer Syntax.
302 */
303  bool FindDataElement(const Tag &t) const {
304  return NestedDataSet.FindDataElement( t );
305  }
306 
307 private:
308  /* NESTED DATA SET a Data Set contained within a Data Element of an other Data Set.
309  * May be nested recursively.
310  * Only Data Elements with VR = SQ may, themselves, contain Data Sets
311  */
312  DataSet NestedDataSet;
313 };
314 //-----------------------------------------------------------------------------
315 inline std::ostream& operator<<(std::ostream& os, const Item &val)
316 {
317  os << val.TagField;
318  os << "\t" << val.ValueLengthField << "\n";
319  val.NestedDataSet.Print( os, "\t" );
320 
321  return os;
322 }
323 
324 
325 } // end namespace gdcm_ns
326 
327 #include "gdcmItem.txx"
328 
329 #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:36
VL ValueLengthField
Definition: gdcmDataElement.h:248
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
std::ostream & operator<<(std::ostream &os, const Item &val)
Definition: gdcmItem.h:315
const DataElement & GetDataElement(const Tag &t) const
Definition: gdcmItem.h:68
bool FindDataElement(const Tag &t) const
Definition: gdcmItem.h:303
const std::ostream & Write(std::ostream &os) const
Definition: gdcmVL.h:99
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:246
void Clear()
Definition: gdcmItem.h:51
Exception.
Definition: gdcmException.h:43

Generated on Fri Sep 25 2015 17:58:23 for GDCM by doxygen 1.8.9.1
SourceForge.net Logo