# gdcmTag.h

Go to the documentation of this file.

    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*)(&copy), 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