GDCM 2.0.17
|
00001 /*========================================================================= 00002 00003 Program: GDCM (Grassroots DICOM). A DICOM library 00004 Module: $URL$ 00005 00006 Copyright (c) 2006-2010 Mathieu Malaterre 00007 All rights reserved. 00008 See Copyright.txt or http://gdcm.sourceforge.net/Copyright.html for details. 00009 00010 This software is distributed WITHOUT ANY WARRANTY; without even 00011 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 00012 PURPOSE. See the above copyright notice for more information. 00013 00014 =========================================================================*/ 00015 #ifndef GDCMSEQUENCEOFFRAGMENTS_H 00016 #define GDCMSEQUENCEOFFRAGMENTS_H 00017 00018 #include "gdcmValue.h" 00019 #include "gdcmVL.h" 00020 #include "gdcmFragment.h" 00021 #include "gdcmBasicOffsetTable.h" 00022 00023 namespace gdcm 00024 { 00025 00026 // FIXME gdcmSequenceOfItems qnd gdcmSequenceOfFragments 00027 // should be rethink (duplicate code) 00032 class GDCM_EXPORT SequenceOfFragments : public Value 00033 { 00034 public: 00035 // Typdefs: 00036 typedef std::vector<Fragment> FragmentVector; 00037 00039 SequenceOfFragments():Table(),SequenceLengthField(0xFFFFFFFF) { } 00040 00042 VL GetLength() const { 00043 return SequenceLengthField; } 00045 void SetLength(VL length) { 00046 SequenceLengthField = length; 00047 } 00048 void Clear(); 00049 00051 void AddFragment(Fragment const &item); 00052 00053 // Compute the length of all fragments (and framents only!). 00054 // Basically the size of the PixelData as stored (in bytes). 00055 unsigned long ComputeByteLength() const; 00056 00057 // Compute the length of fragments (in bytes)+ length of tag... 00058 // to be used for computation of Group Length 00059 VL ComputeLength() const; 00060 00061 // Get the buffer 00062 bool GetBuffer(char *buffer, unsigned long length) const; 00063 bool GetFragBuffer(unsigned int fragNb, char *buffer, unsigned long &length) const; 00064 unsigned int GetNumberOfFragments() const; 00065 const Fragment& GetFragment(unsigned int num) const; 00066 00067 // Write the buffer of each fragment (call WriteBuffer on all Fragments, which are 00068 // ByteValue). No Table information is written. 00069 bool WriteBuffer(std::ostream &os) const; 00070 00071 const BasicOffsetTable &GetTable() const { return Table; } 00072 BasicOffsetTable &GetTable() { return Table; } 00073 00074 00075 template <typename TSwap> 00076 std::istream& Read(std::istream &is) 00077 { 00078 assert( SequenceLengthField.IsUndefined() ); 00079 //if( SequenceLengthField.IsUndefined() ) 00080 { 00081 const Tag seqDelItem(0xfffe,0xe0dd); 00082 // First item is the basic offset table: 00083 try 00084 { 00085 Table.Read<TSwap>(is); 00086 gdcmDebugMacro( "Table: " << Table ); 00087 } 00088 catch(...) 00089 { 00090 // Bug_Siemens_PrivateIconNoItem.dcm 00091 // First thing first let's rewind 00092 is.seekg(-4, std::ios::cur); 00093 if ( Table.GetTag() == Tag(0xd8ff,0xe0ff) ) 00094 { 00095 Fragment frag; 00096 is.seekg( 8340, std::ios::cur ); 00097 char dummy[8340]; 00098 frag.SetByteValue( dummy, 8340 - Table.GetLength() - 16 ); 00099 Fragments.push_back( frag ); 00100 return is; 00101 } 00102 else 00103 { 00104 throw "Catch me if you can"; 00105 //assert(0); 00106 } 00107 } 00108 // not used for now... 00109 Fragment frag; 00110 try 00111 { 00112 while( frag.Read<TSwap>(is) && frag.GetTag() != seqDelItem ) 00113 { 00114 gdcmDebugMacro( "Frag: " << frag ); 00115 Fragments.push_back( frag ); 00116 } 00117 assert( frag.GetTag() == seqDelItem && frag.GetVL() == 0 ); 00118 } 00119 catch(Exception &ex) 00120 { 00121 #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION 00122 // that's ok ! In all cases the whole file was read, because Fragment::Read only fail on eof() reached 00123 // 1. SIEMENS-JPEG-CorruptFrag.dcm is more difficult to deal with, we have a partial fragment, read 00124 // we decide to add it anyway to the stack of fragments (eof was reached so we need to clear error bit) 00125 if( frag.GetTag() == Tag(0xfffe,0xe000) ) 00126 { 00127 gdcmWarningMacro( "Pixel Data Fragment could be corrupted. Use file at own risk" ); 00128 Fragments.push_back( frag ); 00129 is.clear(); // clear the error bit 00130 } 00131 // 2. GENESIS_SIGNA-JPEG-CorruptFrag.dcm 00132 else if ( frag.GetTag() == Tag(0xddff,0x00e0) ) 00133 { 00134 assert( Fragments.size() == 1 ); 00135 const ByteValue *bv = Fragments[0].GetByteValue(); 00136 assert( (unsigned char)bv->GetPointer()[ bv->GetLength() - 1 ] == 0xfe ); 00137 // Yes this is an extra copy, this is a bug anyway, go fix YOUR code 00138 Fragments[0].SetByteValue( bv->GetPointer(), bv->GetLength() - 1 ); 00139 gdcmWarningMacro( "JPEG Fragment length was declared with an extra byte at the end: stripped !" ); 00140 is.clear(); // clear the error bit 00141 } 00142 else 00143 { 00144 // 3. gdcm-JPEG-LossLess3a.dcm: easy case, an extra tag was found instead of terminator (eof is the next char) 00145 gdcmWarningMacro( "Reading failed at Tag:" << frag.GetTag() << ". Use file at own risk." << ex.what() ); 00146 } 00147 #else 00148 (void)ex; 00149 #endif /* GDCM_SUPPORT_BROKEN_IMPLEMENTATION */ 00150 } 00151 } 00152 00153 return is; 00154 } 00155 00156 template <typename TSwap> 00157 std::ostream const &Write(std::ostream &os) const 00158 { 00159 if( !Table.Write<TSwap>(os) ) 00160 { 00161 assert(0 && "Should not happen"); 00162 return os; 00163 } 00164 SequenceOfFragments::FragmentVector::const_iterator it = Fragments.begin(); 00165 for(;it != Fragments.end(); ++it) 00166 { 00167 it->Write<TSwap>(os); 00168 } 00169 // seq del item is not stored, write it ! 00170 const Tag seqDelItem(0xfffe,0xe0dd); 00171 seqDelItem.Write<TSwap>(os); 00172 VL zero = 0; 00173 zero.Write<TSwap>(os); 00174 00175 return os; 00176 } 00177 00178 //#if defined(SWIGPYTHON) || defined(SWIGCSHARP) || defined(SWIGJAVA) 00179 // For now leave it there, this does not make sense in the C++ layer 00180 // Create a new object 00181 static SmartPointer<SequenceOfFragments> New() 00182 { 00183 return new SequenceOfFragments(); 00184 } 00185 //#endif 00186 00187 protected: 00188 public: 00189 void Print(std::ostream &os) const { 00190 os << "SQ L= " << SequenceLengthField << "\n"; 00191 os << "Table:" << Table << "\n"; 00192 FragmentVector::const_iterator it = 00193 Fragments.begin(); 00194 for(;it != Fragments.end(); ++it) 00195 { 00196 os << " " << *it << "\n"; 00197 } 00198 assert( SequenceLengthField.IsUndefined() ); 00199 { 00200 const Tag seqDelItem(0xfffe,0xe0dd); 00201 VL zero = 0; 00202 os << seqDelItem; 00203 os << "\t" << zero; 00204 } 00205 } 00206 bool operator==(const Value &val) const 00207 { 00208 const SequenceOfFragments &sqf = dynamic_cast<const SequenceOfFragments&>(val); 00209 return Table == sqf.Table && 00210 SequenceLengthField == sqf.SequenceLengthField && 00211 Fragments == sqf.Fragments; 00212 } 00213 00214 private: 00215 public: 00216 BasicOffsetTable Table; 00217 VL SequenceLengthField; 00219 FragmentVector Fragments; 00220 }; 00221 00227 } // end namespace gdcm 00228 00229 #endif //GDCMSEQUENCEOFFRAGMENTS_H