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