GDCM
2.0.18
|
00001 /*========================================================================= 00002 00003 Program: GDCM (Grassroots DICOM). A DICOM library 00004 00005 Copyright (c) 2006-2011 Mathieu Malaterre 00006 All rights reserved. 00007 See Copyright.txt or http://gdcm.sourceforge.net/Copyright.html for details. 00008 00009 This software is distributed WITHOUT ANY WARRANTY; without even 00010 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 00011 PURPOSE. See the above copyright notice for more information. 00012 00013 =========================================================================*/ 00014 00015 #ifndef GDCMITEM_H 00016 #define GDCMITEM_H 00017 00018 #include "gdcmDataElement.h" 00019 #include "gdcmDataSet.h" 00020 #include "gdcmParseException.h" 00021 #include "gdcmSwapper.h" 00022 00023 #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION 00024 #include "gdcmByteSwapFilter.h" 00025 #endif 00026 00027 namespace gdcm 00028 { 00029 00030 class DataSet; 00045 class GDCM_EXPORT Item : public DataElement 00046 { 00047 public: 00048 Item() : DataElement(Tag(0xfffe, 0xe000), 0xFFFFFFFF), NestedDataSet() {} 00049 friend std::ostream& operator<< (std::ostream &os, const Item &val); 00050 00051 void Clear() { 00052 this->DataElement::Clear(); 00053 NestedDataSet.Clear(); 00054 } 00055 00056 template <typename TDE> 00057 VL GetLength() const; 00058 00059 void InsertDataElement(const DataElement & de) { 00060 NestedDataSet.Insert(de); 00061 // Update the length 00062 if( !IsUndefinedLength() ) 00063 { 00064 assert( 0 && "InsertDataElement" ); 00065 //ValueLengthField += de.GetLength(); 00066 } 00067 } 00068 const DataElement& GetDataElement(const Tag& t) const 00069 { 00070 return NestedDataSet.GetDataElement(t); 00071 } 00072 00073 // Completely defines it with the nested dataset 00074 // destroy anything present 00075 void SetNestedDataSet(const DataSet& nested) 00076 { 00077 NestedDataSet = nested; 00078 } 00079 // Return a const ref to the Nested Data Set 00080 const DataSet &GetNestedDataSet() const 00081 { 00082 return NestedDataSet; 00083 } 00084 DataSet &GetNestedDataSet() 00085 { 00086 return NestedDataSet; 00087 } 00088 00089 //Value const & GetValue() const { return *NestedDataSet; } 00090 00091 Item(Item const &val):DataElement(val) 00092 { 00093 NestedDataSet = val.NestedDataSet; 00094 } 00095 00096 template <typename TDE, typename TSwap> 00097 std::istream &Read(std::istream &is) { 00098 // Superclass 00099 { 00100 DataSet &nested = NestedDataSet; 00101 nested.Clear(); 00102 assert( nested.IsEmpty() ); 00103 } 00104 if( !TagField.Read<TSwap>(is) ) 00105 { 00106 throw Exception("Should not happen (item)"); 00107 return is; 00108 } 00109 #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION 00110 // MR_Philips_Intera_SwitchIndianess_noLgtSQItem_in_trueLgtSeq.dcm 00111 if( TagField == Tag(0xfeff, 0x00e0) 00112 || TagField == Tag(0xfeff, 0xdde0) ) 00113 { 00114 gdcmWarningMacro( "ByteSwaping Private SQ: " << TagField ); 00115 // Invert previously read TagField since wrong endianess: 00116 TagField = Tag( SwapperDoOp::Swap( TagField.GetGroup() ), SwapperDoOp::Swap( TagField.GetElement() ) ); 00117 assert ( TagField == Tag(0xfffe, 0xe000) 00118 || TagField == Tag(0xfffe, 0xe0dd) ); 00119 00120 if( !ValueLengthField.Read<SwapperDoOp>(is) ) 00121 { 00122 assert(0 && "Should not happen"); 00123 return is; 00124 } 00125 // Self 00126 // Some file written by GDCM 1.0 we writting 0xFFFFFFFF instead of 0x0 00127 if( TagField == Tag(0xfffe,0xe0dd) ) 00128 { 00129 if( ValueLengthField ) 00130 { 00131 gdcmErrorMacro( "ValueLengthField is not 0" ); 00132 } 00133 } 00134 //else if( ValueLengthField == 0 ) 00135 // { 00136 // //assert( TagField == Tag( 0xfffe, 0xe0dd) ); 00137 // if( TagField != Tag( 0xfffe, 0xe0dd) ) 00138 // { 00139 // gdcmErrorMacro( "SQ: " << TagField << " has a length of 0" ); 00140 // } 00141 // } 00142 else if( ValueLengthField.IsUndefined() ) 00143 { 00144 DataSet &nested = NestedDataSet; 00145 nested.Clear(); 00146 assert( nested.IsEmpty() ); 00147 std::streampos start = is.tellg(); 00148 try 00149 { 00150 nested.template ReadNested<TDE,SwapperDoOp>(is); 00151 ByteSwapFilter bsf(nested); 00152 bsf.ByteSwap(); 00153 } 00154 catch(ParseException &pe) 00155 { 00156 (void)pe; 00157 // MR_Philips_Intera_PrivateSequenceExplicitVR_in_SQ_2001_e05f_item_wrong_lgt_use_NOSHADOWSEQ.dcm 00158 // You have to byteswap the length but not the tag...sigh 00159 gdcmWarningMacro( "Attempt to read nested Item without byteswapping the Value Length." ); 00160 start -= is.tellg(); 00161 assert( start < 0 ); 00162 is.seekg( start, std::ios::cur ); 00163 nested.Clear(); 00164 nested.template ReadNested<TDE,SwapperNoOp>(is); 00165 ByteSwapFilter bsf(nested); 00166 // Tag are read in big endian, need to byteswap them back... 00167 bsf.SetByteSwapTag(true); 00168 bsf.ByteSwap(); 00169 } 00170 catch(Exception &e) 00171 { 00172 // MR_Philips_Intera_No_PrivateSequenceImplicitVR.dcm 00173 throw e; 00174 } 00175 catch(...) 00176 { 00177 assert(0); 00178 } 00179 } 00180 else /* if( ValueLengthField.IsUndefined() ) */ 00181 { 00182 DataSet &nested = NestedDataSet; 00183 nested.Clear(); 00184 assert( nested.IsEmpty() ); 00185 nested.template ReadWithLength<TDE,SwapperDoOp>(is, ValueLengthField); 00186 ByteSwapFilter bsf(nested); 00187 bsf.ByteSwap(); 00188 } 00189 return is; 00190 } 00191 // http://groups.google.com/group/comp.protocols.dicom/msg/c07efcf5e759fc83 00192 // Bug_Philips_ItemTag_3F3F.dcm 00193 if( TagField == Tag(0x3f3f, 0x3f00) ) 00194 { 00195 //TagField = Tag(0xfffe, 0xe000); 00196 } 00197 #endif 00198 if( TagField != Tag(0xfffe, 0xe000) && TagField != Tag(0xfffe, 0xe0dd) ) 00199 { 00200 gdcmDebugMacro( "Invalid Item, found tag: " << TagField); 00201 throw Exception( "Not a valid Item" ); 00202 } 00203 assert( TagField == Tag(0xfffe, 0xe000) || TagField == Tag(0xfffe, 0xe0dd) ); 00204 00205 if( !ValueLengthField.Read<TSwap>(is) ) 00206 { 00207 assert(0 && "Should not happen"); 00208 return is; 00209 } 00210 // Self 00211 if( TagField == Tag(0xfffe,0xe0dd) ) 00212 { 00213 // Some file written by GDCM 1.0 were written with 0xFFFFFFFF instead of 0x0 00214 if( ValueLengthField ) 00215 { 00216 gdcmDebugMacro( "ValueLengthField is not 0 but " << ValueLengthField ); 00217 } 00218 } 00219 else if( ValueLengthField.IsUndefined() ) 00220 { 00221 DataSet &nested = NestedDataSet; 00222 nested.Clear(); 00223 assert( nested.IsEmpty() ); 00224 nested.template ReadNested<TDE,TSwap>(is); 00225 } 00226 else /* if( ValueLengthField.IsUndefined() ) */ 00227 { 00228 assert( !ValueLengthField.IsUndefined() ); 00229 DataSet &nested = NestedDataSet; 00230 nested.Clear(); 00231 assert( nested.IsEmpty() ); 00232 nested.template ReadWithLength<TDE,TSwap>(is, ValueLengthField); 00233 } 00234 00235 return is; 00236 } 00237 00238 template <typename TDE, typename TSwap> 00239 const std::ostream &Write(std::ostream &os) const { 00240 #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION 00241 if( TagField == Tag(0x3f3f,0x3f00) && false ) 00242 { 00243 Tag t(0xfffe, 0xe000); 00244 t.Write<TSwap>(os); 00245 } 00246 else 00247 #endif 00248 { 00249 assert ( TagField == Tag(0xfffe, 0xe000) 00250 || TagField == Tag(0xfffe, 0xe0dd) ); 00251 // Not sure how this happen 00252 if( TagField == Tag(0xfffe, 0xe0dd) ) 00253 { 00254 gdcmWarningMacro( "SegDelItem found in defined length Sequence" ); 00255 assert( ValueLengthField == 0 ); 00256 assert( NestedDataSet.Size() == 0 ); 00257 } 00258 if( !TagField.Write<TSwap>(os) ) 00259 { 00260 assert(0 && "Should not happen"); 00261 return os; 00262 } 00263 } 00264 if( ValueLengthField.IsUndefined() ) 00265 { 00266 if( !ValueLengthField.Write<TSwap>(os) ) 00267 { 00268 assert(0 && "Should not happen"); 00269 return os; 00270 } 00271 } 00272 else 00273 { 00274 VL dummy = NestedDataSet.GetLength<TDE>(); 00275 //assert( ValueLengthField == dummy ); 00276 if( !dummy.Write<TSwap>(os) ) 00277 { 00278 assert(0 && "Should not happen"); 00279 return os; 00280 } 00281 } 00282 // Self 00283 NestedDataSet.Write<TDE,TSwap>(os); 00284 if( ValueLengthField.IsUndefined() ) 00285 { 00286 const Tag itemDelItem(0xfffe,0xe00d); 00287 itemDelItem.Write<TSwap>(os); 00288 VL zero = 0; 00289 zero.Write<TSwap>(os); 00290 } 00291 00292 return os; 00293 } 00294 00295 /* 00296 There are three special SQ related Data Elements that are not ruled by the VR encoding rules conveyed 00297 by the Transfer Syntax. They shall be encoded as Implicit VR. These special Data Elements are Item 00298 (FFFE,E000), Item Delimitation Item (FFFE,E00D), and Sequence Delimitation Item (FFFE,E0DD). 00299 However, the Data Set within the Value Field of the Data Element Item (FFFE,E000) shall be encoded 00300 according to the rules conveyed by the Transfer Syntax. 00301 */ 00302 bool FindDataElement(const Tag &t) const { 00303 return NestedDataSet.FindDataElement( t ); 00304 } 00305 00306 private: 00307 /* NESTED DATA SET a Data Set contained within a Data Element of an other Data Set. 00308 * May be nested recursively. 00309 * Only Data Elements with VR = SQ may, themselves, contain Data Sets 00310 */ 00311 DataSet NestedDataSet; 00312 }; 00313 //----------------------------------------------------------------------------- 00314 inline std::ostream& operator<<(std::ostream& os, const Item &val) 00315 { 00316 os << val.TagField; 00317 os << "\t" << val.ValueLengthField << "\n"; 00318 val.NestedDataSet.Print( os, "\t" ); 00319 00320 return os; 00321 } 00322 00323 00324 } // end namespace gdcm 00325 00326 #include "gdcmItem.txx" 00327 00328 #endif //GDCMITEM_H