GDCM 3.2.1

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_ns
33{
34
35// Forward declaration
41 template<long long T> class EncodingImplementation;
42
43
51 template <long long TVR, int TVM>
52 class ElementDisableCombinations {};
53 template <>
54 class ElementDisableCombinations<VR::OB, VM::VM1_n> {};
55 template <>
56 class ElementDisableCombinations<VR::OW, VM::VM1_n> {};
57// Make it impossible to compile these other cases
58 template <int TVM>
59 class ElementDisableCombinations<VR::OB, TVM>;
60template <int TVM>
61class ElementDisableCombinations<VR::OW, TVM>;
62
68template<long long TVR, int TVM>
69class Element
70{
71 enum { ElementDisableCombinationsCheck = sizeof ( ElementDisableCombinations<TVR, TVM> ) };
72 public:
73 typename VRToType<TVR>::Type Internal[VMToLength<TVM>::Length];
74 typedef typename VRToType<TVR>::Type Type;
75
76 static VR GetVR() { return (VR::VRType)TVR; }
77 static VM GetVM() { return (VM::VMType)TVM; }
78
79 unsigned long GetLength() const {
80 return VMToLength<TVM>::Length;
81 }
82 // Implementation of Print is common to all Mode (ASCII/Binary)
83 // TODO: Can we print a \ when in ASCII...well I don't think so
84 // it would mean we used a bad VM then, right?
85 void Print(std::ostream &_os) const {
86 _os << Internal[0]; // VM is at least guarantee to be one
87 for(int i=1; i<VMToLength<TVM>::Length; ++i)
88 _os << "," << Internal[i];
89 }
90
91 const typename VRToType<TVR>::Type *GetValues() const {
92 return Internal;
93 }
94 const typename VRToType<TVR>::Type &GetValue(unsigned int idx = 0) const {
95 gdcm_assert( idx < VMToLength<TVM>::Length );
96 return Internal[idx];
97 }
98 typename VRToType<TVR>::Type &GetValue(unsigned int idx = 0) {
99 gdcm_assert( idx < VMToLength<TVM>::Length );
100 return Internal[idx];
101 }
102 typename VRToType<TVR>::Type operator[] (unsigned int idx) const {
103 return GetValue(idx);
104 }
105 void SetValue(typename VRToType<TVR>::Type v, unsigned int idx = 0) {
106 gdcm_assert( idx < VMToLength<TVM>::Length );
107 Internal[idx] = v;
108 }
109
110 void SetFromDataElement(DataElement const &de) {
111 const ByteValue *bv = de.GetByteValue();
112 if( !bv ) return;
113#ifdef GDCM_WORDS_BIGENDIAN
114 if( de.GetVR() == VR::UN /*|| de.GetVR() == VR::INVALID*/ )
115#else
116 if( de.GetVR() == VR::UN || de.GetVR() == VR::INVALID )
117#endif
118 {
119 Set(de.GetValue());
120 }
121 else
122 {
123 SetNoSwap(de.GetValue());
124 }
125 }
126
127 DataElement GetAsDataElement() const {
128 DataElement ret;
129 std::ostringstream os;
130 EncodingImplementation<VRToEncoding<TVR>::Mode>::Write(Internal,
131 GetLength(),os);
132 ret.SetVR( (VR::VRType)TVR );
133 gdcm_assert( ret.GetVR() != VR::SQ );
134 if( (VR::VRType)VRToEncoding<TVR>::Mode == VR::VRASCII )
135 {
136 if( GetVR() != VR::UI )
137 {
138 if( os.str().size() % 2 )
139 {
140 os << " ";
141 }
142 }
143 }
144 VL::Type osStrSize = (VL::Type)os.str().size();
145 ret.SetByteValue( os.str().c_str(), osStrSize );
146
147 return ret;
148 }
149
150 void Read(std::istream &_is) {
151 return EncodingImplementation<VRToEncoding<TVR>::Mode>::Read(Internal,
152 GetLength(),_is);
153 }
154 void Write(std::ostream &_os) const {
155 return EncodingImplementation<VRToEncoding<TVR>::Mode>::Write(Internal,
156 GetLength(),_os);
157 }
158
159 // FIXME: remove this function
160 // this is only used in gdcm::SplitMosaicFilter / to pass value of a CSAElement
161 void Set(Value const &v) {
162 const ByteValue *bv = dynamic_cast<const ByteValue*>(&v);
163 if( bv ) {
164 //memcpy(Internal, bv->GetPointer(), bv->GetLength());
165 std::stringstream ss;
166 std::string s = std::string( bv->GetPointer(), bv->GetLength() );
167 ss.str( s );
168 EncodingImplementation<VRToEncoding<TVR>::Mode>::Read(Internal,
169 GetLength(),ss);
170 }
171 }
172 protected:
173 void SetNoSwap(Value const &v) {
174 const ByteValue *bv = dynamic_cast<const ByteValue*>(&v);
175 gdcm_assert( bv ); // That would be bad...
176 //memcpy(Internal, bv->GetPointer(), bv->GetLength());
177 std::stringstream ss;
178 std::string s = std::string( bv->GetPointer(), bv->GetLength() );
179 ss.str( s );
180 EncodingImplementation<VRToEncoding<TVR>::Mode>::ReadNoSwap(Internal,
181 GetLength(),ss);
182 }
183};
184
185 struct ignore_char {
186 ignore_char(char c): m_char(c) {}
187 char m_char;
188};
189 ignore_char const backslash('\\');
190
191 inline std::istream& operator>> (std::istream& in, ignore_char const& ic) {
192 if (!in.eof())
193 in.clear(in.rdstate() & ~std::ios_base::failbit);
194 if (in.get() != ic.m_char)
195 in.setstate(std::ios_base::failbit);
196 return in;
197 }
198
199
200// Implementation to perform formatted read and write
201 template<> class EncodingImplementation<VR::VRASCII> {
202 public:
203 template<typename T> // FIXME this should be VRToType<TVR>::Type
204 static inline void ReadComputeLength(T* data, unsigned int &length,
205 std::istream &_is) {
206 gdcm_assert( data );
207 //gdcm_assert( length ); // != 0
208 length = 0;
209 gdcm_assert( _is );
210#if 0
211 char sep;
212 while( _is >> data[length++] )
213 {
214 // Get the separator in between the values
215 gdcm_assert( _is );
216 _is.get(sep);
217 gdcm_assert( sep == '\\' || sep == ' ' ); // FIXME: Bad use of assert
218 if( sep == ' ' ) length--; // FIXME
219 }
220#else
221 while( _is >> std::ws >> data[length++] >> std::ws >> backslash )
222 {
223 }
224#endif
225 }
226
227 template<typename T> // FIXME this should be VRToType<TVR>::Type
228 static inline void Read(T* data, unsigned long length,
229 std::istream &_is) {
230 gdcm_assert( data );
231 gdcm_assert( length ); // != 0
232 gdcm_assert( _is );
233 // FIXME BUG: what if >> operation fails ?
234 // gdcmData/MR00010001.dcm / SpacingBetweenSlices
235 _is >> std::ws >> data[0];
236 char sep;
237 //std::cout << "GetLength: " << af->GetLength() << std::endl;
238 for(unsigned long i=1; i<length;++i) {
239 //gdcm_assert( _is );
240 // Get the separator in between the values
241 _is >> std::ws >> sep; //_is.get(sep);
242 //gdcm_assert( sep == '\\' ); // FIXME: Bad use of assert
243 _is >> std::ws >> data[i];
244 }
245 }
246
247 template<typename T>
248 static inline void ReadNoSwap(T* data, unsigned long length,
249 std::istream &_is) {
250 Read(data,length,_is);
251}
252 template<typename T>
253 static inline void Write(const T* data, unsigned long length,
254 std::ostream &_os) {
255 gdcm_assert( data );
256 gdcm_assert( length );
257 gdcm_assert( _os );
258 _os << data[0];
259 for(unsigned long i=1; i<length; ++i) {
260 gdcm_assert( _os );
261 _os << "\\" << data[i];
262 }
263 }
264};
265
266//#define VRDS16ILLEGAL
267
268#ifdef VRDS16ILLEGAL
269 template < typename Float >
270std::string to_string ( Float data ) {
271 std::stringstream in;
272 // in.imbue(std::locale::classic()); // This is not required AFAIK
273 int const digits =
274 static_cast< int >(
275 - std::log( std::numeric_limits<Float>::epsilon() )
276 / static_cast< Float >( std::log( 10.0 ) ) );
277 if ( in << std::dec << std::setprecision(/*2+*/digits) << data ) {
278 return ( in.str() );
279 } else {
280 throw "Impossible Conversion"; // should not happen ...
281 }
282}
283#else
284// http://stackoverflow.com/questions/32631178/writing-ieee-754-1985-double-as-ascii-on-a-limited-16-bytes-string
285
286 static inline void clean(char *mant) {
287 char *ix = mant + strlen(mant) - 1;
288 while(('0' == *ix) && (ix > mant)) {
289 *ix-- = '\0';
290 }
291 if ('.' == *ix) {
292 *ix = '\0';
293 }
294}
295
296 static int add1(char *buf, int n) {
297 if (n < 0) return 1;
298 if (buf[n] == '9') {
299 buf[n] = '0';
300 return add1(buf, n-1);
301 }
302 else {
303 buf[n] = (char)(buf[n] + 1);
304 }
305 return 0;
306}
307
308 static int doround(char *buf, unsigned int n) {
309 char c;
310 if (n >= strlen(buf)) return 0;
311 c = buf[n];
312 buf[n] = 0;
313 if ((c >= '5') && (c <= '9')) return add1(buf, n-1);
314 return 0;
315}
316
317#if defined(_MSC_VER) && (_MSC_VER < 1900)
318#define snprintf _snprintf
319#endif
320
321 static int roundat(char *buf, size_t bufLen, unsigned int i, int iexp) {
322 if (doround(buf, i) != 0) {
323 iexp += 1;
324 switch(iexp) {
325 case -2:
326 strcpy(buf, ".01");
327 break;
328 case -1:
329 strcpy(buf, ".1");
330 break;
331 case 0:
332 strcpy(buf, "1.");
333 break;
334 case 1:
335 strcpy(buf, "10");
336 break;
337 case 2:
338 strcpy(buf, "100");
339 break;
340 default:
341 snprintf(buf, bufLen, "1e%d", iexp);
342 }
343 return 1;
344 }
345 return 0;
346}
347
348 template < typename Float >
349 static void x16printf(char *buf, int size, Float f) {
350 char line[40];
351 char *mant = line + 1;
352 int iexp, lexp, i;
353 char exp[6];
354
355 if (f < 0) {
356 f = -f;
357 size -= 1;
358 *buf++ = '-';
359 }
360 snprintf(line, sizeof(line), "%1.16e", f);
361 if (line[0] == '-') {
362 f = -f;
363 size -= 1;
364 *buf++ = '-';
365 snprintf(line, sizeof(line), "%1.16e", f);
366 }
367 *mant = line[0];
368 i = (int)strcspn(mant, "eE");
369 mant[i] = '\0';
370 iexp = (int)strtol(mant + i + 1, nullptr, 10);
371 lexp = snprintf(exp, sizeof(exp), "e%d", iexp);
372 if ((iexp >= size) || (iexp < -3)) {
373 i = roundat(mant, sizeof(line) - 1, size - 1 -lexp, iexp);
374 if(i == 1) {
375 strcpy(buf, mant);
376 return;
377 }
378 buf[0] = mant[0];
379 buf[1] = '.';
380 strncpy(buf + i + 2, mant + 1, size - 2 - lexp);
381 buf[size-lexp] = 0;
382 clean(buf);
383 strcat(buf, exp);
384 }
385 else if (iexp >= size - 2) {
386 roundat(mant, sizeof(line) - 1, iexp + 1, iexp);
387 strcpy(buf, mant);
388 }
389 else if (iexp >= 0) {
390 i = roundat(mant, sizeof(line) - 1, size - 1, iexp);
391 if (i == 1) {
392 strcpy(buf, mant);
393 return;
394 }
395 memcpy(buf, mant, iexp + 1);
396 buf[iexp + 1] = '.';
397 strncpy(buf + iexp + 2, mant + iexp + 1, size - iexp - 1);
398 buf[size] = 0;
399 clean(buf);
400 }
401 else {
402 int j;
403 i = roundat(mant, sizeof(line) - 1, size + 1 + iexp, iexp);
404 if (i == 1) {
405 strcpy(buf, mant);
406 return;
407 }
408 buf[0] = '.';
409 for(j=0; j< -1 - iexp; j++) {
410 buf[j+1] = '0';
411 }
412 memcpy(buf - iexp, mant, size + 1 + iexp);
413 buf[size] = 0;
414 clean(buf);
415 }
416}
417#if defined(_MSC_VER) && (_MSC_VER < 1900)
418#undef snprintf
419#endif
420
421#endif
422
423 template<> inline void EncodingImplementation<VR::VRASCII>::Write(const double* data, unsigned long length, std::ostream &_os) {
424 gdcm_assert( data );
425 gdcm_assert( length );
426 gdcm_assert( _os );
427#ifdef VRDS16ILLEGAL
428 _os << to_string(data[0]);
429#else
430 char buf[16+1];
431 x16printf(buf, 16, data[0]);
432 _os << buf;
433#endif
434 for(unsigned long i=1; i<length; ++i) {
435 gdcm_assert( _os );
436#ifdef VRDS16ILLEGAL
437 _os << "\\" << to_string(data[i]);
438#else
439 x16printf(buf, 16, data[i]);
440 _os << "\\" << buf;
441#endif
442 }
443 }
444
445
446// Implementation to perform binary read and write
447// TODO rewrite operation so that either:
448// #1. dummy implementation use a pointer to Internal and do ++p (faster)
449// #2. Actually do some meta programming to unroll the loop
450// (no notion of order in VM ...)
451 template<> class EncodingImplementation<VR::VRBINARY> {
452 public:
453 template<typename T> // FIXME this should be VRToType<TVR>::Type
454 static inline void ReadComputeLength(T* data, unsigned int &length,
455 std::istream &_is) {
456 const unsigned int type_size = sizeof(T);
457 gdcm_assert( data ); // Can we read from pointer ?
458 //gdcm_assert( length );
459 length /= type_size;
460 gdcm_assert( _is ); // Is stream valid ?
461 _is.read( reinterpret_cast<char*>(data+0), type_size);
462 for(unsigned long i=1; i<length; ++i) {
463 gdcm_assert( _is );
464 _is.read( reinterpret_cast<char*>(data+i), type_size );
465 }
466 }
467 template<typename T>
468 static inline void ReadNoSwap(T* data, unsigned long length,
469 std::istream &_is) {
470 const unsigned int type_size = sizeof(T);
471 gdcm_assert( data ); // Can we read from pointer ?
472 gdcm_assert( length );
473 gdcm_assert( _is ); // Is stream valid ?
474 _is.read( reinterpret_cast<char*>(data+0), type_size);
475 for(unsigned long i=1; i<length; ++i) {
476 if( _is )
477 _is.read( reinterpret_cast<char*>(data+i), type_size );
478 }
479 //ByteSwap<T>::SwapRangeFromSwapCodeIntoSystem(data,
480 // _is.GetSwapCode(), length);
481 //SwapperNoOp::SwapArray(data,length);
482 }
483 template<typename T>
484 static inline void Read(T* data, unsigned long length,
485 std::istream &_is) {
486 const unsigned int type_size = sizeof(T);
487 gdcm_assert( data ); // Can we read from pointer ?
488 gdcm_assert( length );
489 gdcm_assert( _is ); // Is stream valid ?
490 _is.read( reinterpret_cast<char*>(data+0), type_size);
491 for(unsigned long i=1; i<length; ++i) {
492 if( _is )
493 _is.read( reinterpret_cast<char*>(data+i), type_size );
494 }
495 //ByteSwap<T>::SwapRangeFromSwapCodeIntoSystem(data,
496 // _is.GetSwapCode(), length);
497 SwapperNoOp::SwapArray(data,length);
498 }
499 template<typename T>
500 static inline void Write(const T* data, unsigned long length,
501 std::ostream &_os) {
502 const unsigned int type_size = sizeof(T);
503 gdcm_assert( data ); // Can we write into pointer ?
504 gdcm_assert( length );
505 gdcm_assert( _os ); // Is stream valid ?
506 //ByteSwap<T>::SwapRangeFromSwapCodeIntoSystem((T*)data,
507 // _os.GetSwapCode(), length);
508 T swappedData = SwapperNoOp::Swap(data[0]);
509 _os.write( reinterpret_cast<const char*>(&swappedData), type_size);
510 for(unsigned long i=1; i<length;++i) {
511 gdcm_assert( _os );
512 swappedData = SwapperNoOp::Swap(data[i]);
513 _os.write( reinterpret_cast<const char*>(&swappedData), type_size );
514 }
515 //ByteSwap<T>::SwapRangeFromSwapCodeIntoSystem((T*)data,
516 // _os.GetSwapCode(), length);
517 }
518};
519
520// For particular case for ASCII string
521// WARNING: This template explicitly instantiates a particular
522// EncodingImplementation THEREFORE it is required to be declared after the
523// EncodingImplementation is needs (doh!)
524#if 0
525 template<int TVM>
526 class Element<TVM>
527{
528 public:
529 Element(const char array[])
530 {
531 unsigned int i = 0;
532 const char sep = '\\';
533 std::string sarray = array;
534 std::string::size_type pos1 = 0;
535 std::string::size_type pos2 = sarray.find(sep, pos1+1);
536 while(pos2 != std::string::npos)
537 {
538 Internal[i++] = sarray.substr(pos1, pos2-pos1);
539 pos1 = pos2+1;
540 pos2 = sarray.find(sep, pos1+1);
541 }
542 Internal[i] = sarray.substr(pos1, pos2-pos1);
543 // Shouldn't we do the contrary, since we know how many separators
544 // (and default behavior is to discard anything after the VM declared
545 gdcm_assert( GetLength()-1 == i );
546 }
547
548 unsigned long GetLength() const {
549 return VMToLength<TVM>::Length;
550 }
551 // Implementation of Print is common to all Mode (ASCII/Binary)
552 void Print(std::ostream &_os) const {
553 _os << Internal[0]; // VM is at least guarantee to be one
554 for(int i=1; i<VMToLength<TVM>::Length; ++i)
555 _os << "," << Internal[i];
556 }
557
558 void Read(std::istream &_is) {
559 EncodingImplementation<VR::VRASCII>::Read(Internal, GetLength(),_is);
560 }
561 void Write(std::ostream &_os) const {
562 EncodingImplementation<VR::VRASCII>::Write(Internal, GetLength(),_os);
563 }
564 private:
565 typename String Internal[VMToLength<TVM>::Length];
566};
567
568 template< int TVM>
569 class Element<VR::PN, TVM> : public StringElement<TVM>
570{
571 enum { ElementDisableCombinationsCheck = sizeof ( ElementDisableCombinations<VR::PN, TVM> ) };
572};
573#endif
574
575// Implementation for the undefined length (dynamically allocated array)
576 template<long long TVR>
577 class Element<TVR, VM::VM1_n>
578{
579 enum { ElementDisableCombinationsCheck = sizeof ( ElementDisableCombinations<TVR, VM::VM1_n> ) };
580 public:
581 // This the way to prevent default initialization
582 explicit Element() { Internal=nullptr; Length=0; Save = false; }
583 ~Element() {
584 if( Save ) {
585 delete[] Internal;
586 }
587 Internal = nullptr;
588 }
589
590 static VR GetVR() { return (VR::VRType)TVR; }
591 static VM GetVM() { return VM::VM1_n; }
592
593 // Length manipulation
594 // SetLength should really be protected anyway...all operation
595 // should go through SetArray
596 unsigned long GetLength() const { return Length; }
597 typedef typename VRToType<TVR>::Type Type;
598
599 void SetLength(unsigned long len) {
600 const unsigned int size = sizeof(Type);
601 if( len ) {
602 if( len > Length ) {
603 // perform realloc
604 gdcm_assert( (len / size) * size == len );
605 Type *internal = new Type[len / size];
606 gdcm_assert( Save == false );
607 Save = true; // ????
608 if( Internal )
609 {
610 memcpy(internal, Internal, len);
611 delete[] Internal;
612 }
613 Internal = internal;
614 }
615 }
616 Length = len / size;
617 }
618
619 // If save is set to zero user should not delete the pointer
620 //void SetArray(const typename VRToType<TVR>::Type *array, int len, bool save = false)
621 void SetArray(const Type *array, unsigned long len,
622 bool save = false) {
623 if( save ) {
624 SetLength(len); // realloc
625 memcpy(Internal, array, len/*/sizeof(Type)*/);
626 gdcm_assert( Save == false );
627 }
628 else {
629 // TODO rewrite this stupid code:
630 gdcm_assert( Length == 0 );
631 gdcm_assert( Internal == nullptr );
632 gdcm_assert( Save == false );
633 Length = len / sizeof(Type);
634 //gdcm_assert( (len / sizeof(Type)) * sizeof(Type) == len );
635 // MR00010001.dcm is a tough kid: 0019,105a is supposed to be VR::FL, VM::VM3 but
636 // length is 14 bytes instead of 12 bytes. Simply consider value is total garbage.
637 if( (len / sizeof(Type)) * sizeof(Type) != len ) { Internal = nullptr; Length = 0; }
638 else Internal = const_cast<Type*>(array);
639 }
640 Save = save;
641 }
642 void SetValue(typename VRToType<TVR>::Type v, unsigned int idx = 0) {
643 gdcm_assert( idx < Length );
644 Internal[idx] = v;
645 }
646 const typename VRToType<TVR>::Type &GetValue(unsigned int idx = 0) const {
647 gdcm_assert( idx < Length );
648 return Internal[idx];
649 }
650 typename VRToType<TVR>::Type &GetValue(unsigned int idx = 0) {
651 //gdcm_assert( idx < Length );
652 return Internal[idx];
653 }
654 typename VRToType<TVR>::Type operator[] (unsigned int idx) const {
655 return GetValue(idx);
656 }
657 void Set(Value const &v) {
658 const ByteValue *bv = dynamic_cast<const ByteValue*>(&v);
659 gdcm_assert( bv ); // That would be bad...
660 if( (VR::VRType)(VRToEncoding<TVR>::Mode) == VR::VRBINARY )
661 {
662 const Type* array = (const Type*)bv->GetVoidPointer();
663 if( array ) {
664 gdcm_assert( array ); // That would be bad...
665 gdcm_assert( Internal == nullptr );
666 SetArray(array, bv->GetLength() ); }
667 }
668 else
669 {
670 std::stringstream ss;
671 std::string s = std::string( bv->GetPointer(), bv->GetLength() );
672 ss.str( s );
673 EncodingImplementation<VRToEncoding<TVR>::Mode>::Read(Internal,
674 GetLength(),ss);
675 }
676 }
677 void SetFromDataElement(DataElement const &de) {
678 const ByteValue *bv = de.GetByteValue();
679 if( !bv ) return;
680#ifdef GDCM_WORDS_BIGENDIAN
681 if( de.GetVR() == VR::UN /*|| de.GetVR() == VR::INVALID*/ )
682#else
683 if( de.GetVR() == VR::UN || de.GetVR() == VR::INVALID )
684#endif
685 {
686 Set(de.GetValue());
687 }
688 else
689 {
690 SetNoSwap(de.GetValue());
691 }
692 }
693
694
695 // Need to be placed after definition of EncodingImplementation<VR::VRASCII>
696 void WriteASCII(std::ostream &os) const {
697 return EncodingImplementation<VR::VRASCII>::Write(Internal, GetLength(), os);
698 }
699
700 // Implementation of Print is common to all Mode (ASCII/Binary)
701 void Print(std::ostream &_os) const {
702 gdcm_assert( Length );
703 gdcm_assert( Internal );
704 _os << Internal[0]; // VM is at least guarantee to be one
705 const unsigned long length = GetLength() < 25 ? GetLength() : 25;
706 for(unsigned long i=1; i<length; ++i)
707 _os << "," << Internal[i];
708 }
709 void Read(std::istream &_is) {
710 if( !Internal ) return;
711 EncodingImplementation<VRToEncoding<TVR>::Mode>::Read(Internal,
712 GetLength(),_is);
713 }
714 //void ReadComputeLength(std::istream &_is) {
715 // if( !Internal ) return;
716 // EncodingImplementation<VRToEncoding<TVR>::Mode>::ReadComputeLength(Internal,
717 // Length,_is);
718 // }
719 void Write(std::ostream &_os) const {
720 EncodingImplementation<VRToEncoding<TVR>::Mode>::Write(Internal,
721 GetLength(),_os);
722 }
723
724 DataElement GetAsDataElement() const {
725 DataElement ret;
726 ret.SetVR( (VR::VRType)TVR );
727 gdcm_assert( ret.GetVR() != VR::SQ );
728 if( Internal )
729 {
730 std::ostringstream os;
731 EncodingImplementation<VRToEncoding<TVR>::Mode>::Write(Internal,
732 GetLength(),os);
733 if( (VR::VRType)VRToEncoding<TVR>::Mode == VR::VRASCII )
734 {
735 if( GetVR() != VR::UI )
736 {
737 if( os.str().size() % 2 )
738 {
739 os << " ";
740 }
741 }
742 }
743 VL::Type osStrSize = (VL::Type)os.str().size();
744 ret.SetByteValue( os.str().c_str(), osStrSize );
745 }
746 return ret;
747 }
748
749 Element(const Element&_val) {
750 if( this != &_val) {
751 *this = _val;
752 }
753 }
754
755 Element &operator=(const Element &_val) {
756 Length = 0; // SYITF
757 Internal = 0;
758 SetArray(_val.Internal, _val.Length, true);
759 return *this;
760 }
761 protected:
762 void SetNoSwap(Value const &v) {
763 const ByteValue *bv = dynamic_cast<const ByteValue*>(&v);
764 gdcm_assert( bv ); // That would be bad...
765 if( (VR::VRType)(VRToEncoding<TVR>::Mode) == VR::VRBINARY )
766 {
767 const Type* array = (const Type*)bv->GetPointer();
768 if( array ) {
769 gdcm_assert( array ); // That would be bad...
770 gdcm_assert( Internal == nullptr );
771 SetArray(array, bv->GetLength() ); }
772 }
773 else
774 {
775 std::stringstream ss;
776 std::string s = std::string( bv->GetPointer(), bv->GetLength() );
777 ss.str( s );
778 EncodingImplementation<VRToEncoding<TVR>::Mode>::ReadNoSwap(Internal,
779 GetLength(),ss);
780 }
781 }
782
783 private:
784 typename VRToType<TVR>::Type *Internal;
785 unsigned long Length; // unsigned int ??
786 bool Save;
787};
788
789//template <int TVM = VM::VM1_n>
790//class Element<VR::OB, TVM > : public Element<VR::OB, VM::VM1_n> {};
791
792// Partial specialization for derivatives of 1-n : 2-n, 3-n ...
793 template<long long TVR>
794 class Element<TVR, VM::VM1_2> : public Element<TVR, VM::VM1_n>
795{
796 public:
797 typedef Element<TVR, VM::VM1_n> Parent;
798 void SetLength(int len) {
799 if( len != 1 && len != 2 ) return;
800 Parent::SetLength(len);
801 }
802};
803 template<long long TVR>
804 class Element<TVR, VM::VM2_n> : public Element<TVR, VM::VM1_n>
805{
806 enum { ElementDisableCombinationsCheck = sizeof ( ElementDisableCombinations<TVR, VM::VM2_n> ) };
807 public:
808 typedef Element<TVR, VM::VM1_n> Parent;
809 void SetLength(int len) {
810 if( len <= 1 ) return;
811 Parent::SetLength(len);
812 }
813};
814 template<long long TVR>
815 class Element<TVR, VM::VM2_2n> : public Element<TVR, VM::VM2_n>
816{
817 enum { ElementDisableCombinationsCheck = sizeof ( ElementDisableCombinations<TVR, VM::VM2_2n> ) };
818 public:
819 typedef Element<TVR, VM::VM2_n> Parent;
820 void SetLength(int len) {
821 if( len % 2 ) return;
822 Parent::SetLength(len);
823 }
824};
825 template<long long TVR>
826 class Element<TVR, VM::VM3_n> : public Element<TVR, VM::VM1_n>
827{
828 enum { ElementDisableCombinationsCheck = sizeof ( ElementDisableCombinations<TVR, VM::VM3_n> ) };
829 public:
830 typedef Element<TVR, VM::VM1_n> Parent;
831 void SetLength(int len) {
832 if( len <= 2 ) return;
833 Parent::SetLength(len);
834 }
835};
836 template<long long TVR>
837 class Element<TVR, VM::VM3_3n> : public Element<TVR, VM::VM3_n>
838{
839 enum { ElementDisableCombinationsCheck = sizeof ( ElementDisableCombinations<TVR, VM::VM3_3n> ) };
840 public:
841 typedef Element<TVR, VM::VM3_n> Parent;
842 void SetLength(int len) {
843 if( len % 3 ) return;
844 Parent::SetLength(len);
845 }
846};
847 template<long long TVR>
848 class Element<TVR, VM::VM3_4> : public Element<TVR, VM::VM1_n>
849{
850 public:
851 typedef Element<TVR, VM::VM1_n> Parent;
852 void SetLength(int len) {
853 if( len != 3 && len != 4 ) return;
854 Parent::SetLength(len);
855 }
856};
857
858
859//template<int T> struct VRToLength;
860//template <> struct VRToLength<VR::AS>
861//{ enum { Length = VM::VM1 }; }
862//template<>
863//class Element<VR::AS> : public Element<VR::AS, VRToLength<VR::AS>::Length >
864
865// only 0010 1010 AS 1 Patient's Age
866 template<>
867 class Element<VR::AS, VM::VM5>
868{
869 enum { ElementDisableCombinationsCheck = sizeof ( ElementDisableCombinations<VR::AS, VM::VM5> ) };
870 public:
871 char Internal[VMToLength<VM::VM5>::Length * sizeof( VRToType<VR::AS>::Type )];
872 void Print(std::ostream &_os) const {
873 _os << Internal;
874 }
875 unsigned long GetLength() const {
876 return VMToLength<VM::VM5>::Length;
877 }
878};
879
880
881 template <>
882 class Element<VR::OB, VM::VM1> : public Element<VR::OB, VM::VM1_n> {};
883
884// Same for OW:
885 template <>
886 class Element<VR::OW, VM::VM1> : public Element<VR::OW, VM::VM1_n> {};
887
888
889} // namespace gdcm_ns
890
891#endif //GDCMELEMENT_H
gdcm::ByteValue
Class to represent binary value (array of bytes)
Definition gdcmByteValue.h:36
gdcm::ByteValue::GetPointer
const char * GetPointer() const
Definition gdcmByteValue.h:114
gdcm::ByteValue::GetLength
VL GetLength() const override
Definition gdcmByteValue.h:81
gdcm::DataElement
Class to represent a Data Element either Implicit or Explicit.
Definition gdcmDataElement.h:59
gdcm::DataElement::GetVR
VR const & GetVR() const
Definition gdcmDataElement.h:84
gdcm::DataElement::GetByteValue
const ByteValue * GetByteValue() const
Definition gdcmDataElement.h:133
gdcm::DataElement::GetValue
Value const & GetValue() const
Set/Get Value (bytes array, SQ of items, SQ of fragments):
Definition gdcmDataElement.h:94
gdcm::DataElement::SetByteValue
void SetByteValue(const char *array, VL length)
Definition gdcmDataElement.h:126
gdcm::DataElement::SetVR
void SetVR(VR const &vr)
Definition gdcmDataElement.h:88
gdcm::ElementDisableCombinations
A class which is used to produce compile errors for an invalid combination of template parameters.
Definition gdcmElement.h:52
gdcm::Element< TVR, VM::VM1_2 >::Parent
Element< TVR, VM::VM1_n > Parent
Definition gdcmElement.h:797
gdcm::Element< TVR, VM::VM1_2 >::SetLength
void SetLength(int len)
Definition gdcmElement.h:798
gdcm::Element< TVR, VM::VM2_2n >::Parent
Element< TVR, VM::VM2_n > Parent
Definition gdcmElement.h:819
gdcm::Element< TVR, VM::VM2_2n >::SetLength
void SetLength(int len)
Definition gdcmElement.h:820
gdcm::Element< TVR, VM::VM3_3n >::SetLength
void SetLength(int len)
Definition gdcmElement.h:842
gdcm::Element< TVR, VM::VM3_3n >::Parent
Element< TVR, VM::VM3_n > Parent
Definition gdcmElement.h:841
gdcm::Element< TVR, VM::VM3_4 >::Parent
Element< TVR, VM::VM1_n > Parent
Definition gdcmElement.h:851
gdcm::Element< TVR, VM::VM3_4 >::SetLength
void SetLength(int len)
Definition gdcmElement.h:852
gdcm::Element< VR::AS, VM::VM5 >::GetLength
unsigned long GetLength() const
Definition gdcmElement.h:875
gdcm::Element< VR::AS, VM::VM5 >::Internal
char Internal[VMToLength< VM::VM5 >::Length *sizeof(VRToType< VR::AS >::Type)]
Definition gdcmElement.h:871
gdcm::Element< VR::AS, VM::VM5 >::Print
void Print(std::ostream &_os) const
Definition gdcmElement.h:872
gdcm::Element
Element class.
Definition gdcmElement.h:70
gdcm::Element::GetVM
static VM GetVM()
Definition gdcmElement.h:77
gdcm::Element::GetAsDataElement
DataElement GetAsDataElement() const
Definition gdcmElement.h:127
gdcm::Element::GetValue
VRToType< TVR >::Type & GetValue(unsigned int idx=0)
Definition gdcmElement.h:98
gdcm::Element::Type
VRToType< TVR >::Type Type
Definition gdcmElement.h:74
gdcm::Element::Read
void Read(std::istream &_is)
Definition gdcmElement.h:150
gdcm::Element::GetLength
unsigned long GetLength() const
Definition gdcmElement.h:79
gdcm::Element::SetValue
void SetValue(typename VRToType< TVR >::Type v, unsigned int idx=0)
Definition gdcmElement.h:105
gdcm::Element::GetValue
const VRToType< TVR >::Type & GetValue(unsigned int idx=0) const
Definition gdcmElement.h:94
gdcm::Element::GetValues
const VRToType< TVR >::Type * GetValues() const
Definition gdcmElement.h:91
gdcm::Element::Write
void Write(std::ostream &_os) const
Definition gdcmElement.h:154
gdcm::Element::Internal
VRToType< TVR >::Type Internal[VMToLength< TVM >::Length]
Definition gdcmElement.h:73
gdcm::Element::SetNoSwap
void SetNoSwap(Value const &v)
Definition gdcmElement.h:173
gdcm::Element::GetVR
static VR GetVR()
Definition gdcmElement.h:76
gdcm::Element::Print
void Print(std::ostream &_os) const
Definition gdcmElement.h:85
gdcm::Element::Set
void Set(Value const &v)
Definition gdcmElement.h:161
gdcm::Element::SetFromDataElement
void SetFromDataElement(DataElement const &de)
Definition gdcmElement.h:110
gdcm::EncodingImplementation< VR::VRASCII >::ReadComputeLength
static void ReadComputeLength(T *data, unsigned int &length, std::istream &_is)
Definition gdcmElement.h:204
gdcm::EncodingImplementation< VR::VRASCII >::ReadNoSwap
static void ReadNoSwap(T *data, unsigned long length, std::istream &_is)
Definition gdcmElement.h:248
gdcm::EncodingImplementation< VR::VRASCII >::Write
static void Write(const T *data, unsigned long length, std::ostream &_os)
Definition gdcmElement.h:253
gdcm::EncodingImplementation< VR::VRASCII >::Read
static void Read(T *data, unsigned long length, std::istream &_is)
Definition gdcmElement.h:228
gdcm::EncodingImplementation< VR::VRBINARY >::ReadNoSwap
static void ReadNoSwap(T *data, unsigned long length, std::istream &_is)
Definition gdcmElement.h:468
gdcm::EncodingImplementation< VR::VRBINARY >::Read
static void Read(T *data, unsigned long length, std::istream &_is)
Definition gdcmElement.h:484
gdcm::EncodingImplementation< VR::VRBINARY >::Write
static void Write(const T *data, unsigned long length, std::ostream &_os)
Definition gdcmElement.h:500
gdcm::EncodingImplementation< VR::VRBINARY >::ReadComputeLength
static void ReadComputeLength(T *data, unsigned int &length, std::istream &_is)
Definition gdcmElement.h:454
gdcm::EncodingImplementation
EncodingImplementation.
Definition gdcmElement.h:41
gdcm::SwapperNoOp::Swap
static T Swap(T val)
Definition gdcmSwapper.h:49
gdcm::SwapperNoOp::SwapArray
static void SwapArray(T *, size_t)
Definition gdcmSwapper.h:50
gdcm::VL::Type
uint32_t Type
Definition gdcmVL.h:32
gdcm::VM
Value Multiplicity Looking at the DICOMV3 dict only there is very few cases: 1 2 3 4 5 6 8 16 24 1-2 ...
Definition gdcmVM.h:68
gdcm::VM::VMType
VMType
Definition gdcmVM.h:70
gdcm::VM::VM1_n
@ VM1_n
Definition gdcmVM.h:98
gdcm::VM::VM5
@ VM5
Definition gdcmVM.h:76
gdcm::VM::VM1
@ VM1
Definition gdcmVM.h:72
gdcm::VR
VR class.
Definition gdcmVR.h:55
gdcm::VR::VRType
VRType
Definition gdcmVR.h:57
gdcm::VR::INVALID
@ INVALID
Definition gdcmVR.h:59
gdcm::VR::UI
@ UI
Definition gdcmVR.h:87
gdcm::VR::VRASCII
@ VRASCII
Definition gdcmVR.h:101
gdcm::VR::SQ
@ SQ
Definition gdcmVR.h:81
gdcm::VR::UN
@ UN
Definition gdcmVR.h:89
gdcm::Value
Class to represent the value of a Data Element.
Definition gdcmValue.h:32
gdcmByteValue.h
gdcmDataElement.h
gdcm_assert
#define gdcm_assert(cond)
Definition gdcmException.h:104
gdcmSwapper.h
gdcmTag.h
gdcmTypes.h
gdcmVM.h
gdcmVR.h
gdcm::add1
static int add1(char *buf, int n)
Definition gdcmElement.h:296
gdcm::roundat
static int roundat(char *buf, size_t bufLen, unsigned int i, int iexp)
Definition gdcmElement.h:321
gdcm::doround
static int doround(char *buf, unsigned int n)
Definition gdcmElement.h:308
gdcm::clean
static void clean(char *mant)
Definition gdcmElement.h:286
gdcm::x16printf
static void x16printf(char *buf, int size, Float f)
Definition gdcmElement.h:349
gdcm::backslash
ignore_char const backslash('\\')
gdcm::VMToLength
Definition gdcmVM.h:155
gdcm::VRToEncoding
Definition gdcmVR.h:242
gdcm::VRToType
Definition gdcmVR.h:244
gdcm::ignore_char
Definition gdcmElement.h:185
gdcm::ignore_char::m_char
char m_char
Definition gdcmElement.h:187
gdcm::ignore_char::ignore_char
ignore_char(char c)
Definition gdcmElement.h:186