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
43namespace RNifti {
44
45typedef std::complex<float> complex64_t;
46typedef std::complex<double> complex128_t;
47
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{
73public:
74 double slope;
75 double intercept;
77protected:
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>
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;
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
263public:
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
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 {
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
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
616template <>
617inline bool NiftiImageData::ConcreteTypeHandler<int>::hasNaN () const { return true; }
618#endif
619
620
625template <typename ElementType, int Length>
627{
628protected:
629 ElementType elements[Length];
630
631public:
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
671template <class NiftiType, typename ElementType, int Order>
673{
674protected:
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
693public:
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
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
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
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{
836public:
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 {
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 != size_t(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
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
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
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;
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
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
1174#ifdef USING_R
1178 Xform & operator= (SEXP source)
1179 {
1180 replace(Matrix(source));
1181 return *this;
1182 }
1183#endif
1184
1188 const Matrix & matrix () const { return mat; }
1189
1193 Submatrix submatrix () const;
1194
1199 Submatrix rotation () const;
1200
1206 Element handedness () const;
1207
1211 Vector4 quaternion () const;
1212
1216 Vector3 offset () const;
1217
1221 Vector3 spacing () const;
1222
1230 std::string orientation () const;
1231 };
1232
1233#ifdef USING_R
1240 static int sexpTypeToNiftiType (const int sexpType)
1241 {
1242 if (sexpType == INTSXP || sexpType == LGLSXP)
1243 return DT_INT32;
1244 else if (sexpType == REALSXP)
1245 return DT_FLOAT64;
1246 else if (sexpType == CPLXSXP)
1247 return DT_COMPLEX128;
1248 else
1249 throw std::runtime_error("Array elements must be numeric");
1250 }
1251#endif
1252
1259 static int fileVersion (const std::string &path);
1260
1261
1262protected:
1263 nifti_image *image;
1272 void acquire (nifti_image * const image);
1273
1278 void acquire (const NiftiImage &source)
1279 {
1280 refCount = source.refCount;
1281 acquire(source.image);
1282 }
1283
1288 void release ();
1289
1294 void copy (const nifti_image *source);
1295
1300 void copy (const NiftiImage &source);
1301
1306 void copy (const Block &source);
1307
1308
1309#ifdef USING_R
1310
1316 void initFromNiftiS4 (const Rcpp::RObject &object, const bool copyData = true);
1317
1323 void initFromMriImage (const Rcpp::RObject &object, const bool copyData = true);
1324
1329 void initFromList (const Rcpp::RObject &object);
1330
1336 void initFromArray (const Rcpp::RObject &object, const bool copyData = true);
1337
1338#endif
1339
1345 void initFromDims (const std::vector<dim_t> &dim, const int datatype);
1346
1351 void updatePixdim (const std::vector<pixdim_t> &pixdim);
1352
1357 void setPixunits (const std::vector<std::string> &pixunits);
1358
1359public:
1364 : image(NULL), refCount(NULL) {}
1365
1372 NiftiImage (const NiftiImage &source, const bool copy = true)
1373 : image(NULL), refCount(NULL)
1374 {
1375 if (copy)
1376 this->copy(source);
1377 else
1378 acquire(source);
1379#ifndef NDEBUG
1380 Rc_printf("Creating NiftiImage (v%d) with pointer %p (from NiftiImage)\n", RNIFTI_NIFTILIB_VERSION, this->image);
1381#endif
1382 }
1383
1388 NiftiImage (const Block &source)
1389 : image(NULL), refCount(NULL)
1390 {
1391 this->copy(source);
1392#ifndef NDEBUG
1393 Rc_printf("Creating NiftiImage (v%d) with pointer %p (from Block)\n", RNIFTI_NIFTILIB_VERSION, this->image);
1394#endif
1395 }
1396
1403 NiftiImage (nifti_image * const image, const bool copy = false)
1404 : image(NULL), refCount(NULL)
1405 {
1406 if (copy)
1407 this->copy(image);
1408 else
1409 acquire(image);
1410#ifndef NDEBUG
1411 Rc_printf("Creating NiftiImage (v%d) with pointer %p (from pointer)\n", RNIFTI_NIFTILIB_VERSION, this->image);
1412#endif
1413 }
1414
1420 NiftiImage (const std::vector<dim_t> &dim, const int datatype);
1421
1427 NiftiImage (const std::vector<dim_t> &dim, const std::string &datatype);
1428
1435 NiftiImage (const std::string &path, const bool readData = true);
1436
1443 NiftiImage (const std::string &path, const std::vector<dim_t> &volumes);
1444
1445#ifdef USING_R
1456 NiftiImage (const SEXP object, const bool readData = true, const bool readOnly = false);
1457#endif
1458
1463 virtual ~NiftiImage () { release(); }
1464
1468 operator const nifti_image* () const { return image; }
1469
1473 operator nifti_image* () { return image; }
1474
1478 const nifti_image * operator-> () const { return image; }
1479
1483 nifti_image * operator-> () { return image; }
1484
1490 {
1491 copy(source);
1492#ifndef NDEBUG
1493 Rc_printf("Creating NiftiImage (v%d), with pointer %p (from NiftiImage)\n", RNIFTI_NIFTILIB_VERSION, this->image);
1494#endif
1495 return *this;
1496 }
1497
1503 NiftiImage & operator= (const Block &source)
1504 {
1505 copy(source);
1506#ifndef NDEBUG
1507 Rc_printf("Creating NiftiImage (v%d) with pointer %p (from Block)\n", RNIFTI_NIFTILIB_VERSION, this->image);
1508#endif
1509 return *this;
1510 }
1511
1519 NiftiImage & setPersistence (const bool persistent) { return *this; }
1520
1525 bool isNull () const { return (image == NULL); }
1526
1531 bool isShared () const { return (refCount != NULL && *refCount > 1); }
1532
1539 bool isPersistent () const { return false; }
1540
1546 bool isDataScaled () const { return (image != NULL && image->scl_slope != 0.0 && (image->scl_slope != 1.0 || image->scl_inter != 0.0)); }
1547
1552 int nDims () const
1553 {
1554 if (image == NULL)
1555 return 0;
1556 else
1557 return image->ndim;
1558 }
1559
1564 std::vector<dim_t> dim () const
1565 {
1566 if (image == NULL)
1567 return std::vector<dim_t>();
1568 else
1569 return std::vector<dim_t>(image->dim+1, image->dim+image->ndim+1);
1570 }
1571
1576 std::vector<pixdim_t> pixdim () const
1577 {
1578 if (image == NULL)
1579 return std::vector<pixdim_t>();
1580 else
1581 return std::vector<pixdim_t>(image->pixdim+1, image->pixdim+image->ndim+1);
1582 }
1583
1591 {
1592 int ndim = image->ndim;
1593 while (image->dim[ndim] < 2)
1594 ndim--;
1595 image->dim[0] = image->ndim = ndim;
1596
1597 return *this;
1598 }
1599
1604 const NiftiImageData data () const { return NiftiImageData(image); }
1605
1611
1621 template <typename TargetType>
1622 std::vector<TargetType> getData (const bool useSlope = true) const;
1623
1631 NiftiImage & changeDatatype (const int datatype, const bool useSlope = false);
1632
1640 NiftiImage & changeDatatype (const std::string &datatype, const bool useSlope = false);
1641
1650 template <typename SourceType>
1651 NiftiImage & replaceData (const std::vector<SourceType> &data, const int datatype = DT_NONE);
1652
1660
1667 {
1668#if RNIFTI_NIFTILIB_VERSION == 1
1669 nifti_image_unload(image);
1670#elif RNIFTI_NIFTILIB_VERSION == 2
1671 nifti2_image_unload(image);
1672#endif
1673 return *this;
1674 }
1675
1682 NiftiImage & rescale (const std::vector<pixdim_t> &scales);
1683
1692 NiftiImage & reorient (const int i, const int j, const int k);
1693
1702 NiftiImage & reorient (const std::string &orientation);
1703
1704#ifdef USING_R
1710 NiftiImage & update (const Rcpp::RObject &object);
1711#endif
1712
1719 const Xform xform (const bool preferQuaternion = true) const;
1720
1725 const Xform qform () const { return (image == NULL ? Xform() : Xform(image->qto_xyz)); }
1726
1731 Xform qform () { return (image == NULL ? Xform() : Xform(image->qto_xyz, image->qto_ijk, &image->quatern_b)); }
1732
1737 const Xform sform () const { return (image == NULL ? Xform() : Xform(image->sto_xyz)); }
1738
1743 Xform sform () { return (image == NULL ? Xform() : Xform(image->sto_xyz, image->sto_ijk)); }
1744
1749 dim_t nBlocks () const { return (image == NULL ? 0 : image->dim[image->ndim]); }
1750
1758 const Block block (const int i) const { return Block(*this, nDims(), i); }
1759
1767 Block block (const int i) { return Block(*this, nDims(), i); }
1768
1774 const Block slice (const int i) const { return Block(*this, 3, i); }
1775
1781 Block slice (const int i) { return Block(*this, 3, i); }
1782
1788 const Block volume (const int i) const { return Block(*this, 4, i); }
1789
1795 Block volume (const int i) { return Block(*this, 4, i); }
1796
1802 int nChannels () const
1803 {
1804 if (image == NULL)
1805 return 0;
1806 else
1807 {
1808 switch (image->datatype)
1809 {
1810 case DT_NONE: return 0;
1811 case DT_RGB24: return 3;
1812 case DT_RGBA32: return 4;
1813 default: return 1;
1814 }
1815 }
1816 }
1817
1822 size_t nVoxels () const { return (image == NULL ? 0 : image->nvox); }
1823
1828 int nExtensions () const { return (image == NULL ? 0 : image->num_ext); }
1829
1836 std::list<Extension> extensions (const int code = -1) const
1837 {
1838 if (image == NULL)
1839 return std::list<Extension>();
1840 else
1841 {
1842 std::list<Extension> result;
1843 for (int i=0; i<image->num_ext; i++)
1844 {
1845 const Extension extension(image->ext_list + i);
1846 if (code < 0 || code == extension.code())
1847 result.push_back(extension);
1848 }
1849 return result;
1850 }
1851 }
1852
1858 NiftiImage & addExtension (const Extension &extension)
1859 {
1860 if (image != NULL)
1861#if RNIFTI_NIFTILIB_VERSION == 1
1862 nifti_add_extension(image, extension.data(), int(extension.length()), extension.code());
1863#elif RNIFTI_NIFTILIB_VERSION == 2
1864 nifti2_add_extension(image, extension.data(), int(extension.length()), extension.code());
1865#endif
1866 return *this;
1867 }
1868
1874 NiftiImage & replaceExtensions (const std::list<Extension> extensions)
1875 {
1877 for (std::list<Extension>::const_iterator it=extensions.begin(); it!=extensions.end(); ++it)
1878 addExtension(*it);
1879 return *this;
1880 }
1881
1887 {
1888 if (image != NULL)
1889#if RNIFTI_NIFTILIB_VERSION == 1
1890 nifti_free_extensions(image);
1891#elif RNIFTI_NIFTILIB_VERSION == 2
1892 nifti2_free_extensions(image);
1893#endif
1894 return *this;
1895 }
1896
1905 std::pair<std::string,std::string> toFile (const std::string fileName, const int datatype = DT_NONE, const int filetype = -1) const;
1906
1915 std::pair<std::string,std::string> toFile (const std::string fileName, const std::string &datatype, const int filetype = -1) const;
1916
1917#ifdef USING_R
1918
1923 Rcpp::RObject toArray () const;
1924
1930 Rcpp::RObject toPointer (const std::string label) const;
1931
1938 Rcpp::RObject toArrayOrPointer (const bool internal, const std::string label) const;
1939
1940#endif
1941
1942};
1943
1944// Include image implementations
1945#include "RNifti/NiftiImage_impl.h"
1946
1947} // main namespace
1948
1949#endif
Simple RGB(A) type encapsulating an 8-bit colour value with optional opacity, which can also be set o...
Definition: NiftiImage.h:55
Definition: NiftiImage.h:56
Wrapper class encapsulating a NIfTI data blob, with responsibility for handling data scaling and poly...
Definition: NiftiImage.h:72
int datatype() const
Return stored datatype code.
Definition: NiftiImage.h:508
bool isRgb() const
Determine whether the datatype corresponds to an RGB type.
Definition: NiftiImage.h:554
NiftiImageData(nifti_image *image)
Convenience constructor for a nifti_image.
Definition: NiftiImage.h:437
size_t length() const
Return the number of elements in the data.
Definition: NiftiImage.h:509
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
bool isScaled() const
Determine whether the object uses data scaling.
Definition: NiftiImage.h:529
NiftiImageData()
Default constructor, creating an empty data object.
Definition: NiftiImage.h:416
int _datatype
Datatype code indicating the actual type of the elements.
Definition: NiftiImage.h:202
TypeHandler * handler
Type handler, which is created to match the datatype.
Definition: NiftiImage.h:203
Iterator end()
Obtain a mutable iterator corresponding to the end of the blob.
Definition: NiftiImage.h:578
NiftiImageData unscaled() const
Return a similar object to the callee, but with the slope and intercept values reset.
Definition: NiftiImage.h:560
size_t totalBytes() const
Return the total size of the data blob, in bytes.
Definition: NiftiImage.h:516
void minmax(double *min, double *max) const
Calculate the minimum and maximum values in the blob, as doubles.
Definition: NiftiImage.h:601
const Iterator begin() const
Obtain a constant iterator corresponding to the start of the blob.
Definition: NiftiImage.h:569
double slope
The slope term used to scale data values.
Definition: NiftiImage.h:74
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
double intercept
The intercept term used to scale data values.
Definition: NiftiImage.h:75
bool isFloatingPoint() const
Determine whether the datatype is floating point.
Definition: NiftiImage.h:542
const Iterator end() const
Obtain a constant iterator corresponding to the end of the blob.
Definition: NiftiImage.h:572
NiftiImageData & disown()
Disown the data blob, removing responsibility for freeing it upon destruction.
Definition: NiftiImage.h:566
const Element operator[](const size_t i) const
Indexing operator, returning a constant element.
Definition: NiftiImage.h:585
size_t _length
The number of data elements in the blob.
Definition: NiftiImage.h:204
TypeHandler * createHandler()
Create a concrete type handler appropriate to the datatype code stored with the data.
Definition: NiftiImage.h:174
NiftiImageData & operator=(const NiftiImageData &source)
Copy assignment operator.
Definition: NiftiImage.h:494
NiftiImageData(const NiftiImageData &source, const int datatype=DT_NONE)
Copy constructor with optional type conversion.
Definition: NiftiImage.h:452
bool isInteger() const
Determine whether the datatype is an integer type.
Definition: NiftiImage.h:548
virtual ~NiftiImageData()
Destructor which frees the type handler, and the data blob if it is owned by this object.
Definition: NiftiImage.h:482
size_t size() const
Return the number of elements in the data.
Definition: NiftiImage.h:510
bool owner
An indicator of whether this object is responsible for cleaning up the data.
Definition: NiftiImage.h:205
NiftiImageData(InputIterator from, InputIterator to, const int datatype)
Iterator-based constructor.
Definition: NiftiImage.h:472
Iterator begin()
Obtain a mutable iterator corresponding to the start of the blob.
Definition: NiftiImage.h:575
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
bool isEmpty() const
Determine whether or not the object is empty.
Definition: NiftiImage.h:522
void * blob() const
Return an opaque pointer to the blob.
Definition: NiftiImage.h:507
void calibrateFrom(const NiftiImageData &data)
Update the slope and intercept to cover the range of another data object.
Definition: NiftiImage.h:243
bool isComplex() const
Determine whether the datatype is complex.
Definition: NiftiImage.h:535
void * dataPtr
Opaque pointer to the underlying data blob.
Definition: NiftiImage.h:201
Abstract inner class defining the type-specific functions required in concrete subclasses.
Definition: NiftiImage.h:82
Concrete inner class template defining behaviour specific to individual data types.
Definition: NiftiImage.h:102
Inner class representing a single element in the data blob.
Definition: NiftiImage.h:268
Element(const NiftiImageData &parent, void *ptr=NULL)
Primary constructor.
Definition: NiftiImage.h:280
Element & operator=(const SourceType &value)
Copy assignment operator.
Iterator type for NiftiImageData, with Element as its value type.
Definition: NiftiImage.h:353
Iterator(const NiftiImageData &parent, void *ptr=NULL, const size_t step=0)
Primary constructor.
Definition: NiftiImage.h:367
Iterator(const Iterator &other)
Copy constructor.
Definition: NiftiImage.h:378
A simple object-oriented wrapper around a fixed-length array.
Definition: NiftiImage.h:627
Vector(const ElementType *source)
Initialise from a C-style array of the appropriate type and length.
Definition: NiftiImage.h:643
Vector< ElementType, Length > operator-() const
Unary negation operator, which reverses the signs of all elements.
Definition: NiftiImage.h:651
Vector(const ElementType value=0.0)
Initialise with a fixed element value, defaulting to zero.
Definition: NiftiImage.h:635
Class representing a numeric square matrix of a fixed order.
Definition: NiftiImage.h:673
SquareMatrix(const ElementType value=0.0)
Initialise with a fixed element value, defaulting to zero.
Definition: NiftiImage.h:701
ElementType elements[Order *Order]
The underlying raw data elements, stored row-major for consistency with niftilib.
Definition: NiftiImage.h:675
const ElementType * begin() const
Return a pointer/iterator to the beginning of the data.
Definition: NiftiImage.h:756
MatrixType inverse() const
Matrix inverse.
SquareMatrix(const ElementType *source)
Initialise from a C-style array of the appropriate type and length.
Definition: NiftiImage.h:709
MatrixType polar() const
Polar decomposition, as implemented in niftilib (Order 3 only)
ElementType * end()
Return a pointer/iterator to the end of the data.
Definition: NiftiImage.h:772
Vector< ElementType, Order > VectorType
Type of vectors for which this matrix is a linear operator.
Definition: NiftiImage.h:696
const ElementType * end() const
Return a pointer/iterator to the end of the data.
Definition: NiftiImage.h:767
NiftiType NativeType
The niftilib structure type corresponding to this matrix.
Definition: NiftiImage.h:694
MatrixType multiply(const MatrixType &other) const
Matrix-matrix multiplication.
ElementType rownorm() const
Maximum row norm, as implemented in niftilib (Order 3 only)
const ElementType & operator()(const int i, const int j) const
Indexing operator.
Definition: NiftiImage.h:799
ElementType colnorm() const
Maximum column norm, as implemented in niftilib (Order 3 only)
NiftiType niftiCopy() const
Copy the data elements into a new NIfTI-style mat44 or dmat44.
Definition: NiftiImage.h:686
ElementType * begin()
Return a pointer/iterator to the beginning of the data.
Definition: NiftiImage.h:762
SquareMatrix< NiftiType, ElementType, Order > MatrixType
Type alias for the current specialisation.
Definition: NiftiImage.h:695
SquareMatrix(SEXP source)
Initialise from an R object representing a numeric matrix.
Definition: NiftiImage.h:727
ElementType determ() const
Matrix determinant, as implemented in niftilib (Order 3 only)
VectorType multiply(const VectorType &vec) const
Matrix-vector multiplication.
static MatrixType eye()
Construct an identity matrix of the appropriate size.
Definition: NiftiImage.h:777
MatrixType operator*(const MatrixType &other) const
Matrix-matrix multiplication (infix shorthand)
Definition: NiftiImage.h:793
SquareMatrix(const NiftiType &source)
Initialise from the appropriate niftilib type.
Definition: NiftiImage.h:717
NiftiType * niftiPointer() const
Obtain a pointer to a NIfTI-style mat44 or dmat44 encapsulating the same data as this object.
Definition: NiftiImage.h:681
Thin wrapper around a C-style nifti_image struct that allows C++-style destruction.
Definition: NiftiImage.h:835
void release()
Release the currently wrapped pointer, if it is not NULL, decrementing the reference count and releas...
NiftiImage & reorient(const std::string &orientation)
Reorient the image by permuting dimensions and potentially reversing some.
void initFromMriImage(const Rcpp::RObject &object, const bool copyData=true)
Initialise the object from a reference object of class "MriImage".
NiftiImage & replaceData(const NiftiImageData &data)
Replace the pixel data in the image with the contents of a NiftiImageData object.
std::list< Extension > extensions(const int code=-1) const
Return a list of the extensions associated with the image.
Definition: NiftiImage.h:1836
NiftiImage(const NiftiImage &source, const bool copy=true)
Copy constructor.
Definition: NiftiImage.h:1372
bool isDataScaled() const
Determine whether nontrivial scale and slope parameters are set.
Definition: NiftiImage.h:1546
NiftiImage & update(const Rcpp::RObject &object)
Update the image from an R array.
void setPixunits(const std::vector< std::string > &pixunits)
Modify the pixel dimension units.
const Xform xform(const bool preferQuaternion=true) const
Obtain an xform matrix, indicating the orientation of the image.
void acquire(const NiftiImage &source)
Acquire the same pointer as another NiftiImage, incrementing the shared reference count.
Definition: NiftiImage.h:1278
static int fileVersion(const std::string &path)
Get the NIfTI format version used by the file at the specified path.
void updatePixdim(const std::vector< pixdim_t > &pixdim)
Modify the pixel dimensions, and potentially the xform matrices to match.
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.
NiftiImage & rescale(const std::vector< pixdim_t > &scales)
Rescale the image, changing its image dimensions and pixel dimensions.
std::vector< pixdim_t > pixdim() const
Return the dimensions of the pixels or voxels in the image.
Definition: NiftiImage.h:1576
int nExtensions() const
Return the number of extensions associated with the image.
Definition: NiftiImage.h:1828
Xform sform()
Access the sform matrix.
Definition: NiftiImage.h:1743
NiftiImage & reorient(const int i, const int j, const int k)
Reorient the image by permuting dimensions and potentially reversing some.
bool isNull() const
Determine whether or not the wrapped pointer is NULL.
Definition: NiftiImage.h:1525
virtual ~NiftiImage()
Destructor which decrements the reference counter, and releases the wrapped pointer if the counter dr...
Definition: NiftiImage.h:1463
NiftiImage(const Block &source)
Initialise from a block, copying in the data.
Definition: NiftiImage.h:1388
const nifti_image * operator->() const
Allows a NiftiImage object to be treated as a pointer to a const nifti_image.
Definition: NiftiImage.h:1478
int nChannels() const
Return the number of colour channels used by the image.
Definition: NiftiImage.h:1802
NiftiImage(const std::vector< dim_t > &dim, const int datatype)
Initialise from basic metadata, allocating and zeroing pixel data.
NiftiImage(const std::vector< dim_t > &dim, const std::string &datatype)
Initialise from basic metadata, allocating and zeroing pixel data.
NiftiImage & dropExtensions()
Remove any extensions from the image.
Definition: NiftiImage.h:1886
void initFromNiftiS4(const Rcpp::RObject &object, const bool copyData=true)
Initialise the object from an S4 object of class "nifti".
const NiftiImageData data() const
Obtain the pixel data within the image.
Definition: NiftiImage.h:1604
std::vector< dim_t > dim() const
Return the dimensions of the image.
Definition: NiftiImage.h:1564
bool isShared() const
Determine whether the wrapped pointer is shared with another NiftiImage.
Definition: NiftiImage.h:1531
dim_t nBlocks() const
Return the number of blocks in the image.
Definition: NiftiImage.h:1749
std::vector< TargetType > getData(const bool useSlope=true) const
Extract a vector of data from the image, casting it to any required element type.
nifti_image * image
The wrapped nifti_image pointer.
Definition: NiftiImage.h:1263
const Block block(const int i) const
Extract a block from the image.
Definition: NiftiImage.h:1758
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.
static int sexpTypeToNiftiType(const int sexpType)
Convert between R SEXP object type and nifti_image datatype codes.
Definition: NiftiImage.h:1240
int * refCount
A reference counter, shared with other objects wrapping the same pointer.
Definition: NiftiImage.h:1264
NiftiImage & operator=(const NiftiImage &source)
Copy assignment operator, which copies from its argument.
Definition: NiftiImage.h:1489
bool isPersistent() const
Determine whether or not the image is marked as persistent.
Definition: NiftiImage.h:1539
Block block(const int i)
Extract a block from the image.
Definition: NiftiImage.h:1767
NiftiImage & replaceExtensions(const std::list< Extension > extensions)
Replace all extensions with new ones.
Definition: NiftiImage.h:1874
Rcpp::RObject toPointer(const std::string label) const
Create an internal image to pass back to R.
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...
Block slice(const int i)
Extract a slice block from a 3D image.
Definition: NiftiImage.h:1781
NiftiImage & dropData()
Drop the data from the image, retaining only the metadata.
Definition: NiftiImage.h:1666
NiftiImage & changeDatatype(const std::string &datatype, const bool useSlope=false)
Change the datatype of the image, casting the pixel data if present.
Rcpp::RObject toArrayOrPointer(const bool internal, const std::string label) const
A conditional method that calls either toArray or toPointer.
void copy(const NiftiImage &source)
Copy the contents of another NiftiImage to create a new image, acquiring a new pointer.
NiftiImage & changeDatatype(const int datatype, const bool useSlope=false)
Change the datatype of the image, casting the pixel data if present.
NiftiImageData data()
Obtain the pixel data within the image.
Definition: NiftiImage.h:1610
Rcpp::RObject toArray() const
Create an R array from the image.
int nDims() const
Return the number of dimensions in the image.
Definition: NiftiImage.h:1552
NiftiImage(nifti_image *const image, const bool copy=false)
Initialise using an existing nifti_image pointer.
Definition: NiftiImage.h:1403
Block volume(const int i)
Extract a volume block from a 4D image.
Definition: NiftiImage.h:1795
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.
void acquire(nifti_image *const image)
Acquire the specified pointer to a nifti_image struct, taking (possibly shared) responsibility for fr...
NiftiImage(const std::string &path, const std::vector< dim_t > &volumes)
Initialise using a path string and sequence of required volumes.
const Block volume(const int i) const
Extract a volume block from a 4D image.
Definition: NiftiImage.h:1788
void initFromArray(const Rcpp::RObject &object, const bool copyData=true)
Initialise the object from an R array.
void copy(const Block &source)
Copy the contents of a Block to create a new image, acquiring a new pointer.
size_t nVoxels() const
Return the number of voxels in the image.
Definition: NiftiImage.h:1822
Xform qform()
Access the qform matrix.
Definition: NiftiImage.h:1731
const Block slice(const int i) const
Extract a slice block from a 3D image.
Definition: NiftiImage.h:1774
const Xform sform() const
Access the sform matrix.
Definition: NiftiImage.h:1737
NiftiImage & drop()
Drop unitary dimensions.
Definition: NiftiImage.h:1590
NiftiImage & setPersistence(const bool persistent)
Mark the image as persistent, so that it can be passed back to R.
Definition: NiftiImage.h:1519
void copy(const nifti_image *source)
Copy the contents of a nifti_image to create a new image, acquiring the new pointer.
NiftiImage()
Default constructor.
Definition: NiftiImage.h:1363
void initFromList(const Rcpp::RObject &object)
Initialise the object from an R list with named elements, which can only contain metadata.
NiftiImage & addExtension(const Extension &extension)
Add an extension to the image.
Definition: NiftiImage.h:1858
void initFromDims(const std::vector< dim_t > &dim, const int datatype)
Initialise an empty object from basic metadata.
NiftiImage(const std::string &path, const bool readData=true)
Initialise using a path string.
const Xform qform() const
Access the qform matrix.
Definition: NiftiImage.h:1725
Inner class referring to a subset of an image.
Definition: NiftiImage.h:852
NiftiImageData data() const
Obtain the data within the block.
Definition: NiftiImage.h:902
const NiftiImage & image
The parent image.
Definition: NiftiImage.h:853
const dim_t index
The location along dimension.
Definition: NiftiImage.h:855
Block(const NiftiImage &image, const int dimension, const dim_t index)
Standard constructor for this class.
Definition: NiftiImage.h:864
const int dimension
The dimension along which the block applies (which should be the last)
Definition: NiftiImage.h:854
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
std::vector< TargetType > getData(const bool useSlope=true) const
Extract a vector of data from a block, casting it to any required element type.
Inner class wrapping a NIfTI extension, a weakly-specified standard for attaching additional metadata...
Definition: NiftiImage.h:931
void copy(const nifti1_extension *source)
Copy an existing nifti1_extension structure into the object.
Extension(const SourceType *data, const size_t length, const int code)
Construct the object from its constituent parts.
Definition: NiftiImage.h:988
Extension(const Extension &source)
Copy constructor.
Definition: NiftiImage.h:976
void copy(const SourceType *data, const size_t length, const int code)
Copy the specified data buffer into the object.
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
int code() const
Return the code associated with the extension.
Definition: NiftiImage.h:1031
size_t length() const
Return the length of the data array.
Definition: NiftiImage.h:1043
Extension()
Default constructor, wrapping NULL.
Definition: NiftiImage.h:954
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
size_t size() const
Return the length of the data array.
Definition: NiftiImage.h:1049
const char * data() const
Return the data blob associated with the extension.
Definition: NiftiImage.h:1037
nifti1_extension * ext
The wrapped extension structure.
Definition: NiftiImage.h:933
Inner class representing an xform matrix, which indicates the orientation and other spatial propertie...
Definition: NiftiImage.h:1077
Xform & operator=(const Xform &source)
Copy assignment operator, taking an Xform and replacing linked data.
Definition: NiftiImage.h:1159
const Matrix & matrix() const
Access the xform matrix as an immutable SquareMatrix object.
Definition: NiftiImage.h:1188
Xform()
Default constructor.
Definition: NiftiImage.h:1107
Xform(Matrix::NativeType &source, Matrix::NativeType &inverse, Element *qparams=NULL)
Initialise from forward and backward matrices, and optionally quaternion parameters.
Definition: NiftiImage.h:1133
Vector3 spacing() const
Obtain the pixel spacing of the image in each spatial dimension.
Xform(const Matrix &source)
Initialise from a 4x4 SquareMatrix.
Definition: NiftiImage.h:1113
Submatrix rotation() const
Obtain the 3x3 rotation matrix from the xform matrix, with scale and skew components removed.
Xform(Matrix::NativeType &source)
Initialise from a NIfTI mat44 or dmat44.
Definition: NiftiImage.h:1126
void replace(const Matrix &source)
Replace the current matrix with a new one.
Matrix mat
The full xform matrix underpinning this object.
Definition: NiftiImage.h:1095
Submatrix submatrix() const
Obtain the upper left 3x3 submatrix from the xform matrix.
Element handedness() const
Returns the qfac value, which should be 1 where the xform matrix represents a right-handed coordinate...
Xform(SEXP source)
Initialise from an R numeric matrix object.
Definition: NiftiImage.h:1140
Vector4 quaternion() const
Obtain the quaternion representation of the xform's rotation component.
std::string orientation() const
Obtain the approximate orientation of the image's coordinate frame, as a three-character string consi...
Xform(const Matrix::NativeType &source)
Initialise from a constant NIfTI mat44 or dmat44.
Definition: NiftiImage.h:1119
Element * qparams
Pointers to linked C-style arrays.
Definition: NiftiImage.h:1094
Vector3 offset() const
Obtain the translation component of the xform matrix.