GDCM
2.2.0
|
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 GDCMSEQUENCEOFITEMS_H 00016 #define GDCMSEQUENCEOFITEMS_H 00017 00018 #include "gdcmValue.h" 00019 #include "gdcmItem.h" 00020 00021 #include <vector> 00022 #include <cstring> // strcmp 00023 00024 namespace gdcm 00025 { 00026 00039 class GDCM_EXPORT SequenceOfItems : public Value 00040 { 00041 public: 00042 // Typdefs: 00043 typedef std::vector< Item > ItemVector; 00044 typedef ItemVector::size_type SizeType; 00045 typedef ItemVector::iterator Iterator; 00046 typedef ItemVector::const_iterator ConstIterator; 00047 Iterator Begin() { return Items.begin(); } 00048 Iterator End() { return Items.end(); } 00049 ConstIterator Begin() const { return Items.begin(); } 00050 ConstIterator End() const { return Items.end(); } 00051 00053 SequenceOfItems():SequenceLengthField(0xFFFFFFFF) { } 00054 //SequenceOfItems(VL const &vl = 0xFFFFFFFF):SequenceLengthField(vl),NType(type) { } 00055 00057 VL GetLength() const { return SequenceLengthField; } 00059 void SetLength(VL length) { 00060 SequenceLengthField = length; 00061 } 00063 void SetLengthToUndefined(); 00065 bool IsUndefinedLength() const { 00066 return SequenceLengthField.IsUndefined(); 00067 } 00068 00069 template <typename TDE> 00070 VL ComputeLength() const; 00071 void Clear() {} 00072 00074 void AddItem(Item const &item); 00075 00076 SizeType GetNumberOfItems() const { return Items.size(); } 00077 void SetNumberOfItems(SizeType n) { Items.resize(n); } 00078 00079 /* WARNING: first item is #1 (see DICOM standard) 00080 * Each Item shall be implicitly assigned an ordinal position starting with the value 1 for the 00081 * first Item in the Sequence, and incremented by 1 with each subsequent Item. The last Item in the 00082 * Sequence shall have an ordinal position equal to the number of Items in the Sequence. 00083 */ 00084 const Item &GetItem(SizeType position) const; 00085 Item &GetItem(SizeType position); 00086 00087 SequenceOfItems &operator=(const SequenceOfItems &val) { 00088 SequenceLengthField = val.SequenceLengthField; 00089 Items = val.Items; 00090 return *this; 00091 } 00092 00093 template <typename TDE, typename TSwap> 00094 std::istream &Read(std::istream &is) 00095 { 00096 const Tag seqDelItem(0xfffe,0xe0dd); 00097 if( SequenceLengthField.IsUndefined() ) 00098 { 00099 Item item; 00100 while( item.Read<TDE,TSwap>(is) && item.GetTag() != seqDelItem ) 00101 { 00102 //gdcmDebugMacro( "Item: " << item ); 00103 assert( item.GetTag() != seqDelItem ); 00104 Items.push_back( item ); 00105 item.Clear(); 00106 } 00107 //assert( item.GetTag() == seqDelItem && item.GetVL() == 0 ); 00108 } 00109 else 00110 { 00111 Item item; 00112 VL l = 0; 00113 //is.seekg( SequenceLengthField, std::ios::cur ); return is; 00114 while( l != SequenceLengthField ) 00115 { 00116 try 00117 { 00118 item.Read<TDE,TSwap>(is); 00119 } 00120 catch( Exception &ex ) 00121 { 00122 if( strcmp( ex.GetDescription(), "Changed Length" ) == 0 ) 00123 { 00124 VL newlength = l + item.template GetLength<TDE>(); 00125 if( newlength > SequenceLengthField ) 00126 { 00127 // BogugsItemAndSequenceLength.dcm 00128 gdcmWarningMacro( "SQ length is wrong" ); 00129 SequenceLengthField = newlength; 00130 } 00131 } 00132 else 00133 { 00134 throw ex; 00135 } 00136 } 00137 #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION 00138 if( item.GetTag() == seqDelItem ) 00139 { 00140 gdcmWarningMacro( "SegDelItem found in defined length Sequence. Skipping" ); 00141 assert( item.GetVL() == 0 ); 00142 assert( item.GetNestedDataSet().Size() == 0 ); 00143 // we need to pay attention that the length of the Sequence of Items will be wrong 00144 // this way. Indeed by not adding this item we are changing the size of this sqi 00145 } 00146 else // Not a seq del item marker 00147 #endif 00148 { 00149 // By design we never load them. If we were to load those attribute 00150 // as normal item it would become very complex to convert a sequence 00151 // from defined length to undefined length with the risk to write two 00152 // seq del marker 00153 Items.push_back( item ); 00154 } 00155 l += item.template GetLength<TDE>(); 00156 if( l > SequenceLengthField ) 00157 { 00158 gdcmDebugMacro( "Found: Length of Item larger than expected" ) 00159 throw "Length of Item larger than expected"; 00160 } 00161 assert( l <= SequenceLengthField ); 00162 #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION 00163 // MR_Philips_Intera_No_PrivateSequenceImplicitVR.dcm 00164 // (0x2005, 0x1080): for some reason computation of length fails... 00165 if( SequenceLengthField == 778 && l == 774 ) 00166 { 00167 gdcmWarningMacro( "PMS: Super bad hack" ); 00168 SequenceLengthField = l; 00169 throw Exception( "Wrong Length" ); 00170 //l = SequenceLengthField; 00171 } 00172 // Bug_Philips_ItemTag_3F3F 00173 // (0x2005, 0x1080): Because we do not handle fully the bug at the item 00174 // level we need to check here too 00175 else if ( SequenceLengthField == 444 && l == 3*71 ) 00176 { 00177 // This one is a double bug. Item length is wrong and impact SQ length 00178 gdcmWarningMacro( "PMS: Super bad hack" ); 00179 l = SequenceLengthField; 00180 } 00181 #endif 00182 } 00183 assert( l == SequenceLengthField ); 00184 } 00185 return is; 00186 } 00187 00188 template <typename TDE,typename TSwap> 00189 std::ostream const &Write(std::ostream &os) const 00190 { 00191 typename ItemVector::const_iterator it = Items.begin(); 00192 for(;it != Items.end(); ++it) 00193 { 00194 it->Write<TDE,TSwap>(os); 00195 } 00196 if( SequenceLengthField.IsUndefined() ) 00197 { 00198 // seq del item is not stored, write it ! 00199 const Tag seqDelItem(0xfffe,0xe0dd); 00200 seqDelItem.Write<TSwap>(os); 00201 VL zero = 0; 00202 zero.Write<TSwap>(os); 00203 } 00204 00205 return os; 00206 } 00207 00208 //protected: 00209 void Print(std::ostream &os) const { 00210 os << "\t(" << SequenceLengthField << ")\n"; 00211 ItemVector::const_iterator it = 00212 Items.begin(); 00213 for(;it != Items.end(); ++it) 00214 { 00215 os << " " << *it; 00216 } 00217 if( SequenceLengthField.IsUndefined() ) 00218 { 00219 const Tag seqDelItem(0xfffe,0xe0dd); 00220 VL zero = 0; 00221 os << seqDelItem; 00222 os << "\t" << zero; 00223 } 00224 } 00225 00226 static SmartPointer<SequenceOfItems> New() 00227 { 00228 return new SequenceOfItems; 00229 } 00230 bool FindDataElement(const Tag &t) const; 00231 00232 bool operator==(const Value &val) const 00233 { 00234 const SequenceOfItems &sqi = dynamic_cast<const SequenceOfItems&>(val); 00235 return SequenceLengthField == sqi.SequenceLengthField && 00236 Items == sqi.Items; 00237 } 00238 00239 private: 00240 public: 00242 VL SequenceLengthField; 00244 ItemVector Items; 00245 }; 00246 00247 } // end namespace gdcm 00248 00249 #include "gdcmSequenceOfItems.txx" 00250 00251 #endif //GDCMSEQUENCEOFITEMS_H