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

Generated on Sat Dec 4 2010 08:58:42 for GDCM by doxygen 1.7.2
SourceForge.net Logo