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