GDCM 3.2.1

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;
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 gdcm_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 gdcm_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 gdcm_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 // //gdcm_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 gdcm_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 gdcm_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 gdcm_assert(0);
178 }
179 }
180 else /* if( ValueLengthField.IsUndefined() ) */
181 {
182 DataSet &nested = NestedDataSet;
183 nested.Clear();
184 gdcm_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 gdcm_assert( TagField == Tag(0xfffe, 0xe000) || TagField == Tag(0xfffe, 0xe0dd) );
204
205 if( !ValueLengthField.Read<TSwap>(is) )
206 {
207 gdcm_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 gdcm_assert( nested.IsEmpty() );
224 nested.template ReadNested<TDE,TSwap>(is);
225 }
226 else /* if( ValueLengthField.IsUndefined() ) */
227 {
228 gdcm_assert( !ValueLengthField.IsUndefined() );
229 DataSet &nested = NestedDataSet;
230 nested.Clear();
231 gdcm_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 gdcm_assert( ValueLengthField == 0 );
256 gdcm_assert( NestedDataSet.Size() == 0 );
257 }
258 if( !TagField.Write<TSwap>(os) )
259 {
260 gdcm_assert(0 && "Should not happen");
261 return os;
262 }
263 }
264 if( ValueLengthField.IsUndefined() )
265 {
266 if( !ValueLengthField.Write<TSwap>(os) )
267 {
268 gdcm_assert(0 && "Should not happen");
269 return os;
270 }
271 }
272 else
273 {
274 const VL dummy = NestedDataSet.GetLength<TDE>();
275 gdcm_assert( dummy % 2 == 0 );
276 //gdcm_assert( ValueLengthField == dummy );
277 if( !dummy.Write<TSwap>(os) )
278 {
279 gdcm_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
gdcm::ByteSwapFilter
ByteSwapFilter.
Definition gdcmByteSwapFilter.h:28
gdcm::ByteSwapFilter::SetByteSwapTag
void SetByteSwapTag(bool b)
Definition gdcmByteSwapFilter.h:36
gdcm::ByteSwapFilter::ByteSwap
bool ByteSwap()
gdcm::DataElement::Clear
void Clear()
Clear Data Element (make Value empty and invalidate Tag & VR)
Definition gdcmDataElement.h:112
gdcm::DataElement::IsUndefinedLength
bool IsUndefinedLength() const
return if Value Length if of undefined length
Definition gdcmDataElement.h:153
gdcm::DataElement::TagField
Tag TagField
Definition gdcmDataElement.h:243
gdcm::DataElement::ReadWithLength
std::istream & ReadWithLength(std::istream &is, VL &length)
Definition gdcmDataElement.h:233
gdcm::DataElement::ValueLengthField
VL ValueLengthField
Definition gdcmDataElement.h:245
gdcm::DataElement::DataElement
DataElement(const Tag &t=Tag(0), const VL &vl=0, const VR &vr=VR::INVALID)
Definition gdcmDataElement.h:61
gdcm::DataSet
Class to represent a Data Set (which contains Data Elements)
Definition gdcmDataSet.h:56
gdcm::DataSet::Clear
void Clear()
Definition gdcmDataSet.h:70
gdcm::DataSet::IsEmpty
bool IsEmpty() const
Returns if the dataset is empty.
Definition gdcmDataSet.h:228
gdcm::DataSet::Print
void Print(std::ostream &os, std::string const &indent="") const
Definition gdcmDataSet.h:79
gdcm::Exception
Exception.
Definition gdcmException.h:46
gdcm::Item
Class to represent an Item.
Definition gdcmItem.h:46
gdcm::Item::Item
Item()
Definition gdcmItem.h:48
gdcm::Item::GetLength
VL GetLength() const
gdcm::Item::GetDataElement
const DataElement & GetDataElement(const Tag &t) const
Definition gdcmItem.h:68
gdcm::Item::Item
Item(Item const &val)
Definition gdcmItem.h:91
gdcm::Item::Clear
void Clear()
Definition gdcmItem.h:51
gdcm::Item::operator<<
friend std::ostream & operator<<(std::ostream &os, const Item &val)
Definition gdcmItem.h:315
gdcm::Item::Read
std::istream & Read(std::istream &is)
Definition gdcmItem.h:97
gdcm::Item::GetNestedDataSet
DataSet & GetNestedDataSet()
Definition gdcmItem.h:84
gdcm::Item::SetNestedDataSet
void SetNestedDataSet(const DataSet &nested)
Definition gdcmItem.h:75
gdcm::Item::GetNestedDataSet
const DataSet & GetNestedDataSet() const
Definition gdcmItem.h:80
gdcm::Item::InsertDataElement
void InsertDataElement(const DataElement &de)
Definition gdcmItem.h:59
gdcm::Item::Write
const std::ostream & Write(std::ostream &os) const
Definition gdcmItem.h:239
gdcm::Item::FindDataElement
bool FindDataElement(const Tag &t) const
Definition gdcmItem.h:303
gdcm::ParseException
ParseException Standard exception handling object.
Definition gdcmParseException.h:37
gdcm::SwapperDoOp
Definition gdcmSwapper.h:54
gdcm::SwapperDoOp::Swap
static T Swap(T val)
gdcm::Tag
Class to represent a DICOM Data Element (Attribute) Tag (Group, Element).
Definition gdcmTag.h:39
gdcm::Tag::Write
const std::ostream & Write(std::ostream &os) const
Write a tag in binary rep.
Definition gdcmTag.h:169
gdcm::VL
Value Length.
Definition gdcmVL.h:30
gdcm::VL::Write
const std::ostream & Write(std::ostream &os) const
Definition gdcmVL.h:99
gdcm::VL::GetLength
VL GetLength() const
Definition gdcmVL.h:68
gdcmByteSwapFilter.h
gdcmDataElement.h
gdcmDataSet.h
gdcm_assert
#define gdcm_assert(cond)
Definition gdcmException.h:104
gdcmParseException.h
gdcmSwapper.h
gdcmWarningMacro
#define gdcmWarningMacro(msg)
Warning.
Definition gdcmTrace.h:142
gdcmErrorMacro
#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
gdcmDebugMacro
#define gdcmDebugMacro(msg)
Debug.
Definition gdcmTrace.h:119
GDCM_EXPORT
#define GDCM_EXPORT
Definition gdcmWin32.h:34