GDCM 2.2.1

- Main Page
- Related Pages
- Namespaces
- Classes
- Files
- Examples

- File List
- File Members

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;
45 class GDCM_EXPORT Item : public DataElement
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 }
84 DataSet &GetNestedDataSet()
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