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 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 TagField.Read<TSwap>(is); 00062 return ReadValue<TSwap>(is); 00063 } 00064 00065 template <typename TSwap> 00066 std::istream &ReadValue(std::istream &is) 00067 { 00068 // Superclass 00069 const Tag itemStart(0xfffe, 0xe000); 00070 const Tag seqDelItem(0xfffe,0xe0dd); 00071 if( !is ) 00072 { 00073 // BogusItemStartItemEnd.dcm 00074 throw Exception( "Problem" ); 00075 return is; 00076 } 00077 if( !ValueLengthField.Read<TSwap>(is) ) 00078 { 00079 // GENESIS_SIGNA-JPEG-CorruptFrag.dcm 00080 // JPEG fragment is declared to have 61902, but infact really is only 61901 00081 // so we end up reading 0xddff,0x00e0, and VL = 0x0 (1 byte) 00082 throw Exception( "Problem" ); 00083 return is; 00084 } 00085 #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION 00086 if( TagField != itemStart && TagField != seqDelItem ) 00087 { 00088 throw Exception( "Problem" ); 00089 } 00090 #endif 00091 // Self 00092 SmartPointer<ByteValue> bv = new ByteValue; 00093 bv->SetLength(ValueLengthField); 00094 if( !bv->Read<TSwap>(is) ) 00095 { 00096 // Fragment is incomplete, but is a itemStart, let's try to push it anyway... 00097 gdcmWarningMacro( "Fragment could not be read" ); 00098 //bv->SetLength(is.gcount()); 00099 ValueField = bv; 00100 ParseException pe; 00101 pe.SetLastElement( *this ); 00102 throw pe; 00103 return is; 00104 } 00105 ValueField = bv; 00106 return is; 00107 } 00108 00109 00110 template <typename TSwap> 00111 std::ostream &Write(std::ostream &os) const { 00112 const Tag itemStart(0xfffe, 0xe000); 00113 const Tag seqDelItem(0xfffe,0xe0dd); 00114 if( !TagField.Write<TSwap>(os) ) 00115 { 00116 assert(0 && "Should not happen"); 00117 return os; 00118 } 00119 assert( TagField == itemStart 00120 || TagField == seqDelItem ); 00121 const ByteValue *bv = GetByteValue(); 00122 // VL 00123 // The following piece of code is hard to read in order to support such broken file as: 00124 // CompressedLossy.dcm 00125 if( IsEmpty() ) 00126 { 00127 //assert( bv ); 00128 VL zero = 0; 00129 if( !zero.Write<TSwap>(os) ) 00130 { 00131 assert(0 && "Should not happen"); 00132 return os; 00133 } 00134 } 00135 else 00136 { 00137 assert( ValueLengthField ); 00138 if( !ValueLengthField.Write<TSwap>(os) ) 00139 { 00140 assert(0 && "Should not happen"); 00141 return os; 00142 } 00143 } 00144 // Value 00145 if( ValueLengthField && bv ) 00146 { 00147 // Self 00148 assert( bv ); 00149 assert( bv->GetLength() == ValueLengthField ); 00150 if( !bv->Write<TSwap>(os) ) 00151 { 00152 assert(0 && "Should not happen"); 00153 return os; 00154 } 00155 } 00156 return os; 00157 } 00158 }; 00159 //----------------------------------------------------------------------------- 00160 inline std::ostream &operator<<(std::ostream &os, const Fragment &val) 00161 { 00162 os << "Tag: " << val.TagField; 00163 os << "\tVL: " << val.ValueLengthField; 00164 if( val.ValueField ) 00165 { 00166 os << "\t" << *(val.ValueField); 00167 } 00168 00169 return os; 00170 } 00171 00172 00173 } // end namespace gdcm 00174 00175 #endif //GDCMFRAGMENT_H