GDCM  2.2.0
gdcmElement.h
Go to the documentation of this file.
1 /*=========================================================================
2 
3  Program: GDCM (Grassroots DICOM). A DICOM library
4 
5  Copyright (c) 2006-2011 Mathieu Malaterre
6  All rights reserved.
7  See Copyright.txt or http://gdcm.sourceforge.net/Copyright.html for details.
8 
9  This software is distributed WITHOUT ANY WARRANTY; without even
10  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
11  PURPOSE. See the above copyright notice for more information.
12 
13 =========================================================================*/
14 #ifndef GDCMELEMENT_H
15 #define GDCMELEMENT_H
16 
17 #include "gdcmTypes.h"
18 #include "gdcmVR.h"
19 #include "gdcmTag.h"
20 #include "gdcmVM.h"
21 #include "gdcmByteValue.h"
22 #include "gdcmDataElement.h"
23 #include "gdcmSwapper.h"
24 
25 #include <string>
26 #include <vector>
27 #include <sstream>
28 #include <limits>
29 #include <cmath>
30 #include <cstring>
31 
32 namespace gdcm
33 {
34 
35 // Forward declaration
41 template<int T> class EncodingImplementation;
42 
48 template<int TVR, int TVM>
49 class Element
50 {
51 public:
52  typename VRToType<TVR>::Type Internal[VMToLength<TVM>::Length];
53  typedef typename VRToType<TVR>::Type Type;
54 
55  static VR GetVR() { return (VR::VRType)TVR; }
56  static VM GetVM() { return (VM::VMType)TVM; }
57 
58  unsigned long GetLength() const {
59  return VMToLength<TVM>::Length;
60  }
61  // Implementation of Print is common to all Mode (ASCII/Binary)
62  // TODO: Can we print a \ when in ASCII...well I don't think so
63  // it would mean we used a bad VM then, right ?
64  void Print(std::ostream &_os) const {
65  _os << Internal[0]; // VM is at least garantee to be one
66  for(int i=1; i<VMToLength<TVM>::Length; ++i)
67  _os << "," << Internal[i];
68  }
69 
70  const typename VRToType<TVR>::Type *GetValues() const {
71  return Internal;
72  }
73  const typename VRToType<TVR>::Type &GetValue(unsigned int idx = 0) const {
74  assert( idx < VMToLength<TVM>::Length );
75  return Internal[idx];
76  }
77  typename VRToType<TVR>::Type &GetValue(unsigned int idx = 0) {
78  assert( idx < VMToLength<TVM>::Length );
79  return Internal[idx];
80  }
81  typename VRToType<TVR>::Type operator[] (unsigned int idx) const {
82  return GetValue(idx);
83  }
84  void SetValue(typename VRToType<TVR>::Type v, unsigned int idx = 0) {
85  assert( idx < VMToLength<TVM>::Length );
86  Internal[idx] = v;
87  }
88 
89  void SetFromDataElement(DataElement const &de) {
90  const ByteValue *bv = de.GetByteValue();
91  if( !bv ) return;
92 #ifdef GDCM_WORDS_BIGENDIAN
93  if( de.GetVR() == VR::UN /*|| de.GetVR() == VR::INVALID*/ )
94 #else
95  if( de.GetVR() == VR::UN || de.GetVR() == VR::INVALID )
96 #endif
97  {
98  Set(de.GetValue());
99  }
100  else
101  {
102  SetNoSwap(de.GetValue());
103  }
104  }
105 
107  DataElement ret;
108  std::ostringstream os;
110  GetLength(),os);
111  ret.SetVR( (VR::VRType)TVR );
112  assert( ret.GetVR() != VR::SQ );
114  {
115  if( GetVR() != VR::UI )
116  {
117  if( os.str().size() % 2 )
118  {
119  os << " ";
120  }
121  }
122  }
123  VL::Type osStrSize = (VL::Type)os.str().size();
124  ret.SetByteValue( os.str().c_str(), osStrSize );
125 
126  return ret;
127  }
128 
129  void Read(std::istream &_is) {
131  GetLength(),_is);
132  }
133  void Write(std::ostream &_os) const {
135  GetLength(),_os);
136  }
137 
138  // FIXME: remove this function
139  // this is only used in gdcm::SplitMosaicFilter / to pass value of a CSAElement
140  void Set(Value const &v) {
141  const ByteValue *bv = dynamic_cast<const ByteValue*>(&v);
142  if( bv ) {
143  //memcpy(Internal, bv->GetPointer(), bv->GetLength());
144  std::stringstream ss;
145  std::string s = std::string( bv->GetPointer(), bv->GetLength() );
146  ss.str( s );
148  GetLength(),ss);
149  }
150  }
151 protected:
152  void SetNoSwap(Value const &v) {
153  const ByteValue *bv = dynamic_cast<const ByteValue*>(&v);
154  assert( bv ); // That would be bad...
155  //memcpy(Internal, bv->GetPointer(), bv->GetLength());
156  std::stringstream ss;
157  std::string s = std::string( bv->GetPointer(), bv->GetLength() );
158  ss.str( s );
160  GetLength(),ss);
161  }
162 };
163 
164 struct ignore_char {
165  ignore_char(char c): m_char(c) {}
166  char m_char;
167 };
168 ignore_char const backslash('\\');
169 
170  inline std::istream& operator>> (std::istream& in, ignore_char const& ic) {
171  if (!in.eof())
172  in.clear(in.rdstate() & ~std::ios_base::failbit);
173  if (in.get() != ic.m_char)
174  in.setstate(std::ios_base::failbit);
175  return in;
176  }
177 
178 
179 // Implementation to perform formatted read and write
180 template<> class EncodingImplementation<VR::VRASCII> {
181 public:
182  template<typename T> // FIXME this should be VRToType<TVR>::Type
183  static inline void ReadComputeLength(T* data, unsigned int &length,
184  std::istream &_is) {
185  assert( data );
186  //assert( length ); // != 0
187  length = 0;
188  assert( _is );
189 #if 0
190  char sep;
191  while( _is >> data[length++] )
192  {
193  // Get the separator in between the values
194  assert( _is );
195  _is.get(sep);
196  assert( sep == '\\' || sep == ' ' ); // FIXME: Bad use of assert
197  if( sep == ' ' ) length--; // FIXME
198  }
199 #else
200  while( _is >> std::ws >> data[length++] >> std::ws >> backslash )
201  {
202  }
203 #endif
204  }
205 
206  template<typename T> // FIXME this should be VRToType<TVR>::Type
207  static inline void Read(T* data, unsigned long length,
208  std::istream &_is) {
209  assert( data );
210  assert( length ); // != 0
211  assert( _is );
212  // FIXME BUG: what if >> operation fails ?
213  // gdcmData/MR00010001.dcm / SpacingBetweenSlices
214  _is >> std::ws >> data[0];
215  char sep;
216  //std::cout << "GetLength: " << af->GetLength() << std::endl;
217  for(unsigned long i=1; i<length;++i) {
218  assert( _is );
219  // Get the separator in between the values
220  _is >> std::ws >> sep; //_is.get(sep);
221  assert( sep == '\\' ); // FIXME: Bad use of assert
222  _is >> std::ws >> data[i];
223  }
224  }
225 
226  template<typename T>
227  static inline void ReadNoSwap(T* data, unsigned long length,
228  std::istream &_is) {
229  Read(data,length,_is);
230 }
231  template<typename T>
232  static inline void Write(const T* data, unsigned long length,
233  std::ostream &_os) {
234  assert( data );
235  assert( length );
236  assert( _os );
237  _os << data[0];
238  for(unsigned long i=1; i<length; ++i) {
239  assert( _os );
240  _os << "\\" << data[i];
241  }
242  }
243 };
244 
245 template < typename Float >
246 std::string to_string ( Float data ) {
247  std::stringstream in;
248  // in.imbue(std::locale::classic()); // This is not required AFAIK
249  unsigned long const digits =
250  static_cast< unsigned long >(
251  - std::log( std::numeric_limits<Float>::epsilon() )
252  / std::log( 10.0 ) );
253  if ( in << std::dec << std::setprecision(/*2+*/digits) << data ) {
254  return ( in.str() );
255  } else {
256  throw "Impossible Conversion"; // should not happen ...
257  }
258 }
259 
260 /* Writing VR::DS is not that easy after all */
261 // http://groups.google.com/group/comp.lang.c++/browse_thread/thread/69ccd26f000a0802
262 template<> inline void EncodingImplementation<VR::VRASCII>::Write(const float * data, unsigned long length, std::ostream &_os) {
263  assert( data );
264  assert( length );
265  assert( _os );
266  _os << to_string(data[0]);
267  for(unsigned long i=1; i<length; ++i) {
268  assert( _os );
269  _os << "\\" << to_string(data[i]);
270  }
271  }
272 
273 template<> inline void EncodingImplementation<VR::VRASCII>::Write(const double* data, unsigned long length, std::ostream &_os) {
274  assert( data );
275  assert( length );
276  assert( _os );
277  _os << to_string(data[0]);
278  for(unsigned long i=1; i<length; ++i) {
279  assert( _os );
280  _os << "\\" << to_string(data[i]);
281  }
282  }
283 
284 
285 // Implementation to perform binary read and write
286 // TODO rewrite operation so that either:
287 // #1. dummy implementation use a pointer to Internal and do ++p (faster)
288 // #2. Actually do some meta programming to unroll the loop
289 // (no notion of order in VM ...)
290 template<> class EncodingImplementation<VR::VRBINARY> {
291 public:
292  template<typename T> // FIXME this should be VRToType<TVR>::Type
293  static inline void ReadComputeLength(T* data, unsigned int &length,
294  std::istream &_is) {
295  const unsigned int type_size = sizeof(T);
296  assert( data ); // Can we read from pointer ?
297  //assert( length );
298  length /= type_size;
299  assert( _is ); // Is stream valid ?
300  _is.read( reinterpret_cast<char*>(data+0), type_size);
301  for(unsigned long i=1; i<length; ++i) {
302  assert( _is );
303  _is.read( reinterpret_cast<char*>(data+i), type_size );
304  }
305  }
306  template<typename T>
307  static inline void ReadNoSwap(T* data, unsigned long length,
308  std::istream &_is) {
309  const unsigned int type_size = sizeof(T);
310  assert( data ); // Can we read from pointer ?
311  assert( length );
312  assert( _is ); // Is stream valid ?
313  _is.read( reinterpret_cast<char*>(data+0), type_size);
314  for(unsigned long i=1; i<length; ++i) {
315  assert( _is );
316  _is.read( reinterpret_cast<char*>(data+i), type_size );
317  }
318  //ByteSwap<T>::SwapRangeFromSwapCodeIntoSystem(data,
319  // _is.GetSwapCode(), length);
320  //SwapperNoOp::SwapArray(data,length);
321  }
322  template<typename T>
323  static inline void Read(T* data, unsigned long length,
324  std::istream &_is) {
325  const unsigned int type_size = sizeof(T);
326  assert( data ); // Can we read from pointer ?
327  assert( length );
328  assert( _is ); // Is stream valid ?
329  _is.read( reinterpret_cast<char*>(data+0), type_size);
330  for(unsigned long i=1; i<length; ++i) {
331  assert( _is );
332  _is.read( reinterpret_cast<char*>(data+i), type_size );
333  }
334  //ByteSwap<T>::SwapRangeFromSwapCodeIntoSystem(data,
335  // _is.GetSwapCode(), length);
336  SwapperNoOp::SwapArray(data,length);
337  }
338  template<typename T>
339  static inline void Write(const T* data, unsigned long length,
340  std::ostream &_os) {
341  const unsigned int type_size = sizeof(T);
342  assert( data ); // Can we write into pointer ?
343  assert( length );
344  assert( _os ); // Is stream valid ?
345  //ByteSwap<T>::SwapRangeFromSwapCodeIntoSystem((T*)data,
346  // _os.GetSwapCode(), length);
347  T swappedData = SwapperNoOp::Swap(data[0]);
348  _os.write( reinterpret_cast<const char*>(&swappedData), type_size);
349  for(unsigned long i=1; i<length;++i) {
350  assert( _os );
351  swappedData = SwapperNoOp::Swap(data[i]);
352  _os.write( reinterpret_cast<const char*>(&swappedData), type_size );
353  }
354  //ByteSwap<T>::SwapRangeFromSwapCodeIntoSystem((T*)data,
355  // _os.GetSwapCode(), length);
356  }
357 };
358 
359 // For particular case for ASCII string
360 // WARNING: This template explicitely instanciates a particular
361 // EncodingImplementation THEREFORE it is required to be declared after the
362 // EncodingImplementation is needs (doh!)
363 #if 0
364 template<int TVM>
365 class Element<TVM>
366 {
367 public:
368  Element(const char array[])
369  {
370  unsigned int i = 0;
371  const char sep = '\\';
372  std::string sarray = array;
373  std::string::size_type pos1 = 0;
374  std::string::size_type pos2 = sarray.find(sep, pos1+1);
375  while(pos2 != std::string::npos)
376  {
377  Internal[i++] = sarray.substr(pos1, pos2-pos1);
378  pos1 = pos2+1;
379  pos2 = sarray.find(sep, pos1+1);
380  }
381  Internal[i] = sarray.substr(pos1, pos2-pos1);
382  // Shouldn't we do the contrary, since we know how many separators
383  // (and default behavior is to discard anything after the VM declared
384  assert( GetLength()-1 == i );
385  }
386 
387  unsigned long GetLength() const {
388  return VMToLength<TVM>::Length;
389  }
390  // Implementation of Print is common to all Mode (ASCII/Binary)
391  void Print(std::ostream &_os) const {
392  _os << Internal[0]; // VM is at least garantee to be one
393  for(int i=1; i<VMToLength<TVM>::Length; ++i)
394  _os << "," << Internal[i];
395  }
396 
397  void Read(std::istream &_is) {
399  }
400  void Write(std::ostream &_os) const {
402  }
403 private:
404  typename String Internal[VMToLength<TVM>::Length];
405 };
406 
407 template< int TVM>
408 class Element<VR::PN, TVM> : public StringElement<TVM>
409 {
410 };
411 #endif
412 
413 // Implementation for the undefined length (dynamically allocated array)
414 template<int TVR>
415 class Element<TVR, VM::VM1_n>
416 {
417 public:
418  // This the way to prevent default initialization
419  explicit Element() { Internal=0; Length=0; Save = false; }
421  if( Save ) {
422  delete[] Internal;
423  }
424  Internal = 0;
425  }
426 
427  static VR GetVR() { return (VR::VRType)TVR; }
428  static VM GetVM() { return VM::VM1_n; }
429 
430  // Length manipulation
431  // SetLength should really be protected anyway...all operation
432  // should go through SetArray
433  unsigned long GetLength() const { return Length; }
434  typedef typename VRToType<TVR>::Type Type;
435 
436  void SetLength(unsigned long len) {
437  const unsigned int size = sizeof(Type);
438  if( len ) {
439  if( len > Length ) {
440  // perform realloc
441  assert( (len / size) * size == len );
442  Type *internal = new Type[len / size];
443  assert( Save == false );
444  Save = true; // ????
445  if( Internal )
446  {
447  memcpy(internal, Internal, len);
448  delete[] Internal;
449  }
450  Internal = internal;
451  }
452  }
453  Length = len / size;
454  }
455 
456  // If save is set to zero user should not delete the pointer
457  //void SetArray(const typename VRToType<TVR>::Type *array, int len, bool save = false)
458  void SetArray(const Type *array, unsigned long len,
459  bool save = false) {
460  if( save ) {
461  SetLength(len); // realloc
462  memcpy(Internal, array, len/*/sizeof(Type)*/);
463  assert( Save == false );
464  }
465  else {
466  // TODO rewrite this stupid code:
467  assert( Length == 0 );
468  assert( Internal == 0 );
469  assert( Save == false );
470  Length = len / sizeof(Type);
471  //assert( (len / sizeof(Type)) * sizeof(Type) == len );
472  // MR00010001.dcm is a tough kid: 0019,105a is supposed to be VR::FL, VM::VM3 but
473  // length is 14 bytes instead of 12 bytes. Simply consider value is total garbage.
474  if( (len / sizeof(Type)) * sizeof(Type) != len ) { Internal = 0; Length = 0; }
475  else Internal = const_cast<Type*>(array);
476  }
477  Save = save;
478  }
479  void SetValue(typename VRToType<TVR>::Type v, unsigned int idx = 0) {
480  assert( idx < Length );
481  Internal[idx] = v;
482  }
483  const typename VRToType<TVR>::Type &GetValue(unsigned int idx = 0) const {
484  assert( idx < Length );
485  return Internal[idx];
486  }
487  typename VRToType<TVR>::Type &GetValue(unsigned int idx = 0) {
488  assert( idx < Length );
489  return Internal[idx];
490  }
491  typename VRToType<TVR>::Type operator[] (unsigned int idx) const {
492  return GetValue(idx);
493  }
494  void Set(Value const &v) {
495  const ByteValue *bv = dynamic_cast<const ByteValue*>(&v);
496  assert( bv ); // That would be bad...
498  {
499  const Type* array = (Type*)bv->GetPointer();
500  if( array ) {
501  assert( array ); // That would be bad...
502  assert( Internal == 0 );
503  SetArray(array, bv->GetLength() ); }
504  }
505  else
506  {
507  std::stringstream ss;
508  std::string s = std::string( bv->GetPointer(), bv->GetLength() );
509  ss.str( s );
511  GetLength(),ss);
512  }
513  }
514  void SetFromDataElement(DataElement const &de) {
515  const ByteValue *bv = de.GetByteValue();
516  if( !bv ) return;
517 #ifdef GDCM_WORDS_BIGENDIAN
518  if( de.GetVR() == VR::UN /*|| de.GetVR() == VR::INVALID*/ )
519 #else
520  if( de.GetVR() == VR::UN || de.GetVR() == VR::INVALID )
521 #endif
522  {
523  Set(de.GetValue());
524  }
525  else
526  {
527  SetNoSwap(de.GetValue());
528  }
529  }
530 
531 
532  // Need to be placed after definition of EncodingImplementation<VR::VRASCII>
533  void WriteASCII(std::ostream &os) const {
535  }
536 
537  // Implementation of Print is common to all Mode (ASCII/Binary)
538  void Print(std::ostream &_os) const {
539  assert( Length );
540  assert( Internal );
541  _os << Internal[0]; // VM is at least garantee to be one
542  const unsigned long length = GetLength() < 25 ? GetLength() : 25;
543  for(unsigned long i=1; i<length; ++i)
544  _os << "," << Internal[i];
545  }
546  void Read(std::istream &_is) {
547  if( !Internal ) return;
549  GetLength(),_is);
550  }
551  //void ReadComputeLength(std::istream &_is) {
552  // if( !Internal ) return;
553  // EncodingImplementation<VRToEncoding<TVR>::Mode>::ReadComputeLength(Internal,
554  // Length,_is);
555  // }
556  void Write(std::ostream &_os) const {
558  GetLength(),_os);
559  }
560 
562  DataElement ret;
563  ret.SetVR( (VR::VRType)TVR );
564  assert( ret.GetVR() != VR::SQ );
565  if( Internal )
566  {
567  std::ostringstream os;
569  GetLength(),os);
571  {
572  if( GetVR() != VR::UI )
573  {
574  if( os.str().size() % 2 )
575  {
576  os << " ";
577  }
578  }
579  }
580  VL::Type osStrSize = (VL::Type)os.str().size();
581  ret.SetByteValue( os.str().c_str(), osStrSize );
582  }
583  return ret;
584  }
585 
586  Element(const Element&_val) {
587  if( this != &_val) {
588  *this = _val;
589  }
590  }
591 
592  Element &operator=(const Element &_val) {
593  Length = 0; // SYITF
594  Internal = 0;
595  SetArray(_val.Internal, _val.Length, true);
596  return *this;
597  }
598 protected:
599  void SetNoSwap(Value const &v) {
600  const ByteValue *bv = dynamic_cast<const ByteValue*>(&v);
601  assert( bv ); // That would be bad...
603  {
604  const Type* array = (Type*)bv->GetPointer();
605  if( array ) {
606  assert( array ); // That would be bad...
607  assert( Internal == 0 );
608  SetArray(array, bv->GetLength() ); }
609  }
610  else
611  {
612  std::stringstream ss;
613  std::string s = std::string( bv->GetPointer(), bv->GetLength() );
614  ss.str( s );
616  GetLength(),ss);
617  }
618  }
619 
620 private:
621  typename VRToType<TVR>::Type *Internal;
622  unsigned long Length; // unsigned int ??
623  bool Save;
624 };
625 
626 //template <int TVM = VM::VM1_n>
627 //class Element<VR::OB, TVM > : public Element<VR::OB, VM::VM1_n> {};
628 
629 // Partial specialization for derivatives of 1-n : 2-n, 3-n ...
630 template<int TVR>
631 class Element<TVR, VM::VM1_2> : public Element<TVR, VM::VM1_n>
632 {
633 public:
635  void SetLength(int len) {
636  if( len != 1 || len != 2 ) return;
637  Parent::SetLength(len);
638  }
639 };
640 template<int TVR>
641 class Element<TVR, VM::VM2_n> : public Element<TVR, VM::VM1_n>
642 {
643 public:
645  void SetLength(int len) {
646  if( len <= 1 ) return;
647  Parent::SetLength(len);
648  }
649 };
650 template<int TVR>
651 class Element<TVR, VM::VM2_2n> : public Element<TVR, VM::VM2_n>
652 {
653 public:
655  void SetLength(int len) {
656  if( len % 2 ) return;
657  Parent::SetLength(len);
658  }
659 };
660 template<int TVR>
661 class Element<TVR, VM::VM3_n> : public Element<TVR, VM::VM1_n>
662 {
663 public:
665  void SetLength(int len) {
666  if( len <= 2 ) return;
667  Parent::SetLength(len);
668  }
669 };
670 template<int TVR>
671 class Element<TVR, VM::VM3_3n> : public Element<TVR, VM::VM3_n>
672 {
673 public:
675  void SetLength(int len) {
676  if( len % 3 ) return;
677  Parent::SetLength(len);
678  }
679 };
680 
681 
682 //template<int T> struct VRToLength;
683 //template <> struct VRToLength<VR::AS>
684 //{ enum { Length = VM::VM1 }; }
685 //template<>
686 //class Element<VR::AS> : public Element<VR::AS, VRToLength<VR::AS>::Length >
687 
688 // only 0010 1010 AS 1 Patient's Age
689 template<>
690 class Element<VR::AS, VM::VM5>
691 {
692 public:
693  char Internal[VMToLength<VM::VM5>::Length * sizeof( VRToType<VR::AS>::Type )];
694  void Print(std::ostream &_os) const {
695  _os << Internal;
696  }
697  unsigned long GetLength() const {
698  return VMToLength<VM::VM5>::Length;
699  }
700 };
701 
702 template <>
703 class Element<VR::OB, VM::VM1> : public Element<VR::OB, VM::VM1_n> {};
704 // Make it impossible to compile any other cases:
705 template <int TVM> class Element<VR::OB, TVM>;
706 
707 // Same for OW:
708 template <>
709 class Element<VR::OW, VM::VM1> : public Element<VR::OW, VM::VM1_n> {};
710 // Make it impossible to compile any other cases:
711 template <int TVM> class Element<VR::OW, TVM>;
712 
713 } // namespace gdcm
714 
715 #endif //GDCMELEMENT_H

Generated on Wed Jun 13 2012 20:40:37 for GDCM by doxygen 1.8.1
SourceForge.net Logo