GDCM 2.0.17
|
00001 /*========================================================================= 00002 00003 Program: GDCM (Grassroots DICOM). A DICOM library 00004 Module: $URL$ 00005 00006 Copyright (c) 2006-2010 Mathieu Malaterre 00007 All rights reserved. 00008 See Copyright.txt or http://gdcm.sourceforge.net/Copyright.html for details. 00009 00010 This software is distributed WITHOUT ANY WARRANTY; without even 00011 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 00012 PURPOSE. See the above copyright notice for more information. 00013 00014 =========================================================================*/ 00015 #ifndef GDCMDATAELEMENT_H 00016 #define GDCMDATAELEMENT_H 00017 00018 #include "gdcmTag.h" 00019 #include "gdcmVL.h" 00020 #include "gdcmVR.h" 00021 #include "gdcmByteValue.h" 00022 #include "gdcmSmartPointer.h" 00023 00024 #include <set> 00025 00026 namespace gdcm 00027 { 00028 // Data Element 00029 // Contains multiple fields: 00030 // -> Tag 00031 // -> Optional VR (Explicit Transfer Syntax) 00032 // -> ValueLength 00033 // -> Value 00034 // TODO: This class SHOULD be pure virtual. I dont want a user 00035 // to shoot himself in the foot. 00036 00037 class SequenceOfItems; 00038 class SequenceOfFragments; 00059 class GDCM_EXPORT DataElement 00060 { 00061 public: 00062 DataElement(const Tag& t = Tag(0), const VL& vl = 0, const VR &vr = VR::INVALID):TagField(t),ValueLengthField(vl),VRField(vr),ValueField(0) {} 00063 //DataElement( Attribute const &att ); 00064 00065 friend std::ostream& operator<<(std::ostream &_os, const DataElement &_val); 00066 00068 const Tag& GetTag() const { return TagField; } 00069 Tag& GetTag() { return TagField; } 00072 void SetTag(const Tag &t) { TagField = t; } 00073 00075 const VL& GetVL() const { return ValueLengthField; } 00076 VL& GetVL() { return ValueLengthField; } 00080 void SetVL(const VL &vl) { ValueLengthField = vl; } 00081 void SetVLToUndefined(); 00082 00085 VR const &GetVR() const { return VRField; } 00089 void SetVR(VR const &vr) { 00090 // assert( vr.IsVRFile() ); 00091 VRField = vr; 00092 } 00093 00095 Value const &GetValue() const { return *ValueField; } 00096 Value &GetValue() { return *ValueField; } 00098 void SetValue(Value const & vl) { 00099 //assert( ValueField == 0 ); 00100 ValueField = vl; 00101 ValueLengthField = vl.GetLength(); 00102 } 00104 bool IsEmpty() const { return ValueField == 0 || (GetByteValue() && GetByteValue()->IsEmpty()); } 00105 00107 void Empty() { ValueField = 0; ValueLengthField = 0; } 00108 00110 void Clear() 00111 { 00112 TagField = 0; 00113 VRField = VR::INVALID; 00114 ValueField = 0; 00115 ValueLengthField = 0; 00116 } 00117 00118 // Helper: 00124 void SetByteValue(const char *array, VL length) 00125 { 00126 ByteValue *bv = new ByteValue(array,length); 00127 SetValue( *bv ); 00128 } 00131 const ByteValue* GetByteValue() const { 00132 // Get the raw pointer from the gdcm::SmartPointer 00133 const ByteValue *bv = dynamic_cast<const ByteValue*>(ValueField.GetPointer()); 00134 return bv; // Will return NULL if not ByteValue 00135 } 00136 ByteValue* GetByteValue() { 00137 // Get the raw pointer from the gdcm::SmartPointer 00138 ByteValue *bv = dynamic_cast<ByteValue*>(ValueField.GetPointer()); 00139 return bv; // Will return NULL if not ByteValue 00140 } 00141 00150 GDCM_LEGACY(const SequenceOfItems* GetSequenceOfItems() const) 00151 GDCM_LEGACY(SequenceOfItems* GetSequenceOfItems()) 00152 00159 SmartPointer<SequenceOfItems> GetValueAsSQ() const; 00160 00163 const SequenceOfFragments* GetSequenceOfFragments() const; 00164 00166 bool IsUndefinedLength() const { 00167 return ValueLengthField.IsUndefined(); 00168 } 00169 00170 DataElement(const DataElement &_val) 00171 { 00172 if( this != &_val) 00173 { 00174 *this = _val; 00175 } 00176 } 00177 00178 bool operator<(const DataElement &de) const 00179 { 00180 return GetTag() < de.GetTag(); 00181 } 00182 DataElement &operator=(const DataElement &de) 00183 { 00184 TagField = de.TagField; 00185 ValueLengthField = de.ValueLengthField; 00186 VRField = de.VRField; 00187 ValueField = de.ValueField; // Pointer copy 00188 return *this; 00189 } 00190 00191 bool operator==(const DataElement &de) const 00192 { 00193 bool b = TagField == de.TagField 00194 && ValueLengthField == de.ValueLengthField 00195 && VRField == de.VRField; 00196 if( !ValueField && !de.ValueField ) 00197 { 00198 return b; 00199 } 00200 if( ValueField && de.ValueField ) 00201 { 00202 return b && (*ValueField == *de.ValueField); 00203 } 00204 // ValueField != de.ValueField 00205 return false; 00206 } 00207 00208 // The following fonctionalities are dependant on: 00209 // # The Transfer Syntax: Explicit or Implicit 00210 // # The Byte encoding: Little Endian / Big Endian 00211 00212 /* 00213 * The following was inspired by a C++ idiom: Curiously Recurring Template Pattern 00214 * Ref: http://en.wikipedia.org/wiki/Curiously_Recurring_Template_Pattern 00215 * The typename TDE is typically a derived class *without* any data 00216 * while TSwap is a simple template parameter to achieve byteswapping (and allow factorization of 00217 * highly identical code) 00218 */ 00219 template <typename TDE> 00220 VL GetLength() const { 00221 return static_cast<const TDE*>(this)->GetLength(); 00222 } 00223 00224 template <typename TDE, typename TSwap> 00225 std::istream &Read(std::istream &is) { 00226 return static_cast<TDE*>(this)->template Read<TSwap>(is); 00227 } 00228 00229 template <typename TDE, typename TSwap> 00230 std::istream &ReadOrSkip(std::istream &is, std::set<Tag> const &skiptags) { 00231 (void)skiptags; 00232 return static_cast<TDE*>(this)->template Read<TSwap>(is); 00233 } 00234 00235 template <typename TDE, typename TSwap> 00236 std::istream &ReadPreValue(std::istream &is, std::set<Tag> const &skiptags) { 00237 (void)skiptags; 00238 return static_cast<TDE*>(this)->template ReadPreValue<TSwap>(is); 00239 } 00240 template <typename TDE, typename TSwap> 00241 std::istream &ReadValue(std::istream &is, std::set<Tag> const &skiptags) { 00242 (void)skiptags; 00243 return static_cast<TDE*>(this)->template ReadValue<TSwap>(is); 00244 } 00245 00246 template <typename TDE, typename TSwap> 00247 std::istream &ReadWithLength(std::istream &is, VL &length) { 00248 return static_cast<TDE*>(this)->template ReadWithLength<TSwap>(is,length); 00249 } 00250 00251 template <typename TDE, typename TSwap> 00252 const std::ostream &Write(std::ostream &os) const { 00253 return static_cast<const TDE*>(this)->template Write<TSwap>(os); 00254 } 00255 00256 protected: 00257 Tag TagField; 00258 // This is the value read from the file, might be different from the length of Value Field 00259 VL ValueLengthField; // Can be 0xFFFFFFFF 00260 00261 // Value Representation 00262 VR VRField; 00263 typedef SmartPointer<Value> ValuePtr; 00264 ValuePtr ValueField; 00265 }; 00266 //----------------------------------------------------------------------------- 00267 inline std::ostream& operator<<(std::ostream &os, const DataElement &val) 00268 { 00269 os << val.TagField; 00270 os << "\t" << val.VRField; 00271 os << "\t" << val.ValueLengthField; 00272 if( val.ValueField ) 00273 { 00274 val.ValueField->Print( os << "\t" ); 00275 } 00276 return os; 00277 } 00278 00279 } // end namespace gdcm 00280 00281 #endif //GDCMDATAELEMENT_H