GDCM
2.2.3
|
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 GDCMELEMENT_H 00015 #define GDCMELEMENT_H 00016 00017 #include "gdcmTypes.h" 00018 #include "gdcmVR.h" 00019 #include "gdcmTag.h" 00020 #include "gdcmVM.h" 00021 #include "gdcmByteValue.h" 00022 #include "gdcmDataElement.h" 00023 #include "gdcmSwapper.h" 00024 00025 #include <string> 00026 #include <vector> 00027 #include <sstream> 00028 #include <limits> 00029 #include <cmath> 00030 #include <cstring> 00031 00032 namespace gdcm 00033 { 00034 00035 // Forward declaration 00041 template<int T> class EncodingImplementation; 00042 00048 template<int TVR, int TVM> 00049 class Element 00050 { 00051 public: 00052 typename VRToType<TVR>::Type Internal[VMToLength<TVM>::Length]; 00053 typedef typename VRToType<TVR>::Type Type; 00054 00055 static VR GetVR() { return (VR::VRType)TVR; } 00056 static VM GetVM() { return (VM::VMType)TVM; } 00057 00058 unsigned long GetLength() const { 00059 return VMToLength<TVM>::Length; 00060 } 00061 // Implementation of Print is common to all Mode (ASCII/Binary) 00062 // TODO: Can we print a \ when in ASCII...well I don't think so 00063 // it would mean we used a bad VM then, right ? 00064 void Print(std::ostream &_os) const { 00065 _os << Internal[0]; // VM is at least garantee to be one 00066 for(int i=1; i<VMToLength<TVM>::Length; ++i) 00067 _os << "," << Internal[i]; 00068 } 00069 00070 const typename VRToType<TVR>::Type *GetValues() const { 00071 return Internal; 00072 } 00073 const typename VRToType<TVR>::Type &GetValue(unsigned int idx = 0) const { 00074 assert( idx < VMToLength<TVM>::Length ); 00075 return Internal[idx]; 00076 } 00077 typename VRToType<TVR>::Type &GetValue(unsigned int idx = 0) { 00078 assert( idx < VMToLength<TVM>::Length ); 00079 return Internal[idx]; 00080 } 00081 typename VRToType<TVR>::Type operator[] (unsigned int idx) const { 00082 return GetValue(idx); 00083 } 00084 void SetValue(typename VRToType<TVR>::Type v, unsigned int idx = 0) { 00085 assert( idx < VMToLength<TVM>::Length ); 00086 Internal[idx] = v; 00087 } 00088 00089 void SetFromDataElement(DataElement const &de) { 00090 const ByteValue *bv = de.GetByteValue(); 00091 if( !bv ) return; 00092 #ifdef GDCM_WORDS_BIGENDIAN 00093 if( de.GetVR() == VR::UN /*|| de.GetVR() == VR::INVALID*/ ) 00094 #else 00095 if( de.GetVR() == VR::UN || de.GetVR() == VR::INVALID ) 00096 #endif 00097 { 00098 Set(de.GetValue()); 00099 } 00100 else 00101 { 00102 SetNoSwap(de.GetValue()); 00103 } 00104 } 00105 00106 DataElement GetAsDataElement() const { 00107 DataElement ret; 00108 std::ostringstream os; 00109 EncodingImplementation<VRToEncoding<TVR>::Mode>::Write(Internal, 00110 GetLength(),os); 00111 ret.SetVR( (VR::VRType)TVR ); 00112 assert( ret.GetVR() != VR::SQ ); 00113 if( (VR::VRType)VRToEncoding<TVR>::Mode == VR::VRASCII ) 00114 { 00115 if( GetVR() != VR::UI ) 00116 { 00117 if( os.str().size() % 2 ) 00118 { 00119 os << " "; 00120 } 00121 } 00122 } 00123 VL::Type osStrSize = (VL::Type)os.str().size(); 00124 ret.SetByteValue( os.str().c_str(), osStrSize ); 00125 00126 return ret; 00127 } 00128 00129 void Read(std::istream &_is) { 00130 return EncodingImplementation<VRToEncoding<TVR>::Mode>::Read(Internal, 00131 GetLength(),_is); 00132 } 00133 void Write(std::ostream &_os) const { 00134 return EncodingImplementation<VRToEncoding<TVR>::Mode>::Write(Internal, 00135 GetLength(),_os); 00136 } 00137 00138 // FIXME: remove this function 00139 // this is only used in gdcm::SplitMosaicFilter / to pass value of a CSAElement 00140 void Set(Value const &v) { 00141 const ByteValue *bv = dynamic_cast<const ByteValue*>(&v); 00142 if( bv ) { 00143 //memcpy(Internal, bv->GetPointer(), bv->GetLength()); 00144 std::stringstream ss; 00145 std::string s = std::string( bv->GetPointer(), bv->GetLength() ); 00146 ss.str( s ); 00147 EncodingImplementation<VRToEncoding<TVR>::Mode>::Read(Internal, 00148 GetLength(),ss); 00149 } 00150 } 00151 protected: 00152 void SetNoSwap(Value const &v) { 00153 const ByteValue *bv = dynamic_cast<const ByteValue*>(&v); 00154 assert( bv ); // That would be bad... 00155 //memcpy(Internal, bv->GetPointer(), bv->GetLength()); 00156 std::stringstream ss; 00157 std::string s = std::string( bv->GetPointer(), bv->GetLength() ); 00158 ss.str( s ); 00159 EncodingImplementation<VRToEncoding<TVR>::Mode>::ReadNoSwap(Internal, 00160 GetLength(),ss); 00161 } 00162 }; 00163 00164 struct ignore_char { 00165 ignore_char(char c): m_char(c) {} 00166 char m_char; 00167 }; 00168 ignore_char const backslash('\\'); 00169 00170 inline std::istream& operator>> (std::istream& in, ignore_char const& ic) { 00171 if (!in.eof()) 00172 in.clear(in.rdstate() & ~std::ios_base::failbit); 00173 if (in.get() != ic.m_char) 00174 in.setstate(std::ios_base::failbit); 00175 return in; 00176 } 00177 00178 00179 // Implementation to perform formatted read and write 00180 template<> class EncodingImplementation<VR::VRASCII> { 00181 public: 00182 template<typename T> // FIXME this should be VRToType<TVR>::Type 00183 static inline void ReadComputeLength(T* data, unsigned int &length, 00184 std::istream &_is) { 00185 assert( data ); 00186 //assert( length ); // != 0 00187 length = 0; 00188 assert( _is ); 00189 #if 0 00190 char sep; 00191 while( _is >> data[length++] ) 00192 { 00193 // Get the separator in between the values 00194 assert( _is ); 00195 _is.get(sep); 00196 assert( sep == '\\' || sep == ' ' ); // FIXME: Bad use of assert 00197 if( sep == ' ' ) length--; // FIXME 00198 } 00199 #else 00200 while( _is >> std::ws >> data[length++] >> std::ws >> backslash ) 00201 { 00202 } 00203 #endif 00204 } 00205 00206 template<typename T> // FIXME this should be VRToType<TVR>::Type 00207 static inline void Read(T* data, unsigned long length, 00208 std::istream &_is) { 00209 assert( data ); 00210 assert( length ); // != 0 00211 assert( _is ); 00212 // FIXME BUG: what if >> operation fails ? 00213 // gdcmData/MR00010001.dcm / SpacingBetweenSlices 00214 _is >> std::ws >> data[0]; 00215 char sep; 00216 //std::cout << "GetLength: " << af->GetLength() << std::endl; 00217 for(unsigned long i=1; i<length;++i) { 00218 assert( _is ); 00219 // Get the separator in between the values 00220 _is >> std::ws >> sep; //_is.get(sep); 00221 assert( sep == '\\' ); // FIXME: Bad use of assert 00222 _is >> std::ws >> data[i]; 00223 } 00224 } 00225 00226 template<typename T> 00227 static inline void ReadNoSwap(T* data, unsigned long length, 00228 std::istream &_is) { 00229 Read(data,length,_is); 00230 } 00231 template<typename T> 00232 static inline void Write(const T* data, unsigned long length, 00233 std::ostream &_os) { 00234 assert( data ); 00235 assert( length ); 00236 assert( _os ); 00237 _os << data[0]; 00238 for(unsigned long i=1; i<length; ++i) { 00239 assert( _os ); 00240 _os << "\\" << data[i]; 00241 } 00242 } 00243 }; 00244 00245 template < typename Float > 00246 std::string to_string ( Float data ) { 00247 std::stringstream in; 00248 // in.imbue(std::locale::classic()); // This is not required AFAIK 00249 int const digits = 00250 static_cast< int >( 00251 - std::log( std::numeric_limits<Float>::epsilon() ) 00252 / std::log( 10.0 ) ); 00253 if ( in << std::dec << std::setprecision(/*2+*/digits) << data ) { 00254 return ( in.str() ); 00255 } else { 00256 throw "Impossible Conversion"; // should not happen ... 00257 } 00258 } 00259 00260 /* Writing VR::DS is not that easy after all */ 00261 // http://groups.google.com/group/comp.lang.c++/browse_thread/thread/69ccd26f000a0802 00262 template<> inline void EncodingImplementation<VR::VRASCII>::Write(const float * data, unsigned long length, std::ostream &_os) { 00263 assert( data ); 00264 assert( length ); 00265 assert( _os ); 00266 _os << to_string(data[0]); 00267 for(unsigned long i=1; i<length; ++i) { 00268 assert( _os ); 00269 _os << "\\" << to_string(data[i]); 00270 } 00271 } 00272 00273 template<> inline void EncodingImplementation<VR::VRASCII>::Write(const double* data, unsigned long length, std::ostream &_os) { 00274 assert( data ); 00275 assert( length ); 00276 assert( _os ); 00277 _os << to_string(data[0]); 00278 for(unsigned long i=1; i<length; ++i) { 00279 assert( _os ); 00280 _os << "\\" << to_string(data[i]); 00281 } 00282 } 00283 00284 00285 // Implementation to perform binary read and write 00286 // TODO rewrite operation so that either: 00287 // #1. dummy implementation use a pointer to Internal and do ++p (faster) 00288 // #2. Actually do some meta programming to unroll the loop 00289 // (no notion of order in VM ...) 00290 template<> class EncodingImplementation<VR::VRBINARY> { 00291 public: 00292 template<typename T> // FIXME this should be VRToType<TVR>::Type 00293 static inline void ReadComputeLength(T* data, unsigned int &length, 00294 std::istream &_is) { 00295 const unsigned int type_size = sizeof(T); 00296 assert( data ); // Can we read from pointer ? 00297 //assert( length ); 00298 length /= type_size; 00299 assert( _is ); // Is stream valid ? 00300 _is.read( reinterpret_cast<char*>(data+0), type_size); 00301 for(unsigned long i=1; i<length; ++i) { 00302 assert( _is ); 00303 _is.read( reinterpret_cast<char*>(data+i), type_size ); 00304 } 00305 } 00306 template<typename T> 00307 static inline void ReadNoSwap(T* data, unsigned long length, 00308 std::istream &_is) { 00309 const unsigned int type_size = sizeof(T); 00310 assert( data ); // Can we read from pointer ? 00311 assert( length ); 00312 assert( _is ); // Is stream valid ? 00313 _is.read( reinterpret_cast<char*>(data+0), type_size); 00314 for(unsigned long i=1; i<length; ++i) { 00315 assert( _is ); 00316 _is.read( reinterpret_cast<char*>(data+i), type_size ); 00317 } 00318 //ByteSwap<T>::SwapRangeFromSwapCodeIntoSystem(data, 00319 // _is.GetSwapCode(), length); 00320 //SwapperNoOp::SwapArray(data,length); 00321 } 00322 template<typename T> 00323 static inline void Read(T* data, unsigned long length, 00324 std::istream &_is) { 00325 const unsigned int type_size = sizeof(T); 00326 assert( data ); // Can we read from pointer ? 00327 assert( length ); 00328 assert( _is ); // Is stream valid ? 00329 _is.read( reinterpret_cast<char*>(data+0), type_size); 00330 for(unsigned long i=1; i<length; ++i) { 00331 assert( _is ); 00332 _is.read( reinterpret_cast<char*>(data+i), type_size ); 00333 } 00334 //ByteSwap<T>::SwapRangeFromSwapCodeIntoSystem(data, 00335 // _is.GetSwapCode(), length); 00336 SwapperNoOp::SwapArray(data,length); 00337 } 00338 template<typename T> 00339 static inline void Write(const T* data, unsigned long length, 00340 std::ostream &_os) { 00341 const unsigned int type_size = sizeof(T); 00342 assert( data ); // Can we write into pointer ? 00343 assert( length ); 00344 assert( _os ); // Is stream valid ? 00345 //ByteSwap<T>::SwapRangeFromSwapCodeIntoSystem((T*)data, 00346 // _os.GetSwapCode(), length); 00347 T swappedData = SwapperNoOp::Swap(data[0]); 00348 _os.write( reinterpret_cast<const char*>(&swappedData), type_size); 00349 for(unsigned long i=1; i<length;++i) { 00350 assert( _os ); 00351 swappedData = SwapperNoOp::Swap(data[i]); 00352 _os.write( reinterpret_cast<const char*>(&swappedData), type_size ); 00353 } 00354 //ByteSwap<T>::SwapRangeFromSwapCodeIntoSystem((T*)data, 00355 // _os.GetSwapCode(), length); 00356 } 00357 }; 00358 00359 // For particular case for ASCII string 00360 // WARNING: This template explicitely instanciates a particular 00361 // EncodingImplementation THEREFORE it is required to be declared after the 00362 // EncodingImplementation is needs (doh!) 00363 #if 0 00364 template<int TVM> 00365 class Element<TVM> 00366 { 00367 public: 00368 Element(const char array[]) 00369 { 00370 unsigned int i = 0; 00371 const char sep = '\\'; 00372 std::string sarray = array; 00373 std::string::size_type pos1 = 0; 00374 std::string::size_type pos2 = sarray.find(sep, pos1+1); 00375 while(pos2 != std::string::npos) 00376 { 00377 Internal[i++] = sarray.substr(pos1, pos2-pos1); 00378 pos1 = pos2+1; 00379 pos2 = sarray.find(sep, pos1+1); 00380 } 00381 Internal[i] = sarray.substr(pos1, pos2-pos1); 00382 // Shouldn't we do the contrary, since we know how many separators 00383 // (and default behavior is to discard anything after the VM declared 00384 assert( GetLength()-1 == i ); 00385 } 00386 00387 unsigned long GetLength() const { 00388 return VMToLength<TVM>::Length; 00389 } 00390 // Implementation of Print is common to all Mode (ASCII/Binary) 00391 void Print(std::ostream &_os) const { 00392 _os << Internal[0]; // VM is at least garantee to be one 00393 for(int i=1; i<VMToLength<TVM>::Length; ++i) 00394 _os << "," << Internal[i]; 00395 } 00396 00397 void Read(std::istream &_is) { 00398 EncodingImplementation<VR::VRASCII>::Read(Internal, GetLength(),_is); 00399 } 00400 void Write(std::ostream &_os) const { 00401 EncodingImplementation<VR::VRASCII>::Write(Internal, GetLength(),_os); 00402 } 00403 private: 00404 typename String Internal[VMToLength<TVM>::Length]; 00405 }; 00406 00407 template< int TVM> 00408 class Element<VR::PN, TVM> : public StringElement<TVM> 00409 { 00410 }; 00411 #endif 00412 00413 // Implementation for the undefined length (dynamically allocated array) 00414 template<int TVR> 00415 class Element<TVR, VM::VM1_n> 00416 { 00417 public: 00418 // This the way to prevent default initialization 00419 explicit Element() { Internal=0; Length=0; Save = false; } 00420 ~Element() { 00421 if( Save ) { 00422 delete[] Internal; 00423 } 00424 Internal = 0; 00425 } 00426 00427 static VR GetVR() { return (VR::VRType)TVR; } 00428 static VM GetVM() { return VM::VM1_n; } 00429 00430 // Length manipulation 00431 // SetLength should really be protected anyway...all operation 00432 // should go through SetArray 00433 unsigned long GetLength() const { return Length; } 00434 typedef typename VRToType<TVR>::Type Type; 00435 00436 void SetLength(unsigned long len) { 00437 const unsigned int size = sizeof(Type); 00438 if( len ) { 00439 if( len > Length ) { 00440 // perform realloc 00441 assert( (len / size) * size == len ); 00442 Type *internal = new Type[len / size]; 00443 assert( Save == false ); 00444 Save = true; // ???? 00445 if( Internal ) 00446 { 00447 memcpy(internal, Internal, len); 00448 delete[] Internal; 00449 } 00450 Internal = internal; 00451 } 00452 } 00453 Length = len / size; 00454 } 00455 00456 // If save is set to zero user should not delete the pointer 00457 //void SetArray(const typename VRToType<TVR>::Type *array, int len, bool save = false) 00458 void SetArray(const Type *array, unsigned long len, 00459 bool save = false) { 00460 if( save ) { 00461 SetLength(len); // realloc 00462 memcpy(Internal, array, len/*/sizeof(Type)*/); 00463 assert( Save == false ); 00464 } 00465 else { 00466 // TODO rewrite this stupid code: 00467 assert( Length == 0 ); 00468 assert( Internal == 0 ); 00469 assert( Save == false ); 00470 Length = len / sizeof(Type); 00471 //assert( (len / sizeof(Type)) * sizeof(Type) == len ); 00472 // MR00010001.dcm is a tough kid: 0019,105a is supposed to be VR::FL, VM::VM3 but 00473 // length is 14 bytes instead of 12 bytes. Simply consider value is total garbage. 00474 if( (len / sizeof(Type)) * sizeof(Type) != len ) { Internal = 0; Length = 0; } 00475 else Internal = const_cast<Type*>(array); 00476 } 00477 Save = save; 00478 } 00479 void SetValue(typename VRToType<TVR>::Type v, unsigned int idx = 0) { 00480 assert( idx < Length ); 00481 Internal[idx] = v; 00482 } 00483 const typename VRToType<TVR>::Type &GetValue(unsigned int idx = 0) const { 00484 assert( idx < Length ); 00485 return Internal[idx]; 00486 } 00487 typename VRToType<TVR>::Type &GetValue(unsigned int idx = 0) { 00488 assert( idx < Length ); 00489 return Internal[idx]; 00490 } 00491 typename VRToType<TVR>::Type operator[] (unsigned int idx) const { 00492 return GetValue(idx); 00493 } 00494 void Set(Value const &v) { 00495 const ByteValue *bv = dynamic_cast<const ByteValue*>(&v); 00496 assert( bv ); // That would be bad... 00497 if( (VR::VRType)(VRToEncoding<TVR>::Mode) == VR::VRBINARY ) 00498 { 00499 const Type* array = (Type*)bv->GetPointer(); 00500 if( array ) { 00501 assert( array ); // That would be bad... 00502 assert( Internal == 0 ); 00503 SetArray(array, bv->GetLength() ); } 00504 } 00505 else 00506 { 00507 std::stringstream ss; 00508 std::string s = std::string( bv->GetPointer(), bv->GetLength() ); 00509 ss.str( s ); 00510 EncodingImplementation<VRToEncoding<TVR>::Mode>::Read(Internal, 00511 GetLength(),ss); 00512 } 00513 } 00514 void SetFromDataElement(DataElement const &de) { 00515 const ByteValue *bv = de.GetByteValue(); 00516 if( !bv ) return; 00517 #ifdef GDCM_WORDS_BIGENDIAN 00518 if( de.GetVR() == VR::UN /*|| de.GetVR() == VR::INVALID*/ ) 00519 #else 00520 if( de.GetVR() == VR::UN || de.GetVR() == VR::INVALID ) 00521 #endif 00522 { 00523 Set(de.GetValue()); 00524 } 00525 else 00526 { 00527 SetNoSwap(de.GetValue()); 00528 } 00529 } 00530 00531 00532 // Need to be placed after definition of EncodingImplementation<VR::VRASCII> 00533 void WriteASCII(std::ostream &os) const { 00534 return EncodingImplementation<VR::VRASCII>::Write(Internal, GetLength(), os); 00535 } 00536 00537 // Implementation of Print is common to all Mode (ASCII/Binary) 00538 void Print(std::ostream &_os) const { 00539 assert( Length ); 00540 assert( Internal ); 00541 _os << Internal[0]; // VM is at least garantee to be one 00542 const unsigned long length = GetLength() < 25 ? GetLength() : 25; 00543 for(unsigned long i=1; i<length; ++i) 00544 _os << "," << Internal[i]; 00545 } 00546 void Read(std::istream &_is) { 00547 if( !Internal ) return; 00548 EncodingImplementation<VRToEncoding<TVR>::Mode>::Read(Internal, 00549 GetLength(),_is); 00550 } 00551 //void ReadComputeLength(std::istream &_is) { 00552 // if( !Internal ) return; 00553 // EncodingImplementation<VRToEncoding<TVR>::Mode>::ReadComputeLength(Internal, 00554 // Length,_is); 00555 // } 00556 void Write(std::ostream &_os) const { 00557 EncodingImplementation<VRToEncoding<TVR>::Mode>::Write(Internal, 00558 GetLength(),_os); 00559 } 00560 00561 DataElement GetAsDataElement() const { 00562 DataElement ret; 00563 ret.SetVR( (VR::VRType)TVR ); 00564 assert( ret.GetVR() != VR::SQ ); 00565 if( Internal ) 00566 { 00567 std::ostringstream os; 00568 EncodingImplementation<VRToEncoding<TVR>::Mode>::Write(Internal, 00569 GetLength(),os); 00570 if( (VR::VRType)VRToEncoding<TVR>::Mode == VR::VRASCII ) 00571 { 00572 if( GetVR() != VR::UI ) 00573 { 00574 if( os.str().size() % 2 ) 00575 { 00576 os << " "; 00577 } 00578 } 00579 } 00580 VL::Type osStrSize = (VL::Type)os.str().size(); 00581 ret.SetByteValue( os.str().c_str(), osStrSize ); 00582 } 00583 return ret; 00584 } 00585 00586 Element(const Element&_val) { 00587 if( this != &_val) { 00588 *this = _val; 00589 } 00590 } 00591 00592 Element &operator=(const Element &_val) { 00593 Length = 0; // SYITF 00594 Internal = 0; 00595 SetArray(_val.Internal, _val.Length, true); 00596 return *this; 00597 } 00598 protected: 00599 void SetNoSwap(Value const &v) { 00600 const ByteValue *bv = dynamic_cast<const ByteValue*>(&v); 00601 assert( bv ); // That would be bad... 00602 if( (VR::VRType)(VRToEncoding<TVR>::Mode) == VR::VRBINARY ) 00603 { 00604 const Type* array = (Type*)bv->GetPointer(); 00605 if( array ) { 00606 assert( array ); // That would be bad... 00607 assert( Internal == 0 ); 00608 SetArray(array, bv->GetLength() ); } 00609 } 00610 else 00611 { 00612 std::stringstream ss; 00613 std::string s = std::string( bv->GetPointer(), bv->GetLength() ); 00614 ss.str( s ); 00615 EncodingImplementation<VRToEncoding<TVR>::Mode>::ReadNoSwap(Internal, 00616 GetLength(),ss); 00617 } 00618 } 00619 00620 private: 00621 typename VRToType<TVR>::Type *Internal; 00622 unsigned long Length; // unsigned int ?? 00623 bool Save; 00624 }; 00625 00626 //template <int TVM = VM::VM1_n> 00627 //class Element<VR::OB, TVM > : public Element<VR::OB, VM::VM1_n> {}; 00628 00629 // Partial specialization for derivatives of 1-n : 2-n, 3-n ... 00630 template<int TVR> 00631 class Element<TVR, VM::VM1_2> : public Element<TVR, VM::VM1_n> 00632 { 00633 public: 00634 typedef Element<TVR, VM::VM1_n> Parent; 00635 void SetLength(int len) { 00636 if( len != 1 || len != 2 ) return; 00637 Parent::SetLength(len); 00638 } 00639 }; 00640 template<int TVR> 00641 class Element<TVR, VM::VM2_n> : public Element<TVR, VM::VM1_n> 00642 { 00643 public: 00644 typedef Element<TVR, VM::VM1_n> Parent; 00645 void SetLength(int len) { 00646 if( len <= 1 ) return; 00647 Parent::SetLength(len); 00648 } 00649 }; 00650 template<int TVR> 00651 class Element<TVR, VM::VM2_2n> : public Element<TVR, VM::VM2_n> 00652 { 00653 public: 00654 typedef Element<TVR, VM::VM2_n> Parent; 00655 void SetLength(int len) { 00656 if( len % 2 ) return; 00657 Parent::SetLength(len); 00658 } 00659 }; 00660 template<int TVR> 00661 class Element<TVR, VM::VM3_n> : public Element<TVR, VM::VM1_n> 00662 { 00663 public: 00664 typedef Element<TVR, VM::VM1_n> Parent; 00665 void SetLength(int len) { 00666 if( len <= 2 ) return; 00667 Parent::SetLength(len); 00668 } 00669 }; 00670 template<int TVR> 00671 class Element<TVR, VM::VM3_3n> : public Element<TVR, VM::VM3_n> 00672 { 00673 public: 00674 typedef Element<TVR, VM::VM3_n> Parent; 00675 void SetLength(int len) { 00676 if( len % 3 ) return; 00677 Parent::SetLength(len); 00678 } 00679 }; 00680 00681 00682 //template<int T> struct VRToLength; 00683 //template <> struct VRToLength<VR::AS> 00684 //{ enum { Length = VM::VM1 }; } 00685 //template<> 00686 //class Element<VR::AS> : public Element<VR::AS, VRToLength<VR::AS>::Length > 00687 00688 // only 0010 1010 AS 1 Patient's Age 00689 template<> 00690 class Element<VR::AS, VM::VM5> 00691 { 00692 public: 00693 char Internal[VMToLength<VM::VM5>::Length * sizeof( VRToType<VR::AS>::Type )]; 00694 void Print(std::ostream &_os) const { 00695 _os << Internal; 00696 } 00697 unsigned long GetLength() const { 00698 return VMToLength<VM::VM5>::Length; 00699 } 00700 }; 00701 00702 template <> 00703 class Element<VR::OB, VM::VM1> : public Element<VR::OB, VM::VM1_n> {}; 00704 // Make it impossible to compile any other cases: 00705 template <int TVM> class Element<VR::OB, TVM>; 00706 00707 // Same for OW: 00708 template <> 00709 class Element<VR::OW, VM::VM1> : public Element<VR::OW, VM::VM1_n> {}; 00710 // Make it impossible to compile any other cases: 00711 template <int TVM> class Element<VR::OW, TVM>; 00712 00713 } // namespace gdcm 00714 00715 #endif //GDCMELEMENT_H