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 #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 qnd 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 00038 SequenceOfFragments():Table(),SequenceLengthField(0xFFFFFFFF) { } 00039 00041 VL GetLength() const { 00042 return SequenceLengthField; } 00044 void SetLength(VL length) { 00045 SequenceLengthField = length; 00046 } 00047 void Clear(); 00048 00050 void AddFragment(Fragment const &item); 00051 00052 // Compute the length of all fragments (and framents only!). 00053 // Basically the size of the PixelData as stored (in bytes). 00054 unsigned long ComputeByteLength() const; 00055 00056 // Compute the length of fragments (in bytes)+ length of tag... 00057 // to be used for computation of Group Length 00058 VL ComputeLength() const; 00059 00060 // Get the buffer 00061 bool GetBuffer(char *buffer, unsigned long length) const; 00062 bool GetFragBuffer(unsigned int fragNb, char *buffer, unsigned long &length) const; 00063 unsigned int GetNumberOfFragments() const; 00064 const Fragment& GetFragment(unsigned int num) const; 00065 00066 // Write the buffer of each fragment (call WriteBuffer on all Fragments, which are 00067 // ByteValue). No Table information is written. 00068 bool WriteBuffer(std::ostream &os) const; 00069 00070 const BasicOffsetTable &GetTable() const { return Table; } 00071 BasicOffsetTable &GetTable() { return Table; } 00072 00073 00074 template <typename TSwap> 00075 std::istream& Read(std::istream &is) 00076 { 00077 assert( SequenceLengthField.IsUndefined() ); 00078 //if( SequenceLengthField.IsUndefined() ) 00079 { 00080 const Tag seqDelItem(0xfffe,0xe0dd); 00081 // First item is the basic offset table: 00082 try 00083 { 00084 Table.Read<TSwap>(is); 00085 gdcmDebugMacro( "Table: " << Table ); 00086 } 00087 catch(...) 00088 { 00089 // Bug_Siemens_PrivateIconNoItem.dcm 00090 // First thing first let's rewind 00091 is.seekg(-4, std::ios::cur); 00092 if ( Table.GetTag() == Tag(0xd8ff,0xe0ff) ) 00093 { 00094 Fragment frag; 00095 is.seekg( 8340, std::ios::cur ); 00096 char dummy[8340]; 00097 frag.SetByteValue( dummy, 8340 - Table.GetLength() - 16 ); 00098 Fragments.push_back( frag ); 00099 return is; 00100 } 00101 else 00102 { 00103 throw "Catch me if you can"; 00104 //assert(0); 00105 } 00106 } 00107 // not used for now... 00108 Fragment frag; 00109 try 00110 { 00111 while( frag.Read<TSwap>(is) && frag.GetTag() != seqDelItem ) 00112 { 00113 gdcmDebugMacro( "Frag: " << frag ); 00114 Fragments.push_back( frag ); 00115 } 00116 assert( frag.GetTag() == seqDelItem && frag.GetVL() == 0 ); 00117 } 00118 catch(Exception &ex) 00119 { 00120 (void)ex; //to avoid unreferenced variable warning on release 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