GDCM
2.2.3
|
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 #ifndef GDCMSEQUENCEOFFRAGMENTS_H 00015 #define GDCMSEQUENCEOFFRAGMENTS_H 00016 00017 #include "gdcmValue.h" 00018 #include "gdcmVL.h" 00019 #include "gdcmFragment.h" 00020 #include "gdcmBasicOffsetTable.h" 00021 00022 namespace gdcm 00023 { 00024 00025 // FIXME gdcmSequenceOfItems and gdcmSequenceOfFragments 00026 // should be rethink (duplicate code) 00031 class GDCM_EXPORT SequenceOfFragments : public Value 00032 { 00033 public: 00034 // Typdefs: 00035 typedef std::vector<Fragment> FragmentVector; 00036 typedef FragmentVector::size_type SizeType; 00037 typedef FragmentVector::iterator Iterator; 00038 typedef FragmentVector::const_iterator ConstIterator; 00039 Iterator Begin() { return Fragments.begin(); } 00040 Iterator End() { return Fragments.end(); } 00041 ConstIterator Begin() const { return Fragments.begin(); } 00042 ConstIterator End() const { return Fragments.end(); } 00043 00045 SequenceOfFragments():Table(),SequenceLengthField(0xFFFFFFFF) { } 00046 00048 VL GetLength() const { 00049 return SequenceLengthField; 00050 } 00051 00053 void SetLength(VL length) { 00054 SequenceLengthField = length; 00055 } 00056 00058 void Clear(); 00059 00061 void AddFragment(Fragment const &item); 00062 00063 // Compute the length of all fragments (and framents only!). 00064 // Basically the size of the PixelData as stored (in bytes). 00065 unsigned long ComputeByteLength() const; 00066 00067 // Compute the length of fragments (in bytes)+ length of tag... 00068 // to be used for computation of Group Length 00069 VL ComputeLength() const; 00070 00071 // Get the buffer 00072 bool GetBuffer(char *buffer, unsigned long length) const; 00073 bool GetFragBuffer(unsigned int fragNb, char *buffer, unsigned long &length) const; 00074 00075 SizeType GetNumberOfFragments() const; 00076 const Fragment& GetFragment(SizeType num) const; 00077 00078 // Write the buffer of each fragment (call WriteBuffer on all Fragments, which are 00079 // ByteValue). No Table information is written. 00080 bool WriteBuffer(std::ostream &os) const; 00081 00082 const BasicOffsetTable &GetTable() const { return Table; } 00083 BasicOffsetTable &GetTable() { return Table; } 00084 00085 template <typename TSwap> 00086 std::istream& Read(std::istream &is) 00087 { 00088 assert( SequenceLengthField.IsUndefined() ); 00089 ReadPreValue<TSwap>(is); 00090 return ReadValue<TSwap>(is); 00091 } 00092 00093 template <typename TSwap> 00094 std::istream& ReadPreValue(std::istream &is) 00095 { 00096 //if( SequenceLengthField.IsUndefined() ) 00097 // First item is the basic offset table: 00098 try 00099 { 00100 Table.Read<TSwap>(is); 00101 gdcmDebugMacro( "Table: " << Table ); 00102 } 00103 catch(...) 00104 { 00105 // Bug_Siemens_PrivateIconNoItem.dcm 00106 // First thing first let's rewind 00107 is.seekg(-4, std::ios::cur); 00108 if ( Table.GetTag() == Tag(0xd8ff,0xe0ff) ) 00109 { 00110 Fragment frag; 00111 is.seekg( 8340, std::ios::cur ); 00112 char dummy[8340]; 00113 frag.SetByteValue( dummy, 8340 - Table.GetLength() - 16 ); 00114 Fragments.push_back( frag ); 00115 return is; 00116 } 00117 else 00118 { 00119 throw "Catch me if you can"; 00120 //assert(0); 00121 } 00122 } 00123 return is; 00124 } 00125 00126 template <typename TSwap> 00127 std::istream& ReadValue(std::istream &is) 00128 { 00129 const Tag seqDelItem(0xfffe,0xe0dd); 00130 // not used for now... 00131 Fragment frag; 00132 try 00133 { 00134 while( frag.Read<TSwap>(is) && frag.GetTag() != seqDelItem ) 00135 { 00136 gdcmDebugMacro( "Frag: " << frag ); 00137 Fragments.push_back( frag ); 00138 } 00139 assert( frag.GetTag() == seqDelItem && frag.GetVL() == 0 ); 00140 } 00141 catch(Exception &ex) 00142 { 00143 (void)ex; 00144 #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION 00145 // that's ok ! In all cases the whole file was read, because 00146 // Fragment::Read only fail on eof() reached 1. 00147 // SIEMENS-JPEG-CorruptFrag.dcm is more difficult to deal with, we have a 00148 // partial fragment, read we decide to add it anyway to the stack of 00149 // fragments (eof was reached so we need to clear error bit) 00150 if( frag.GetTag() == Tag(0xfffe,0xe000) ) 00151 { 00152 gdcmWarningMacro( "Pixel Data Fragment could be corrupted. Use file at own risk" ); 00153 Fragments.push_back( frag ); 00154 is.clear(); // clear the error bit 00155 } 00156 // 2. GENESIS_SIGNA-JPEG-CorruptFrag.dcm 00157 else if ( frag.GetTag() == Tag(0xddff,0x00e0) ) 00158 { 00159 assert( Fragments.size() == 1 ); 00160 const ByteValue *bv = Fragments[0].GetByteValue(); 00161 assert( (unsigned char)bv->GetPointer()[ bv->GetLength() - 1 ] == 0xfe ); 00162 // Yes this is an extra copy, this is a bug anyway, go fix YOUR code 00163 Fragments[0].SetByteValue( bv->GetPointer(), bv->GetLength() - 1 ); 00164 gdcmWarningMacro( "JPEG Fragment length was declared with an extra byte" 00165 " at the end: stripped !" ); 00166 is.clear(); // clear the error bit 00167 } 00168 // 3. LEICA/WSI 00169 else if ( (frag.GetTag().GetGroup() == 0x00ff) 00170 && ((frag.GetTag().GetElement() & 0x00ff) == 0xe0) ) 00171 { 00172 // Looks like there is a mess with offset and odd byte array 00173 // We are going first to backtrack one byte back, and then use a 00174 // ReadBacktrack function which in turn may backtrack up to 10 bytes 00175 // backward. This appears to be working on a set of DICOM/WSI files from 00176 // LEICA 00177 gdcmWarningMacro( "Trying to fix the even-but-odd value length bug" ); 00178 assert( Fragments.size() ); 00179 const size_t lastf = Fragments.size() - 1; 00180 const ByteValue *bv = Fragments[ lastf ].GetByteValue(); 00181 const char *a = bv->GetPointer(); 00182 assert( (unsigned char)a[ bv->GetLength() - 1 ] == 0xfe ); 00183 Fragments[ lastf ].SetByteValue( bv->GetPointer(), bv->GetLength() - 1 ); 00184 is.seekg( -9, std::ios::cur ); 00185 assert( is.good() ); 00186 while( frag.ReadBacktrack<TSwap>(is) && frag.GetTag() != seqDelItem ) 00187 { 00188 gdcmDebugMacro( "Frag: " << frag ); 00189 Fragments.push_back( frag ); 00190 } 00191 assert( frag.GetTag() == seqDelItem && frag.GetVL() == 0 ); 00192 } 00193 else 00194 { 00195 // 3. gdcm-JPEG-LossLess3a.dcm: easy case, an extra tag was found 00196 // instead of terminator (eof is the next char) 00197 gdcmWarningMacro( "Reading failed at Tag:" << frag.GetTag() << " Index #" 00198 << Fragments.size() << " Offset " << is.tellg() << ". Use file at own risk." 00199 << ex.what() ); 00200 } 00201 #endif /* GDCM_SUPPORT_BROKEN_IMPLEMENTATION */ 00202 } 00203 00204 return is; 00205 } 00206 00207 template <typename TSwap> 00208 std::ostream const &Write(std::ostream &os) const 00209 { 00210 if( !Table.Write<TSwap>(os) ) 00211 { 00212 assert(0 && "Should not happen"); 00213 return os; 00214 } 00215 for(ConstIterator it = Begin();it != End(); ++it) 00216 { 00217 it->Write<TSwap>(os); 00218 } 00219 // seq del item is not stored, write it ! 00220 const Tag seqDelItem(0xfffe,0xe0dd); 00221 seqDelItem.Write<TSwap>(os); 00222 VL zero = 0; 00223 zero.Write<TSwap>(os); 00224 00225 return os; 00226 } 00227 00228 //#if defined(SWIGPYTHON) || defined(SWIGCSHARP) || defined(SWIGJAVA) 00229 // For now leave it there, this does not make sense in the C++ layer 00230 // Create a new object 00231 static SmartPointer<SequenceOfFragments> New() 00232 { 00233 return new SequenceOfFragments(); 00234 } 00235 //#endif 00236 00237 protected: 00238 public: 00239 void Print(std::ostream &os) const { 00240 os << "SQ L= " << SequenceLengthField << "\n"; 00241 os << "Table:" << Table << "\n"; 00242 for(ConstIterator it = Begin();it != End(); ++it) 00243 { 00244 os << " " << *it << "\n"; 00245 } 00246 assert( SequenceLengthField.IsUndefined() ); 00247 { 00248 const Tag seqDelItem(0xfffe,0xe0dd); 00249 VL zero = 0; 00250 os << seqDelItem; 00251 os << "\t" << zero; 00252 } 00253 } 00254 bool operator==(const Value &val) const 00255 { 00256 const SequenceOfFragments &sqf = dynamic_cast<const SequenceOfFragments&>(val); 00257 return Table == sqf.Table && 00258 SequenceLengthField == sqf.SequenceLengthField && 00259 Fragments == sqf.Fragments; 00260 } 00261 00262 private: 00263 BasicOffsetTable Table; 00264 VL SequenceLengthField; 00266 FragmentVector Fragments; 00267 }; 00268 00274 } // end namespace gdcm 00275 00276 #endif //GDCMSEQUENCEOFFRAGMENTS_H