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 compatibility with 3.0.x
10 #ifndef MAYBE_SHARED
11 #define MAYBE_SHARED(x) (NAMED(x) > 1)
12 #endif
13 
14 #else
15 
16 #define R_NegInf -INFINITY
17 
18 #include <stdint.h>
19 #include <cstddef>
20 #include <cmath>
21 #include <string>
22 #include <sstream>
23 #include <vector>
24 #include <stdexcept>
25 #include <algorithm>
26 #include <map>
27 #include <locale>
28 #include <limits>
29 
30 #endif
31 
32 
33 #include "niftilib/nifti1_io.h"
34 
43 namespace RNifti {
44 
53 {
54 public:
55  double slope;
56  double intercept;
58 protected:
62  struct TypeHandler
63  {
64  virtual ~TypeHandler() {}
65  virtual size_t size () const { return 0; }
66  virtual bool hasNaN () const { return false; }
67  virtual double getDouble (void *ptr) const = 0;
68  virtual int getInt (void *ptr) const = 0;
69  virtual void setDouble (void *ptr, const double value) const = 0;
70  virtual void setInt (void *ptr, const int value) const = 0;
71  virtual void minmax (void *ptr, const size_t length, double *min, double *max) const = 0;
72  };
73 
77  template <typename Type>
79  {
80  size_t size () const { return (sizeof(Type)); }
81  bool hasNaN () const { return std::numeric_limits<Type>::has_quiet_NaN; }
82  double getDouble (void *ptr) const { return static_cast<double>(*static_cast<Type*>(ptr)); }
83  int getInt (void *ptr) const { return static_cast<int>(*static_cast<Type*>(ptr)); }
84  void setDouble (void *ptr, const double value) const { *(static_cast<Type*>(ptr)) = static_cast<Type>(value); }
85  void setInt (void *ptr, const int value) const { *(static_cast<Type*>(ptr)) = static_cast<Type>(value); }
86  void minmax (void *ptr, const size_t length, double *min, double *max) const;
87  };
88 
95  {
96  if (_datatype == DT_NONE)
97  return NULL;
98 
99  switch (_datatype)
100  {
101  case DT_UINT8: return new ConcreteTypeHandler<uint8_t>(); break;
102  case DT_INT16: return new ConcreteTypeHandler<int16_t>(); break;
103  case DT_INT32: return new ConcreteTypeHandler<int32_t>(); break;
104  case DT_FLOAT32: return new ConcreteTypeHandler<float>(); break;
105  case DT_FLOAT64: return new ConcreteTypeHandler<double>(); break;
106  case DT_INT8: return new ConcreteTypeHandler<int8_t>(); break;
107  case DT_UINT16: return new ConcreteTypeHandler<uint16_t>(); break;
108  case DT_UINT32: return new ConcreteTypeHandler<uint32_t>(); break;
109  case DT_INT64: return new ConcreteTypeHandler<int64_t>(); break;
110  case DT_UINT64: return new ConcreteTypeHandler<uint64_t>(); break;
111 
112  default:
113  throw std::runtime_error("Unsupported data type (" + std::string(nifti_datatype_string(_datatype)) + ")");
114  }
115  }
116 
117  void *dataPtr;
118  int _datatype;
120  size_t _length;
121  bool owner;
133  void init (void *data, const size_t length, const int datatype, const double slope, const double intercept, const bool alloc = true)
134  {
135  this->_length = length;
136  this->_datatype = datatype;
137  this->slope = slope;
138  this->intercept = intercept;
139 
140  owner = false;
142  if (handler == NULL)
143  dataPtr = NULL;
144  else if (alloc && data == NULL)
145  {
146  dataPtr = calloc(length, handler->size());
147  owner = true;
148  }
149  else
150  dataPtr = data;
151  }
152 
159  void calibrateFrom (const NiftiImageData &data)
160  {
161  slope = 1.0;
162  intercept = 0.0;
163 
164  if (this->isInteger())
165  {
166  double dataMin, dataMax, typeMin, typeMax;
167  data.minmax(&dataMin, &dataMax);
168  handler->minmax(NULL, 0, &typeMin, &typeMax);
169 
170  // If the source type is floating-point but values are in range, we will just round them
171  if (dataMin < typeMin || dataMax > typeMax)
172  {
173  slope = (dataMax - dataMin) / (typeMax - typeMin);
174  intercept = dataMin - (slope) * typeMin;
175  }
176  }
177  }
178 
179 public:
183  struct Element
184  {
185  private:
186  const NiftiImageData &parent;
187  void *ptr;
188 
189  public:
196  Element (const NiftiImageData &parent, void *ptr = NULL)
197  : parent(parent)
198  {
199  this->ptr = (ptr == NULL ? parent.dataPtr : ptr);
200  }
201 
209  template <typename SourceType>
210  Element & operator= (const SourceType &value);
211 
217  Element & operator= (const Element &other);
218 
222  template <typename TargetType>
223  operator TargetType() const
224  {
225  if (parent.isScaled())
226  return TargetType(parent.handler->getDouble(ptr) * parent.slope + parent.intercept);
227  else if (std::numeric_limits<TargetType>::is_integer)
228  return TargetType(parent.handler->getInt(ptr));
229  else
230  return TargetType(parent.handler->getDouble(ptr));
231  }
232  };
233 
237  class Iterator : public std::iterator<std::random_access_iterator_tag, Element>
238  {
239  private:
240  const NiftiImageData &parent;
241  void *ptr;
242  size_t step;
243 
244  public:
252  Iterator (const NiftiImageData &parent, void *ptr = NULL, const size_t step = 0)
253  : parent(parent)
254  {
255  this->ptr = (ptr == NULL ? parent.dataPtr : ptr);
256  this->step = (step == 0 ? parent.handler->size() : step);
257  }
258 
263  Iterator (const Iterator &other)
264  : parent(other.parent), ptr(other.ptr), step(other.step) {}
265 
266  Iterator & operator++ () { ptr = static_cast<char*>(ptr) + step; return *this; }
267  Iterator operator++ (int) { Iterator copy(*this); ptr = static_cast<char*>(ptr) + step; return copy; }
268  Iterator operator+ (ptrdiff_t n) const
269  {
270  void *newptr = static_cast<char*>(ptr) + (n * step);
271  return Iterator(parent, newptr, step);
272  }
273  Iterator & operator-- () { ptr = static_cast<char*>(ptr) - step; return *this; }
274  Iterator operator-- (int) { Iterator copy(*this); ptr = static_cast<char*>(ptr) - step; return copy; }
275  Iterator operator- (ptrdiff_t n) const
276  {
277  void *newptr = static_cast<char*>(ptr) - (n * step);
278  return Iterator(parent, newptr, step);
279  }
280 
281  ptrdiff_t operator- (const Iterator &other) const
282  {
283  const ptrdiff_t difference = static_cast<char*>(ptr) - static_cast<char*>(other.ptr);
284  return difference / step;
285  }
286 
287  bool operator== (const Iterator &other) const { return (ptr==other.ptr && step==other.step); }
288  bool operator!= (const Iterator &other) const { return (ptr!=other.ptr || step!=other.step); }
289  bool operator> (const Iterator &other) const { return (ptr > other.ptr); }
290  bool operator< (const Iterator &other) const { return (ptr < other.ptr); }
291 
292  const Element operator* () const { return Element(parent, ptr); }
293  Element operator* () { return Element(parent, ptr); }
294  const Element operator[] (const size_t i) const { return Element(parent, static_cast<char*>(ptr) + (i * step)); }
295  Element operator[] (const size_t i) { return Element(parent, static_cast<char*>(ptr) + (i * step)); }
296  };
297 
302  : dataPtr(NULL), _datatype(DT_NONE), _length(0), handler(NULL), slope(1.0), intercept(0.0), owner(false) {}
303 
313  NiftiImageData (void *data, const size_t length, const int datatype, const double slope = 1.0, const double intercept = 0.0)
314  {
315  init(data, length, datatype, slope, intercept);
316  }
317 
322  NiftiImageData (nifti_image *image)
323  {
324  if (image == NULL)
325  init(NULL, 0, DT_NONE, 0.0, 0.0, false);
326  else
327  init(image->data, image->nvox, image->datatype, static_cast<double>(image->scl_slope), static_cast<double>(image->scl_inter), false);
328  }
329 
337  NiftiImageData (const NiftiImageData &source, const int datatype = DT_NONE)
338  {
339  init(NULL, source.length(), datatype == DT_NONE ? source.datatype() : datatype, source.slope, source.intercept);
340 
341  if (datatype == DT_NONE || datatype == source.datatype())
342  memcpy(dataPtr, source.dataPtr, source.totalBytes());
343  else
344  {
345  calibrateFrom(source);
346  std::copy(source.begin(), source.end(), this->begin());
347  }
348  }
349 
356  template <class InputIterator>
357  NiftiImageData (InputIterator from, InputIterator to, const int datatype)
358  {
359  const size_t length = static_cast<size_t>(std::distance(from, to));
360  init(NULL, length, datatype, 1.0, 0.0);
361  std::copy(from, to, this->begin());
362  }
363 
367  virtual ~NiftiImageData ()
368  {
369  delete handler;
370  if (owner)
371  free(dataPtr);
372  }
373 
380  {
381  if (source.dataPtr != NULL)
382  {
383  // Free the old data, if we allocated it
384  if (owner)
385  free(dataPtr);
386  init(NULL, source.length(), source.datatype(), source.slope, source.intercept);
387  memcpy(dataPtr, source.dataPtr, source.totalBytes());
388  }
389  return *this;
390  }
391 
392  void * blob () const { return dataPtr; }
393  int datatype () const { return _datatype; }
394  size_t length () const { return _length; }
395  size_t size () const { return _length; }
398  size_t bytesPerPixel () const { return (handler == NULL ? 0 : handler->size()); }
399 
401  size_t totalBytes () const { return _length * bytesPerPixel(); }
402 
407  bool isEmpty () const { return (dataPtr == NULL); }
408 
414  bool isScaled () const { return (slope != 0.0 && (slope != 1.0 || intercept != 0.0)); }
415 
420  bool isComplex () const { return false; }
421 
427  bool isFloatingPoint () const { return (_datatype == DT_FLOAT32 || _datatype == DT_FLOAT64); }
428 
433  bool isInteger () const { return nifti_is_inttype(_datatype); }
434 
439  bool isRgb () const { return false; }
440 
446 
451  NiftiImageData & disown () { this->owner = false; return *this; }
452 
454  const Iterator begin () const { return Iterator(*this); }
455 
457  const Iterator end () const { return Iterator(*this, static_cast<char*>(dataPtr) + totalBytes()); }
458 
460  Iterator begin () { return Iterator(*this); }
461 
463  Iterator end () { return Iterator(*this, static_cast<char*>(dataPtr) + totalBytes()); }
464 
470  const Element operator[] (const size_t i) const { return Element(*this, static_cast<char*>(dataPtr) + (i * bytesPerPixel())); }
471 
477  Element operator[] (const size_t i) { return Element(*this, static_cast<char*>(dataPtr) + (i * bytesPerPixel())); }
478 
486  void minmax (double *min, double *max) const
487  {
488  if (handler == NULL)
489  {
490  *min = 0.0;
491  *max = 0.0;
492  }
493  else
494  handler->minmax(dataPtr, _length, min, max);
495  }
496 };
497 
498 
499 #ifdef USING_R
500 template <>
501 inline bool NiftiImageData::ConcreteTypeHandler<int>::hasNaN () const { return true; }
502 #endif
503 
504 
512 {
513 public:
518  struct Block
519  {
520  const NiftiImage &image;
521  const int dimension;
522  const int index;
531  Block (const NiftiImage &image, const int dimension, const int index)
533  {
534  if (dimension != image->ndim)
535  throw std::runtime_error("Blocks must be along the last dimension in the image");
536  }
537 
546  Block & operator= (const NiftiImage &source)
547  {
548  if (source->datatype != image->datatype)
549  throw std::runtime_error("New data does not have the same datatype as the target block");
550  if (source->scl_slope != image->scl_slope || source->scl_inter != image->scl_inter)
551  throw std::runtime_error("New data does not have the same scale parameters as the target block");
552 
553  size_t blockSize = 1;
554  for (int i=1; i<dimension; i++)
555  blockSize *= image->dim[i];
556 
557  if (blockSize != source->nvox)
558  throw std::runtime_error("New data does not have the same size as the target block");
559 
560  blockSize *= image->nbyper;
561  memcpy(static_cast<char*>(image->data) + blockSize*index, source->data, blockSize);
562  return *this;
563  }
564 
570  {
571  if (image.isNull())
572  return NiftiImageData();
573  else
574  {
575  size_t blockSize = 1;
576  for (int i=1; i<dimension; i++)
577  blockSize *= image->dim[i];
578  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));
579  }
580  }
581 
589  template <typename TargetType>
590  std::vector<TargetType> getData (const bool useSlope = true) const;
591  };
592 
593 #ifdef USING_R
594 
600  static int sexpTypeToNiftiType (const int sexpType)
601  {
602  if (sexpType == INTSXP || sexpType == LGLSXP)
603  return DT_INT32;
604  else if (sexpType == REALSXP)
605  return DT_FLOAT64;
606  else
607  throw std::runtime_error("Array elements must be numeric");
608  }
609 #endif
610 
616  static mat33 xformToRotation (const mat44 matrix);
617 
623  static std::string xformToString (const mat44 matrix);
624 
631  static int fileVersion (const std::string &path);
632 
633 
634 protected:
635  nifti_image *image;
636  int *refCount;
644  void acquire (nifti_image * const image);
645 
650  void acquire (const NiftiImage &source)
651  {
652  refCount = source.refCount;
653  acquire(source.image);
654  }
655 
660  void release ();
661 
666  void copy (const nifti_image *source);
667 
672  void copy (const NiftiImage &source);
673 
678  void copy (const Block &source);
679 
680 
681 #ifdef USING_R
682 
688  void initFromNiftiS4 (const Rcpp::RObject &object, const bool copyData = true);
689 
695  void initFromMriImage (const Rcpp::RObject &object, const bool copyData = true);
696 
701  void initFromList (const Rcpp::RObject &object);
702 
708  void initFromArray (const Rcpp::RObject &object, const bool copyData = true);
709 
710 #endif
711 
716  void updatePixdim (const std::vector<float> &pixdim);
717 
722  void setPixunits (const std::vector<std::string> &pixunits);
723 
724 public:
729  : image(NULL), refCount(NULL) {}
730 
737  NiftiImage (const NiftiImage &source, const bool copy = true)
738  : image(NULL), refCount(NULL)
739  {
740  if (copy)
741  this->copy(source);
742  else
743  acquire(source);
744 #ifndef NDEBUG
745  Rc_printf("Creating NiftiImage with pointer %p (from NiftiImage)\n", this->image);
746 #endif
747  }
748 
753  NiftiImage (const Block &source)
754  : image(NULL), refCount(NULL)
755  {
756  this->copy(source);
757 #ifndef NDEBUG
758  Rc_printf("Creating NiftiImage with pointer %p (from Block)\n", this->image);
759 #endif
760  }
761 
768  NiftiImage (nifti_image * const image, const bool copy = false)
769  : image(NULL), refCount(NULL)
770  {
771  if (copy)
772  this->copy(image);
773  else
774  acquire(image);
775 #ifndef NDEBUG
776  Rc_printf("Creating NiftiImage with pointer %p (from pointer)\n", this->image);
777 #endif
778  }
779 
786  NiftiImage (const std::string &path, const bool readData = true)
787  : image(NULL), refCount(NULL)
788  {
789  acquire(nifti_image_read(path.c_str(), readData));
790  if (image == NULL)
791  throw std::runtime_error("Failed to read image from path " + path);
792 #ifndef NDEBUG
793  Rc_printf("Creating NiftiImage with pointer %p (from string)\n", this->image);
794 #endif
795  }
796 
803  NiftiImage (const std::string &path, const std::vector<int> &volumes);
804 
805 #ifdef USING_R
806 
816  NiftiImage (const SEXP object, const bool readData = true, const bool readOnly = false);
817 #endif
818 
823  virtual ~NiftiImage () { release(); }
824 
828  operator const nifti_image* () const { return image; }
829 
833  operator nifti_image* () { return image; }
834 
838  const nifti_image * operator-> () const { return image; }
839 
843  nifti_image * operator-> () { return image; }
844 
850  {
851  copy(source);
852 #ifndef NDEBUG
853  Rc_printf("Creating NiftiImage with pointer %p (from NiftiImage)\n", this->image);
854 #endif
855  return *this;
856  }
857 
863  NiftiImage & operator= (const Block &source)
864  {
865  copy(source);
866 #ifndef NDEBUG
867  Rc_printf("Creating NiftiImage with pointer %p (from Block)\n", this->image);
868 #endif
869  return *this;
870  }
871 
879  NiftiImage & setPersistence (const bool persistent) { return *this; }
880 
885  bool isNull () const { return (image == NULL); }
886 
891  bool isShared () const { return (refCount != NULL && *refCount > 1); }
892 
899  bool isPersistent () const { return false; }
900 
906  bool isDataScaled () const { return (image != NULL && image->scl_slope != 0.0 && (image->scl_slope != 1.0 || image->scl_inter != 0.0)); }
907 
912  int nDims () const
913  {
914  if (image == NULL)
915  return 0;
916  else
917  return image->ndim;
918  }
919 
924  std::vector<int> dim () const
925  {
926  if (image == NULL)
927  return std::vector<int>();
928  else
929  return std::vector<int>(image->dim+1, image->dim+image->ndim+1);
930  }
931 
936  std::vector<float> pixdim () const
937  {
938  if (image == NULL)
939  return std::vector<float>();
940  else
941  return std::vector<float>(image->pixdim+1, image->pixdim+image->ndim+1);
942  }
943 
951  {
952  int ndim = image->ndim;
953  while (image->dim[ndim] < 2)
954  ndim--;
955  image->dim[0] = image->ndim = ndim;
956 
957  return *this;
958  }
959 
964  const NiftiImageData data () const { return NiftiImageData(image); }
965 
971 
981  template <typename TargetType>
982  std::vector<TargetType> getData (const bool useSlope = true) const;
983 
991  NiftiImage & changeDatatype (const int datatype, const bool useSlope = false);
992 
1000  NiftiImage & changeDatatype (const std::string &datatype, const bool useSlope = false);
1001 
1010  template <typename SourceType>
1011  NiftiImage & replaceData (const std::vector<SourceType> &data, const int datatype = DT_NONE);
1012 
1020 
1026  {
1027  nifti_image_unload(image);
1028  return *this;
1029  }
1030 
1037  NiftiImage & rescale (const std::vector<float> &scales);
1038 
1047  NiftiImage & reorient (const int i, const int j, const int k);
1048 
1057  NiftiImage & reorient (const std::string &orientation);
1058 
1059 #ifdef USING_R
1060 
1065  NiftiImage & update (const Rcpp::RObject &object);
1066 #endif
1067 
1073  mat44 xform (const bool preferQuaternion = true) const;
1074 
1079  int nBlocks () const
1080  {
1081  if (image == NULL)
1082  return 0;
1083  else
1084  return image->dim[image->ndim];
1085  }
1086 
1094  const Block block (const int i) const { return Block(*this, nDims(), i); }
1095 
1103  Block block (const int i) { return Block(*this, nDims(), i); }
1104 
1110  const Block slice (const int i) const { return Block(*this, 3, i); }
1111 
1117  Block slice (const int i) { return Block(*this, 3, i); }
1118 
1124  const Block volume (const int i) const { return Block(*this, 4, i); }
1125 
1131  Block volume (const int i) { return Block(*this, 4, i); }
1132 
1138  void toFile (const std::string fileName, const int datatype = DT_NONE) const;
1139 
1145  void toFile (const std::string fileName, const std::string &datatype) const;
1146 
1147 #ifdef USING_R
1148 
1153  Rcpp::RObject toArray () const;
1154 
1160  Rcpp::RObject toPointer (const std::string label) const;
1161 
1168  Rcpp::RObject toArrayOrPointer (const bool internal, const std::string label) const;
1169 
1174  Rcpp::RObject headerToList () const;
1175 
1176 #endif
1177 
1178 };
1179 
1180 // Include implementations
1181 #include "lib/NiftiImage_impl.h"
1182 
1183 } // main namespace
1184 
1185 #endif
bool isInteger() const
Determine whether the datatype is an integer type.
Definition: NiftiImage.h:433
NiftiImage()
Default constructor.
Definition: NiftiImage.h:728
const int index
The location along dimension.
Definition: NiftiImage.h:522
static std::string xformToString(const mat44 matrix)
Convert a 4x4 xform matrix to a string describing its canonical axes.
std::vector< int > dim() const
Return the dimensions of the image.
Definition: NiftiImage.h:924
const nifti_image * operator->() const
Allows a NiftiImage object to be treated as a pointer to a const nifti_image.
Definition: NiftiImage.h:838
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:133
int datatype() const
Return stored datatype code.
Definition: NiftiImage.h:393
const Iterator begin() const
Obtain a constant iterator corresponding to the start of the blob.
Definition: NiftiImage.h:454
bool isComplex() const
Determine whether the datatype is complex.
Definition: NiftiImage.h:420
NiftiImage & rescale(const std::vector< float > &scales)
Rescale the image, changing its image dimensions and pixel dimensions.
bool isRgb() const
Determine whether the datatype corresponds to an RGB value.
Definition: NiftiImage.h:439
int * refCount
A reference counter, shared with other objects wrapping the same pointer.
Definition: NiftiImage.h:636
Abstract inner class defining the type-specific functions required in concrete subclasses.
Definition: NiftiImage.h:62
const Element operator[](const size_t i) const
Indexing operator, returning a constant element.
Definition: NiftiImage.h:470
Iterator end()
Obtain a mutable iterator corresponding to the end of the blob.
Definition: NiftiImage.h:463
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.
std::vector< float > pixdim() const
Return the dimensions of the pixels or voxels in the image.
Definition: NiftiImage.h:936
void minmax(double *min, double *max) const
Calculate the minimum and maximum values in the blob, as doubles.
Definition: NiftiImage.h:486
Concrete inner class template defining behaviour specific to individual data types.
Definition: NiftiImage.h:78
NiftiImage(const std::string &path, const bool readData=true)
Initialise using a path string.
Definition: NiftiImage.h:786
size_t size() const
Return the number of elements in the data.
Definition: NiftiImage.h:395
Iterator type for NiftiImageData, with Element as its value type.
Definition: NiftiImage.h:237
double slope
The slope term used to scale data values.
Definition: NiftiImage.h:55
NiftiImage(nifti_image *const image, const bool copy=false)
Initialise using an existing nifti_image pointer.
Definition: NiftiImage.h:768
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:313
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:546
bool isNull() const
Determine whether or not the wrapped pointer is NULL.
Definition: NiftiImage.h:885
Inner class referring to a subset of an image.
Definition: NiftiImage.h:518
Block slice(const int i)
Extract a slice block from a 3D image.
Definition: NiftiImage.h:1117
const NiftiImageData data() const
Obtain the pixel data within the image.
Definition: NiftiImage.h:964
bool isShared() const
Determine whether the wrapped pointer is shared with another NiftiImage.
Definition: NiftiImage.h:891
void acquire(const NiftiImage &source)
Acquire the same pointer as another NiftiImage, incrementing the shared reference count.
Definition: NiftiImage.h:650
NiftiImageData()
Default constructor, creating an empty data object.
Definition: NiftiImage.h:301
Iterator(const NiftiImageData &parent, void *ptr=NULL, const size_t step=0)
Primary constructor.
Definition: NiftiImage.h:252
void acquire(nifti_image *const image)
Acquire the specified pointer to a nifti_image struct, taking (possibly shared) responsibility for fr...
bool isDataScaled() const
Determine whether nontrivial scale and slope parameters are set.
Definition: NiftiImage.h:906
const Block slice(const int i) const
Extract a slice block from a 3D image.
Definition: NiftiImage.h:1110
NiftiImageData data() const
Obtain the data within the block.
Definition: NiftiImage.h:569
const Block volume(const int i) const
Extract a volume block from a 4D image.
Definition: NiftiImage.h:1124
bool owner
An indicator of whether this object is responsible for cleaning up the data.
Definition: NiftiImage.h:121
bool isPersistent() const
Determine whether or not the image is marked as persistent.
Definition: NiftiImage.h:899
size_t totalBytes() const
Return the total size of the data blob, in bytes.
Definition: NiftiImage.h:401
std::vector< TargetType > getData(const bool useSlope=true) const
Extract a vector of data from a block, casting it to any required element type.
void setPixunits(const std::vector< std::string > &pixunits)
Modify the pixel dimension units.
Element & operator=(const SourceType &value)
Copy assignment operator.
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:398
void * blob() const
Return an opaque pointer to the blob.
Definition: NiftiImage.h:392
NiftiImage(const Block &source)
Initialise from a block, copying in the data.
Definition: NiftiImage.h:753
virtual ~NiftiImage()
Destructor which decrements the reference counter, and releases the wrapped pointer if the counter dr...
Definition: NiftiImage.h:823
Thin wrapper around a C-style nifti_image struct that allows C++-style destruction.
Definition: NiftiImage.h:511
virtual ~NiftiImageData()
Destructor which frees the type handler, and the data blob if it is owned by this object.
Definition: NiftiImage.h:367
int _datatype
Datatype code indicating the actual type of the elements.
Definition: NiftiImage.h:118
NiftiImage(const NiftiImage &source, const bool copy=true)
Copy constructor.
Definition: NiftiImage.h:737
NiftiImageData & operator=(const NiftiImageData &source)
Copy assignment operator.
Definition: NiftiImage.h:379
TypeHandler * handler
Type handler, which is created to match the datatype.
Definition: NiftiImage.h:119
int nBlocks() const
Return the number of blocks in the image.
Definition: NiftiImage.h:1079
Inner class representing a single element in the data blob.
Definition: NiftiImage.h:183
void release()
Release the currently wrapped pointer, if it is not NULL, decrementing the reference count and releas...
void calibrateFrom(const NiftiImageData &data)
Update the slope and intercept to cover the range of another data object.
Definition: NiftiImage.h:159
const int dimension
The dimension along which the block applies (which should be the last)
Definition: NiftiImage.h:521
const NiftiImage & image
The parent image.
Definition: NiftiImage.h:520
NiftiImage & operator=(const NiftiImage &source)
Copy assignment operator, which copies from its argument.
Definition: NiftiImage.h:849
NiftiImage & changeDatatype(const int datatype, const bool useSlope=false)
Change the datatype of the image, casting the pixel data if present.
NiftiImageData unscaled() const
Return a similar object to the callee, but with the slope and intercept values reset.
Definition: NiftiImage.h:445
static int fileVersion(const std::string &path)
Get the NIfTI format version used by the file at the specified path.
static mat33 xformToRotation(const mat44 matrix)
Extract the pure rotation part of a 4x4 xform matrix.
void updatePixdim(const std::vector< float > &pixdim)
Modify the pixel dimensions, and potentially the xform matrices to match.
const Block block(const int i) const
Extract a block from the image.
Definition: NiftiImage.h:1094
NiftiImageData(const NiftiImageData &source, const int datatype=DT_NONE)
Copy constructor with optional type conversion.
Definition: NiftiImage.h:337
Element(const NiftiImageData &parent, void *ptr=NULL)
Primary constructor.
Definition: NiftiImage.h:196
bool isScaled() const
Determine whether the object uses data scaling.
Definition: NiftiImage.h:414
NiftiImageData data()
Obtain the pixel data within the image.
Definition: NiftiImage.h:970
NiftiImage & setPersistence(const bool persistent)
Mark the image as persistent, so that it can be passed back to R.
Definition: NiftiImage.h:879
std::vector< TargetType > getData(const bool useSlope=true) const
Extract a vector of data from the image, casting it to any required element type.
Iterator(const Iterator &other)
Copy constructor.
Definition: NiftiImage.h:263
void copy(const nifti_image *source)
Copy the contents of a nifti_image to create a new image, acquiring the new pointer.
mat44 xform(const bool preferQuaternion=true) const
Obtain an xform matrix, indicating the orientation of the image.
nifti_image * image
The wrapped nifti_image pointer.
Definition: NiftiImage.h:635
double intercept
The intercept term used to scale data values.
Definition: NiftiImage.h:56
int nDims() const
Return the number of dimensions in the image.
Definition: NiftiImage.h:912
void * dataPtr
Opaque pointer to the underlying data blob.
Definition: NiftiImage.h:117
TypeHandler * createHandler()
Create a concrete type handler appropriate to the datatype code stored with the data.
Definition: NiftiImage.h:94
size_t _length
The number of data elements in the blob.
Definition: NiftiImage.h:120
Iterator begin()
Obtain a mutable iterator corresponding to the start of the blob.
Definition: NiftiImage.h:460
Block volume(const int i)
Extract a volume block from a 4D image.
Definition: NiftiImage.h:1131
size_t length() const
Return the number of elements in the data.
Definition: NiftiImage.h:394
Wrapper class encapsulating a NIfTI data blob, with responsibility for handling data scaling and poly...
Definition: NiftiImage.h:52
NiftiImage & drop()
Drop unitary dimensions.
Definition: NiftiImage.h:950
NiftiImageData & disown()
Disown the data blob, removing responsibility for freeing it upon destruction.
Definition: NiftiImage.h:451
NiftiImage & reorient(const int i, const int j, const int k)
Reorient the image by permuting dimensions and potentially reversing some.
Block(const NiftiImage &image, const int dimension, const int index)
Standard constructor for this class.
Definition: NiftiImage.h:531
void toFile(const std::string fileName, const int datatype=DT_NONE) const
Write the image to a NIfTI-1 file.
bool isFloatingPoint() const
Determine whether the datatype is floating point.
Definition: NiftiImage.h:427
NiftiImageData(nifti_image *image)
Convenience constructor for a nifti_image.
Definition: NiftiImage.h:322
const Iterator end() const
Obtain a constant iterator corresponding to the end of the blob.
Definition: NiftiImage.h:457
bool isEmpty() const
Determine whether or not the object is empty.
Definition: NiftiImage.h:407
NiftiImageData(InputIterator from, InputIterator to, const int datatype)
Iterator-based constructor.
Definition: NiftiImage.h:357
NiftiImage & dropData()
Drop the data from the image, retaining only the metadata.
Definition: NiftiImage.h:1025
Block block(const int i)
Extract a block from the image.
Definition: NiftiImage.h:1103