RNifti
Fast R and C++ Access to NIfTI Images
NiftiImage.h
1 #ifndef _NIFTI_IMAGE_H_
2 #define _NIFTI_IMAGE_H_
3 
4 
5 #ifdef USING_R
6 
7 #include <Rcpp.h>
8 
9 // Defined since R 3.1.0, according to Tomas Kalibera, but there's no reason to break
10 // compatibility with 3.0.x
11 #ifndef MAYBE_SHARED
12 #define MAYBE_SHARED(x) (NAMED(x) > 1)
13 #endif
14 
15 #else
16 
17 #define R_NegInf -INFINITY
18 
19 #include <stdint.h>
20 #include <cstddef>
21 #include <cmath>
22 #include <string>
23 #include <sstream>
24 #include <vector>
25 #include <list>
26 #include <complex>
27 #include <stdexcept>
28 #include <algorithm>
29 #include <map>
30 #include <locale>
31 #include <limits>
32 
33 #endif
34 
43 namespace RNifti {
44 
45 typedef std::complex<float> complex64_t;
46 typedef std::complex<double> complex128_t;
47 
54 struct rgba32_t
55 {
56  union ValueType {
57  int packed;
58  unsigned char bytes[4];
59  };
60  ValueType value;
61  rgba32_t () { value.packed = 0; }
62 };
63 
72 {
73 public:
74  double slope;
75  double intercept;
77 protected:
81  struct TypeHandler
82  {
83  virtual ~TypeHandler() {}
84  virtual size_t size () const { return 0; }
85  virtual bool hasNaN () const { return false; }
86  virtual complex128_t getComplex (void *ptr) const { return complex128_t(0.0, 0.0); }
87  virtual double getDouble (void *ptr) const { return 0.0; }
88  virtual int getInt (void *ptr) const { return 0; }
89  virtual rgba32_t getRgb (void *ptr) const { return rgba32_t(); }
90  virtual void setComplex (void *ptr, const complex128_t value) const {}
91  virtual void setDouble (void *ptr, const double value) const {}
92  virtual void setInt (void *ptr, const int value) const {}
93  virtual void setRgb (void *ptr, const rgba32_t value) const {}
94  virtual void minmax (void *ptr, const size_t length, double *min, double *max) const { *min = 0.0; *max = 0.0; }
95  };
96 
100  template <typename Type, bool alpha = false>
102  {
103  size_t size () const { return (sizeof(Type)); }
104  bool hasNaN () const { return std::numeric_limits<Type>::has_quiet_NaN; }
105  complex128_t getComplex (void *ptr) const { return complex128_t(static_cast<double>(*static_cast<Type*>(ptr)), 0.0); }
106  double getDouble (void *ptr) const { return static_cast<double>(*static_cast<Type*>(ptr)); }
107  int getInt (void *ptr) const { return static_cast<int>(*static_cast<Type*>(ptr)); }
108  void setComplex (void *ptr, const complex128_t value) const
109  {
110  *(static_cast<Type*>(ptr)) = Type(value.real());
111  *(static_cast<Type*>(ptr) + 1) = Type(0);
112  }
113  void setDouble (void *ptr, const double value) const { *(static_cast<Type*>(ptr)) = Type(value); }
114  void setInt (void *ptr, const int value) const { *(static_cast<Type*>(ptr)) = Type(value); }
115  void minmax (void *ptr, const size_t length, double *min, double *max) const;
116  };
117 
118  template <typename ElementType>
119  struct ConcreteTypeHandler<std::complex<ElementType>,false> : public TypeHandler
120  {
121  size_t size () const { return (sizeof(ElementType) * 2); }
122  bool hasNaN () const { return std::numeric_limits<ElementType>::has_quiet_NaN; }
123  std::complex<ElementType> getNative (void *ptr) const
124  {
125  const ElementType real = *static_cast<ElementType*>(ptr);
126  const ElementType imag = *(static_cast<ElementType*>(ptr) + 1);
127  return std::complex<ElementType>(real, imag);
128  }
129  void setNative (void *ptr, const std::complex<ElementType> native) const
130  {
131  *(static_cast<ElementType*>(ptr)) = native.real();
132  *(static_cast<ElementType*>(ptr) + 1) = native.imag();
133  }
134  complex128_t getComplex (void *ptr) const { return complex128_t(getNative(ptr)); }
135  double getDouble (void *ptr) const { return static_cast<double>(getNative(ptr).real()); }
136  int getInt (void *ptr) const { return static_cast<int>(getNative(ptr).real()); }
137  void setComplex (void *ptr, const complex128_t value) const { setNative(ptr, std::complex<ElementType>(value)); }
138  void setDouble (void *ptr, const double value) const { setNative(ptr, std::complex<ElementType>(value, 0.0)); }
139  void setInt (void *ptr, const int value) const { setNative(ptr, std::complex<ElementType>(static_cast<ElementType>(value), 0.0)); }
140  void minmax (void *ptr, const size_t length, double *min, double *max) const;
141  };
142 
143  template <bool alpha>
144  struct ConcreteTypeHandler<rgba32_t,alpha> : public TypeHandler
145  {
146  size_t size () const { return alpha ? 4 : 3; }
147  int getInt (void *ptr) const { return getRgb(ptr).value.packed; }
148  rgba32_t getRgb (void *ptr) const
149  {
150  rgba32_t value;
151  unsigned char *source = static_cast<unsigned char *>(ptr);
152  std::copy(source, source + (alpha ? 4 : 3), value.value.bytes);
153  return value;
154  }
155  void setInt (void *ptr, const int value) const
156  {
157  rgba32_t native;
158  native.value.packed = value;
159  setRgb(ptr, native);
160  }
161  void setRgb (void *ptr, const rgba32_t value) const
162  {
163  unsigned char *target = static_cast<unsigned char *>(ptr);
164  std::copy(value.value.bytes, value.value.bytes + (alpha ? 4 : 3), target);
165  }
166  void minmax (void *ptr, const size_t length, double *min, double *max) const { *min = 0.0; *max = 255.0; }
167  };
168 
175  {
176  if (_datatype == DT_NONE)
177  return NULL;
178 
179  switch (_datatype)
180  {
181  case DT_UINT8: return new ConcreteTypeHandler<uint8_t>(); break;
182  case DT_INT16: return new ConcreteTypeHandler<int16_t>(); break;
183  case DT_INT32: return new ConcreteTypeHandler<int32_t>(); break;
184  case DT_FLOAT32: return new ConcreteTypeHandler<float>(); break;
185  case DT_FLOAT64: return new ConcreteTypeHandler<double>(); break;
186  case DT_INT8: return new ConcreteTypeHandler<int8_t>(); break;
187  case DT_UINT16: return new ConcreteTypeHandler<uint16_t>(); break;
188  case DT_UINT32: return new ConcreteTypeHandler<uint32_t>(); break;
189  case DT_INT64: return new ConcreteTypeHandler<int64_t>(); break;
190  case DT_UINT64: return new ConcreteTypeHandler<uint64_t>(); break;
191  case DT_COMPLEX64: return new ConcreteTypeHandler<complex64_t>(); break;
192  case DT_COMPLEX128: return new ConcreteTypeHandler<complex128_t>(); break;
193  case DT_RGB24: return new ConcreteTypeHandler<rgba32_t,false>(); break;
194  case DT_RGBA32: return new ConcreteTypeHandler<rgba32_t,true>(); break;
195 
196  default:
197  throw std::runtime_error("Unsupported data type (" + std::string(nifti_datatype_string(_datatype)) + ")");
198  }
199  }
200 
201  void *dataPtr;
202  int _datatype;
204  size_t _length;
205  bool owner;
217  void init (void *data, const size_t length, const int datatype, const double slope, const double intercept, const bool alloc = true)
218  {
219  this->_length = length;
220  this->_datatype = datatype;
221  this->slope = slope;
222  this->intercept = intercept;
223 
224  owner = false;
226  if (handler == NULL)
227  dataPtr = NULL;
228  else if (alloc && data == NULL)
229  {
230  dataPtr = calloc(length, handler->size());
231  owner = true;
232  }
233  else
234  dataPtr = data;
235  }
236 
243  void calibrateFrom (const NiftiImageData &data)
244  {
245  slope = 1.0;
246  intercept = 0.0;
247 
248  if (this->isInteger())
249  {
250  double dataMin, dataMax, typeMin, typeMax;
251  data.minmax(&dataMin, &dataMax);
252  handler->minmax(NULL, 0, &typeMin, &typeMax);
253 
254  // If the source type is floating-point but values are in range, we will just round them
255  if (dataMin < typeMin || dataMax > typeMax)
256  {
257  slope = (dataMax - dataMin) / (typeMax - typeMin);
258  intercept = dataMin - (slope) * typeMin;
259  }
260  }
261  }
262 
263 public:
267  struct Element
268  {
269  private:
270  const NiftiImageData &parent;
271  void *ptr;
272 
273  public:
280  Element (const NiftiImageData &parent, void *ptr = NULL)
281  : parent(parent)
282  {
283  this->ptr = (ptr == NULL ? parent.dataPtr : ptr);
284  }
285 
293  template <typename SourceType>
294  Element & operator= (const SourceType &value);
295 
301  Element & operator= (const Element &other);
302 
306  template <typename TargetType>
307  operator TargetType() const
308  {
309  if (parent.isScaled())
310  return TargetType(parent.handler->getDouble(ptr) * parent.slope + parent.intercept);
311  else if (std::numeric_limits<TargetType>::is_integer)
312  return TargetType(parent.handler->getInt(ptr));
313  else
314  return TargetType(parent.handler->getDouble(ptr));
315  }
316 
317  template <typename ElementType>
318  operator std::complex<ElementType>() const
319  {
320  if (parent.isScaled())
321  return std::complex<ElementType>(parent.handler->getComplex(ptr) * parent.slope + complex128_t(parent.intercept, parent.intercept));
322  else
323  return std::complex<ElementType>(parent.handler->getComplex(ptr));
324  }
325 
326 #ifdef USING_R
327 
330  operator Rcomplex() const
331  {
332  const complex128_t value = parent.handler->getComplex(ptr);
333  Rcomplex rValue = { value.real(), value.imag() };
334  if (parent.isScaled())
335  {
336  rValue.r = rValue.r * parent.slope + parent.intercept;
337  rValue.i = rValue.i * parent.slope + parent.intercept;
338  }
339  return rValue;
340  }
341 #endif
342 
343  operator rgba32_t() const
344  {
345  return parent.handler->getRgb(ptr);
346  }
347  };
348 
352  class Iterator : public std::iterator<std::random_access_iterator_tag, Element>
353  {
354  private:
355  const NiftiImageData &parent;
356  void *ptr;
357  size_t step;
358 
359  public:
367  Iterator (const NiftiImageData &parent, void *ptr = NULL, const size_t step = 0)
368  : parent(parent)
369  {
370  this->ptr = (ptr == NULL ? parent.dataPtr : ptr);
371  this->step = (step == 0 ? parent.handler->size() : step);
372  }
373 
378  Iterator (const Iterator &other)
379  : parent(other.parent), ptr(other.ptr), step(other.step) {}
380 
381  Iterator & operator++ () { ptr = static_cast<char*>(ptr) + step; return *this; }
382  Iterator operator++ (int) { Iterator copy(*this); ptr = static_cast<char*>(ptr) + step; return copy; }
383  Iterator operator+ (ptrdiff_t n) const
384  {
385  void *newptr = static_cast<char*>(ptr) + (n * step);
386  return Iterator(parent, newptr, step);
387  }
388  Iterator & operator-- () { ptr = static_cast<char*>(ptr) - step; return *this; }
389  Iterator operator-- (int) { Iterator copy(*this); ptr = static_cast<char*>(ptr) - step; return copy; }
390  Iterator operator- (ptrdiff_t n) const
391  {
392  void *newptr = static_cast<char*>(ptr) - (n * step);
393  return Iterator(parent, newptr, step);
394  }
395 
396  ptrdiff_t operator- (const Iterator &other) const
397  {
398  const ptrdiff_t difference = static_cast<char*>(ptr) - static_cast<char*>(other.ptr);
399  return difference / step;
400  }
401 
402  bool operator== (const Iterator &other) const { return (ptr==other.ptr && step==other.step); }
403  bool operator!= (const Iterator &other) const { return (ptr!=other.ptr || step!=other.step); }
404  bool operator> (const Iterator &other) const { return (ptr > other.ptr); }
405  bool operator< (const Iterator &other) const { return (ptr < other.ptr); }
406 
407  const Element operator* () const { return Element(parent, ptr); }
408  Element operator* () { return Element(parent, ptr); }
409  const Element operator[] (const size_t i) const { return Element(parent, static_cast<char*>(ptr) + (i * step)); }
410  Element operator[] (const size_t i) { return Element(parent, static_cast<char*>(ptr) + (i * step)); }
411  };
412 
417  : slope(1.0), intercept(0.0), dataPtr(NULL), _datatype(DT_NONE), handler(NULL), _length(0), owner(false) {}
418 
428  NiftiImageData (void *data, const size_t length, const int datatype, const double slope = 1.0, const double intercept = 0.0)
429  {
430  init(data, length, datatype, slope, intercept);
431  }
432 
437  NiftiImageData (nifti_image *image)
438  {
439  if (image == NULL)
440  init(NULL, 0, DT_NONE, 0.0, 0.0, false);
441  else
442  init(image->data, image->nvox, image->datatype, static_cast<double>(image->scl_slope), static_cast<double>(image->scl_inter), false);
443  }
444 
452  NiftiImageData (const NiftiImageData &source, const int datatype = DT_NONE)
453  {
454  init(NULL, source.length(), datatype == DT_NONE ? source.datatype() : datatype, source.slope, source.intercept);
455 
456  if (datatype == DT_NONE || datatype == source.datatype())
457  memcpy(dataPtr, source.dataPtr, source.totalBytes());
458  else
459  {
460  calibrateFrom(source);
461  std::copy(source.begin(), source.end(), this->begin());
462  }
463  }
464 
471  template <class InputIterator>
472  NiftiImageData (InputIterator from, InputIterator to, const int datatype)
473  {
474  const size_t length = static_cast<size_t>(std::distance(from, to));
475  init(NULL, length, datatype, 1.0, 0.0);
476  std::copy(from, to, this->begin());
477  }
478 
482  virtual ~NiftiImageData ()
483  {
484  delete handler;
485  if (owner)
486  free(dataPtr);
487  }
488 
495  {
496  if (source.dataPtr != NULL)
497  {
498  // Free the old data, if we allocated it
499  if (owner)
500  free(dataPtr);
501  init(NULL, source.length(), source.datatype(), source.slope, source.intercept);
502  memcpy(dataPtr, source.dataPtr, source.totalBytes());
503  }
504  return *this;
505  }
506 
507  void * blob () const { return dataPtr; }
508  int datatype () const { return _datatype; }
509  size_t length () const { return _length; }
510  size_t size () const { return _length; }
513  size_t bytesPerPixel () const { return (handler == NULL ? 0 : handler->size()); }
514 
516  size_t totalBytes () const { return _length * bytesPerPixel(); }
517 
522  bool isEmpty () const { return (dataPtr == NULL); }
523 
529  bool isScaled () const { return (slope != 0.0 && (slope != 1.0 || intercept != 0.0)); }
530 
535  bool isComplex () const { return (_datatype == DT_COMPLEX64 || _datatype == DT_COMPLEX128); }
536 
542  bool isFloatingPoint () const { return (_datatype == DT_FLOAT32 || _datatype == DT_FLOAT64); }
543 
548  bool isInteger () const { return nifti_is_inttype(_datatype); }
549 
554  bool isRgb () const { return (_datatype == DT_RGB24 || _datatype == DT_RGBA32); }
555 
561 
566  NiftiImageData & disown () { this->owner = false; return *this; }
567 
569  const Iterator begin () const { return Iterator(*this); }
570 
572  const Iterator end () const { return Iterator(*this, static_cast<char*>(dataPtr) + totalBytes()); }
573 
575  Iterator begin () { return Iterator(*this); }
576 
578  Iterator end () { return Iterator(*this, static_cast<char*>(dataPtr) + totalBytes()); }
579 
585  const Element operator[] (const size_t i) const { return Element(*this, static_cast<char*>(dataPtr) + (i * bytesPerPixel())); }
586 
592  Element operator[] (const size_t i) { return Element(*this, static_cast<char*>(dataPtr) + (i * bytesPerPixel())); }
593 
601  void minmax (double *min, double *max) const
602  {
603  if (handler == NULL)
604  {
605  *min = 0.0;
606  *max = 0.0;
607  }
608  else
609  handler->minmax(dataPtr, _length, min, max);
610  }
611 };
612 
613 
614 // R provides an NaN (NA) value for integers
615 #ifdef USING_R
616 template <>
617 inline bool NiftiImageData::ConcreteTypeHandler<int>::hasNaN () const { return true; }
618 #endif
619 
620 
625 template <typename ElementType, int Length>
626 class Vector
627 {
628 protected:
629  ElementType elements[Length];
630 
631 public:
635  Vector (const ElementType value = 0.0)
636  {
637  std::fill(elements, elements + Length, value);
638  }
639 
643  Vector (const ElementType * source)
644  {
645  std::copy(source, source + Length, this->elements);
646  }
647 
652  {
654  for (int i=0; i<Length; i++)
655  result.elements[i] = -elements[i];
656  return result;
657  }
658 
659  const ElementType & operator[] (const size_t i) const { return elements[i]; }
660 
661  ElementType & operator[] (const size_t i) { return elements[i]; }
662 };
663 
664 
671 template <class NiftiType, typename ElementType, int Order>
673 {
674 protected:
675  ElementType elements[Order*Order];
681  NiftiType * niftiPointer () const { return (NiftiType *) elements; }
682 
686  NiftiType niftiCopy () const
687  {
688  NiftiType value;
689  std::copy(elements, elements + Order*Order, *value.m);
690  return value;
691  }
692 
693 public:
694  typedef NiftiType NativeType;
701  SquareMatrix (const ElementType value = 0.0)
702  {
703  std::fill(elements, elements + Order*Order, value);
704  }
705 
709  SquareMatrix (const ElementType * source)
710  {
711  std::copy(source, source + Order*Order, this->elements);
712  }
713 
717  SquareMatrix (const NiftiType &source)
718  {
719  const ElementType *castSource = (const ElementType *) *source.m;
720  std::copy(castSource, castSource + Order*Order, this->elements);
721  }
722 
723 #ifdef USING_R
724 
727  SquareMatrix (SEXP source)
728  {
729  Rcpp::NumericMatrix matrix(source);
730  if (matrix.cols() != Order && matrix.rows() != Order)
731  throw std::runtime_error("Matrix does not have the expected dimensions");
732  for (int i=0; i<Order; i++)
733  {
734  for (int j=0; j<Order; j++)
735  elements[j + i*Order] = matrix(i,j);
736  }
737  }
738 #endif
739 
744  operator const NiftiType () const { return niftiCopy(); }
745 
750  operator NiftiType () { return niftiCopy(); }
751 
756  const ElementType * begin () const { return elements; }
757 
762  ElementType * begin () { return elements; }
763 
767  const ElementType * end () const { return elements + Order*Order; }
768 
772  ElementType * end () { return elements + Order*Order; }
773 
777  static MatrixType eye ()
778  {
779  MatrixType matrix;
780  for (int i=0; i<Order; i++)
781  matrix.elements[i + i*Order] = 1.0;
782  return matrix;
783  }
784 
785  MatrixType inverse () const;
786  MatrixType polar () const;
787  ElementType colnorm () const;
788  ElementType rownorm () const;
789  ElementType determ () const;
790  MatrixType multiply (const MatrixType &other) const;
791  VectorType multiply (const VectorType &vec) const;
793  MatrixType operator* (const MatrixType &other) const { return multiply(other); }
794  VectorType operator* (const VectorType &vec) const { return multiply(vec); }
799  const ElementType & operator() (const int i, const int j) const { return elements[j + i*Order]; }
800 
804  ElementType & operator() (const int i, const int j) { return elements[j + i*Order]; }
805 
806 #ifdef USING_R
807 
810  operator SEXP () const
811  {
812  Rcpp::NumericMatrix result(Order, Order);
813  for (int i=0; i<Order; i++)
814  {
815  for (int j=0; j<Order; j++)
816  result(i,j) = elements[j + i*Order];
817  }
818  return result;
819  }
820 #endif
821 };
822 
823 
824 // Include matrix implementations
825 #include "RNifti/NiftiImage_matrix.h"
826 
827 
835 {
836 public:
837 #if RNIFTI_NIFTILIB_VERSION == 1
838  typedef int dim_t;
839  typedef float pixdim_t;
840  typedef float scale_t;
841 #elif RNIFTI_NIFTILIB_VERSION == 2
842  typedef int64_t dim_t;
843  typedef double pixdim_t;
844  typedef double scale_t;
845 #endif
846 
851  struct Block
852  {
853  const NiftiImage &image;
854  const int dimension;
855  const dim_t index;
864  Block (const NiftiImage &image, const int dimension, const dim_t index)
866  {
867  if (dimension != image->ndim)
868  throw std::runtime_error("Blocks must be along the last dimension in the image");
869  }
870 
879  Block & operator= (const NiftiImage &source)
880  {
881  if (source->datatype != image->datatype)
882  throw std::runtime_error("New data does not have the same datatype as the target block");
883  if (source->scl_slope != image->scl_slope || source->scl_inter != image->scl_inter)
884  throw std::runtime_error("New data does not have the same scale parameters as the target block");
885 
886  size_t blockSize = 1;
887  for (int i=1; i<dimension; i++)
888  blockSize *= image->dim[i];
889 
890  if (blockSize != source->nvox)
891  throw std::runtime_error("New data does not have the same size as the target block");
892 
893  blockSize *= image->nbyper;
894  memcpy(static_cast<char*>(image->data) + blockSize*index, source->data, blockSize);
895  return *this;
896  }
897 
903  {
904  if (image.isNull())
905  return NiftiImageData();
906  else
907  {
908  size_t blockSize = 1;
909  for (int i=1; i<dimension; i++)
910  blockSize *= image->dim[i];
911  return NiftiImageData(static_cast<char*>(image->data) + blockSize * index * image->nbyper, blockSize, image->datatype, static_cast<double>(image->scl_slope), static_cast<double>(image->scl_inter));
912  }
913  }
914 
922  template <typename TargetType>
923  std::vector<TargetType> getData (const bool useSlope = true) const;
924  };
925 
930  class Extension
931  {
932  protected:
933  nifti1_extension *ext;
939  void copy (const nifti1_extension *source);
940 
947  template <typename SourceType>
948  void copy (const SourceType *data, const size_t length, const int code);
949 
950  public:
955  : ext(NULL) {}
956 
964  Extension (nifti1_extension * const extension, const bool copy = false)
965  {
966  if (!copy || extension == NULL)
967  this->ext = extension;
968  else
969  this->copy(extension);
970  }
971 
976  Extension (const Extension &source)
977  {
978  copy(source.ext);
979  }
980 
987  template <typename SourceType>
988  Extension (const SourceType *data, const size_t length, const int code)
989  {
990  copy(data, length, code);
991  }
992 
993 #ifdef USING_R
994 
1001  Extension (SEXP source, int code = -1)
1002  {
1003  const Rcpp::RObject object(source);
1004  if (code == -1 && object.hasAttribute("code"))
1005  code = Rcpp::as<int>(object.attr("code"));
1006 
1007  switch (object.sexp_type())
1008  {
1009  case RAWSXP: copy(RAW(source), Rf_length(source), code); break;
1010  case REALSXP: copy(REAL(source), Rf_length(source), code); break;
1011  case CPLXSXP: copy(COMPLEX(source), Rf_length(source), code); break;
1012  case INTSXP: copy(INTEGER(source), Rf_length(source), code); break;
1013  case LGLSXP: copy(LOGICAL(source), Rf_length(source), code); break;
1014  case STRSXP:
1015  {
1016  if (Rf_length(source) > 1)
1017  Rf_warning("Character vector elements after the first will not be stored in a NIfTI extension");
1018  const char *string = CHAR(STRING_ELT(source, 0));
1019  copy(string, strlen(string), code);
1020  break;
1021  }
1022  default: Rf_error("Unable to convert SEXP type %d to NIfTI extension", object.sexp_type());
1023  }
1024  }
1025 #endif
1026 
1031  int code () const { return (ext == NULL ? -1 : ext->ecode); }
1032 
1037  const char * data () const { return (ext == NULL ? NULL : ext->edata); }
1038 
1043  size_t length () const { return (ext == NULL || ext->esize < 8 ? 0 : size_t(ext->esize - 8)); }
1044 
1049  size_t size () const { return (ext == NULL || ext->esize < 8 ? 0 : size_t(ext->esize - 8)); }
1050 
1051 #ifdef USING_R
1052 
1055  operator SEXP () const
1056  {
1057  if (ext == NULL || ext->esize < 8)
1058  return R_NilValue;
1059 
1060  const int length = ext->esize - 8;
1061  Rcpp::RawVector result(length);
1062  const Rbyte *source = (const Rbyte *) ext->edata;
1063  std::copy(source, source+length, result.begin());
1064  result.attr("code") = ext->ecode;
1065  return result;
1066  }
1067 #endif
1068  };
1069 
1076  class Xform
1077  {
1078  public:
1079 #if RNIFTI_NIFTILIB_VERSION == 1
1080  typedef float Element;
1081  typedef Vector<float,4> Vector4;
1082  typedef Vector<float,3> Vector3;
1083  typedef SquareMatrix<mat44,float,4> Matrix;
1084  typedef SquareMatrix<mat33,float,3> Submatrix;
1085 #elif RNIFTI_NIFTILIB_VERSION == 2
1086  typedef double Element;
1087  typedef Vector<double,4> Vector4;
1088  typedef Vector<double,3> Vector3;
1089  typedef SquareMatrix<nifti_dmat44,double,4> Matrix;
1090  typedef SquareMatrix<nifti_dmat33,double,3> Submatrix;
1091 #endif
1092 
1093  protected:
1094  Element *forward, *inverse, *qparams;
1095  Matrix mat;
1101  void replace (const Matrix &source);
1102 
1103  public:
1108  : forward(NULL), inverse(NULL), qparams(NULL), mat() {}
1109 
1113  Xform (const Matrix &source)
1114  : forward(NULL), inverse(NULL), qparams(NULL), mat(source) {}
1115 
1119  Xform (const Matrix::NativeType &source)
1120  : forward(NULL), inverse(NULL), qparams(NULL), mat(source) {}
1121 
1126  Xform (Matrix::NativeType &source)
1127  : forward(*source.m), inverse(NULL), qparams(NULL), mat(source) {}
1128 
1133  Xform (Matrix::NativeType &source, Matrix::NativeType &inverse, Element *qparams = NULL)
1134  : forward(*source.m), inverse(*inverse.m), qparams(qparams), mat(source) {}
1135 
1136 #ifdef USING_R
1137 
1140  Xform (SEXP source)
1141  : forward(NULL), inverse(NULL), qparams(NULL), mat(Matrix(source)) {}
1142 #endif
1143 
1148  operator const Matrix::NativeType () const { return mat; }
1149 
1154  operator Matrix::NativeType () { return mat; }
1155 
1159  Xform & operator= (const Xform &source)
1160  {
1161  replace(source.mat);
1162  return *this;
1163  }
1164 
1168  Xform & operator= (const Matrix &source)
1169  {
1170  replace(source);
1171  return *this;
1172  }
1173 
1177  const Matrix & matrix () const { return mat; }
1178 
1182  Submatrix submatrix () const;
1183 
1188  Submatrix rotation () const;
1189 
1195  Element handedness () const;
1196 
1200  Vector4 quaternion () const;
1201 
1205  Vector3 offset () const;
1206 
1210  Vector3 spacing () const;
1211 
1219  std::string orientation () const;
1220  };
1221 
1222 #ifdef USING_R
1223 
1229  static int sexpTypeToNiftiType (const int sexpType)
1230  {
1231  if (sexpType == INTSXP || sexpType == LGLSXP)
1232  return DT_INT32;
1233  else if (sexpType == REALSXP)
1234  return DT_FLOAT64;
1235  else if (sexpType == CPLXSXP)
1236  return DT_COMPLEX128;
1237  else
1238  throw std::runtime_error("Array elements must be numeric");
1239  }
1240 #endif
1241 
1248  static int fileVersion (const std::string &path);
1249 
1250 
1251 protected:
1252  nifti_image *image;
1253  int *refCount;
1261  void acquire (nifti_image * const image);
1262 
1267  void acquire (const NiftiImage &source)
1268  {
1269  refCount = source.refCount;
1270  acquire(source.image);
1271  }
1272 
1277  void release ();
1278 
1283  void copy (const nifti_image *source);
1284 
1289  void copy (const NiftiImage &source);
1290 
1295  void copy (const Block &source);
1296 
1297 
1298 #ifdef USING_R
1299 
1305  void initFromNiftiS4 (const Rcpp::RObject &object, const bool copyData = true);
1306 
1312  void initFromMriImage (const Rcpp::RObject &object, const bool copyData = true);
1313 
1318  void initFromList (const Rcpp::RObject &object);
1319 
1325  void initFromArray (const Rcpp::RObject &object, const bool copyData = true);
1326 
1327 #endif
1328 
1334  void initFromDims (const std::vector<dim_t> &dim, const int datatype);
1335 
1340  void updatePixdim (const std::vector<pixdim_t> &pixdim);
1341 
1346  void setPixunits (const std::vector<std::string> &pixunits);
1347 
1348 public:
1353  : image(NULL), refCount(NULL) {}
1354 
1361  NiftiImage (const NiftiImage &source, const bool copy = true)
1362  : image(NULL), refCount(NULL)
1363  {
1364  if (copy)
1365  this->copy(source);
1366  else
1367  acquire(source);
1368 #ifndef NDEBUG
1369  Rc_printf("Creating NiftiImage (v%d) with pointer %p (from NiftiImage)\n", RNIFTI_NIFTILIB_VERSION, this->image);
1370 #endif
1371  }
1372 
1377  NiftiImage (const Block &source)
1378  : image(NULL), refCount(NULL)
1379  {
1380  this->copy(source);
1381 #ifndef NDEBUG
1382  Rc_printf("Creating NiftiImage (v%d) with pointer %p (from Block)\n", RNIFTI_NIFTILIB_VERSION, this->image);
1383 #endif
1384  }
1385 
1392  NiftiImage (nifti_image * const image, const bool copy = false)
1393  : image(NULL), refCount(NULL)
1394  {
1395  if (copy)
1396  this->copy(image);
1397  else
1398  acquire(image);
1399 #ifndef NDEBUG
1400  Rc_printf("Creating NiftiImage (v%d) with pointer %p (from pointer)\n", RNIFTI_NIFTILIB_VERSION, this->image);
1401 #endif
1402  }
1403 
1409  NiftiImage (const std::vector<dim_t> &dim, const int datatype);
1410 
1416  NiftiImage (const std::vector<dim_t> &dim, const std::string &datatype);
1417 
1424  NiftiImage (const std::string &path, const bool readData = true);
1425 
1432  NiftiImage (const std::string &path, const std::vector<dim_t> &volumes);
1433 
1434 #ifdef USING_R
1435 
1445  NiftiImage (const SEXP object, const bool readData = true, const bool readOnly = false);
1446 #endif
1447 
1452  virtual ~NiftiImage () { release(); }
1453 
1457  operator const nifti_image* () const { return image; }
1458 
1462  operator nifti_image* () { return image; }
1463 
1467  const nifti_image * operator-> () const { return image; }
1468 
1472  nifti_image * operator-> () { return image; }
1473 
1479  {
1480  copy(source);
1481 #ifndef NDEBUG
1482  Rc_printf("Creating NiftiImage (v%d), with pointer %p (from NiftiImage)\n", RNIFTI_NIFTILIB_VERSION, this->image);
1483 #endif
1484  return *this;
1485  }
1486 
1492  NiftiImage & operator= (const Block &source)
1493  {
1494  copy(source);
1495 #ifndef NDEBUG
1496  Rc_printf("Creating NiftiImage (v%d) with pointer %p (from Block)\n", RNIFTI_NIFTILIB_VERSION, this->image);
1497 #endif
1498  return *this;
1499  }
1500 
1508  NiftiImage & setPersistence (const bool persistent) { return *this; }
1509 
1514  bool isNull () const { return (image == NULL); }
1515 
1520  bool isShared () const { return (refCount != NULL && *refCount > 1); }
1521 
1528  bool isPersistent () const { return false; }
1529 
1535  bool isDataScaled () const { return (image != NULL && image->scl_slope != 0.0 && (image->scl_slope != 1.0 || image->scl_inter != 0.0)); }
1536 
1541  int nDims () const
1542  {
1543  if (image == NULL)
1544  return 0;
1545  else
1546  return image->ndim;
1547  }
1548 
1553  std::vector<dim_t> dim () const
1554  {
1555  if (image == NULL)
1556  return std::vector<dim_t>();
1557  else
1558  return std::vector<dim_t>(image->dim+1, image->dim+image->ndim+1);
1559  }
1560 
1565  std::vector<pixdim_t> pixdim () const
1566  {
1567  if (image == NULL)
1568  return std::vector<pixdim_t>();
1569  else
1570  return std::vector<pixdim_t>(image->pixdim+1, image->pixdim+image->ndim+1);
1571  }
1572 
1580  {
1581  int ndim = image->ndim;
1582  while (image->dim[ndim] < 2)
1583  ndim--;
1584  image->dim[0] = image->ndim = ndim;
1585 
1586  return *this;
1587  }
1588 
1593  const NiftiImageData data () const { return NiftiImageData(image); }
1594 
1600 
1610  template <typename TargetType>
1611  std::vector<TargetType> getData (const bool useSlope = true) const;
1612 
1620  NiftiImage & changeDatatype (const int datatype, const bool useSlope = false);
1621 
1629  NiftiImage & changeDatatype (const std::string &datatype, const bool useSlope = false);
1630 
1639  template <typename SourceType>
1640  NiftiImage & replaceData (const std::vector<SourceType> &data, const int datatype = DT_NONE);
1641 
1649 
1656  {
1657 #if RNIFTI_NIFTILIB_VERSION == 1
1658  nifti_image_unload(image);
1659 #elif RNIFTI_NIFTILIB_VERSION == 2
1660  nifti2_image_unload(image);
1661 #endif
1662  return *this;
1663  }
1664 
1671  NiftiImage & rescale (const std::vector<pixdim_t> &scales);
1672 
1681  NiftiImage & reorient (const int i, const int j, const int k);
1682 
1691  NiftiImage & reorient (const std::string &orientation);
1692 
1693 #ifdef USING_R
1694 
1699  NiftiImage & update (const Rcpp::RObject &object);
1700 #endif
1701 
1708  const Xform xform (const bool preferQuaternion = true) const;
1709 
1714  const Xform qform () const { return (image == NULL ? Xform() : Xform(image->qto_xyz)); }
1715 
1720  Xform qform () { return (image == NULL ? Xform() : Xform(image->qto_xyz, image->qto_ijk, &image->quatern_b)); }
1721 
1726  const Xform sform () const { return (image == NULL ? Xform() : Xform(image->sto_xyz)); }
1727 
1732  Xform sform () { return (image == NULL ? Xform() : Xform(image->sto_xyz, image->sto_ijk)); }
1733 
1738  dim_t nBlocks () const { return (image == NULL ? 0 : image->dim[image->ndim]); }
1739 
1747  const Block block (const int i) const { return Block(*this, nDims(), i); }
1748 
1756  Block block (const int i) { return Block(*this, nDims(), i); }
1757 
1763  const Block slice (const int i) const { return Block(*this, 3, i); }
1764 
1770  Block slice (const int i) { return Block(*this, 3, i); }
1771 
1777  const Block volume (const int i) const { return Block(*this, 4, i); }
1778 
1784  Block volume (const int i) { return Block(*this, 4, i); }
1785 
1791  int nChannels () const
1792  {
1793  if (image == NULL)
1794  return 0;
1795  else
1796  {
1797  switch (image->datatype)
1798  {
1799  case DT_NONE: return 0;
1800  case DT_RGB24: return 3;
1801  case DT_RGBA32: return 4;
1802  default: return 1;
1803  }
1804  }
1805  }
1806 
1811  size_t nVoxels () const { return (image == NULL ? 0 : image->nvox); }
1812 
1817  int nExtensions () const { return (image == NULL ? 0 : image->num_ext); }
1818 
1825  std::list<Extension> extensions (const int code = -1) const
1826  {
1827  if (image == NULL)
1828  return std::list<Extension>();
1829  else
1830  {
1831  std::list<Extension> result;
1832  for (int i=0; i<image->num_ext; i++)
1833  {
1834  const Extension extension(image->ext_list + i);
1835  if (code < 0 || code == extension.code())
1836  result.push_back(extension);
1837  }
1838  return result;
1839  }
1840  }
1841 
1847  NiftiImage & addExtension (const Extension &extension)
1848  {
1849  if (image != NULL)
1850 #if RNIFTI_NIFTILIB_VERSION == 1
1851  nifti_add_extension(image, extension.data(), int(extension.length()), extension.code());
1852 #elif RNIFTI_NIFTILIB_VERSION == 2
1853  nifti2_add_extension(image, extension.data(), int(extension.length()), extension.code());
1854 #endif
1855  return *this;
1856  }
1857 
1863  NiftiImage & replaceExtensions (const std::list<Extension> extensions)
1864  {
1865  dropExtensions();
1866  for (std::list<Extension>::const_iterator it=extensions.begin(); it!=extensions.end(); ++it)
1867  addExtension(*it);
1868  return *this;
1869  }
1870 
1876  {
1877  if (image != NULL)
1878 #if RNIFTI_NIFTILIB_VERSION == 1
1879  nifti_free_extensions(image);
1880 #elif RNIFTI_NIFTILIB_VERSION == 2
1881  nifti2_free_extensions(image);
1882 #endif
1883  return *this;
1884  }
1885 
1894  std::pair<std::string,std::string> toFile (const std::string fileName, const int datatype = DT_NONE, const int filetype = -1) const;
1895 
1904  std::pair<std::string,std::string> toFile (const std::string fileName, const std::string &datatype, const int filetype = -1) const;
1905 
1906 #ifdef USING_R
1907 
1912  Rcpp::RObject toArray () const;
1913 
1919  Rcpp::RObject toPointer (const std::string label) const;
1920 
1927  Rcpp::RObject toArrayOrPointer (const bool internal, const std::string label) const;
1928 
1929 #endif
1930 
1931 };
1932 
1933 // Include image implementations
1934 #include "RNifti/NiftiImage_impl.h"
1935 
1936 } // main namespace
1937 
1938 #endif
RNifti::NiftiImage::sform
const Xform sform() const
Access the sform matrix.
Definition: NiftiImage.h:1726
RNifti::NiftiImage::Xform::quaternion
Vector4 quaternion() const
Obtain the quaternion representation of the xform's rotation component.
RNifti::SquareMatrix::operator*
MatrixType operator*(const MatrixType &other) const
Matrix-matrix multiplication (infix shorthand)
Definition: NiftiImage.h:793
RNifti::NiftiImage::NiftiImage
NiftiImage(const std::string &path, const std::vector< dim_t > &volumes)
Initialise using a path string and sequence of required volumes.
RNifti::NiftiImage::Xform::orientation
std::string orientation() const
Obtain the approximate orientation of the image's coordinate frame, as a three-character string consi...
RNifti::NiftiImage::rescale
NiftiImage & rescale(const std::vector< pixdim_t > &scales)
Rescale the image, changing its image dimensions and pixel dimensions.
RNifti::NiftiImage::release
void release()
Release the currently wrapped pointer, if it is not NULL, decrementing the reference count and releas...
RNifti::NiftiImageData::isScaled
bool isScaled() const
Determine whether the object uses data scaling.
Definition: NiftiImage.h:529
RNifti::NiftiImage::Block
Inner class referring to a subset of an image.
Definition: NiftiImage.h:852
RNifti::NiftiImage::NiftiImage
NiftiImage(const Block &source)
Initialise from a block, copying in the data.
Definition: NiftiImage.h:1377
RNifti::NiftiImage::toFile
std::pair< std::string, std::string > toFile(const std::string fileName, const std::string &datatype, const int filetype=-1) const
Write the image to a NIfTI-1 file.
RNifti::SquareMatrix::colnorm
ElementType colnorm() const
Maximum column norm, as implemented in niftilib (Order 3 only)
RNifti::NiftiImage::dim
std::vector< dim_t > dim() const
Return the dimensions of the image.
Definition: NiftiImage.h:1553
RNifti::NiftiImageData::isComplex
bool isComplex() const
Determine whether the datatype is complex.
Definition: NiftiImage.h:535
RNifti::NiftiImageData::operator=
NiftiImageData & operator=(const NiftiImageData &source)
Copy assignment operator.
Definition: NiftiImage.h:494
RNifti::NiftiImage::image
nifti_image * image
The wrapped nifti_image pointer.
Definition: NiftiImage.h:1252
RNifti::SquareMatrix::SquareMatrix
SquareMatrix(const ElementType *source)
Initialise from a C-style array of the appropriate type and length.
Definition: NiftiImage.h:709
RNifti::NiftiImageData::Iterator
Iterator type for NiftiImageData, with Element as its value type.
Definition: NiftiImage.h:353
RNifti::NiftiImage::Extension::data
const char * data() const
Return the data blob associated with the extension.
Definition: NiftiImage.h:1037
RNifti::NiftiImage::Extension::size
size_t size() const
Return the length of the data array.
Definition: NiftiImage.h:1049
RNifti::SquareMatrix::operator()
const ElementType & operator()(const int i, const int j) const
Indexing operator.
Definition: NiftiImage.h:799
RNifti::SquareMatrix::SquareMatrix
SquareMatrix(SEXP source)
Initialise from an R object representing a numeric matrix.
Definition: NiftiImage.h:727
RNifti::NiftiImage::qform
Xform qform()
Access the qform matrix.
Definition: NiftiImage.h:1720
RNifti::NiftiImage::block
Block block(const int i)
Extract a block from the image.
Definition: NiftiImage.h:1756
RNifti::NiftiImage::volume
const Block volume(const int i) const
Extract a volume block from a 4D image.
Definition: NiftiImage.h:1777
RNifti::NiftiImage::dropData
NiftiImage & dropData()
Drop the data from the image, retaining only the metadata.
Definition: NiftiImage.h:1655
RNifti::NiftiImage::refCount
int * refCount
A reference counter, shared with other objects wrapping the same pointer.
Definition: NiftiImage.h:1253
RNifti::NiftiImage::Extension::Extension
Extension(const Extension &source)
Copy constructor.
Definition: NiftiImage.h:976
RNifti::NiftiImageData::Element::Element
Element(const NiftiImageData &parent, void *ptr=NULL)
Primary constructor.
Definition: NiftiImage.h:280
RNifti::NiftiImage::operator=
NiftiImage & operator=(const NiftiImage &source)
Copy assignment operator, which copies from its argument.
Definition: NiftiImage.h:1478
RNifti::NiftiImage::NiftiImage
NiftiImage(const std::string &path, const bool readData=true)
Initialise using a path string.
RNifti::NiftiImage::NiftiImage
NiftiImage(const NiftiImage &source, const bool copy=true)
Copy constructor.
Definition: NiftiImage.h:1361
RNifti::NiftiImage::changeDatatype
NiftiImage & changeDatatype(const int datatype, const bool useSlope=false)
Change the datatype of the image, casting the pixel data if present.
RNifti::NiftiImage::Xform
Inner class representing an xform matrix, which indicates the orientation and other spatial propertie...
Definition: NiftiImage.h:1077
RNifti::NiftiImageData::NiftiImageData
NiftiImageData(void *data, const size_t length, const int datatype, const double slope=1.0, const double intercept=0.0)
Primary constructor.
Definition: NiftiImage.h:428
RNifti::NiftiImage::updatePixdim
void updatePixdim(const std::vector< pixdim_t > &pixdim)
Modify the pixel dimensions, and potentially the xform matrices to match.
RNifti::NiftiImageData::TypeHandler
Abstract inner class defining the type-specific functions required in concrete subclasses.
Definition: NiftiImage.h:82
RNifti::NiftiImageData::end
const Iterator end() const
Obtain a constant iterator corresponding to the end of the blob.
Definition: NiftiImage.h:572
RNifti::Vector::operator-
Vector< ElementType, Length > operator-() const
Unary negation operator, which reverses the signs of all elements.
Definition: NiftiImage.h:651
RNifti::NiftiImage
Thin wrapper around a C-style nifti_image struct that allows C++-style destruction.
Definition: NiftiImage.h:835
RNifti::rgba32_t
Simple RGB(A) type encapsulating an 8-bit colour value with optional opacity, which can also be set o...
Definition: NiftiImage.h:55
RNifti::NiftiImage::Xform::Xform
Xform(const Matrix::NativeType &source)
Initialise from a constant NIfTI mat44 or dmat44.
Definition: NiftiImage.h:1119
RNifti::NiftiImageData::NiftiImageData
NiftiImageData(InputIterator from, InputIterator to, const int datatype)
Iterator-based constructor.
Definition: NiftiImage.h:472
RNifti::NiftiImageData::isFloatingPoint
bool isFloatingPoint() const
Determine whether the datatype is floating point.
Definition: NiftiImage.h:542
RNifti::SquareMatrix::multiply
VectorType multiply(const VectorType &vec) const
Matrix-vector multiplication.
RNifti::NiftiImage::Xform::mat
Matrix mat
The full xform matrix underpinning this object.
Definition: NiftiImage.h:1095
RNifti::NiftiImage::Extension::Extension
Extension(const SourceType *data, const size_t length, const int code)
Construct the object from its constituent parts.
Definition: NiftiImage.h:988
RNifti::NiftiImageData::size
size_t size() const
Return the number of elements in the data.
Definition: NiftiImage.h:510
RNifti::SquareMatrix::polar
MatrixType polar() const
Polar decomposition, as implemented in niftilib (Order 3 only)
RNifti::NiftiImage::isNull
bool isNull() const
Determine whether or not the wrapped pointer is NULL.
Definition: NiftiImage.h:1514
RNifti::NiftiImage::copy
void copy(const nifti_image *source)
Copy the contents of a nifti_image to create a new image, acquiring the new pointer.
RNifti::NiftiImage::setPixunits
void setPixunits(const std::vector< std::string > &pixunits)
Modify the pixel dimension units.
RNifti::NiftiImage::Extension::Extension
Extension(SEXP source, int code=-1)
Construct the object from an atomic R object, copying the data into a new extension.
Definition: NiftiImage.h:1001
RNifti::SquareMatrix::SquareMatrix
SquareMatrix(const NiftiType &source)
Initialise from the appropriate niftilib type.
Definition: NiftiImage.h:717
RNifti::NiftiImage::replaceData
NiftiImage & replaceData(const std::vector< SourceType > &data, const int datatype=DT_NONE)
Replace the pixel data in the image with the contents of a vector.
RNifti::NiftiImageData::length
size_t length() const
Return the number of elements in the data.
Definition: NiftiImage.h:509
RNifti::NiftiImageData::slope
double slope
The slope term used to scale data values.
Definition: NiftiImage.h:74
RNifti::NiftiImage::Xform::offset
Vector3 offset() const
Obtain the translation component of the xform matrix.
RNifti::NiftiImage::slice
Block slice(const int i)
Extract a slice block from a 3D image.
Definition: NiftiImage.h:1770
RNifti::NiftiImage::toPointer
Rcpp::RObject toPointer(const std::string label) const
Create an internal image to pass back to R.
RNifti::NiftiImageData::operator[]
const Element operator[](const size_t i) const
Indexing operator, returning a constant element.
Definition: NiftiImage.h:585
RNifti::SquareMatrix::eye
static MatrixType eye()
Construct an identity matrix of the appropriate size.
Definition: NiftiImage.h:777
RNifti::NiftiImage::acquire
void acquire(const NiftiImage &source)
Acquire the same pointer as another NiftiImage, incrementing the shared reference count.
Definition: NiftiImage.h:1267
RNifti::NiftiImageData::NiftiImageData
NiftiImageData(const NiftiImageData &source, const int datatype=DT_NONE)
Copy constructor with optional type conversion.
Definition: NiftiImage.h:452
RNifti::NiftiImage::isShared
bool isShared() const
Determine whether the wrapped pointer is shared with another NiftiImage.
Definition: NiftiImage.h:1520
RNifti::NiftiImage::Xform::submatrix
Submatrix submatrix() const
Obtain the upper left 3x3 submatrix from the xform matrix.
RNifti::NiftiImageData::intercept
double intercept
The intercept term used to scale data values.
Definition: NiftiImage.h:75
RNifti::NiftiImage::nBlocks
dim_t nBlocks() const
Return the number of blocks in the image.
Definition: NiftiImage.h:1738
RNifti::NiftiImageData::end
Iterator end()
Obtain a mutable iterator corresponding to the end of the blob.
Definition: NiftiImage.h:578
RNifti::NiftiImage::toArrayOrPointer
Rcpp::RObject toArrayOrPointer(const bool internal, const std::string label) const
A conditional method that calls either toArray or toPointer.
RNifti::NiftiImage::toFile
std::pair< std::string, std::string > toFile(const std::string fileName, const int datatype=DT_NONE, const int filetype=-1) const
Write the image to a NIfTI-1 file.
RNifti::NiftiImage::reorient
NiftiImage & reorient(const std::string &orientation)
Reorient the image by permuting dimensions and potentially reversing some.
RNifti::SquareMatrix::rownorm
ElementType rownorm() const
Maximum row norm, as implemented in niftilib (Order 3 only)
RNifti::NiftiImage::getData
std::vector< TargetType > getData(const bool useSlope=true) const
Extract a vector of data from the image, casting it to any required element type.
RNifti::NiftiImageData::Element
Inner class representing a single element in the data blob.
Definition: NiftiImage.h:268
RNifti::NiftiImage::replaceExtensions
NiftiImage & replaceExtensions(const std::list< Extension > extensions)
Replace all extensions with new ones.
Definition: NiftiImage.h:1863
RNifti::NiftiImage::update
NiftiImage & update(const Rcpp::RObject &object)
Update the image from an R array.
RNifti::NiftiImage::data
const NiftiImageData data() const
Obtain the pixel data within the image.
Definition: NiftiImage.h:1593
RNifti::NiftiImage::reorient
NiftiImage & reorient(const int i, const int j, const int k)
Reorient the image by permuting dimensions and potentially reversing some.
RNifti::NiftiImageData::_length
size_t _length
The number of data elements in the blob.
Definition: NiftiImage.h:204
RNifti::NiftiImage::Xform::matrix
const Matrix & matrix() const
Access the xform matrix as an immutable SquareMatrix object.
Definition: NiftiImage.h:1177
RNifti::NiftiImageData::isRgb
bool isRgb() const
Determine whether the datatype corresponds to an RGB type.
Definition: NiftiImage.h:554
RNifti::SquareMatrix::inverse
MatrixType inverse() const
Matrix inverse.
RNifti::NiftiImage::Xform::Xform
Xform(Matrix::NativeType &source)
Initialise from a NIfTI mat44 or dmat44.
Definition: NiftiImage.h:1126
RNifti::SquareMatrix::NativeType
NiftiType NativeType
The niftilib structure type corresponding to this matrix.
Definition: NiftiImage.h:694
RNifti::NiftiImage::nExtensions
int nExtensions() const
Return the number of extensions associated with the image.
Definition: NiftiImage.h:1817
RNifti::NiftiImage::Xform::Xform
Xform(const Matrix &source)
Initialise from a 4x4 SquareMatrix.
Definition: NiftiImage.h:1113
RNifti::NiftiImage::NiftiImage
NiftiImage(nifti_image *const image, const bool copy=false)
Initialise using an existing nifti_image pointer.
Definition: NiftiImage.h:1392
RNifti::SquareMatrix::MatrixType
SquareMatrix< NiftiType, ElementType, Order > MatrixType
Type alias for the current specialisation.
Definition: NiftiImage.h:695
RNifti::NiftiImageData
Wrapper class encapsulating a NIfTI data blob, with responsibility for handling data scaling and poly...
Definition: NiftiImage.h:72
RNifti::NiftiImage::toArray
Rcpp::RObject toArray() const
Create an R array from the image.
RNifti::NiftiImage::Xform::rotation
Submatrix rotation() const
Obtain the 3x3 rotation matrix from the xform matrix, with scale and skew components removed.
RNifti::NiftiImage::Block::data
NiftiImageData data() const
Obtain the data within the block.
Definition: NiftiImage.h:902
RNifti::NiftiImage::block
const Block block(const int i) const
Extract a block from the image.
Definition: NiftiImage.h:1747
RNifti::Vector
A simple object-oriented wrapper around a fixed-length array.
Definition: NiftiImage.h:627
RNifti::NiftiImageData::isInteger
bool isInteger() const
Determine whether the datatype is an integer type.
Definition: NiftiImage.h:548
RNifti::SquareMatrix::niftiPointer
NiftiType * niftiPointer() const
Obtain a pointer to a NIfTI-style mat44 or dmat44 encapsulating the same data as this object.
Definition: NiftiImage.h:681
RNifti::SquareMatrix::SquareMatrix
SquareMatrix(const ElementType value=0.0)
Initialise with a fixed element value, defaulting to zero.
Definition: NiftiImage.h:701
RNifti::NiftiImage::setPersistence
NiftiImage & setPersistence(const bool persistent)
Mark the image as persistent, so that it can be passed back to R.
Definition: NiftiImage.h:1508
RNifti::NiftiImage::replaceData
NiftiImage & replaceData(const NiftiImageData &data)
Replace the pixel data in the image with the contents of a NiftiImageData object.
RNifti::NiftiImage::volume
Block volume(const int i)
Extract a volume block from a 4D image.
Definition: NiftiImage.h:1784
RNifti::NiftiImageData::unscaled
NiftiImageData unscaled() const
Return a similar object to the callee, but with the slope and intercept values reset.
Definition: NiftiImage.h:560
RNifti::NiftiImage::Xform::Xform
Xform()
Default constructor.
Definition: NiftiImage.h:1107
RNifti::NiftiImage::~NiftiImage
virtual ~NiftiImage()
Destructor which decrements the reference counter, and releases the wrapped pointer if the counter dr...
Definition: NiftiImage.h:1452
RNifti::Vector::Vector
Vector(const ElementType value=0.0)
Initialise with a fixed element value, defaulting to zero.
Definition: NiftiImage.h:635
RNifti::NiftiImage::changeDatatype
NiftiImage & changeDatatype(const std::string &datatype, const bool useSlope=false)
Change the datatype of the image, casting the pixel data if present.
RNifti::NiftiImage::Extension::ext
nifti1_extension * ext
The wrapped extension structure.
Definition: NiftiImage.h:933
RNifti::NiftiImageData::disown
NiftiImageData & disown()
Disown the data blob, removing responsibility for freeing it upon destruction.
Definition: NiftiImage.h:566
RNifti::NiftiImage::Extension::copy
void copy(const SourceType *data, const size_t length, const int code)
Copy the specified data buffer into the object.
RNifti::NiftiImage::isDataScaled
bool isDataScaled() const
Determine whether nontrivial scale and slope parameters are set.
Definition: NiftiImage.h:1535
RNifti::NiftiImage::acquire
void acquire(nifti_image *const image)
Acquire the specified pointer to a nifti_image struct, taking (possibly shared) responsibility for fr...
RNifti::NiftiImage::Xform::operator=
Xform & operator=(const Xform &source)
Copy assignment operator, taking an Xform and replacing linked data.
Definition: NiftiImage.h:1159
RNifti::NiftiImageData::begin
Iterator begin()
Obtain a mutable iterator corresponding to the start of the blob.
Definition: NiftiImage.h:575
RNifti::NiftiImage::xform
const Xform xform(const bool preferQuaternion=true) const
Obtain an xform matrix, indicating the orientation of the image.
RNifti::NiftiImageData::ConcreteTypeHandler
Concrete inner class template defining behaviour specific to individual data types.
Definition: NiftiImage.h:102
RNifti::NiftiImage::Block::index
const dim_t index
The location along dimension.
Definition: NiftiImage.h:855
RNifti::NiftiImageData::createHandler
TypeHandler * createHandler()
Create a concrete type handler appropriate to the datatype code stored with the data.
Definition: NiftiImage.h:174
RNifti::NiftiImage::Extension::Extension
Extension(nifti1_extension *const extension, const bool copy=false)
Initialise from an existing nifti1_extension (which is used by both NIfTI-1 and NIfTI-2 images),...
Definition: NiftiImage.h:964
RNifti::rgba32_t::ValueType
Definition: NiftiImage.h:56
RNifti::NiftiImage::fileVersion
static int fileVersion(const std::string &path)
Get the NIfTI format version used by the file at the specified path.
RNifti::NiftiImage::Extension::length
size_t length() const
Return the length of the data array.
Definition: NiftiImage.h:1043
RNifti::NiftiImage::Block::getData
std::vector< TargetType > getData(const bool useSlope=true) const
Extract a vector of data from a block, casting it to any required element type.
RNifti::NiftiImage::NiftiImage
NiftiImage()
Default constructor.
Definition: NiftiImage.h:1352
RNifti::NiftiImage::operator->
const nifti_image * operator->() const
Allows a NiftiImage object to be treated as a pointer to a const nifti_image.
Definition: NiftiImage.h:1467
RNifti::NiftiImageData::dataPtr
void * dataPtr
Opaque pointer to the underlying data blob.
Definition: NiftiImage.h:201
RNifti::NiftiImageData::datatype
int datatype() const
Return stored datatype code.
Definition: NiftiImage.h:508
RNifti::NiftiImage::Block::operator=
Block & operator=(const NiftiImage &source)
Copy assignment operator, which allows a block in one image to be replaced with the contents of anoth...
Definition: NiftiImage.h:879
RNifti::NiftiImageData::handler
TypeHandler * handler
Type handler, which is created to match the datatype.
Definition: NiftiImage.h:203
RNifti::NiftiImage::nVoxels
size_t nVoxels() const
Return the number of voxels in the image.
Definition: NiftiImage.h:1811
RNifti::NiftiImage::Xform::Xform
Xform(SEXP source)
Initialise from an R numeric matrix object.
Definition: NiftiImage.h:1140
RNifti::SquareMatrix::multiply
MatrixType multiply(const MatrixType &other) const
Matrix-matrix multiplication.
RNifti::NiftiImage::Xform::Xform
Xform(Matrix::NativeType &source, Matrix::NativeType &inverse, Element *qparams=NULL)
Initialise from forward and backward matrices, and optionally quaternion parameters.
Definition: NiftiImage.h:1133
RNifti::NiftiImageData::totalBytes
size_t totalBytes() const
Return the total size of the data blob, in bytes.
Definition: NiftiImage.h:516
RNifti::SquareMatrix::VectorType
Vector< ElementType, Order > VectorType
Type of vectors for which this matrix is a linear operator.
Definition: NiftiImage.h:696
RNifti::NiftiImageData::calibrateFrom
void calibrateFrom(const NiftiImageData &data)
Update the slope and intercept to cover the range of another data object.
Definition: NiftiImage.h:243
RNifti::NiftiImage::initFromMriImage
void initFromMriImage(const Rcpp::RObject &object, const bool copyData=true)
Initialise the object from a reference object of class "MriImage".
RNifti::NiftiImage::Extension::copy
void copy(const nifti1_extension *source)
Copy an existing nifti1_extension structure into the object.
RNifti::SquareMatrix::elements
ElementType elements[Order *Order]
The underlying raw data elements, stored row-major for consistency with niftilib.
Definition: NiftiImage.h:675
RNifti::NiftiImageData::bytesPerPixel
size_t bytesPerPixel() const
Return the number of bytes used per element, or zero if the datatype is undefined or the blob is NULL...
Definition: NiftiImage.h:513
RNifti::NiftiImageData::init
void init(void *data, const size_t length, const int datatype, const double slope, const double intercept, const bool alloc=true)
Initialiser method, used by constructors.
Definition: NiftiImage.h:217
RNifti::NiftiImage::Xform::handedness
Element handedness() const
Returns the qfac value, which should be 1 where the xform matrix represents a right-handed coordinate...
RNifti::NiftiImage::Extension
Inner class wrapping a NIfTI extension, a weakly-specified standard for attaching additional metadata...
Definition: NiftiImage.h:931
RNifti::SquareMatrix::end
ElementType * end()
Return a pointer/iterator to the end of the data.
Definition: NiftiImage.h:772
RNifti::NiftiImageData::owner
bool owner
An indicator of whether this object is responsible for cleaning up the data.
Definition: NiftiImage.h:205
RNifti::SquareMatrix
Class representing a numeric square matrix of a fixed order.
Definition: NiftiImage.h:673
RNifti::NiftiImage::dropExtensions
NiftiImage & dropExtensions()
Remove any extensions from the image.
Definition: NiftiImage.h:1875
RNifti::NiftiImage::Block::image
const NiftiImage & image
The parent image.
Definition: NiftiImage.h:853
RNifti::NiftiImage::Extension::Extension
Extension()
Default constructor, wrapping NULL.
Definition: NiftiImage.h:954
RNifti::NiftiImage::extensions
std::list< Extension > extensions(const int code=-1) const
Return a list of the extensions associated with the image.
Definition: NiftiImage.h:1825
RNifti::NiftiImageData::NiftiImageData
NiftiImageData(nifti_image *image)
Convenience constructor for a nifti_image.
Definition: NiftiImage.h:437
RNifti::NiftiImageData::blob
void * blob() const
Return an opaque pointer to the blob.
Definition: NiftiImage.h:507
RNifti::NiftiImage::NiftiImage
NiftiImage(const std::vector< dim_t > &dim, const std::string &datatype)
Initialise from basic metadata, allocating and zeroing pixel data.
RNifti::NiftiImage::pixdim
std::vector< pixdim_t > pixdim() const
Return the dimensions of the pixels or voxels in the image.
Definition: NiftiImage.h:1565
RNifti::NiftiImage::Xform::spacing
Vector3 spacing() const
Obtain the pixel spacing of the image in each spatial dimension.
RNifti::NiftiImageData::minmax
void minmax(double *min, double *max) const
Calculate the minimum and maximum values in the blob, as doubles.
Definition: NiftiImage.h:601
RNifti::SquareMatrix::determ
ElementType determ() const
Matrix determinant, as implemented in niftilib (Order 3 only)
RNifti::NiftiImage::nDims
int nDims() const
Return the number of dimensions in the image.
Definition: NiftiImage.h:1541
RNifti::SquareMatrix::begin
ElementType * begin()
Return a pointer/iterator to the beginning of the data.
Definition: NiftiImage.h:762
RNifti::NiftiImageData::Iterator::Iterator
Iterator(const Iterator &other)
Copy constructor.
Definition: NiftiImage.h:378
RNifti::NiftiImage::NiftiImage
NiftiImage(const SEXP object, const bool readData=true, const bool readOnly=false)
Initialise from an R object, retrieving an existing image from an external pointer attribute if avail...
RNifti::NiftiImageData::Iterator::Iterator
Iterator(const NiftiImageData &parent, void *ptr=NULL, const size_t step=0)
Primary constructor.
Definition: NiftiImage.h:367
RNifti::NiftiImage::drop
NiftiImage & drop()
Drop unitary dimensions.
Definition: NiftiImage.h:1579
RNifti::NiftiImage::initFromNiftiS4
void initFromNiftiS4(const Rcpp::RObject &object, const bool copyData=true)
Initialise the object from an S4 object of class "nifti".
RNifti::NiftiImage::sform
Xform sform()
Access the sform matrix.
Definition: NiftiImage.h:1732
RNifti::NiftiImage::initFromArray
void initFromArray(const Rcpp::RObject &object, const bool copyData=true)
Initialise the object from an R array.
RNifti::NiftiImage::initFromList
void initFromList(const Rcpp::RObject &object)
Initialise the object from an R list with named elements, which can only contain metadata.
RNifti::NiftiImage::data
NiftiImageData data()
Obtain the pixel data within the image.
Definition: NiftiImage.h:1599
RNifti::NiftiImage::nChannels
int nChannels() const
Return the number of colour channels used by the image.
Definition: NiftiImage.h:1791
RNifti::SquareMatrix::begin
const ElementType * begin() const
Return a pointer/iterator to the beginning of the data.
Definition: NiftiImage.h:756
RNifti::NiftiImage::copy
void copy(const NiftiImage &source)
Copy the contents of another NiftiImage to create a new image, acquiring a new pointer.
RNifti::NiftiImage::qform
const Xform qform() const
Access the qform matrix.
Definition: NiftiImage.h:1714
RNifti::NiftiImage::Block::dimension
const int dimension
The dimension along which the block applies (which should be the last)
Definition: NiftiImage.h:854
RNifti::NiftiImage::addExtension
NiftiImage & addExtension(const Extension &extension)
Add an extension to the image.
Definition: NiftiImage.h:1847
RNifti::NiftiImage::Block::Block
Block(const NiftiImage &image, const int dimension, const dim_t index)
Standard constructor for this class.
Definition: NiftiImage.h:864
RNifti::NiftiImage::slice
const Block slice(const int i) const
Extract a slice block from a 3D image.
Definition: NiftiImage.h:1763
RNifti::NiftiImage::isPersistent
bool isPersistent() const
Determine whether or not the image is marked as persistent.
Definition: NiftiImage.h:1528
RNifti::NiftiImageData::Element::operator=
Element & operator=(const SourceType &value)
Copy assignment operator.
RNifti::NiftiImage::Xform::qparams
Element * qparams
Pointers to linked C-style arrays.
Definition: NiftiImage.h:1094
RNifti::NiftiImage::Extension::code
int code() const
Return the code associated with the extension.
Definition: NiftiImage.h:1031
RNifti::NiftiImageData::~NiftiImageData
virtual ~NiftiImageData()
Destructor which frees the type handler, and the data blob if it is owned by this object.
Definition: NiftiImage.h:482
RNifti::NiftiImageData::isEmpty
bool isEmpty() const
Determine whether or not the object is empty.
Definition: NiftiImage.h:522
RNifti::NiftiImageData::begin
const Iterator begin() const
Obtain a constant iterator corresponding to the start of the blob.
Definition: NiftiImage.h:569
RNifti::NiftiImageData::NiftiImageData
NiftiImageData()
Default constructor, creating an empty data object.
Definition: NiftiImage.h:416
RNifti::SquareMatrix::niftiCopy
NiftiType niftiCopy() const
Copy the data elements into a new NIfTI-style mat44 or dmat44.
Definition: NiftiImage.h:686
RNifti::SquareMatrix::end
const ElementType * end() const
Return a pointer/iterator to the end of the data.
Definition: NiftiImage.h:767
RNifti::NiftiImage::initFromDims
void initFromDims(const std::vector< dim_t > &dim, const int datatype)
Initialise an empty object from basic metadata.
RNifti::NiftiImage::Xform::replace
void replace(const Matrix &source)
Replace the current matrix with a new one.
RNifti::NiftiImage::copy
void copy(const Block &source)
Copy the contents of a Block to create a new image, acquiring a new pointer.
RNifti::NiftiImage::NiftiImage
NiftiImage(const std::vector< dim_t > &dim, const int datatype)
Initialise from basic metadata, allocating and zeroing pixel data.
RNifti::NiftiImageData::_datatype
int _datatype
Datatype code indicating the actual type of the elements.
Definition: NiftiImage.h:202
RNifti::NiftiImage::sexpTypeToNiftiType
static int sexpTypeToNiftiType(const int sexpType)
Convert between R SEXP object type and nifti_image datatype codes.
Definition: NiftiImage.h:1229
RNifti::Vector::Vector
Vector(const ElementType *source)
Initialise from a C-style array of the appropriate type and length.
Definition: NiftiImage.h:643