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 GDCMTAG_H 00016 #define GDCMTAG_H 00017 00018 #include "gdcmTypes.h" 00019 00020 #include <iostream> 00021 #include <iomanip> 00022 00023 namespace gdcm 00024 { 00025 00039 class GDCM_EXPORT Tag 00040 { 00041 public: 00043 Tag(uint16_t group, uint16_t element) { 00044 ElementTag.tags[0] = group; ElementTag.tags[1] = element; 00045 } 00048 Tag(uint32_t tag = 0) { 00049 SetElementTag(tag); 00050 } 00051 00052 friend std::ostream& operator<<(std::ostream &_os, const Tag &_val); 00053 friend std::istream& operator>>(std::istream &_is, Tag &_val); 00054 00056 uint16_t GetGroup() const { return ElementTag.tags[0]; } 00058 uint16_t GetElement() const { return ElementTag.tags[1]; } 00060 void SetGroup(uint16_t group) { ElementTag.tags[0] = group; } 00062 void SetElement(uint16_t element) { ElementTag.tags[1] = element; } 00064 void SetElementTag(uint16_t group, uint16_t element) { 00065 ElementTag.tags[0] = group; ElementTag.tags[1] = element; 00066 } 00067 00069 uint32_t GetElementTag() const { 00070 #ifndef GDCM_WORDS_BIGENDIAN 00071 return (ElementTag.tag<<16) | (ElementTag.tag>>16); 00072 #else 00073 return ElementTag.tag; 00074 #endif 00075 } 00076 00078 void SetElementTag(uint32_t tag) { 00079 #ifndef GDCM_WORDS_BIGENDIAN 00080 tag = ( (tag<<16) | (tag>>16) ); 00081 #endif 00082 ElementTag.tag = tag; 00083 } 00084 00086 const uint16_t &operator[](const unsigned int &_id) const 00087 { 00088 assert(_id<2); 00089 return ElementTag.tags[_id]; 00090 } 00092 uint16_t &operator[](const unsigned int &_id) 00093 { 00094 assert(_id<2); 00095 return ElementTag.tags[_id]; 00096 } 00097 00098 Tag &operator=(const Tag &_val) 00099 { 00100 ElementTag.tag = _val.ElementTag.tag; 00101 return *this; 00102 } 00103 00104 bool operator==(const Tag &_val) const 00105 { 00106 return ElementTag.tag == _val.ElementTag.tag; 00107 } 00108 bool operator!=(const Tag &_val) const 00109 { 00110 return ElementTag.tag != _val.ElementTag.tag; 00111 } 00112 00115 // FIXME FIXME FIXME TODO 00116 // the following is pretty dumb. Since we have control over who is group 00117 // and who is element, we should reverse them in little endian and big endian case 00118 // since what we really want is fast comparison and not garantee that group is in #0 00119 // ... 00120 bool operator<(const Tag &_val) const 00121 { 00122 #ifndef GDCM_WORDS_BIGENDIAN 00123 if( ElementTag.tags[0] < _val.ElementTag.tags[0] ) 00124 return true; 00125 if( ElementTag.tags[0] == _val.ElementTag.tags[0] 00126 && ElementTag.tags[1] < _val.ElementTag.tags[1] ) 00127 return true; 00128 return false; 00129 #else 00130 // Plain comparison is enough! 00131 return ( ElementTag.tag < _val.ElementTag.tag ); 00132 #endif 00133 } 00134 bool operator<=(const Tag &t2) const 00135 { 00136 const Tag &t1 = *this; 00137 return t1 == t2 || t1 < t2; 00138 } 00139 00140 Tag(const Tag &_val) 00141 { 00142 ElementTag.tag = _val.ElementTag.tag; 00143 } 00145 uint32_t GetLength() const { return 4; } 00146 00151 bool IsPublic() const { return !(ElementTag.tags[0] % 2); } 00152 00156 bool IsPrivate() const { return !IsPublic(); } 00157 00158 //----------------------------------------------------------------------------- 00160 template <typename TSwap> 00161 std::istream &Read(std::istream &is) 00162 { 00163 is.read(ElementTag.bytes, 4); 00164 TSwap::SwapArray(ElementTag.tags, 2); 00165 return is; 00166 } 00167 00169 template <typename TSwap> 00170 const std::ostream &Write(std::ostream &os) const 00171 { 00172 uint16_t copy[2]; 00173 copy[0]= ElementTag.tags[0]; 00174 copy[1]= ElementTag.tags[1]; 00175 TSwap::SwapArray(copy, 2); 00176 return os.write((char*)(©), 4); 00177 } 00178 00180 Tag GetPrivateCreator() const 00181 { 00182 // See PS 3.5 - 7.8.1 PRIVATE DATA ELEMENT TAGS 00183 // eg: 0x0123,0x1425 -> 0x0123,0x0014 00184 assert( IsPrivate() && !IsPrivateCreator() ); 00185 Tag r = *this; 00186 r.SetElement( (uint16_t)(GetElement() >> 8) ); 00187 return r; 00188 } 00190 void SetPrivateCreator(Tag const &t) 00191 { 00192 // See PS 3.5 - 7.8.1 PRIVATE DATA ELEMENT TAGS 00193 // eg: 0x0123,0x0045 -> 0x0123,0x4567 00194 assert( t.IsPrivate() /*&& t.IsPrivateCreator()*/ ); 00195 uint16_t element = (uint16_t)(t.GetElement() << 8); 00196 uint16_t base = (uint16_t)(GetElement() << 8); 00197 SetElement( (uint16_t)((base >> 8) + element) ); 00198 } 00199 00202 bool IsPrivateCreator() const 00203 { 00204 return IsPrivate() && (GetElement() <= 0xFF && GetElement() >= 0x10); 00205 } 00206 00208 bool IsIllegal() const 00209 { 00210 // DICOM reserved those groups: 00211 return GetGroup() == 0x0001 || GetGroup() == 0x0003 || GetGroup() == 0x0005 || GetGroup() == 0x0007 00212 // This is a very special case, in private group, one cannot use element [0x01,0x09] ... 00213 // || (IsPrivate() && !IsPrivateCreator() && !IsGroupLength()); 00214 || (IsPrivate() && GetElement() > 0x0 && GetElement() < 0x10 ); 00215 } 00216 00218 bool IsGroupLength() const 00219 { 00220 return GetElement() == 0x0; 00221 } 00222 00224 bool IsGroupXX(const Tag &t) const 00225 { 00226 if( t.GetElement() == GetElement() ) 00227 { 00228 if( t.IsPrivate() ) return false; 00229 uint16_t group = (uint16_t)((GetGroup() >> 8 ) << 8); 00230 return group == t.GetGroup(); 00231 } 00232 return false; 00233 } 00234 00240 bool ReadFromCommaSeparatedString(const char *str); 00241 00244 bool ReadFromPipeSeparatedString(const char *str); 00245 00248 std::string PrintAsPipeSeparatedString() const; 00249 00250 private: 00251 union { uint32_t tag; uint16_t tags[2]; char bytes[4]; } ElementTag; 00252 }; 00253 //----------------------------------------------------------------------------- 00254 inline std::istream& operator>>(std::istream &_is, Tag &_val) 00255 { 00256 char c; 00257 _is >> c; 00258 uint16_t a, b; 00259 _is >> std::hex >> a; 00260 //_is >> std::hex >> _val[0]; 00261 //_is >> std::hex >> _val.ElementTag.tags[0]; 00262 _is >> c; 00263 //_is >> _val[1]; 00264 //_is >> std::hex >> _val.ElementTag.tags[1]; 00265 _is >> std::hex >> b; 00266 _is >> c; 00267 _val.SetGroup( a ); 00268 _val.SetElement( b ); 00269 return _is; 00270 } 00271 00272 inline std::ostream& operator<<(std::ostream &_os, const Tag &_val) 00273 { 00274 _os.setf( std::ios::right); 00275 _os << std::hex << '(' << std::setw( 4 ) << std::setfill( '0' ) 00276 << _val[0] << ',' << std::setw( 4 ) << std::setfill( '0' ) 00277 << _val[1] << ')' << std::setfill( ' ' ) << std::dec; 00278 return _os; 00279 } 00280 00281 } // end namespace gdcm 00282 00283 #endif //GDCMTAG_H