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 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 00144 GDCM_LEGACY(const SequenceOfItems* GetSequenceOfItems() const) 00145 GDCM_LEGACY(SequenceOfItems* GetSequenceOfItems()) 00146 00153 SmartPointer<SequenceOfItems> GetValueAsSQ() const; 00154 00157 const SequenceOfFragments* GetSequenceOfFragments() const; 00158 00160 bool IsUndefinedLength() const { 00161 return ValueLengthField.IsUndefined(); 00162 } 00163 00164 DataElement(const DataElement &_val) 00165 { 00166 if( this != &_val) 00167 { 00168 *this = _val; 00169 } 00170 } 00171 00172 bool operator<(const DataElement &de) const 00173 { 00174 return GetTag() < de.GetTag(); 00175 } 00176 DataElement &operator=(const DataElement &de) 00177 { 00178 TagField = de.TagField; 00179 ValueLengthField = de.ValueLengthField; 00180 VRField = de.VRField; 00181 ValueField = de.ValueField; // Pointer copy 00182 return *this; 00183 } 00184 00185 bool operator==(const DataElement &de) const 00186 { 00187 bool b = TagField == de.TagField 00188 && ValueLengthField == de.ValueLengthField 00189 && VRField == de.VRField; 00190 if( !ValueField && !de.ValueField ) 00191 { 00192 return b; 00193 } 00194 if( ValueField && de.ValueField ) 00195 { 00196 return b && (*ValueField == *de.ValueField); 00197 } 00198 // ValueField != de.ValueField 00199 return false; 00200 } 00201 00202 // The following fonctionalities are dependant on: 00203 // # The Transfer Syntax: Explicit or Implicit 00204 // # The Byte encoding: Little Endian / Big Endian 00205 00206 /* 00207 * The following was inspired by a C++ idiom: Curiously Recurring Template Pattern 00208 * Ref: http://en.wikipedia.org/wiki/Curiously_Recurring_Template_Pattern 00209 * The typename TDE is typically a derived class *without* any data 00210 * while TSwap is a simple template parameter to achieve byteswapping (and allow factorization of 00211 * highly identical code) 00212 */ 00213 template <typename TDE> 00214 VL GetLength() const { 00215 return static_cast<const TDE*>(this)->GetLength(); 00216 } 00217 00218 template <typename TDE, typename TSwap> 00219 std::istream &Read(std::istream &is) { 00220 return static_cast<TDE*>(this)->template Read<TSwap>(is); 00221 } 00222 00223 template <typename TDE, typename TSwap> 00224 std::istream &ReadOrSkip(std::istream &is, std::set<Tag> const &skiptags) { 00225 (void)skiptags; 00226 return static_cast<TDE*>(this)->template Read<TSwap>(is); 00227 } 00228 00229 template <typename TDE, typename TSwap> 00230 std::istream &ReadPreValue(std::istream &is, std::set<Tag> const &skiptags) { 00231 (void)skiptags; 00232 return static_cast<TDE*>(this)->template ReadPreValue<TSwap>(is); 00233 } 00234 template <typename TDE, typename TSwap> 00235 std::istream &ReadValue(std::istream &is, std::set<Tag> const &skiptags) { 00236 (void)skiptags; 00237 return static_cast<TDE*>(this)->template ReadValue<TSwap>(is); 00238 } 00239 00240 template <typename TDE, typename TSwap> 00241 std::istream &ReadWithLength(std::istream &is, VL &length) { 00242 return static_cast<TDE*>(this)->template ReadWithLength<TSwap>(is,length); 00243 } 00244 00245 template <typename TDE, typename TSwap> 00246 const std::ostream &Write(std::ostream &os) const { 00247 return static_cast<const TDE*>(this)->template Write<TSwap>(os); 00248 } 00249 00250 protected: 00251 Tag TagField; 00252 // This is the value read from the file, might be different from the length of Value Field 00253 VL ValueLengthField; // Can be 0xFFFFFFFF 00254 00255 // Value Representation 00256 VR VRField; 00257 typedef SmartPointer<Value> ValuePtr; 00258 ValuePtr ValueField; 00259 }; 00260 //----------------------------------------------------------------------------- 00261 inline std::ostream& operator<<(std::ostream &os, const DataElement &val) 00262 { 00263 os << val.TagField; 00264 os << "\t" << val.VRField; 00265 os << "\t" << val.ValueLengthField; 00266 if( val.ValueField ) 00267 { 00268 val.ValueField->Print( os << "\t" ); 00269 } 00270 return os; 00271 } 00272 00273 inline bool operator!=(const DataElement& lhs, const DataElement& rhs) 00274 { 00275 return ! ( lhs == rhs ); 00276 } 00277 00278 } // end namespace gdcm 00279 00280 #endif //GDCMDATAELEMENT_H