gdcmElement.h
Go to the documentation of this file.
/*=========================================================================
Program: GDCM (Grassroots DICOM). A DICOM library
Copyright (c) 2006-2011 Mathieu Malaterre
All rights reserved.
See Copyright.txt or http://gdcm.sourceforge.net/Copyright.html for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
#ifndef GDCMELEMENT_H
#define GDCMELEMENT_H
#include "gdcmTypes.h"
#include "gdcmVR.h"
#include "gdcmTag.h"
#include "gdcmVM.h"
#include "gdcmByteValue.h"
#include "gdcmDataElement.h"
#include "gdcmSwapper.h"
#include <string>
#include <vector>
#include <sstream>
#include <limits>
#include <cmath>
#include <cstring>
namespace gdcm_ns
{
// Forward declaration
template<long long T> class EncodingImplementation;
template <long long TVR, int TVM>
class ElementDisableCombinations {};
template <>
class ElementDisableCombinations<VR::OB, VM::VM1_n> {};
template <>
class ElementDisableCombinations<VR::OW, VM::VM1_n> {};
// Make it impossible to compile these other cases
template <int TVM>
class ElementDisableCombinations<VR::OB, TVM>;
template <int TVM>
class ElementDisableCombinations<VR::OW, TVM>;
template<long long TVR, int TVM>
class Element
{
enum { ElementDisableCombinationsCheck = sizeof ( ElementDisableCombinations<TVR, TVM> ) };
public:
typename VRToType<TVR>::Type Internal[VMToLength<TVM>::Length];
typedef typename VRToType<TVR>::Type Type;
static VR GetVR() { return (VR::VRType)TVR; }
static VM GetVM() { return (VM::VMType)TVM; }
unsigned long GetLength() const {
return VMToLength<TVM>::Length;
}
// Implementation of Print is common to all Mode (ASCII/Binary)
// TODO: Can we print a \ when in ASCII...well I don't think so
// it would mean we used a bad VM then, right?
void Print(std::ostream &_os) const {
_os << Internal[0]; // VM is at least guarantee to be one
for(int i=1; i<VMToLength<TVM>::Length; ++i)
_os << "," << Internal[i];
}
const typename VRToType<TVR>::Type *GetValues() const {
return Internal;
}
const typename VRToType<TVR>::Type &GetValue(unsigned int idx = 0) const {
assert( idx < VMToLength<TVM>::Length );
return Internal[idx];
}
typename VRToType<TVR>::Type &GetValue(unsigned int idx = 0) {
assert( idx < VMToLength<TVM>::Length );
return Internal[idx];
}
typename VRToType<TVR>::Type operator[] (unsigned int idx) const {
return GetValue(idx);
}
void SetValue(typename VRToType<TVR>::Type v, unsigned int idx = 0) {
assert( idx < VMToLength<TVM>::Length );
Internal[idx] = v;
}
void SetFromDataElement(DataElement const &de) {
const ByteValue *bv = de.GetByteValue();
if( !bv ) return;
#ifdef GDCM_WORDS_BIGENDIAN
if( de.GetVR() == VR::UN /*|| de.GetVR() == VR::INVALID*/ )
#else
if( de.GetVR() == VR::UN || de.GetVR() == VR::INVALID )
#endif
{
Set(de.GetValue());
}
else
{
SetNoSwap(de.GetValue());
}
}
DataElement GetAsDataElement() const {
DataElement ret;
std::ostringstream os;
EncodingImplementation<VRToEncoding<TVR>::Mode>::Write(Internal,
GetLength(),os);
ret.SetVR( (VR::VRType)TVR );
assert( ret.GetVR() != VR::SQ );
if( (VR::VRType)VRToEncoding<TVR>::Mode == VR::VRASCII )
{
if( GetVR() != VR::UI )
{
if( os.str().size() % 2 )
{
os << " ";
}
}
}
VL::Type osStrSize = (VL::Type)os.str().size();
ret.SetByteValue( os.str().c_str(), osStrSize );
return ret;
}
void Read(std::istream &_is) {
return EncodingImplementation<VRToEncoding<TVR>::Mode>::Read(Internal,
GetLength(),_is);
}
void Write(std::ostream &_os) const {
return EncodingImplementation<VRToEncoding<TVR>::Mode>::Write(Internal,
GetLength(),_os);
}
// FIXME: remove this function
// this is only used in gdcm::SplitMosaicFilter / to pass value of a CSAElement
void Set(Value const &v) {
const ByteValue *bv = dynamic_cast<const ByteValue*>(&v);
if( bv ) {
//memcpy(Internal, bv->GetPointer(), bv->GetLength());
std::stringstream ss;
std::string s = std::string( bv->GetPointer(), bv->GetLength() );
ss.str( s );
EncodingImplementation<VRToEncoding<TVR>::Mode>::Read(Internal,
GetLength(),ss);
}
}
protected:
void SetNoSwap(Value const &v) {
const ByteValue *bv = dynamic_cast<const ByteValue*>(&v);
assert( bv ); // That would be bad...
//memcpy(Internal, bv->GetPointer(), bv->GetLength());
std::stringstream ss;
std::string s = std::string( bv->GetPointer(), bv->GetLength() );
ss.str( s );
EncodingImplementation<VRToEncoding<TVR>::Mode>::ReadNoSwap(Internal,
GetLength(),ss);
}
};
struct ignore_char {
ignore_char(char c): m_char(c) {}
char m_char;
};
ignore_char const backslash('\\');
inline std::istream& operator>> (std::istream& in, ignore_char const& ic) {
if (!in.eof())
in.clear(in.rdstate() & ~std::ios_base::failbit);
if (in.get() != ic.m_char)
in.setstate(std::ios_base::failbit);
return in;
}
// Implementation to perform formatted read and write
template<> class EncodingImplementation<VR::VRASCII> {
public:
template<typename T> // FIXME this should be VRToType<TVR>::Type
static inline void ReadComputeLength(T* data, unsigned int &length,
std::istream &_is) {
assert( data );
//assert( length ); // != 0
length = 0;
assert( _is );
#if 0
char sep;
while( _is >> data[length++] )
{
// Get the separator in between the values
assert( _is );
_is.get(sep);
assert( sep == '\\' || sep == ' ' ); // FIXME: Bad use of assert
if( sep == ' ' ) length--; // FIXME
}
#else
while( _is >> std::ws >> data[length++] >> std::ws >> backslash )
{
}
#endif
}
template<typename T> // FIXME this should be VRToType<TVR>::Type
static inline void Read(T* data, unsigned long length,
std::istream &_is) {
assert( data );
assert( length ); // != 0
assert( _is );
// FIXME BUG: what if >> operation fails ?
// gdcmData/MR00010001.dcm / SpacingBetweenSlices
_is >> std::ws >> data[0];
char sep;
//std::cout << "GetLength: " << af->GetLength() << std::endl;
for(unsigned long i=1; i<length;++i) {
//assert( _is );
// Get the separator in between the values
_is >> std::ws >> sep; //_is.get(sep);
//assert( sep == '\\' ); // FIXME: Bad use of assert
_is >> std::ws >> data[i];
}
}
template<typename T>
static inline void ReadNoSwap(T* data, unsigned long length,
std::istream &_is) {
Read(data,length,_is);
}
template<typename T>
static inline void Write(const T* data, unsigned long length,
std::ostream &_os) {
assert( data );
assert( length );
assert( _os );
_os << data[0];
for(unsigned long i=1; i<length; ++i) {
assert( _os );
_os << "\\" << data[i];
}
}
};
//#define VRDS16ILLEGAL
#ifdef VRDS16ILLEGAL
template < typename Float >
std::string to_string ( Float data ) {
std::stringstream in;
// in.imbue(std::locale::classic()); // This is not required AFAIK
int const digits =
static_cast< int >(
- std::log( std::numeric_limits<Float>::epsilon() )
/ static_cast< Float >( std::log( 10.0 ) ) );
if ( in << std::dec << std::setprecision(/*2+*/digits) << data ) {
return ( in.str() );
} else {
throw "Impossible Conversion"; // should not happen ...
}
}
#else
// http://stackoverflow.com/questions/32631178/writing-ieee-754-1985-double-as-ascii-on-a-limited-16-bytes-string
static inline void clean(char *mant) {
char *ix = mant + strlen(mant) - 1;
while(('0' == *ix) && (ix > mant)) {
*ix-- = '\0';
}
if ('.' == *ix) {
*ix = '\0';
}
}
static int add1(char *buf, int n) {
if (n < 0) return 1;
if (buf[n] == '9') {
buf[n] = '0';
return add1(buf, n-1);
}
else {
buf[n] = (char)(buf[n] + 1);
}
return 0;
}
static int doround(char *buf, unsigned int n) {
char c;
if (n >= strlen(buf)) return 0;
c = buf[n];
buf[n] = 0;
if ((c >= '5') && (c <= '9')) return add1(buf, n-1);
return 0;
}
#if defined(_MSC_VER) && (_MSC_VER < 1900)
#define snprintf _snprintf
#endif
static int roundat(char *buf, size_t bufLen, unsigned int i, int iexp) {
if (doround(buf, i) != 0) {
iexp += 1;
switch(iexp) {
case -2:
strcpy(buf, ".01");
break;
case -1:
strcpy(buf, ".1");
break;
case 0:
strcpy(buf, "1.");
break;
case 1:
strcpy(buf, "10");
break;
case 2:
strcpy(buf, "100");
break;
default:
snprintf(buf, bufLen, "1e%d", iexp);
}
return 1;
}
return 0;
}
template < typename Float >
static void x16printf(char *buf, int size, Float f) {
char line[40];
char *mant = line + 1;
int iexp, lexp, i;
char exp[6];
if (f < 0) {
f = -f;
size -= 1;
*buf++ = '-';
}
snprintf(line, sizeof(line), "%1.16e", f);
if (line[0] == '-') {
f = -f;
size -= 1;
*buf++ = '-';
snprintf(line, sizeof(line), "%1.16e", f);
}
*mant = line[0];
i = (int)strcspn(mant, "eE");
mant[i] = '\0';
iexp = (int)strtol(mant + i + 1, nullptr, 10);
lexp = snprintf(exp, sizeof(exp), "e%d", iexp);
if ((iexp >= size) || (iexp < -3)) {
i = roundat(mant, sizeof(line) - 1, size - 1 -lexp, iexp);
if(i == 1) {
strcpy(buf, mant);
return;
}
buf[0] = mant[0];
buf[1] = '.';
strncpy(buf + i + 2, mant + 1, size - 2 - lexp);
buf[size-lexp] = 0;
clean(buf);
strcat(buf, exp);
}
else if (iexp >= size - 2) {
roundat(mant, sizeof(line) - 1, iexp + 1, iexp);
strcpy(buf, mant);
}
else if (iexp >= 0) {
i = roundat(mant, sizeof(line) - 1, size - 1, iexp);
if (i == 1) {
strcpy(buf, mant);
return;
}
strncpy(buf, mant, iexp + 1);
buf[iexp + 1] = '.';
strncpy(buf + iexp + 2, mant + iexp + 1, size - iexp - 1);
buf[size] = 0;
clean(buf);
}
else {
int j;
i = roundat(mant, sizeof(line) - 1, size + 1 + iexp, iexp);
if (i == 1) {
strcpy(buf, mant);
return;
}
buf[0] = '.';
for(j=0; j< -1 - iexp; j++) {
buf[j+1] = '0';
}
strncpy(buf - iexp, mant, size + 1 + iexp);
buf[size] = 0;
clean(buf);
}
}
#if defined(_MSC_VER) && (_MSC_VER < 1900)
#undef snprintf
#endif
#endif
template<> inline void EncodingImplementation<VR::VRASCII>::Write(const double* data, unsigned long length, std::ostream &_os) {
assert( data );
assert( length );
assert( _os );
#ifdef VRDS16ILLEGAL
_os << to_string(data[0]);
#else
char buf[16+1];
x16printf(buf, 16, data[0]);
_os << buf;
#endif
for(unsigned long i=1; i<length; ++i) {
assert( _os );
#ifdef VRDS16ILLEGAL
_os << "\\" << to_string(data[i]);
#else
x16printf(buf, 16, data[i]);
_os << "\\" << buf;
#endif
}
}
// Implementation to perform binary read and write
// TODO rewrite operation so that either:
// #1. dummy implementation use a pointer to Internal and do ++p (faster)
// #2. Actually do some meta programming to unroll the loop
// (no notion of order in VM ...)
template<> class EncodingImplementation<VR::VRBINARY> {
public:
template<typename T> // FIXME this should be VRToType<TVR>::Type
static inline void ReadComputeLength(T* data, unsigned int &length,
std::istream &_is) {
const unsigned int type_size = sizeof(T);
assert( data ); // Can we read from pointer ?
//assert( length );
length /= type_size;
assert( _is ); // Is stream valid ?
_is.read( reinterpret_cast<char*>(data+0), type_size);
for(unsigned long i=1; i<length; ++i) {
assert( _is );
_is.read( reinterpret_cast<char*>(data+i), type_size );
}
}
template<typename T>
static inline void ReadNoSwap(T* data, unsigned long length,
std::istream &_is) {
const unsigned int type_size = sizeof(T);
assert( data ); // Can we read from pointer ?
assert( length );
assert( _is ); // Is stream valid ?
_is.read( reinterpret_cast<char*>(data+0), type_size);
for(unsigned long i=1; i<length; ++i) {
if( _is )
_is.read( reinterpret_cast<char*>(data+i), type_size );
}
//ByteSwap<T>::SwapRangeFromSwapCodeIntoSystem(data,
// _is.GetSwapCode(), length);
//SwapperNoOp::SwapArray(data,length);
}
template<typename T>
static inline void Read(T* data, unsigned long length,
std::istream &_is) {
const unsigned int type_size = sizeof(T);
assert( data ); // Can we read from pointer ?
assert( length );
assert( _is ); // Is stream valid ?
_is.read( reinterpret_cast<char*>(data+0), type_size);
for(unsigned long i=1; i<length; ++i) {
if( _is )
_is.read( reinterpret_cast<char*>(data+i), type_size );
}
//ByteSwap<T>::SwapRangeFromSwapCodeIntoSystem(data,
// _is.GetSwapCode(), length);
SwapperNoOp::SwapArray(data,length);
}
template<typename T>
static inline void Write(const T* data, unsigned long length,
std::ostream &_os) {
const unsigned int type_size = sizeof(T);
assert( data ); // Can we write into pointer ?
assert( length );
assert( _os ); // Is stream valid ?
//ByteSwap<T>::SwapRangeFromSwapCodeIntoSystem((T*)data,
// _os.GetSwapCode(), length);
T swappedData = SwapperNoOp::Swap(data[0]);
_os.write( reinterpret_cast<const char*>(&swappedData), type_size);
for(unsigned long i=1; i<length;++i) {
assert( _os );
swappedData = SwapperNoOp::Swap(data[i]);
_os.write( reinterpret_cast<const char*>(&swappedData), type_size );
}
//ByteSwap<T>::SwapRangeFromSwapCodeIntoSystem((T*)data,
// _os.GetSwapCode(), length);
}
};
// For particular case for ASCII string
// WARNING: This template explicitly instantiates a particular
// EncodingImplementation THEREFORE it is required to be declared after the
// EncodingImplementation is needs (doh!)
#if 0
template<int TVM>
class Element<TVM>
{
public:
Element(const char array[])
{
unsigned int i = 0;
const char sep = '\\';
std::string sarray = array;
std::string::size_type pos1 = 0;
std::string::size_type pos2 = sarray.find(sep, pos1+1);
while(pos2 != std::string::npos)
{
Internal[i++] = sarray.substr(pos1, pos2-pos1);
pos1 = pos2+1;
pos2 = sarray.find(sep, pos1+1);
}
Internal[i] = sarray.substr(pos1, pos2-pos1);
// Shouldn't we do the contrary, since we know how many separators
// (and default behavior is to discard anything after the VM declared
assert( GetLength()-1 == i );
}
unsigned long GetLength() const {
return VMToLength<TVM>::Length;
}
// Implementation of Print is common to all Mode (ASCII/Binary)
void Print(std::ostream &_os) const {
_os << Internal[0]; // VM is at least guarantee to be one
for(int i=1; i<VMToLength<TVM>::Length; ++i)
_os << "," << Internal[i];
}
void Read(std::istream &_is) {
EncodingImplementation<VR::VRASCII>::Read(Internal, GetLength(),_is);
}
void Write(std::ostream &_os) const {
EncodingImplementation<VR::VRASCII>::Write(Internal, GetLength(),_os);
}
private:
typename String Internal[VMToLength<TVM>::Length];
};
template< int TVM>
class Element<VR::PN, TVM> : public StringElement<TVM>
{
enum { ElementDisableCombinationsCheck = sizeof ( ElementDisableCombinations<VR::PN, TVM> ) };
};
#endif
// Implementation for the undefined length (dynamically allocated array)
template<long long TVR>
class Element<TVR, VM::VM1_n>
{
enum { ElementDisableCombinationsCheck = sizeof ( ElementDisableCombinations<TVR, VM::VM1_n> ) };
public:
// This the way to prevent default initialization
explicit Element() { Internal=nullptr; Length=0; Save = false; }
~Element() {
if( Save ) {
delete[] Internal;
}
Internal = nullptr;
}
static VR GetVR() { return (VR::VRType)TVR; }
static VM GetVM() { return VM::VM1_n; }
// Length manipulation
// SetLength should really be protected anyway...all operation
// should go through SetArray
unsigned long GetLength() const { return Length; }
typedef typename VRToType<TVR>::Type Type;
void SetLength(unsigned long len) {
const unsigned int size = sizeof(Type);
if( len ) {
if( len > Length ) {
// perform realloc
assert( (len / size) * size == len );
Type *internal = new Type[len / size];
assert( Save == false );
Save = true; // ????
if( Internal )
{
memcpy(internal, Internal, len);
delete[] Internal;
}
Internal = internal;
}
}
Length = len / size;
}
// If save is set to zero user should not delete the pointer
//void SetArray(const typename VRToType<TVR>::Type *array, int len, bool save = false)
void SetArray(const Type *array, unsigned long len,
bool save = false) {
if( save ) {
SetLength(len); // realloc
memcpy(Internal, array, len/*/sizeof(Type)*/);
assert( Save == false );
}
else {
// TODO rewrite this stupid code:
assert( Length == 0 );
assert( Internal == nullptr );
assert( Save == false );
Length = len / sizeof(Type);
//assert( (len / sizeof(Type)) * sizeof(Type) == len );
// MR00010001.dcm is a tough kid: 0019,105a is supposed to be VR::FL, VM::VM3 but
// length is 14 bytes instead of 12 bytes. Simply consider value is total garbage.
if( (len / sizeof(Type)) * sizeof(Type) != len ) { Internal = nullptr; Length = 0; }
else Internal = const_cast<Type*>(array);
}
Save = save;
}
void SetValue(typename VRToType<TVR>::Type v, unsigned int idx = 0) {
assert( idx < Length );
Internal[idx] = v;
}
const typename VRToType<TVR>::Type &GetValue(unsigned int idx = 0) const {
assert( idx < Length );
return Internal[idx];
}
typename VRToType<TVR>::Type &GetValue(unsigned int idx = 0) {
//assert( idx < Length );
return Internal[idx];
}
typename VRToType<TVR>::Type operator[] (unsigned int idx) const {
return GetValue(idx);
}
void Set(Value const &v) {
const ByteValue *bv = dynamic_cast<const ByteValue*>(&v);
assert( bv ); // That would be bad...
if( (VR::VRType)(VRToEncoding<TVR>::Mode) == VR::VRBINARY )
{
const Type* array = (const Type*)bv->GetVoidPointer();
if( array ) {
assert( array ); // That would be bad...
assert( Internal == nullptr );
SetArray(array, bv->GetLength() ); }
}
else
{
std::stringstream ss;
std::string s = std::string( bv->GetPointer(), bv->GetLength() );
ss.str( s );
EncodingImplementation<VRToEncoding<TVR>::Mode>::Read(Internal,
GetLength(),ss);
}
}
void SetFromDataElement(DataElement const &de) {
const ByteValue *bv = de.GetByteValue();
if( !bv ) return;
#ifdef GDCM_WORDS_BIGENDIAN
if( de.GetVR() == VR::UN /*|| de.GetVR() == VR::INVALID*/ )
#else
if( de.GetVR() == VR::UN || de.GetVR() == VR::INVALID )
#endif
{
Set(de.GetValue());
}
else
{
SetNoSwap(de.GetValue());
}
}
// Need to be placed after definition of EncodingImplementation<VR::VRASCII>
void WriteASCII(std::ostream &os) const {
return EncodingImplementation<VR::VRASCII>::Write(Internal, GetLength(), os);
}
// Implementation of Print is common to all Mode (ASCII/Binary)
void Print(std::ostream &_os) const {
assert( Length );
assert( Internal );
_os << Internal[0]; // VM is at least guarantee to be one
const unsigned long length = GetLength() < 25 ? GetLength() : 25;
for(unsigned long i=1; i<length; ++i)
_os << "," << Internal[i];
}
void Read(std::istream &_is) {
if( !Internal ) return;
EncodingImplementation<VRToEncoding<TVR>::Mode>::Read(Internal,
GetLength(),_is);
}
//void ReadComputeLength(std::istream &_is) {
// if( !Internal ) return;
// EncodingImplementation<VRToEncoding<TVR>::Mode>::ReadComputeLength(Internal,
// Length,_is);
// }
void Write(std::ostream &_os) const {
EncodingImplementation<VRToEncoding<TVR>::Mode>::Write(Internal,
GetLength(),_os);
}
DataElement GetAsDataElement() const {
DataElement ret;
ret.SetVR( (VR::VRType)TVR );
assert( ret.GetVR() != VR::SQ );
if( Internal )
{
std::ostringstream os;
EncodingImplementation<VRToEncoding<TVR>::Mode>::Write(Internal,
GetLength(),os);
if( (VR::VRType)VRToEncoding<TVR>::Mode == VR::VRASCII )
{
if( GetVR() != VR::UI )
{
if( os.str().size() % 2 )
{
os << " ";
}
}
}
VL::Type osStrSize = (VL::Type)os.str().size();
ret.SetByteValue( os.str().c_str(), osStrSize );
}
return ret;
}
Element(const Element&_val) {
if( this != &_val) {
*this = _val;
}
}
Element &operator=(const Element &_val) {
Length = 0; // SYITF
Internal = 0;
SetArray(_val.Internal, _val.Length, true);
return *this;
}
protected:
void SetNoSwap(Value const &v) {
const ByteValue *bv = dynamic_cast<const ByteValue*>(&v);
assert( bv ); // That would be bad...
if( (VR::VRType)(VRToEncoding<TVR>::Mode) == VR::VRBINARY )
{
const Type* array = (const Type*)bv->GetPointer();
if( array ) {
assert( array ); // That would be bad...
assert( Internal == nullptr );
SetArray(array, bv->GetLength() ); }
}
else
{
std::stringstream ss;
std::string s = std::string( bv->GetPointer(), bv->GetLength() );
ss.str( s );
EncodingImplementation<VRToEncoding<TVR>::Mode>::ReadNoSwap(Internal,
GetLength(),ss);
}
}
private:
typename VRToType<TVR>::Type *Internal;
unsigned long Length; // unsigned int ??
bool Save;
};
//template <int TVM = VM::VM1_n>
//class Element<VR::OB, TVM > : public Element<VR::OB, VM::VM1_n> {};
// Partial specialization for derivatives of 1-n : 2-n, 3-n ...
template<long long TVR>
class Element<TVR, VM::VM1_2> : public Element<TVR, VM::VM1_n>
{
public:
typedef Element<TVR, VM::VM1_n> Parent;
void SetLength(int len) {
if( len != 1 && len != 2 ) return;
Parent::SetLength(len);
}
};
template<long long TVR>
class Element<TVR, VM::VM2_n> : public Element<TVR, VM::VM1_n>
{
enum { ElementDisableCombinationsCheck = sizeof ( ElementDisableCombinations<TVR, VM::VM2_n> ) };
public:
typedef Element<TVR, VM::VM1_n> Parent;
void SetLength(int len) {
if( len <= 1 ) return;
Parent::SetLength(len);
}
};
template<long long TVR>
class Element<TVR, VM::VM2_2n> : public Element<TVR, VM::VM2_n>
{
enum { ElementDisableCombinationsCheck = sizeof ( ElementDisableCombinations<TVR, VM::VM2_2n> ) };
public:
typedef Element<TVR, VM::VM2_n> Parent;
void SetLength(int len) {
if( len % 2 ) return;
Parent::SetLength(len);
}
};
template<long long TVR>
class Element<TVR, VM::VM3_n> : public Element<TVR, VM::VM1_n>
{
enum { ElementDisableCombinationsCheck = sizeof ( ElementDisableCombinations<TVR, VM::VM3_n> ) };
public:
typedef Element<TVR, VM::VM1_n> Parent;
void SetLength(int len) {
if( len <= 2 ) return;
Parent::SetLength(len);
}
};
template<long long TVR>
class Element<TVR, VM::VM3_3n> : public Element<TVR, VM::VM3_n>
{
enum { ElementDisableCombinationsCheck = sizeof ( ElementDisableCombinations<TVR, VM::VM3_3n> ) };
public:
typedef Element<TVR, VM::VM3_n> Parent;
void SetLength(int len) {
if( len % 3 ) return;
Parent::SetLength(len);
}
};
template<long long TVR>
class Element<TVR, VM::VM3_4> : public Element<TVR, VM::VM1_n>
{
public:
typedef Element<TVR, VM::VM1_n> Parent;
void SetLength(int len) {
if( len != 3 && len != 4 ) return;
Parent::SetLength(len);
}
};
//template<int T> struct VRToLength;
//template <> struct VRToLength<VR::AS>
//{ enum { Length = VM::VM1 }; }
//template<>
//class Element<VR::AS> : public Element<VR::AS, VRToLength<VR::AS>::Length >
// only 0010 1010 AS 1 Patient's Age
template<>
class Element<VR::AS, VM::VM5>
{
enum { ElementDisableCombinationsCheck = sizeof ( ElementDisableCombinations<VR::AS, VM::VM5> ) };
public:
char Internal[VMToLength<VM::VM5>::Length * sizeof( VRToType<VR::AS>::Type )];
void Print(std::ostream &_os) const {
_os << Internal;
}
unsigned long GetLength() const {
return VMToLength<VM::VM5>::Length;
}
};
template <>
class Element<VR::OB, VM::VM1> : public Element<VR::OB, VM::VM1_n> {};
// Same for OW:
template <>
class Element<VR::OW, VM::VM1> : public Element<VR::OW, VM::VM1_n> {};
} // namespace gdcm_ns
#endif //GDCMELEMENT_H
gdcm::ByteValue
Class to represent binary value (array of bytes).
Definition gdcmByteValue.h:35
gdcm::ByteValue::GetVoidPointer
const void * GetVoidPointer() const
Definition gdcmByteValue.h:115
gdcm::ByteValue::GetPointer
const char * GetPointer() const
Definition gdcmByteValue.h:110
gdcm::ByteValue::GetLength
VL GetLength() const override
Definition gdcmByteValue.h:77
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::VM1_n >::Element
Element()
Definition gdcmElement.h:582
gdcm::Element< TVR, VM::VM1_n >::Read
void Read(std::istream &_is)
Definition gdcmElement.h:709
gdcm::Element< TVR, VM::VM1_n >::SetNoSwap
void SetNoSwap(Value const &v)
Definition gdcmElement.h:762
gdcm::Element< TVR, VM::VM1_n >::SetLength
void SetLength(unsigned long len)
Definition gdcmElement.h:599
gdcm::Element< TVR, VM::VM1_n >::WriteASCII
void WriteASCII(std::ostream &os) const
Definition gdcmElement.h:696
gdcm::Element< TVR, VM::VM1_n >::GetVR
static VR GetVR()
Definition gdcmElement.h:590
gdcm::Element< TVR, VM::VM1_n >::GetValue
VRToType< TVR >::Type & GetValue(unsigned int idx=0)
Definition gdcmElement.h:650
gdcm::Element< TVR, VM::VM1_n >::Set
void Set(Value const &v)
Definition gdcmElement.h:657
gdcm::Element< TVR, VM::VM1_n >::GetVM
static VM GetVM()
Definition gdcmElement.h:591
gdcm::Element< TVR, VM::VM1_n >::SetFromDataElement
void SetFromDataElement(DataElement const &de)
Definition gdcmElement.h:677
gdcm::Element< TVR, VM::VM1_n >::SetArray
void SetArray(const Type *array, unsigned long len, bool save=false)
Definition gdcmElement.h:621
gdcm::Element< TVR, VM::VM1_n >::operator=
Element & operator=(const Element &_val)
Definition gdcmElement.h:755
gdcm::Element< TVR, VM::VM1_n >::Print
void Print(std::ostream &_os) const
Definition gdcmElement.h:701
gdcm::Element< TVR, VM::VM1_n >::GetLength
unsigned long GetLength() const
Definition gdcmElement.h:596
gdcm::Element< TVR, VM::VM1_n >::GetAsDataElement
DataElement GetAsDataElement() const
Definition gdcmElement.h:724
gdcm::Element< TVR, VM::VM1_n >::SetValue
void SetValue(typename VRToType< TVR >::Type v, unsigned int idx=0)
Definition gdcmElement.h:642
gdcm::Element< TVR, VM::VM1_n >::Type
VRToType< TVR >::Type Type
Definition gdcmElement.h:597
gdcm::Element< TVR, VM::VM1_n >::GetValue
const VRToType< TVR >::Type & GetValue(unsigned int idx=0) const
Definition gdcmElement.h:646
gdcm::Element< TVR, VM::VM1_n >::~Element
~Element()
Definition gdcmElement.h:583
gdcm::Element< TVR, VM::VM1_n >::Write
void Write(std::ostream &_os) const
Definition gdcmElement.h:719
gdcm::Element< TVR, VM::VM1_n >::Element
Element(const Element &_val)
Definition gdcmElement.h:749
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::VM2_n >::SetLength
void SetLength(int len)
Definition gdcmElement.h:809
gdcm::Element< TVR, VM::VM2_n >::Parent
Element< TVR, VM::VM1_n > Parent
Definition gdcmElement.h:808
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< TVR, VM::VM3_n >::Parent
Element< TVR, VM::VM1_n > Parent
Definition gdcmElement.h:830
gdcm::Element< TVR, VM::VM3_n >::SetLength
void SetLength(int len)
Definition gdcmElement.h:831
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::VRBINARY
@ VRBINARY
Definition gdcmVR.h:102
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
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