# gdcmVR.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 GDCMVR_H
    00016 #define GDCMVR_H
    00017
    00018 #include "gdcmTag.h"
    00019 #include "gdcmTrace.h"
    00020 #include "gdcmString.h"
    00021
    00022 #include <iostream>
    00023 #include <fstream>
    00024 #include <assert.h>
    00025
    00026 //these defines are here to ensure compilation on sunos gcc
    00027 #if defined (CS)
    00028 # undef CS
    00029 #endif
    00030 #if defined (DS)
    00031 # undef DS
    00032 #endif
    00033 #if defined (SS)
    00034 # undef SS
    00035 #endif
    00036
    00037
    00038 namespace gdcm
    00039 {
    00040
    00055 class GDCM_EXPORT VR
    00056 {
    00057 public:
    00058   typedef enum {
    00059     // Warning: Do not write if ( vr & VR::INVALID ) but if ( vr == VR::INVALID )
    00060     INVALID = 0, // For Item/(Seq) Item Delimitation Item
    00061     AE = 1,
    00062     AS = 2,
    00063     AT = 4,
    00064     CS = 8,
    00065     DA = 16,
    00066     DS = 32,
    00067     DT = 64,
    00068     FD = 128,
    00069     FL = 256,
    00070     IS = 512,
    00071     LO = 1024,
    00072     LT = 2048,
    00073     OB = 4096,
    00074     OF = 8192,
    00075     OW = 16384,
    00076     PN = 32768,
    00077     SH = 65536,
    00078     SL = 131072,
    00079     SQ = 262144,
    00080     SS = 524288,
    00081     ST = 1048576,
    00082     TM = 2097152,
    00083     UI = 4194304,
    00084     UL = 8388608,
    00085     UN = 16777216,
    00086     US = 33554432,
    00087     UT = 67108864,
    00088     OB_OW = OB | OW,
    00089     US_SS = US | SS,
    00090     US_SS_OW = US | SS | OW,
    00091     // The following do not have a VRString equivalent (ie cannot be found in PS 3.6)
    00092     VL16 = AE | AS | AT | CS | DA | DS | DT | FD | FL | IS | LO | LT | PN | SH | SL | SS | ST | TM | UI | UL | US, // if( VR & VL16 ) => VR has its VL coded over 16bits
    00093     VL32 = OB | OW | OF | SQ | UN | UT, // if( VR & VL32 ) => VR has its VL coded over 32bits
    00094     VRASCII = AE | AS | CS | DA | DS | DT | IS | LO | LT | PN | SH | ST | TM | UI | UT,
    00095     VRBINARY = AT | FL | FD | OB | OF | OW | SL | SQ | SS | UL | UN | US, // FIXME: UN ?
    00096     // PS 3.5:
    00097     // Data Elements with a VR of SQ, OF, OW, OB or UN shall always have a Value Multiplicity of one.
    00098     // GDCM is adding a couple more: AS, LT, ST, UT
    00099     VR_VM1 = AS | LT | ST | UT | SQ | OF | OW | OB | UN, // All those VR have a VM1
    00100     VRALL = VRASCII | VRBINARY,
    00101     VR_END = UT+1  // Invalid VR, need to be max(VRType)+1
    00102   } VRType;
    00103
    00104   static const char *GetVRString(VRType vr);
    00105
    00106   // This function will only look at the very first two chars nothing else
    00107   static VRType GetVRTypeFromFile(const char *vr);
    00108
    00109   // You need to make sure end of string is \0
    00110   static VRType GetVRType(const char *vr);
    00111   static const char *GetVRStringFromFile(VRType vr);
    00112
    00113   static bool IsValid(const char *vr);
    00114   // Check if vr1 is valid against vr2,
    00115   // Typically vr1 is read from the file and vr2 is taken from the dict
    00116   static bool IsValid(const char *vr1, VRType vr2);
    00117   //static bool IsValid(const VRType &vr1, const VRType &vr2);
    00118   // Find out if the string read is byte swapped
    00119   static bool IsSwap(const char *vr);
    00120
    00121   // Size read on disk
    00122   // FIXME: int ?
    00123   int GetLength() const {
    00124     return VR::GetLength(VRField);
    00125   }
    00126   unsigned int GetSizeof() const;
    00127   static uint32_t GetLength(VRType vr) {
    00128     //if( vr == VR::INVALID ) return 4;
    00129     if( vr & VL32 )
    00130       {
    00131       return 4;
    00132       }
    00133     else
    00134       return 2;
    00135   }
    00136
    00137   // Some use of template metaprograming with ugly macro
    00138   static bool IsBinary(VRType vr);
    00139   static bool IsASCII(VRType vr);
    00140   // TODO: REMOVE ME
    00141   static bool CanDisplay(VRType vr);
    00142   // TODO: REMOVE ME
    00143   static bool IsBinary2(VRType vr);
    00144   // TODO: REMOVE ME
    00145   static bool IsASCII2(VRType vr);
    00146
    00147   VR(VRType vr = INVALID):VRField(vr) { }
    00148   //VR(VR const &vr):VRField(vr.VRField) { }
    00149   std::istream &Read(std::istream &is)
    00150     {
    00151     char vr[2];
    00152     is.read(vr, 2);
    00153     VRField = GetVRTypeFromFile(vr);
    00154     assert( VRField != VR::VR_END );
    00155     //assert( VRField != VR::INVALID );
    00156     if( VRField == VR::INVALID ) throw Exception( "INVALID VR" );
    00157     if( VRField & VL32 )
    00158       {
    00159 #if 0
    00160       // For some reason this seems slower on my linux box...
    00161       is.seekg(2, std::ios::cur );
    00162 #else
    00163       char dum[2];
    00164       is.read(dum, 2);
    00165       if( !(dum[0] == 0 && dum[1] == 0 ))
    00166         {
    00167         // JDDICOM_Sample4.dcm
    00168         gdcmDebugMacro( "32bits VR contains non zero bytes. Skipped" );
    00169         }
    00170 #endif
    00171       }
    00172     return is;
    00173     }
    00174
    00175   const std::ostream &Write(std::ostream &os) const
    00176     {
    00177     VRType vrfield = VRField;
    00178     gdcmAssertAlwaysMacro( !IsDual() );
    00179     if( vrfield == VR::INVALID )
    00180       {
    00181       //vrfield = VR::UN;
    00182       }
    00183     const char *vr = GetVRString(vrfield);
    00184     //assert( strlen( vr ) == 2 );
    00185     assert( vr[0] && vr[1] && vr[2] == 0 );
    00186     os.write(vr, 2);
    00187     // See PS 3.5, Data Element Structure With Explicit VR
    00188     if( vrfield & VL32 )
    00189       {
    00190       const char dum[2] = {0, 0};
    00191       os.write(dum,2);
    00192       }
    00193     return os;
    00194     }
    00195   friend std::ostream &operator<<(std::ostream &os, const VR &vr);
    00196
    00197   operator VRType () const { return VRField; }
    00198
    00199   unsigned int GetSize() const;
    00200
    00201   bool Compatible(VR const &vr) const;
    00202
    00203   bool IsVRFile() const;
    00204
    00205   bool IsDual() const;
    00206
    00207 private:
    00208   // Internal function that map a VRType to an index in the VRStrings table
    00209   static int GetIndex(VRType vr);
    00210   VRType VRField;
    00211 };
    00212 //-----------------------------------------------------------------------------
    00213 inline std::ostream &operator<<(std::ostream &_os, const VR &val)
    00214 {
    00215   //_os << VR::GetVRStringFromFile(val.VRField);
    00216   _os << VR::GetVRString(val.VRField);
    00217   return _os;
    00218 }
    00219
    00220 // Apparently SWIG is not happy with something, somewhere below...
    00221 #ifndef SWIG
    00222
    00223 // Tells whether VR Type is ASCII or Binary
    00224 template<int T> struct VRToEncoding;
    00225 // Convert from VR Type to real underlying type
    00226 template<int T> struct VRToType;
    00227 #define TYPETOENCODING(type,rep, rtype)         \
    00228   template<> struct VRToEncoding<VR::type>    \
    00229   { enum { Mode = VR::rep }; };                 \
    00230   template<> struct VRToType<VR::type>        \
    00231   { typedef rtype Type; };
    00232
    00233
    00234 // Do not use me
    00235 struct UI { char Internal[64+1];
    00236   friend std::ostream& operator<<(std::ostream &_os, const UI &_val);
    00237 };
    00238 inline std::ostream& operator<<(std::ostream &_os, const UI &_val)
    00239 {
    00240   _os << _val.Internal;
    00241   return _os;
    00242 }
    00243
    00244 typedef String<'\\',16> AEComp;
    00245 typedef String<'\\',64> ASComp;
    00246 typedef String<'\\',16> CSComp;
    00247 typedef String<'\\',64> DAComp;
    00248 typedef String<'\\',64> DTComp;
    00249 typedef String<'\\',64> LOComp;
    00250 typedef String<'\\',64> LTComp;
    00251 typedef String<'\\',64> PNComp;
    00252 typedef String<'\\',64> SHComp;
    00253 typedef String<'\\',64> STComp;
    00254 typedef String<'\\',64> TMComp;
    00255 typedef String<'\\',64,0> UIComp;
    00256 typedef String<'\\',64> UTComp;
    00257
    00258
    00259 // TODO: Could be generated from XML file
    00260 TYPETOENCODING(AE,VRASCII ,AEComp)
    00261 TYPETOENCODING(AS,VRASCII ,ASComp)
    00262 TYPETOENCODING(AT,VRBINARY,Tag)
    00263 TYPETOENCODING(CS,VRASCII ,CSComp)
    00264 TYPETOENCODING(DA,VRASCII ,DAComp)
    00265 TYPETOENCODING(DS,VRASCII ,double)
    00266 TYPETOENCODING(DT,VRASCII ,DTComp)
    00267 TYPETOENCODING(FL,VRBINARY,float)
    00268 TYPETOENCODING(FD,VRBINARY,double)
    00269 TYPETOENCODING(IS,VRASCII ,int32_t)
    00270 TYPETOENCODING(LO,VRASCII ,LOComp)
    00271 TYPETOENCODING(LT,VRASCII ,LTComp)
    00272 TYPETOENCODING(OB,VRBINARY,uint8_t)
    00273 TYPETOENCODING(OF,VRBINARY,float)
    00274 TYPETOENCODING(OW,VRBINARY,uint16_t)
    00275 TYPETOENCODING(PN,VRASCII ,PNComp)
    00276 TYPETOENCODING(SH,VRASCII ,SHComp)
    00277 TYPETOENCODING(SL,VRBINARY,int32_t)
    00278 TYPETOENCODING(SQ,VRBINARY,unsigned char) // FIXME
    00279 TYPETOENCODING(SS,VRBINARY,int16_t)
    00280 TYPETOENCODING(ST,VRASCII ,STComp)
    00281 TYPETOENCODING(TM,VRASCII ,TMComp)
    00282 TYPETOENCODING(UI,VRASCII ,UIComp)
    00283 TYPETOENCODING(UL,VRBINARY,uint32_t)
    00284 TYPETOENCODING(UN,VRBINARY,uint8_t) // FIXME ?
    00285 TYPETOENCODING(US,VRBINARY,uint16_t)
    00286 TYPETOENCODING(UT,VRASCII ,UTComp)
    00287
    00288 #define VRTypeTemplateCase(type) \
    00289   case VR::type: \
    00290     return sizeof ( VRToType<VR::type>::Type );
    00291
    00292 inline unsigned int VR::GetSize() const
    00293 {
    00294   switch(VRField)
    00295   {
    00296     VRTypeTemplateCase(AE)
    00297     VRTypeTemplateCase(AS)
    00298     VRTypeTemplateCase(AT)
    00299     VRTypeTemplateCase(CS)
    00300     VRTypeTemplateCase(DA)
    00301     VRTypeTemplateCase(DS)
    00302     VRTypeTemplateCase(DT)
    00303     VRTypeTemplateCase(FL)
    00304     VRTypeTemplateCase(FD)
    00305     VRTypeTemplateCase(IS)
    00306     VRTypeTemplateCase(LO)
    00307     VRTypeTemplateCase(LT)
    00308     VRTypeTemplateCase(OB)
    00309     VRTypeTemplateCase(OF)
    00310     VRTypeTemplateCase(OW)
    00311     VRTypeTemplateCase(PN)
    00312     VRTypeTemplateCase(SH)
    00313     VRTypeTemplateCase(SL)
    00314     VRTypeTemplateCase(SQ)
    00315     VRTypeTemplateCase(SS)
    00316     VRTypeTemplateCase(ST)
    00317     VRTypeTemplateCase(TM)
    00318     VRTypeTemplateCase(UI)
    00319     VRTypeTemplateCase(UL)
    00320     VRTypeTemplateCase(UN)
    00321     VRTypeTemplateCase(US)
    00322     VRTypeTemplateCase(UT)
    00323     case VR::US_SS:
    00324       return 2;
    00325     default:
    00326        assert( 0 && "should not" );
    00327   }
    00328   return 0;
    00329 }
    00330 #endif // SWIG
    00331
    00332
    00333 } // end namespace gdcm
    00334
    00335 #endif //GDCMVR_H