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 GDCMFRAGMENT_H 00015 #define GDCMFRAGMENT_H 00016 00017 #include "gdcmDataElement.h" 00018 #include "gdcmByteValue.h" 00019 #include "gdcmSmartPointer.h" 00020 #include "gdcmParseException.h" 00021 00022 namespace gdcm 00023 { 00024 00025 // Implementation detail: 00026 // I think Fragment should be a protected sublclass of DataElement: 00027 // looking somewhat like this: 00028 /* 00029 class GDCM_EXPORT Fragment : protected DataElement 00030 { 00031 public: 00032 using DataElement::GetTag; 00033 using DataElement::GetVL; 00034 using DataElement::SetByteValue; 00035 using DataElement::GetByteValue; 00036 using DataElement::GetValue; 00037 */ 00038 // Instead I am only hiding the SetTag member... 00039 00043 class GDCM_EXPORT Fragment : public DataElement 00044 { 00045 //protected: 00046 // void SetTag(const Tag &t); 00047 public: 00048 Fragment() : DataElement(Tag(0xfffe, 0xe000), 0) {} 00049 friend std::ostream &operator<<(std::ostream &os, const Fragment &val); 00050 00051 VL GetLength() const { 00052 assert( !ValueLengthField.IsUndefined() ); 00053 assert( !ValueField || ValueField->GetLength() == ValueLengthField ); 00054 return TagField.GetLength() + ValueLengthField.GetLength() 00055 + ValueLengthField; 00056 } 00057 00058 template <typename TSwap> 00059 std::istream &Read(std::istream &is) 00060 { 00061 ReadPreValue<TSwap>(is); 00062 return ReadValue<TSwap>(is); 00063 } 00064 00065 template <typename TSwap> 00066 std::istream &ReadPreValue(std::istream &is) 00067 { 00068 const Tag itemStart(0xfffe, 0xe000); 00069 const Tag seqDelItem(0xfffe,0xe0dd); 00070 00071 TagField.Read<TSwap>(is); 00072 if( !is ) 00073 { 00074 // BogusItemStartItemEnd.dcm 00075 throw Exception( "Problem #1" ); 00076 return is; 00077 } 00078 if( !ValueLengthField.Read<TSwap>(is) ) 00079 { 00080 // GENESIS_SIGNA-JPEG-CorruptFrag.dcm 00081 // JPEG fragment is declared to have 61902, but infact really is only 61901 00082 // so we end up reading 0xddff,0x00e0, and VL = 0x0 (1 byte) 00083 throw Exception( "Problem #2" ); 00084 return is; 00085 } 00086 #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION 00087 if( TagField != itemStart && TagField != seqDelItem ) 00088 { 00089 throw Exception( "Problem #3" ); 00090 } 00091 #endif 00092 return is; 00093 } 00094 00095 template <typename TSwap> 00096 std::istream &ReadValue(std::istream &is) 00097 { 00098 // Superclass 00099 const Tag itemStart(0xfffe, 0xe000); 00100 const Tag seqDelItem(0xfffe,0xe0dd); 00101 // Self 00102 SmartPointer<ByteValue> bv = new ByteValue; 00103 bv->SetLength(ValueLengthField); 00104 if( !bv->Read<TSwap>(is) ) 00105 { 00106 // Fragment is incomplete, but is a itemStart, let's try to push it anyway... 00107 gdcmWarningMacro( "Fragment could not be read" ); 00108 //bv->SetLength(is.gcount()); 00109 ValueField = bv; 00110 ParseException pe; 00111 pe.SetLastElement( *this ); 00112 throw pe; 00113 return is; 00114 } 00115 ValueField = bv; 00116 return is; 00117 } 00118 00119 template <typename TSwap> 00120 std::istream &ReadBacktrack(std::istream &is) 00121 { 00122 const Tag itemStart(0xfffe, 0xe000); 00123 const Tag seqDelItem(0xfffe,0xe0dd); 00124 00125 bool cont = true; 00126 const std::streampos start = is.tellg(); 00127 const int max = 10; 00128 int offset = 0; 00129 while( cont ) 00130 { 00131 TagField.Read<TSwap>(is); 00132 assert( is ); 00133 if( TagField != itemStart && TagField != seqDelItem ) 00134 { 00135 ++offset; 00136 is.seekg( (std::streampos)((size_t)start - offset) ); 00137 gdcmWarningMacro( "Fuzzy Search, backtrack: " << (start - is.tellg()) << " Offset: " << is.tellg() ); 00138 if( offset > max ) 00139 { 00140 gdcmErrorMacro( "Giving up" ); 00141 throw "Impossible to backtrack"; 00142 return is; 00143 } 00144 } 00145 else 00146 { 00147 cont = false; 00148 } 00149 } 00150 assert( TagField == itemStart || TagField == seqDelItem ); 00151 if( !ValueLengthField.Read<TSwap>(is) ) 00152 { 00153 return is; 00154 } 00155 00156 // Self 00157 SmartPointer<ByteValue> bv = new ByteValue; 00158 bv->SetLength(ValueLengthField); 00159 if( !bv->Read<TSwap>(is) ) 00160 { 00161 // Fragment is incomplete, but is a itemStart, let's try to push it anyway... 00162 gdcmWarningMacro( "Fragment could not be read" ); 00163 //bv->SetLength(is.gcount()); 00164 ValueField = bv; 00165 ParseException pe; 00166 pe.SetLastElement( *this ); 00167 throw pe; 00168 return is; 00169 } 00170 ValueField = bv; 00171 return is; 00172 } 00173 00174 00175 template <typename TSwap> 00176 std::ostream &Write(std::ostream &os) const { 00177 const Tag itemStart(0xfffe, 0xe000); 00178 const Tag seqDelItem(0xfffe,0xe0dd); 00179 if( !TagField.Write<TSwap>(os) ) 00180 { 00181 assert(0 && "Should not happen"); 00182 return os; 00183 } 00184 assert( TagField == itemStart 00185 || TagField == seqDelItem ); 00186 const ByteValue *bv = GetByteValue(); 00187 // VL 00188 // The following piece of code is hard to read in order to support such broken file as: 00189 // CompressedLossy.dcm 00190 if( IsEmpty() ) 00191 { 00192 //assert( bv ); 00193 VL zero = 0; 00194 if( !zero.Write<TSwap>(os) ) 00195 { 00196 assert(0 && "Should not happen"); 00197 return os; 00198 } 00199 } 00200 else 00201 { 00202 assert( ValueLengthField ); 00203 if( !ValueLengthField.Write<TSwap>(os) ) 00204 { 00205 assert(0 && "Should not happen"); 00206 return os; 00207 } 00208 } 00209 // Value 00210 if( ValueLengthField && bv ) 00211 { 00212 // Self 00213 assert( bv ); 00214 assert( bv->GetLength() == ValueLengthField ); 00215 if( !bv->Write<TSwap>(os) ) 00216 { 00217 assert(0 && "Should not happen"); 00218 return os; 00219 } 00220 } 00221 return os; 00222 } 00223 }; 00224 //----------------------------------------------------------------------------- 00225 inline std::ostream &operator<<(std::ostream &os, const Fragment &val) 00226 { 00227 os << "Tag: " << val.TagField; 00228 os << "\tVL: " << val.ValueLengthField; 00229 if( val.ValueField ) 00230 { 00231 os << "\t" << *(val.ValueField); 00232 } 00233 00234 return os; 00235 } 00236 00237 } // end namespace gdcm 00238 00239 #endif //GDCMFRAGMENT_H