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