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 GDCMDATAELEMENT_H 00015 #define GDCMDATAELEMENT_H 00016 00017 #include "gdcmTag.h" 00018 #include "gdcmVL.h" 00019 #include "gdcmVR.h" 00020 #include "gdcmByteValue.h" 00021 #include "gdcmSmartPointer.h" 00022 00023 #include <set> 00024 00025 namespace gdcm 00026 { 00027 // Data Element 00028 // Contains multiple fields: 00029 // -> Tag 00030 // -> Optional VR (Explicit Transfer Syntax) 00031 // -> ValueLength 00032 // -> Value 00033 // TODO: This class SHOULD be pure virtual. I dont want a user 00034 // to shoot himself in the foot. 00035 00036 class SequenceOfItems; 00037 class SequenceOfFragments; 00058 class GDCM_EXPORT DataElement 00059 { 00060 public: 00061 DataElement(const Tag& t = Tag(0), const VL& vl = 0, const VR &vr = VR::INVALID):TagField(t),ValueLengthField(vl),VRField(vr),ValueField(0) {} 00062 //DataElement( Attribute const &att ); 00063 00064 friend std::ostream& operator<<(std::ostream &_os, const DataElement &_val); 00065 00067 const Tag& GetTag() const { return TagField; } 00068 Tag& GetTag() { return TagField; } 00071 void SetTag(const Tag &t) { TagField = t; } 00072 00074 const VL& GetVL() const { return ValueLengthField; } 00075 VL& GetVL() { return ValueLengthField; } 00079 void SetVL(const VL &vl) { ValueLengthField = vl; } 00080 void SetVLToUndefined(); 00081 00084 VR const &GetVR() const { return VRField; } 00088 void SetVR(VR const &vr) { 00089 if( vr.IsVRFile() ) 00090 VRField = vr; 00091 } 00092 00094 Value const &GetValue() const { return *ValueField; } 00095 Value &GetValue() { return *ValueField; } 00097 void SetValue(Value const & vl) { 00098 //assert( ValueField == 0 ); 00099 ValueField = vl; 00100 ValueLengthField = vl.GetLength(); 00101 } 00103 bool IsEmpty() const { return ValueField == 0 || (GetByteValue() && GetByteValue()->IsEmpty()); } 00104 00106 void Empty() { ValueField = 0; ValueLengthField = 0; } 00107 00109 void Clear() 00110 { 00111 TagField = 0; 00112 VRField = VR::INVALID; 00113 ValueField = 0; 00114 ValueLengthField = 0; 00115 } 00116 00117 // Helper: 00123 void SetByteValue(const char *array, VL length) 00124 { 00125 ByteValue *bv = new ByteValue(array,length); 00126 SetValue( *bv ); 00127 } 00130 const ByteValue* GetByteValue() const { 00131 // Get the raw pointer from the gdcm::SmartPointer 00132 const ByteValue *bv = dynamic_cast<const ByteValue*>(ValueField.GetPointer()); 00133 return bv; // Will return NULL if not ByteValue 00134 } 00135 //GDCM_LEGACY(ByteValue* GetByteValue()) 00136 00145 GDCM_LEGACY(const SequenceOfItems* GetSequenceOfItems() const) 00146 GDCM_LEGACY(SequenceOfItems* GetSequenceOfItems()) 00147 00154 SmartPointer<SequenceOfItems> GetValueAsSQ() const; 00155 00158 const SequenceOfFragments* GetSequenceOfFragments() const; 00159 00161 bool IsUndefinedLength() const { 00162 return ValueLengthField.IsUndefined(); 00163 } 00164 00165 DataElement(const DataElement &_val) 00166 { 00167 if( this != &_val) 00168 { 00169 *this = _val; 00170 } 00171 } 00172 00173 bool operator<(const DataElement &de) const 00174 { 00175 return GetTag() < de.GetTag(); 00176 } 00177 DataElement &operator=(const DataElement &de) 00178 { 00179 TagField = de.TagField; 00180 ValueLengthField = de.ValueLengthField; 00181 VRField = de.VRField; 00182 ValueField = de.ValueField; // Pointer copy 00183 return *this; 00184 } 00185 00186 bool operator==(const DataElement &de) const 00187 { 00188 bool b = TagField == de.TagField 00189 && ValueLengthField == de.ValueLengthField 00190 && VRField == de.VRField; 00191 if( !ValueField && !de.ValueField ) 00192 { 00193 return b; 00194 } 00195 if( ValueField && de.ValueField ) 00196 { 00197 return b && (*ValueField == *de.ValueField); 00198 } 00199 // ValueField != de.ValueField 00200 return false; 00201 } 00202 00203 // The following fonctionalities are dependant on: 00204 // # The Transfer Syntax: Explicit or Implicit 00205 // # The Byte encoding: Little Endian / Big Endian 00206 00207 /* 00208 * The following was inspired by a C++ idiom: Curiously Recurring Template Pattern 00209 * Ref: http://en.wikipedia.org/wiki/Curiously_Recurring_Template_Pattern 00210 * The typename TDE is typically a derived class *without* any data 00211 * while TSwap is a simple template parameter to achieve byteswapping (and allow factorization of 00212 * highly identical code) 00213 */ 00214 template <typename TDE> 00215 VL GetLength() const { 00216 return static_cast<const TDE*>(this)->GetLength(); 00217 } 00218 00219 template <typename TDE, typename TSwap> 00220 std::istream &Read(std::istream &is) { 00221 return static_cast<TDE*>(this)->template Read<TSwap>(is); 00222 } 00223 00224 template <typename TDE, typename TSwap> 00225 std::istream &ReadOrSkip(std::istream &is, std::set<Tag> const &skiptags) { 00226 (void)skiptags; 00227 return static_cast<TDE*>(this)->template Read<TSwap>(is); 00228 } 00229 00230 template <typename TDE, typename TSwap> 00231 std::istream &ReadPreValue(std::istream &is, std::set<Tag> const &skiptags) { 00232 (void)skiptags; 00233 return static_cast<TDE*>(this)->template ReadPreValue<TSwap>(is); 00234 } 00235 template <typename TDE, typename TSwap> 00236 std::istream &ReadValue(std::istream &is, std::set<Tag> const &skiptags) { 00237 (void)skiptags; 00238 return static_cast<TDE*>(this)->template ReadValue<TSwap>(is); 00239 } 00240 00241 template <typename TDE, typename TSwap> 00242 std::istream &ReadWithLength(std::istream &is, VL &length) { 00243 return static_cast<TDE*>(this)->template ReadWithLength<TSwap>(is,length); 00244 } 00245 00246 template <typename TDE, typename TSwap> 00247 const std::ostream &Write(std::ostream &os) const { 00248 return static_cast<const TDE*>(this)->template Write<TSwap>(os); 00249 } 00250 00251 protected: 00252 Tag TagField; 00253 // This is the value read from the file, might be different from the length of Value Field 00254 VL ValueLengthField; // Can be 0xFFFFFFFF 00255 00256 // Value Representation 00257 VR VRField; 00258 typedef SmartPointer<Value> ValuePtr; 00259 ValuePtr ValueField; 00260 }; 00261 //----------------------------------------------------------------------------- 00262 inline std::ostream& operator<<(std::ostream &os, const DataElement &val) 00263 { 00264 os << val.TagField; 00265 os << "\t" << val.VRField; 00266 os << "\t" << val.ValueLengthField; 00267 if( val.ValueField ) 00268 { 00269 val.ValueField->Print( os << "\t" ); 00270 } 00271 return os; 00272 } 00273 00274 inline bool operator!=(const DataElement& lhs, const DataElement& rhs) 00275 { 00276 return ! ( lhs == rhs ); 00277 } 00278 00279 } // end namespace gdcm 00280 00281 #endif //GDCMDATAELEMENT_H