GDCM 3.0.24
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
27namespace gdcm_ns
28{
29
30class DataSet;
46{
47public:
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
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 write 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( "SeqDelItem 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/*
297There are three special SQ related Data Elements that are not ruled by the VR encoding rules conveyed
298by 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).
300However, the Data Set within the Value Field of the Data Element Item (FFFE,E000) shall be encoded
301according to the rules conveyed by the Transfer Syntax.
302*/
303 bool FindDataElement(const Tag &t) const {
304 return NestedDataSet.FindDataElement( t );
305 }
306
307private:
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//-----------------------------------------------------------------------------
315inline 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
ByteSwapFilter.
Definition gdcmByteSwapFilter.h:28
void SetByteSwapTag(bool b)
Definition gdcmByteSwapFilter.h:36
Class to represent a Data Element either Implicit or Explicit.
Definition gdcmDataElement.h:59
Tag TagField
Definition gdcmDataElement.h:243
VL ValueLengthField
Definition gdcmDataElement.h:245
Class to represent a Data Set (which contains Data Elements)
Definition gdcmDataSet.h:56
void Clear()
Definition gdcmDataSet.h:70
bool IsEmpty() const
Returns if the dataset is empty.
Definition gdcmDataSet.h:228
void Print(std::ostream &os, std::string const &indent="") const
Definition gdcmDataSet.h:79
Exception.
Definition gdcmException.h:44
Class to represent an Item.
Definition gdcmItem.h:46
Item()
Definition gdcmItem.h:48
VL GetLength() const
const DataElement & GetDataElement(const Tag &t) const
Definition gdcmItem.h:68
Item(Item const &val)
Definition gdcmItem.h:91
void Clear()
Definition gdcmItem.h:51
std::istream & Read(std::istream &is)
Definition gdcmItem.h:97
DataSet & GetNestedDataSet()
Definition gdcmItem.h:84
void SetNestedDataSet(const DataSet &nested)
Definition gdcmItem.h:75
const DataSet & GetNestedDataSet() const
Definition gdcmItem.h:80
void InsertDataElement(const DataElement &de)
Definition gdcmItem.h:59
const std::ostream & Write(std::ostream &os) const
Definition gdcmItem.h:239
bool FindDataElement(const Tag &t) const
Definition gdcmItem.h:303
ParseException Standard exception handling object.
Definition gdcmParseException.h:37
Definition gdcmSwapper.h:54
Class to represent a DICOM Data Element (Attribute) Tag (Group, Element).
Definition gdcmTag.h:39
const std::ostream & Write(std::ostream &os) const
Write a tag in binary rep.
Definition gdcmTag.h:169
Value Length.
Definition gdcmVL.h:30
const std::ostream & Write(std::ostream &os) const
Definition gdcmVL.h:99
VL GetLength() const
Definition gdcmVL.h:68
#define gdcmWarningMacro(msg)
Warning.
Definition gdcmTrace.h:142
#define gdcmErrorMacro(msg)
Error this is pretty bad, more than just warning It could mean lost of data, something not handle....
Definition gdcmTrace.h:165
#define gdcmDebugMacro(msg)
Debug.
Definition gdcmTrace.h:119
#define GDCM_EXPORT
Definition gdcmWin32.h:34
std::ostream & operator<<(std::ostream &os, const Directory &d)
Definition gdcmDirectory.h:88