GDCM 2.0.17
|
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