GDCM 2.2.0

- Main Page
- Related Pages
- Namespaces
- Classes
- Files
- Directories
- Examples

- File List
- File Members

gdcmVR.h
Go to the documentation of this file.

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