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#else
10
11#define R_NegInf -INFINITY
12
13#include <stdint.h>
14#include <cstddef>
15#include <cmath>
16#include <string>
17#include <sstream>
18#include <vector>
19#include <list>
20#include <complex>
21#include <stdexcept>
22#include <algorithm>
23#include <map>
24#include <locale>
25#include <limits>
26
27#endif
28
36
37namespace RNifti {
38
39typedef std::complex<float> complex64_t;
40typedef std::complex<double> complex128_t;
41
48struct rgba32_t
49{
50 union ValueType {
51 int packed;
52 unsigned char bytes[4];
53 };
54 ValueType value;
55 rgba32_t () { value.packed = 0; }
56};
57
66{
67public:
68 double slope;
69 double intercept;
70
71protected:
76 {
77 virtual ~TypeHandler() {}
78 virtual size_t size () const { return 0; }
79 virtual bool hasNaN () const { return false; }
80 virtual complex128_t getComplex (void *ptr) const { return complex128_t(0.0, 0.0); }
81 virtual double getDouble (void *ptr) const { return 0.0; }
82 virtual int getInt (void *ptr) const { return 0; }
83 virtual rgba32_t getRgb (void *ptr) const { return rgba32_t(); }
84 virtual void setComplex (void *ptr, const complex128_t value) const {}
85 virtual void setDouble (void *ptr, const double value) const {}
86 virtual void setInt (void *ptr, const int value) const {}
87 virtual void setRgb (void *ptr, const rgba32_t value) const {}
88 virtual void minmax (void *ptr, const size_t length, double *min, double *max) const { *min = 0.0; *max = 0.0; }
89 };
90
94 template <typename Type, bool alpha = false>
96 {
97 size_t size () const { return (sizeof(Type)); }
98 bool hasNaN () const { return std::numeric_limits<Type>::has_quiet_NaN; }
99 complex128_t getComplex (void *ptr) const { return complex128_t(static_cast<double>(*static_cast<Type*>(ptr)), 0.0); }
100 double getDouble (void *ptr) const { return static_cast<double>(*static_cast<Type*>(ptr)); }
101 int getInt (void *ptr) const { return static_cast<int>(*static_cast<Type*>(ptr)); }
102 void setComplex (void *ptr, const complex128_t value) const
103 {
104 *(static_cast<Type*>(ptr)) = Type(value.real());
105 *(static_cast<Type*>(ptr) + 1) = Type(0);
106 }
107 void setDouble (void *ptr, const double value) const { *(static_cast<Type*>(ptr)) = Type(value); }
108 void setInt (void *ptr, const int value) const { *(static_cast<Type*>(ptr)) = Type(value); }
109 void minmax (void *ptr, const size_t length, double *min, double *max) const;
110 };
111
112 template <typename ElementType>
113 struct ConcreteTypeHandler<std::complex<ElementType>,false> : public TypeHandler
114 {
115 size_t size () const { return (sizeof(ElementType) * 2); }
116 bool hasNaN () const { return std::numeric_limits<ElementType>::has_quiet_NaN; }
117 std::complex<ElementType> getNative (void *ptr) const
118 {
119 const ElementType real = *static_cast<ElementType*>(ptr);
120 const ElementType imag = *(static_cast<ElementType*>(ptr) + 1);
121 return std::complex<ElementType>(real, imag);
122 }
123 void setNative (void *ptr, const std::complex<ElementType> native) const
124 {
125 *(static_cast<ElementType*>(ptr)) = native.real();
126 *(static_cast<ElementType*>(ptr) + 1) = native.imag();
127 }
128 complex128_t getComplex (void *ptr) const { return complex128_t(getNative(ptr)); }
129 double getDouble (void *ptr) const { return static_cast<double>(getNative(ptr).real()); }
130 int getInt (void *ptr) const { return static_cast<int>(getNative(ptr).real()); }
131 void setComplex (void *ptr, const complex128_t value) const { setNative(ptr, std::complex<ElementType>(value)); }
132 void setDouble (void *ptr, const double value) const { setNative(ptr, std::complex<ElementType>(value, 0.0)); }
133 void setInt (void *ptr, const int value) const { setNative(ptr, std::complex<ElementType>(static_cast<ElementType>(value), 0.0)); }
134 void minmax (void *ptr, const size_t length, double *min, double *max) const;
135 };
136
137 template <bool alpha>
139 {
140 size_t size () const { return alpha ? 4 : 3; }
141 int getInt (void *ptr) const { return getRgb(ptr).value.packed; }
142 rgba32_t getRgb (void *ptr) const
143 {
144 rgba32_t value;
145 unsigned char *source = static_cast<unsigned char *>(ptr);
146 std::copy(source, source + (alpha ? 4 : 3), value.value.bytes);
147 return value;
148 }
149 void setInt (void *ptr, const int value) const
150 {
151 rgba32_t native;
152 native.value.packed = value;
153 setRgb(ptr, native);
154 }
155 void setRgb (void *ptr, const rgba32_t value) const
156 {
157 unsigned char *target = static_cast<unsigned char *>(ptr);
158 std::copy(value.value.bytes, value.value.bytes + (alpha ? 4 : 3), target);
159 }
160 void minmax (void *ptr, const size_t length, double *min, double *max) const { *min = 0.0; *max = 255.0; }
161 };
162
169 {
170 if (_datatype == DT_NONE)
171 return NULL;
172
173 switch (_datatype)
174 {
175 case DT_UINT8: return new ConcreteTypeHandler<uint8_t>(); break;
176 case DT_INT16: return new ConcreteTypeHandler<int16_t>(); break;
177 case DT_INT32: return new ConcreteTypeHandler<int32_t>(); break;
178 case DT_FLOAT32: return new ConcreteTypeHandler<float>(); break;
179 case DT_FLOAT64: return new ConcreteTypeHandler<double>(); break;
180 case DT_INT8: return new ConcreteTypeHandler<int8_t>(); break;
181 case DT_UINT16: return new ConcreteTypeHandler<uint16_t>(); break;
182 case DT_UINT32: return new ConcreteTypeHandler<uint32_t>(); break;
183 case DT_INT64: return new ConcreteTypeHandler<int64_t>(); break;
184 case DT_UINT64: return new ConcreteTypeHandler<uint64_t>(); break;
185 case DT_COMPLEX64: return new ConcreteTypeHandler<complex64_t>(); break;
186 case DT_COMPLEX128: return new ConcreteTypeHandler<complex128_t>(); break;
187 case DT_RGB24: return new ConcreteTypeHandler<rgba32_t,false>(); break;
188 case DT_RGBA32: return new ConcreteTypeHandler<rgba32_t,true>(); break;
189
190 default:
191 throw std::runtime_error("Unsupported data type (" + std::string(nifti_datatype_string(_datatype)) + ")");
192 }
193 }
194
195 void *dataPtr;
198 size_t _length;
199 bool owner;
200
211 void init (void *data, const size_t length, const int datatype, const double slope, const double intercept, const bool alloc = true)
212 {
213 this->_length = length;
214 this->_datatype = datatype;
215 this->slope = slope;
216 this->intercept = intercept;
217
218 owner = false;
220 if (handler == NULL)
221 dataPtr = NULL;
222 else if (alloc && data == NULL)
223 {
224 dataPtr = calloc(length, handler->size());
225 owner = true;
226 }
227 else
228 dataPtr = data;
229 }
230
237 void calibrateFrom (const NiftiImageData &data)
238 {
239 slope = 1.0;
240 intercept = 0.0;
241
242 if (this->isInteger())
243 {
244 double dataMin, dataMax, typeMin, typeMax;
245 data.minmax(&dataMin, &dataMax);
246 handler->minmax(NULL, 0, &typeMin, &typeMax);
247
248 // If the source type is floating-point but values are in range, we will just round them
249 if (dataMin < typeMin || dataMax > typeMax)
250 {
251 slope = (dataMax - dataMin) / (typeMax - typeMin);
252 intercept = dataMin - (slope) * typeMin;
253 }
254 }
255 }
256
257public:
261 struct Element
262 {
263 private:
264 const NiftiImageData &parent;
265 void *ptr;
266
267 public:
274 Element (const NiftiImageData &parent, void *ptr = NULL)
275 : parent(parent)
276 {
277 this->ptr = (ptr == NULL ? parent.dataPtr : ptr);
278 }
279
287 template <typename SourceType>
288 Element & operator= (const SourceType &value);
289
295 Element & operator= (const Element &other);
296
300 template <typename TargetType>
301 operator TargetType() const
302 {
303 if (parent.isScaled())
304 return TargetType(parent.handler->getDouble(ptr) * parent.slope + parent.intercept);
305 else if (std::numeric_limits<TargetType>::is_integer)
306 return TargetType(parent.handler->getInt(ptr));
307 else
308 return TargetType(parent.handler->getDouble(ptr));
309 }
310
311 template <typename ElementType>
312 operator std::complex<ElementType>() const
313 {
314 if (parent.isScaled())
315 return std::complex<ElementType>(parent.handler->getComplex(ptr) * parent.slope + complex128_t(parent.intercept, parent.intercept));
316 else
317 return std::complex<ElementType>(parent.handler->getComplex(ptr));
318 }
319
320#ifdef USING_R
324 operator Rcomplex() const
325 {
326 const complex128_t value = parent.handler->getComplex(ptr);
327 Rcomplex rValue;
328 rValue.r = value.real();
329 rValue.i = value.imag();
330 if (parent.isScaled())
331 {
332 rValue.r = rValue.r * parent.slope + parent.intercept;
333 rValue.i = rValue.i * parent.slope + parent.intercept;
334 }
335 return rValue;
336 }
337#endif
338
339 operator rgba32_t() const
340 {
341 return parent.handler->getRgb(ptr);
342 }
343 };
344
349 {
350 private:
351 // NB: "parent" cannot be a reference because reference members are immutable. That renders
352 // the class non-copy-assignable, which is a requirement for iterators (issue #31)
353 const NiftiImageData *parent;
354 void *ptr;
355 size_t step;
356
357 public:
358 // Standard iterator typedefs
359 typedef std::random_access_iterator_tag iterator_category;
360 typedef Element value_type;
361 typedef std::ptrdiff_t difference_type;
362 typedef Element* pointer;
363 typedef Element& reference;
364
373 Iterator (const NiftiImageData *parent = NULL, void *ptr = NULL, const size_t step = 0)
374 : parent(parent)
375 {
376 this->ptr = (ptr == NULL ? parent->dataPtr : ptr);
377 this->step = (step == 0 ? parent->handler->size() : step);
378 }
379
384 Iterator (const Iterator &other)
385 : parent(other.parent), ptr(other.ptr), step(other.step) {}
386
387 Iterator & operator++ () { ptr = static_cast<char*>(ptr) + step; return *this; }
388 Iterator operator++ (int) { Iterator copy(*this); ptr = static_cast<char*>(ptr) + step; return copy; }
389 Iterator operator+ (ptrdiff_t n) const
390 {
391 void *newptr = static_cast<char*>(ptr) + (n * step);
392 return Iterator(parent, newptr, step);
393 }
394 Iterator & operator-- () { ptr = static_cast<char*>(ptr) - step; return *this; }
395 Iterator operator-- (int) { Iterator copy(*this); ptr = static_cast<char*>(ptr) - step; return copy; }
396 Iterator operator- (ptrdiff_t n) const
397 {
398 void *newptr = static_cast<char*>(ptr) - (n * step);
399 return Iterator(parent, newptr, step);
400 }
401
402 ptrdiff_t operator- (const Iterator &other) const
403 {
404 const ptrdiff_t difference = static_cast<char*>(ptr) - static_cast<char*>(other.ptr);
405 return difference / step;
406 }
407
408 bool operator== (const Iterator &other) const { return (ptr==other.ptr && step==other.step); }
409 bool operator!= (const Iterator &other) const { return (ptr!=other.ptr || step!=other.step); }
410 bool operator> (const Iterator &other) const { return (ptr > other.ptr); }
411 bool operator< (const Iterator &other) const { return (ptr < other.ptr); }
412
413 const Element operator* () const { return Element(*parent, ptr); }
414 Element operator* () { return Element(*parent, ptr); }
415 const Element operator[] (const size_t i) const { return Element(*parent, static_cast<char*>(ptr) + (i * step)); }
416 Element operator[] (const size_t i) { return Element(*parent, static_cast<char*>(ptr) + (i * step)); }
417 };
418
423 : slope(1.0), intercept(0.0), dataPtr(NULL), _datatype(DT_NONE), handler(NULL), _length(0), owner(false) {}
424
434 NiftiImageData (void *data, const size_t length, const int datatype, const double slope = 1.0, const double intercept = 0.0)
435 {
437 }
438
443 NiftiImageData (nifti_image *image)
444 {
445 if (image == NULL)
446 init(NULL, 0, DT_NONE, 0.0, 0.0, false);
447 else
448 init(image->data, image->nvox, image->datatype, static_cast<double>(image->scl_slope), static_cast<double>(image->scl_inter), false);
449 }
450
458 NiftiImageData (const NiftiImageData &source, const int datatype = DT_NONE)
459 {
460 init(NULL, source.length(), datatype == DT_NONE ? source.datatype() : datatype, source.slope, source.intercept);
461
462 if (datatype == DT_NONE || datatype == source.datatype())
463 memcpy(dataPtr, source.dataPtr, source.totalBytes());
464 else
465 {
466 calibrateFrom(source);
467 std::copy(source.begin(), source.end(), this->begin());
468 }
469 }
470
477 template <class InputIterator>
478 NiftiImageData (InputIterator from, InputIterator to, const int datatype)
479 {
480 const size_t length = static_cast<size_t>(std::distance(from, to));
481 init(NULL, length, datatype, 1.0, 0.0);
482 std::copy(from, to, this->begin());
483 }
484
489 {
490 delete handler;
491 if (owner)
492 free(dataPtr);
493 }
494
501 {
502 if (source.dataPtr != NULL)
503 {
504 // Free the old data, if we allocated it
505 if (owner)
506 free(dataPtr);
507 init(NULL, source.length(), source.datatype(), source.slope, source.intercept);
508 memcpy(dataPtr, source.dataPtr, source.totalBytes());
509 }
510 return *this;
511 }
512
513 void * blob () const { return dataPtr; }
514 int datatype () const { return _datatype; }
515 size_t length () const { return _length; }
516 size_t size () const { return _length; }
517
519 size_t bytesPerPixel () const { return (handler == NULL ? 0 : handler->size()); }
520
522 size_t totalBytes () const { return _length * bytesPerPixel(); }
523
528 bool isEmpty () const { return (dataPtr == NULL); }
529
535 bool isScaled () const { return (slope != 0.0 && (slope != 1.0 || intercept != 0.0)); }
536
541 bool isComplex () const { return (_datatype == DT_COMPLEX64 || _datatype == DT_COMPLEX128); }
542
548 bool isFloatingPoint () const { return (_datatype == DT_FLOAT32 || _datatype == DT_FLOAT64); }
549
554 bool isInteger () const { return nifti_is_inttype(_datatype); }
555
560 bool isRgb () const { return (_datatype == DT_RGB24 || _datatype == DT_RGBA32); }
561
567
572 NiftiImageData & disown () { this->owner = false; return *this; }
573
575 const Iterator begin () const { return Iterator(this); }
576
578 const Iterator end () const { return Iterator(this, static_cast<char*>(dataPtr) + totalBytes()); }
579
581 Iterator begin () { return Iterator(this); }
582
584 Iterator end () { return Iterator(this, static_cast<char*>(dataPtr) + totalBytes()); }
585
591 const Element operator[] (const size_t i) const { return Element(*this, static_cast<char*>(dataPtr) + (i * bytesPerPixel())); }
592
598 Element operator[] (const size_t i) { return Element(*this, static_cast<char*>(dataPtr) + (i * bytesPerPixel())); }
599
607 void minmax (double *min, double *max) const
608 {
609 if (handler == NULL)
610 {
611 *min = 0.0;
612 *max = 0.0;
613 }
614 else
615 handler->minmax(dataPtr, _length, min, max);
616 }
617};
618
619
620// R provides an NaN (NA) value for integers
621#ifdef USING_R
622template <>
623inline bool NiftiImageData::ConcreteTypeHandler<int>::hasNaN () const { return true; }
624#endif
625
626
631template <typename ElementType, int Length>
633{
634protected:
635 ElementType elements[Length];
636
637public:
641 Vector (const ElementType value = 0.0)
642 {
643 std::fill(elements, elements + Length, value);
644 }
645
649 Vector (const ElementType * source)
650 {
651 std::copy(source, source + Length, this->elements);
652 }
653
658 {
660 for (int i=0; i<Length; i++)
661 result.elements[i] = -elements[i];
662 return result;
663 }
664
665 const ElementType & operator[] (const size_t i) const { return elements[i]; }
666
667 ElementType & operator[] (const size_t i) { return elements[i]; }
668};
669
670
677template <class NiftiType, typename ElementType, int Order>
679{
680protected:
681 ElementType elements[Order*Order];
682
687 NiftiType * niftiPointer () const { return (NiftiType *) elements; }
688
692 NiftiType niftiCopy () const
693 {
694 NiftiType value;
695 std::copy(elements, elements + Order*Order, *value.m);
696 return value;
697 }
698
699public:
700 typedef NiftiType NativeType;
703
707 SquareMatrix (const ElementType value = 0.0)
708 {
709 std::fill(elements, elements + Order*Order, value);
710 }
711
715 SquareMatrix (const ElementType * source)
716 {
717 std::copy(source, source + Order*Order, this->elements);
718 }
719
723 SquareMatrix (const NiftiType &source)
724 {
725 const ElementType *castSource = (const ElementType *) *source.m;
726 std::copy(castSource, castSource + Order*Order, this->elements);
727 }
728
729#ifdef USING_R
733 SquareMatrix (SEXP source)
734 {
735 Rcpp::NumericMatrix matrix(source);
736 if (matrix.cols() != Order && matrix.rows() != Order)
737 throw std::runtime_error("Matrix does not have the expected dimensions");
738 for (int i=0; i<Order; i++)
739 {
740 for (int j=0; j<Order; j++)
741 elements[j + i*Order] = matrix(i,j);
742 }
743 }
744#endif
745
750 operator const NiftiType () const { return niftiCopy(); }
751
756 operator NiftiType () { return niftiCopy(); }
757
762 const ElementType * begin () const { return elements; }
763
768 ElementType * begin () { return elements; }
769
773 const ElementType * end () const { return elements + Order*Order; }
774
778 ElementType * end () { return elements + Order*Order; }
779
783 static MatrixType eye ()
784 {
785 MatrixType matrix;
786 for (int i=0; i<Order; i++)
787 matrix.elements[i + i*Order] = 1.0;
788 return matrix;
789 }
790
792 MatrixType polar () const;
793 ElementType colnorm () const;
794 ElementType rownorm () const;
795 ElementType determ () const;
796 MatrixType multiply (const MatrixType &other) const;
797 VectorType multiply (const VectorType &vec) const;
798
799 MatrixType operator* (const MatrixType &other) const { return multiply(other); }
800 VectorType operator* (const VectorType &vec) const { return multiply(vec); }
801
805 const ElementType & operator() (const int i, const int j) const { return elements[j + i*Order]; }
806
810 ElementType & operator() (const int i, const int j) { return elements[j + i*Order]; }
811
812#ifdef USING_R
816 operator SEXP () const
817 {
818 Rcpp::NumericMatrix result(Order, Order);
819 for (int i=0; i<Order; i++)
820 {
821 for (int j=0; j<Order; j++)
822 result(i,j) = elements[j + i*Order];
823 }
824 return result;
825 }
826#endif
827};
828
829
830// Include matrix implementations
831#include "RNifti/NiftiImage_matrix.h"
832
833
841{
842public:
843#if RNIFTI_NIFTILIB_VERSION == 1
844 typedef int dim_t;
845 typedef float pixdim_t;
846 typedef float scale_t;
847#elif RNIFTI_NIFTILIB_VERSION == 2
848 typedef int64_t dim_t;
849 typedef double pixdim_t;
850 typedef double scale_t;
851#endif
852
857 struct Block
858 {
860 const int dimension;
861 const dim_t index;
862
870 Block (const NiftiImage &image, const int dimension, const dim_t index)
872 {
873 if (dimension != image->ndim)
874 throw std::runtime_error("Blocks must be along the last dimension in the image");
875 }
876
885 Block & operator= (const NiftiImage &source)
886 {
887 if (source->datatype != image->datatype)
888 throw std::runtime_error("New data does not have the same datatype as the target block");
889 if (source->scl_slope != image->scl_slope || source->scl_inter != image->scl_inter)
890 throw std::runtime_error("New data does not have the same scale parameters as the target block");
891
892 size_t blockSize = 1;
893 for (int i=1; i<dimension; i++)
894 blockSize *= image->dim[i];
895
896 if (blockSize != size_t(source->nvox))
897 throw std::runtime_error("New data does not have the same size as the target block");
898
899 blockSize *= image->nbyper;
900 memcpy(static_cast<char*>(image->data) + blockSize*index, source->data, blockSize);
901 return *this;
902 }
903
909 {
910 if (image.isNull())
911 return NiftiImageData();
912 else
913 {
914 size_t blockSize = 1;
915 for (int i=1; i<dimension; i++)
916 blockSize *= image->dim[i];
917 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));
918 }
919 }
920
928 template <typename TargetType>
929 std::vector<TargetType> getData (const bool useSlope = true) const;
930 };
931
937 {
938 protected:
939 nifti1_extension *ext;
940
945 void copy (const nifti1_extension *source);
946
953 template <typename SourceType>
954 void copy (const SourceType *data, const size_t length, const int code);
955
956 public:
961 : ext(NULL) {}
962
970 Extension (nifti1_extension * const extension, const bool copy = false)
971 {
972 if (!copy || extension == NULL)
973 this->ext = extension;
974 else
975 this->copy(extension);
976 }
977
982 Extension (const Extension &source)
983 {
984 copy(source.ext);
985 }
986
993 template <typename SourceType>
994 Extension (const SourceType *data, const size_t length, const int code)
995 {
996 copy(data, length, code);
997 }
998
999#ifdef USING_R
1007 Extension (SEXP source, int code = -1)
1008 {
1009 const Rcpp::RObject object(source);
1010 if (code == -1 && object.hasAttribute("code"))
1011 code = Rcpp::as<int>(object.attr("code"));
1012
1013 switch (object.sexp_type())
1014 {
1015 case RAWSXP: copy(RAW(source), Rf_length(source), code); break;
1016 case REALSXP: copy(REAL(source), Rf_length(source), code); break;
1017 case CPLXSXP: copy(COMPLEX(source), Rf_length(source), code); break;
1018 case INTSXP: copy(INTEGER(source), Rf_length(source), code); break;
1019 case LGLSXP: copy(LOGICAL(source), Rf_length(source), code); break;
1020 case STRSXP:
1021 {
1022 if (Rf_length(source) > 1)
1023 Rf_warning("Character vector elements after the first will not be stored in a NIfTI extension");
1024 const char *string = CHAR(STRING_ELT(source, 0));
1025 copy(string, strlen(string), code);
1026 break;
1027 }
1028 default: Rf_error("Unable to convert SEXP type %d to NIfTI extension", object.sexp_type());
1029 }
1030 }
1031#endif
1032
1037 int code () const { return (ext == NULL ? -1 : ext->ecode); }
1038
1043 const char * data () const { return (ext == NULL ? NULL : ext->edata); }
1044
1049 size_t length () const { return (ext == NULL || ext->esize < 8 ? 0 : size_t(ext->esize - 8)); }
1050
1055 size_t size () const { return (ext == NULL || ext->esize < 8 ? 0 : size_t(ext->esize - 8)); }
1056
1057#ifdef USING_R
1061 operator SEXP () const
1062 {
1063 if (ext == NULL || ext->esize < 8)
1064 return R_NilValue;
1065
1066 const int length = ext->esize - 8;
1067 Rcpp::RawVector result(length);
1068 const Rbyte *source = (const Rbyte *) ext->edata;
1069 std::copy(source, source+length, result.begin());
1070 result.attr("code") = ext->ecode;
1071 return result;
1072 }
1073#endif
1074 };
1075
1082 class Xform
1083 {
1084 public:
1085#if RNIFTI_NIFTILIB_VERSION == 1
1086 typedef float Element;
1087 typedef Vector<float,4> Vector4;
1088 typedef Vector<float,3> Vector3;
1089 typedef SquareMatrix<mat44,float,4> Matrix;
1090 typedef SquareMatrix<mat33,float,3> Submatrix;
1091#elif RNIFTI_NIFTILIB_VERSION == 2
1092 typedef double Element;
1093 typedef Vector<double,4> Vector4;
1094 typedef Vector<double,3> Vector3;
1096 typedef SquareMatrix<nifti_dmat33,double,3> Submatrix;
1097#endif
1098
1099 protected:
1100 Element *forward, *inverse, *qparams;
1101 Matrix mat;
1102
1107 void replace (const Matrix &source);
1108
1109 public:
1114 : forward(NULL), inverse(NULL), qparams(NULL), mat() {}
1115
1119 Xform (const Matrix &source)
1120 : forward(NULL), inverse(NULL), qparams(NULL), mat(source) {}
1121
1125 Xform (const Matrix::NativeType &source)
1126 : forward(NULL), inverse(NULL), qparams(NULL), mat(source) {}
1127
1132 Xform (Matrix::NativeType &source)
1133 : forward(*source.m), inverse(NULL), qparams(NULL), mat(source) {}
1134
1139 Xform (Matrix::NativeType &source, Matrix::NativeType &inverse, Element *qparams = NULL)
1140 : forward(*source.m), inverse(*inverse.m), qparams(qparams), mat(source) {}
1141
1142#ifdef USING_R
1146 Xform (SEXP source)
1147 : forward(NULL), inverse(NULL), qparams(NULL), mat(Matrix(source)) {}
1148#endif
1149
1154 operator const Matrix::NativeType () const { return mat; }
1155
1160 operator Matrix::NativeType () { return mat; }
1161
1165 Xform & operator= (const Xform &source)
1166 {
1167 replace(source.mat);
1168 return *this;
1169 }
1170
1174 Xform & operator= (const Matrix &source)
1175 {
1176 replace(source);
1177 return *this;
1178 }
1179
1180#ifdef USING_R
1184 Xform & operator= (SEXP source)
1185 {
1186 replace(Matrix(source));
1187 return *this;
1188 }
1189#endif
1190
1194 const Matrix & matrix () const { return mat; }
1195
1199 Submatrix submatrix () const;
1200
1205 Submatrix rotation () const;
1206
1212 Element handedness () const;
1213
1217 Vector4 quaternion () const;
1218
1222 Vector3 offset () const;
1223
1227 Vector3 spacing () const;
1228
1236 std::string orientation () const;
1237 };
1238
1239#ifdef USING_R
1246 static int sexpTypeToNiftiType (const int sexpType)
1247 {
1248 if (sexpType == INTSXP || sexpType == LGLSXP)
1249 return DT_INT32;
1250 else if (sexpType == REALSXP)
1251 return DT_FLOAT64;
1252 else if (sexpType == CPLXSXP)
1253 return DT_COMPLEX128;
1254 else
1255 throw std::runtime_error("Array elements must be numeric");
1256 }
1257#endif
1258
1265 static int fileVersion (const std::string &path);
1266
1267
1268protected:
1269 nifti_image *image;
1271
1278 void acquire (nifti_image * const image);
1279
1284 void acquire (const NiftiImage &source)
1285 {
1286 refCount = source.refCount;
1287 acquire(source.image);
1288 }
1289
1294 void release ();
1295
1300 void copy (const nifti_image *source);
1301
1306 void copy (const NiftiImage &source);
1307
1312 void copy (const Block &source);
1313
1314
1315#ifdef USING_R
1316
1322 void initFromNiftiS4 (const Rcpp::RObject &object, const bool copyData = true);
1323
1329 void initFromMriImage (const Rcpp::RObject &object, const bool copyData = true);
1330
1335 void initFromList (const Rcpp::RObject &object);
1336
1342 void initFromArray (const Rcpp::RObject &object, const bool copyData = true);
1343
1344#endif
1345
1351 void initFromDims (const std::vector<dim_t> &dim, const int datatype);
1352
1357 void updatePixdim (const std::vector<pixdim_t> &pixdim);
1358
1363 void setPixunits (const std::vector<std::string> &pixunits);
1364
1365public:
1370 : image(NULL), refCount(NULL) {}
1371
1378 NiftiImage (const NiftiImage &source, const bool copy = true)
1379 : image(NULL), refCount(NULL)
1380 {
1381 if (copy)
1382 this->copy(source);
1383 else
1384 acquire(source);
1385#ifndef NDEBUG
1386 Rc_printf("Creating NiftiImage (v%d) with pointer %p (from NiftiImage)\n", RNIFTI_NIFTILIB_VERSION, (void *) this->image);
1387#endif
1388 }
1389
1394 NiftiImage (const Block &source)
1395 : image(NULL), refCount(NULL)
1396 {
1397 this->copy(source);
1398#ifndef NDEBUG
1399 Rc_printf("Creating NiftiImage (v%d) with pointer %p (from Block)\n", RNIFTI_NIFTILIB_VERSION, (void *) this->image);
1400#endif
1401 }
1402
1409 NiftiImage (nifti_image * const image, const bool copy = false)
1410 : image(NULL), refCount(NULL)
1411 {
1412 if (copy)
1413 this->copy(image);
1414 else
1415 acquire(image);
1416#ifndef NDEBUG
1417 Rc_printf("Creating NiftiImage (v%d) with pointer %p (from pointer)\n", RNIFTI_NIFTILIB_VERSION, (void *) this->image);
1418#endif
1419 }
1420
1425 NiftiImage (const nifti_1_header &header)
1426 : image(NULL), refCount(NULL)
1427 {
1428#if RNIFTI_NIFTILIB_VERSION == 1
1429 acquire(nifti_convert_nhdr2nim(header, NULL));
1430#elif RNIFTI_NIFTILIB_VERSION == 2
1431 acquire(nifti_convert_n1hdr2nim(header, NULL));
1432#endif
1433#ifndef NDEBUG
1434 Rc_printf("Creating NiftiImage (v%d) with pointer %p (from header)\n", RNIFTI_NIFTILIB_VERSION, (void *) this->image);
1435#endif
1436 }
1437
1438#if RNIFTI_NIFTILIB_VERSION == 2
1443 NiftiImage (const nifti_2_header &header)
1444 : image(NULL), refCount(NULL)
1445 {
1446 acquire(nifti_convert_n2hdr2nim(header, NULL));
1447#ifndef NDEBUG
1448 Rc_printf("Creating NiftiImage (v%d) with pointer %p (from header)\n", RNIFTI_NIFTILIB_VERSION, (void *) this->image);
1449#endif
1450 }
1451#endif
1452
1458 NiftiImage (const std::vector<dim_t> &dim, const int datatype);
1459
1465 NiftiImage (const std::vector<dim_t> &dim, const std::string &datatype);
1466
1473 NiftiImage (const std::string &path, const bool readData = true);
1474
1481 NiftiImage (const std::string &path, const std::vector<dim_t> &volumes);
1482
1483#ifdef USING_R
1494 NiftiImage (const SEXP object, const bool readData = true, const bool readOnly = false);
1495#endif
1496
1501 virtual ~NiftiImage () { release(); }
1502
1506 operator const nifti_image* () const { return image; }
1507
1511 operator nifti_image* () { return image; }
1512
1516 const nifti_image * operator-> () const { return image; }
1517
1521 nifti_image * operator-> () { return image; }
1522
1528 {
1529 copy(source);
1530#ifndef NDEBUG
1531 Rc_printf("Creating NiftiImage (v%d), with pointer %p (from NiftiImage)\n", RNIFTI_NIFTILIB_VERSION, (void *) this->image);
1532#endif
1533 return *this;
1534 }
1535
1541 NiftiImage & operator= (const Block &source)
1542 {
1543 copy(source);
1544#ifndef NDEBUG
1545 Rc_printf("Creating NiftiImage (v%d) with pointer %p (from Block)\n", RNIFTI_NIFTILIB_VERSION, (void *) this->image);
1546#endif
1547 return *this;
1548 }
1549
1557 NiftiImage & setPersistence (const bool persistent) { return *this; }
1558
1563 bool isNull () const { return (image == NULL); }
1564
1569 bool isShared () const { return (refCount != NULL && *refCount > 1); }
1570
1577 bool isPersistent () const { return false; }
1578
1584 bool isDataScaled () const { return (image != NULL && image->scl_slope != 0.0 && (image->scl_slope != 1.0 || image->scl_inter != 0.0)); }
1585
1590 int nDims () const
1591 {
1592 if (image == NULL)
1593 return 0;
1594 else
1595 return image->ndim;
1596 }
1597
1602 std::vector<dim_t> dim () const
1603 {
1604 if (image == NULL)
1605 return std::vector<dim_t>();
1606 else
1607 return std::vector<dim_t>(image->dim+1, image->dim+image->ndim+1);
1608 }
1609
1614 std::vector<pixdim_t> pixdim () const
1615 {
1616 if (image == NULL)
1617 return std::vector<pixdim_t>();
1618 else
1619 return std::vector<pixdim_t>(image->pixdim+1, image->pixdim+image->ndim+1);
1620 }
1621
1629 {
1630 int ndim = image->ndim;
1631 while (image->dim[ndim] < 2)
1632 ndim--;
1633 image->dim[0] = image->ndim = ndim;
1634
1635 return *this;
1636 }
1637
1642 const NiftiImageData data () const { return NiftiImageData(image); }
1643
1649
1659 template <typename TargetType>
1660 std::vector<TargetType> getData (const bool useSlope = true) const;
1661
1669 NiftiImage & changeDatatype (const int datatype, const bool useSlope = false);
1670
1678 NiftiImage & changeDatatype (const std::string &datatype, const bool useSlope = false);
1679
1688 template <typename SourceType>
1689 NiftiImage & replaceData (const std::vector<SourceType> &data, const int datatype = DT_NONE);
1690
1698
1705 {
1706#if RNIFTI_NIFTILIB_VERSION == 1
1707 nifti_image_unload(image);
1708#elif RNIFTI_NIFTILIB_VERSION == 2
1709 nifti2_image_unload(image);
1710#endif
1711 return *this;
1712 }
1713
1720 NiftiImage & rescale (const std::vector<pixdim_t> &scales);
1721
1730 NiftiImage & reorient (const int i, const int j, const int k);
1731
1740 NiftiImage & reorient (const std::string &orientation);
1741
1742#ifdef USING_R
1748 NiftiImage & update (const Rcpp::RObject &object);
1749#endif
1750
1757 const Xform xform (const bool preferQuaternion = true) const;
1758
1763 const Xform qform () const { return (image == NULL ? Xform() : Xform(image->qto_xyz)); }
1764
1769 Xform qform () { return (image == NULL ? Xform() : Xform(image->qto_xyz, image->qto_ijk, &image->quatern_b)); }
1770
1775 const Xform sform () const { return (image == NULL ? Xform() : Xform(image->sto_xyz)); }
1776
1781 Xform sform () { return (image == NULL ? Xform() : Xform(image->sto_xyz, image->sto_ijk)); }
1782
1787 dim_t nBlocks () const { return (image == NULL ? 0 : image->dim[image->ndim]); }
1788
1796 const Block block (const int i) const { return Block(*this, nDims(), i); }
1797
1805 Block block (const int i) { return Block(*this, nDims(), i); }
1806
1812 const Block slice (const int i) const { return Block(*this, 3, i); }
1813
1819 Block slice (const int i) { return Block(*this, 3, i); }
1820
1826 const Block volume (const int i) const { return Block(*this, 4, i); }
1827
1833 Block volume (const int i) { return Block(*this, 4, i); }
1834
1840 int nChannels () const
1841 {
1842 if (image == NULL)
1843 return 0;
1844 else
1845 {
1846 switch (image->datatype)
1847 {
1848 case DT_NONE: return 0;
1849 case DT_RGB24: return 3;
1850 case DT_RGBA32: return 4;
1851 default: return 1;
1852 }
1853 }
1854 }
1855
1860 size_t nVoxels () const { return (image == NULL ? 0 : image->nvox); }
1861
1866 int nExtensions () const { return (image == NULL ? 0 : image->num_ext); }
1867
1874 std::list<Extension> extensions (const int code = -1) const
1875 {
1876 if (image == NULL)
1877 return std::list<Extension>();
1878 else
1879 {
1880 std::list<Extension> result;
1881 for (int i=0; i<image->num_ext; i++)
1882 {
1883 const Extension extension(image->ext_list + i);
1884 if (code < 0 || code == extension.code())
1885 result.push_back(extension);
1886 }
1887 return result;
1888 }
1889 }
1890
1896 NiftiImage & addExtension (const Extension &extension)
1897 {
1898 if (image != NULL)
1899#if RNIFTI_NIFTILIB_VERSION == 1
1900 nifti_add_extension(image, extension.data(), int(extension.length()), extension.code());
1901#elif RNIFTI_NIFTILIB_VERSION == 2
1902 nifti2_add_extension(image, extension.data(), int(extension.length()), extension.code());
1903#endif
1904 return *this;
1905 }
1906
1912 NiftiImage & replaceExtensions (const std::list<Extension> extensions)
1913 {
1915 for (std::list<Extension>::const_iterator it=extensions.begin(); it!=extensions.end(); ++it)
1916 addExtension(*it);
1917 return *this;
1918 }
1919
1925 {
1926 if (image != NULL)
1927#if RNIFTI_NIFTILIB_VERSION == 1
1928 nifti_free_extensions(image);
1929#elif RNIFTI_NIFTILIB_VERSION == 2
1930 nifti2_free_extensions(image);
1931#endif
1932 return *this;
1933 }
1934
1945 std::pair<std::string,std::string> toFile (const std::string fileName, const int datatype = DT_NONE, const int filetype = -1, const int compression = 6) const;
1946
1957 std::pair<std::string,std::string> toFile (const std::string fileName, const std::string &datatype, const int filetype = -1, const int compression = 6) const;
1958
1959#ifdef USING_R
1960
1965 Rcpp::RObject toArray () const;
1966
1972 Rcpp::RObject toPointer (const std::string label) const;
1973
1980 Rcpp::RObject toArrayOrPointer (const bool internal, const std::string label) const;
1981
1982#endif
1983
1984};
1985
1986// Include image implementations
1987#include "RNifti/NiftiImage_impl.h"
1988
1989} // main namespace
1990
1991#endif
Simple RGB(A) type encapsulating an 8-bit colour value with optional opacity, which can also be set o...
Definition NiftiImage.h:49
Definition NiftiImage.h:50
Wrapper class encapsulating a NIfTI data blob, with responsibility for handling data scaling and poly...
Definition NiftiImage.h:66
int datatype() const
Return stored datatype code.
Definition NiftiImage.h:514
bool isRgb() const
Determine whether the datatype corresponds to an RGB type.
Definition NiftiImage.h:560
NiftiImageData(nifti_image *image)
Convenience constructor for a nifti_image.
Definition NiftiImage.h:443
size_t length() const
Return the number of elements in the data.
Definition NiftiImage.h:515
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:519
bool isScaled() const
Determine whether the object uses data scaling.
Definition NiftiImage.h:535
NiftiImageData()
Default constructor, creating an empty data object.
Definition NiftiImage.h:422
int _datatype
Datatype code indicating the actual type of the elements.
Definition NiftiImage.h:196
TypeHandler * handler
Type handler, which is created to match the datatype.
Definition NiftiImage.h:197
Iterator end()
Obtain a mutable iterator corresponding to the end of the blob.
Definition NiftiImage.h:584
NiftiImageData unscaled() const
Return a similar object to the callee, but with the slope and intercept values reset.
Definition NiftiImage.h:566
size_t totalBytes() const
Return the total size of the data blob, in bytes.
Definition NiftiImage.h:522
void minmax(double *min, double *max) const
Calculate the minimum and maximum values in the blob, as doubles.
Definition NiftiImage.h:607
const Iterator begin() const
Obtain a constant iterator corresponding to the start of the blob.
Definition NiftiImage.h:575
double slope
The slope term used to scale data values.
Definition NiftiImage.h:68
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:434
double intercept
The intercept term used to scale data values.
Definition NiftiImage.h:69
bool isFloatingPoint() const
Determine whether the datatype is floating point.
Definition NiftiImage.h:548
const Iterator end() const
Obtain a constant iterator corresponding to the end of the blob.
Definition NiftiImage.h:578
NiftiImageData & disown()
Disown the data blob, removing responsibility for freeing it upon destruction.
Definition NiftiImage.h:572
const Element operator[](const size_t i) const
Indexing operator, returning a constant element.
Definition NiftiImage.h:591
size_t _length
The number of data elements in the blob.
Definition NiftiImage.h:198
TypeHandler * createHandler()
Create a concrete type handler appropriate to the datatype code stored with the data.
Definition NiftiImage.h:168
NiftiImageData & operator=(const NiftiImageData &source)
Copy assignment operator.
Definition NiftiImage.h:500
NiftiImageData(const NiftiImageData &source, const int datatype=DT_NONE)
Copy constructor with optional type conversion.
Definition NiftiImage.h:458
bool isInteger() const
Determine whether the datatype is an integer type.
Definition NiftiImage.h:554
virtual ~NiftiImageData()
Destructor which frees the type handler, and the data blob if it is owned by this object.
Definition NiftiImage.h:488
size_t size() const
Return the number of elements in the data.
Definition NiftiImage.h:516
bool owner
An indicator of whether this object is responsible for cleaning up the data.
Definition NiftiImage.h:199
NiftiImageData(InputIterator from, InputIterator to, const int datatype)
Iterator-based constructor.
Definition NiftiImage.h:478
Iterator begin()
Obtain a mutable iterator corresponding to the start of the blob.
Definition NiftiImage.h:581
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:211
bool isEmpty() const
Determine whether or not the object is empty.
Definition NiftiImage.h:528
void * blob() const
Return an opaque pointer to the blob.
Definition NiftiImage.h:513
void calibrateFrom(const NiftiImageData &data)
Update the slope and intercept to cover the range of another data object.
Definition NiftiImage.h:237
bool isComplex() const
Determine whether the datatype is complex.
Definition NiftiImage.h:541
void * dataPtr
Opaque pointer to the underlying data blob.
Definition NiftiImage.h:195
Abstract inner class defining the type-specific functions required in concrete subclasses.
Definition NiftiImage.h:76
Concrete inner class template defining behaviour specific to individual data types.
Definition NiftiImage.h:96
Inner class representing a single element in the data blob.
Definition NiftiImage.h:262
Element(const NiftiImageData &parent, void *ptr=NULL)
Primary constructor.
Definition NiftiImage.h:274
Element & operator=(const SourceType &value)
Copy assignment operator.
Iterator type for NiftiImageData, with Element as its value type.
Definition NiftiImage.h:349
Iterator(const NiftiImageData *parent=NULL, void *ptr=NULL, const size_t step=0)
Primary constructor.
Definition NiftiImage.h:373
Iterator(const Iterator &other)
Copy constructor.
Definition NiftiImage.h:384
A simple object-oriented wrapper around a fixed-length array.
Definition NiftiImage.h:633
Vector(const ElementType *source)
Initialise from a C-style array of the appropriate type and length.
Definition NiftiImage.h:649
Vector< ElementType, Length > operator-() const
Unary negation operator, which reverses the signs of all elements.
Definition NiftiImage.h:657
Vector(const ElementType value=0.0)
Initialise with a fixed element value, defaulting to zero.
Definition NiftiImage.h:641
Class representing a numeric square matrix of a fixed order.
Definition NiftiImage.h:679
SquareMatrix(const ElementType value=0.0)
Initialise with a fixed element value, defaulting to zero.
Definition NiftiImage.h:707
ElementType elements[Order *Order]
The underlying raw data elements, stored row-major for consistency with niftilib.
Definition NiftiImage.h:681
const ElementType * begin() const
Return a pointer/iterator to the beginning of the data.
Definition NiftiImage.h:762
MatrixType inverse() const
Matrix inverse.
SquareMatrix(const ElementType *source)
Initialise from a C-style array of the appropriate type and length.
Definition NiftiImage.h:715
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:778
Vector< ElementType, Order > VectorType
Type of vectors for which this matrix is a linear operator.
Definition NiftiImage.h:702
const ElementType * end() const
Return a pointer/iterator to the end of the data.
Definition NiftiImage.h:773
NiftiType NativeType
The niftilib structure type corresponding to this matrix.
Definition NiftiImage.h:700
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:805
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:692
ElementType * begin()
Return a pointer/iterator to the beginning of the data.
Definition NiftiImage.h:768
SquareMatrix< NiftiType, ElementType, Order > MatrixType
Type alias for the current specialisation.
Definition NiftiImage.h:701
SquareMatrix(SEXP source)
Initialise from an R object representing a numeric matrix.
Definition NiftiImage.h:733
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:783
MatrixType operator*(const MatrixType &other) const
Matrix-matrix multiplication (infix shorthand)
Definition NiftiImage.h:799
SquareMatrix(const NiftiType &source)
Initialise from the appropriate niftilib type.
Definition NiftiImage.h:723
NiftiType * niftiPointer() const
Obtain a pointer to a NIfTI-style mat44 or dmat44 encapsulating the same data as this object.
Definition NiftiImage.h:687
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:1874
NiftiImage(const NiftiImage &source, const bool copy=true)
Copy constructor.
Definition NiftiImage.h:1378
bool isDataScaled() const
Determine whether nontrivial scale and slope parameters are set.
Definition NiftiImage.h:1584
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.
std::pair< std::string, std::string > toFile(const std::string fileName, const std::string &datatype, const int filetype=-1, const int compression=6) const
Write the image to a NIfTI-1 file.
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:1284
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:1614
int nExtensions() const
Return the number of extensions associated with the image.
Definition NiftiImage.h:1866
Xform sform()
Access the sform matrix.
Definition NiftiImage.h:1781
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:1563
virtual ~NiftiImage()
Destructor which decrements the reference counter, and releases the wrapped pointer if the counter dr...
Definition NiftiImage.h:1501
NiftiImage(const Block &source)
Initialise from a block, copying in the data.
Definition NiftiImage.h:1394
const nifti_image * operator->() const
Allows a NiftiImage object to be treated as a pointer to a const nifti_image.
Definition NiftiImage.h:1516
int nChannels() const
Return the number of colour channels used by the image.
Definition NiftiImage.h:1840
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:1924
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:1642
std::vector< dim_t > dim() const
Return the dimensions of the image.
Definition NiftiImage.h:1602
bool isShared() const
Determine whether the wrapped pointer is shared with another NiftiImage.
Definition NiftiImage.h:1569
dim_t nBlocks() const
Return the number of blocks in the image.
Definition NiftiImage.h:1787
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:1269
const Block block(const int i) const
Extract a block from the image.
Definition NiftiImage.h:1796
static int sexpTypeToNiftiType(const int sexpType)
Convert between R SEXP object type and nifti_image datatype codes.
Definition NiftiImage.h:1246
int * refCount
A reference counter, shared with other objects wrapping the same pointer.
Definition NiftiImage.h:1270
NiftiImage & operator=(const NiftiImage &source)
Copy assignment operator, which copies from its argument.
Definition NiftiImage.h:1527
bool isPersistent() const
Determine whether or not the image is marked as persistent.
Definition NiftiImage.h:1577
Block block(const int i)
Extract a block from the image.
Definition NiftiImage.h:1805
NiftiImage & replaceExtensions(const std::list< Extension > extensions)
Replace all extensions with new ones.
Definition NiftiImage.h:1912
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:1819
NiftiImage & dropData()
Drop the data from the image, retaining only the metadata.
Definition NiftiImage.h:1704
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:1648
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:1590
NiftiImage(nifti_image *const image, const bool copy=false)
Initialise using an existing nifti_image pointer.
Definition NiftiImage.h:1409
Block volume(const int i)
Extract a volume block from a 4D image.
Definition NiftiImage.h:1833
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:1826
std::pair< std::string, std::string > toFile(const std::string fileName, const int datatype=DT_NONE, const int filetype=-1, const int compression=6) const
Write the image to a NIfTI-1 file.
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:1860
Xform qform()
Access the qform matrix.
Definition NiftiImage.h:1769
const Block slice(const int i) const
Extract a slice block from a 3D image.
Definition NiftiImage.h:1812
const Xform sform() const
Access the sform matrix.
Definition NiftiImage.h:1775
NiftiImage & drop()
Drop unitary dimensions.
Definition NiftiImage.h:1628
NiftiImage & setPersistence(const bool persistent)
Mark the image as persistent, so that it can be passed back to R.
Definition NiftiImage.h:1557
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:1369
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:1896
NiftiImage(const nifti_1_header &header)
Initialise using a NIfTI-1 header.
Definition NiftiImage.h:1425
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:1763
Inner class referring to a subset of an image.
Definition NiftiImage.h:858
NiftiImageData data() const
Obtain the data within the block.
Definition NiftiImage.h:908
const NiftiImage & image
The parent image.
Definition NiftiImage.h:859
const dim_t index
The location along dimension.
Definition NiftiImage.h:861
Block(const NiftiImage &image, const int dimension, const dim_t index)
Standard constructor for this class.
Definition NiftiImage.h:870
const int dimension
The dimension along which the block applies (which should be the last)
Definition NiftiImage.h:860
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:885
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:937
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:994
Extension(const Extension &source)
Copy constructor.
Definition NiftiImage.h:982
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:1007
int code() const
Return the code associated with the extension.
Definition NiftiImage.h:1037
size_t length() const
Return the length of the data array.
Definition NiftiImage.h:1049
Extension()
Default constructor, wrapping NULL.
Definition NiftiImage.h:960
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:970
size_t size() const
Return the length of the data array.
Definition NiftiImage.h:1055
const char * data() const
Return the data blob associated with the extension.
Definition NiftiImage.h:1043
nifti1_extension * ext
The wrapped extension structure.
Definition NiftiImage.h:939
Inner class representing an xform matrix, which indicates the orientation and other spatial propertie...
Definition NiftiImage.h:1083
Xform & operator=(const Xform &source)
Copy assignment operator, taking an Xform and replacing linked data.
Definition NiftiImage.h:1165
const Matrix & matrix() const
Access the xform matrix as an immutable SquareMatrix object.
Definition NiftiImage.h:1194
Xform()
Default constructor.
Definition NiftiImage.h:1113
Xform(Matrix::NativeType &source, Matrix::NativeType &inverse, Element *qparams=NULL)
Initialise from forward and backward matrices, and optionally quaternion parameters.
Definition NiftiImage.h:1139
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:1119
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:1132
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:1101
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:1146
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:1125
Element * qparams
Pointers to linked C-style arrays.
Definition NiftiImage.h:1100
Vector3 offset() const
Obtain the translation component of the xform matrix.