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
37 namespace RNifti {
38
39 typedef std::complex<float> complex64_t;
40 typedef std::complex<double> complex128_t;
41
48 struct 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
65 class NiftiImageData
66{
67 public:
68 double slope;
69 double intercept;
70
71 protected:
75 struct TypeHandler
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>
95 struct ConcreteTypeHandler : public TypeHandler
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>
138 struct ConcreteTypeHandler<rgba32_t,alpha> : public TypeHandler
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
168 TypeHandler * createHandler ()
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;
196 int _datatype;
197 TypeHandler *handler;
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;
219 handler = createHandler();
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
257 public:
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
348 class Iterator
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
422 NiftiImageData ()
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 {
436 init(data, length, datatype, slope, intercept);
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
488 virtual ~NiftiImageData ()
489 {
490 delete handler;
491 if (owner)
492 free(dataPtr);
493 }
494
500 NiftiImageData & operator= (const NiftiImageData &source)
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
566 NiftiImageData unscaled () const { return NiftiImageData(dataPtr, _length, _datatype); }
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
622 template <>
623 inline bool NiftiImageData::ConcreteTypeHandler<int>::hasNaN () const { return true; }
624#endif
625
626
631 template <typename ElementType, int Length>
632 class Vector
633{
634 protected:
635 ElementType elements[Length];
636
637 public:
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
657 Vector<ElementType,Length> operator- () const
658 {
659 Vector<ElementType,Length> result;
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
677 template <class NiftiType, typename ElementType, int Order>
678 class SquareMatrix
679{
680 protected:
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
699 public:
700 typedef NiftiType NativeType;
701 typedef SquareMatrix<NiftiType,ElementType,Order> MatrixType;
702 typedef Vector<ElementType,Order> VectorType;
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
791 MatrixType inverse () const;
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
840 class NiftiImage
841{
842 public:
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 {
859 const NiftiImage &image;
860 const int dimension;
861 const dim_t index;
862
870 Block (const NiftiImage &image, const int dimension, const dim_t index)
871 : image(image), dimension(dimension), index(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
908 NiftiImageData data () const
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
936 class Extension
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:
960 Extension ()
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;
1095 typedef SquareMatrix<nifti_dmat44,double,4> Matrix;
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:
1113 Xform ()
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
1268 protected:
1269 nifti_image *image;
1270 int *refCount;
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
1365 public:
1369 NiftiImage ()
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
1527 NiftiImage & operator= (const NiftiImage &source)
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
1628 NiftiImage & drop ()
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
1648 NiftiImageData data () { return NiftiImageData(image); }
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
1697 NiftiImage & replaceData (const NiftiImageData &data);
1698
1704 NiftiImage & dropData ()
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 {
1914 dropExtensions();
1915 for (std::list<Extension>::const_iterator it=extensions.begin(); it!=extensions.end(); ++it)
1916 addExtension(*it);
1917 return *this;
1918 }
1919
1924 NiftiImage & dropExtensions ()
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
RNifti::rgba32_t
Simple RGB(A) type encapsulating an 8-bit colour value with optional opacity, which can also be set o...
Definition NiftiImage.h:49
RNifti::rgba32_t::ValueType
Definition NiftiImage.h:50
RNifti::NiftiImageData
Wrapper class encapsulating a NIfTI data blob, with responsibility for handling data scaling and poly...
Definition NiftiImage.h:66
RNifti::NiftiImageData::datatype
int datatype() const
Return stored datatype code.
Definition NiftiImage.h:514
RNifti::NiftiImageData::isRgb
bool isRgb() const
Determine whether the datatype corresponds to an RGB type.
Definition NiftiImage.h:560
RNifti::NiftiImageData::NiftiImageData
NiftiImageData(nifti_image *image)
Convenience constructor for a nifti_image.
Definition NiftiImage.h:443
RNifti::NiftiImageData::length
size_t length() const
Return the number of elements in the data.
Definition NiftiImage.h:515
RNifti::NiftiImageData::bytesPerPixel
size_t bytesPerPixel() const
Return the number of bytes used per element, or zero if the datatype is undefined or the blob is NULL...
Definition NiftiImage.h:519
RNifti::NiftiImageData::isScaled
bool isScaled() const
Determine whether the object uses data scaling.
Definition NiftiImage.h:535
RNifti::NiftiImageData::NiftiImageData
NiftiImageData()
Default constructor, creating an empty data object.
Definition NiftiImage.h:422
RNifti::NiftiImageData::_datatype
int _datatype
Datatype code indicating the actual type of the elements.
Definition NiftiImage.h:196
RNifti::NiftiImageData::handler
TypeHandler * handler
Type handler, which is created to match the datatype.
Definition NiftiImage.h:197
RNifti::NiftiImageData::end
Iterator end()
Obtain a mutable iterator corresponding to the end of the blob.
Definition NiftiImage.h:584
RNifti::NiftiImageData::unscaled
NiftiImageData unscaled() const
Return a similar object to the callee, but with the slope and intercept values reset.
Definition NiftiImage.h:566
RNifti::NiftiImageData::totalBytes
size_t totalBytes() const
Return the total size of the data blob, in bytes.
Definition NiftiImage.h:522
RNifti::NiftiImageData::minmax
void minmax(double *min, double *max) const
Calculate the minimum and maximum values in the blob, as doubles.
Definition NiftiImage.h:607
RNifti::NiftiImageData::begin
const Iterator begin() const
Obtain a constant iterator corresponding to the start of the blob.
Definition NiftiImage.h:575
RNifti::NiftiImageData::slope
double slope
The slope term used to scale data values.
Definition NiftiImage.h:68
RNifti::NiftiImageData::NiftiImageData
NiftiImageData(void *data, const size_t length, const int datatype, const double slope=1.0, const double intercept=0.0)
Primary constructor.
Definition NiftiImage.h:434
RNifti::NiftiImageData::intercept
double intercept
The intercept term used to scale data values.
Definition NiftiImage.h:69
RNifti::NiftiImageData::isFloatingPoint
bool isFloatingPoint() const
Determine whether the datatype is floating point.
Definition NiftiImage.h:548
RNifti::NiftiImageData::end
const Iterator end() const
Obtain a constant iterator corresponding to the end of the blob.
Definition NiftiImage.h:578
RNifti::NiftiImageData::disown
NiftiImageData & disown()
Disown the data blob, removing responsibility for freeing it upon destruction.
Definition NiftiImage.h:572
RNifti::NiftiImageData::operator[]
const Element operator[](const size_t i) const
Indexing operator, returning a constant element.
Definition NiftiImage.h:591
RNifti::NiftiImageData::_length
size_t _length
The number of data elements in the blob.
Definition NiftiImage.h:198
RNifti::NiftiImageData::createHandler
TypeHandler * createHandler()
Create a concrete type handler appropriate to the datatype code stored with the data.
Definition NiftiImage.h:168
RNifti::NiftiImageData::operator=
NiftiImageData & operator=(const NiftiImageData &source)
Copy assignment operator.
Definition NiftiImage.h:500
RNifti::NiftiImageData::NiftiImageData
NiftiImageData(const NiftiImageData &source, const int datatype=DT_NONE)
Copy constructor with optional type conversion.
Definition NiftiImage.h:458
RNifti::NiftiImageData::isInteger
bool isInteger() const
Determine whether the datatype is an integer type.
Definition NiftiImage.h:554
RNifti::NiftiImageData::~NiftiImageData
virtual ~NiftiImageData()
Destructor which frees the type handler, and the data blob if it is owned by this object.
Definition NiftiImage.h:488
RNifti::NiftiImageData::size
size_t size() const
Return the number of elements in the data.
Definition NiftiImage.h:516
RNifti::NiftiImageData::owner
bool owner
An indicator of whether this object is responsible for cleaning up the data.
Definition NiftiImage.h:199
RNifti::NiftiImageData::NiftiImageData
NiftiImageData(InputIterator from, InputIterator to, const int datatype)
Iterator-based constructor.
Definition NiftiImage.h:478
RNifti::NiftiImageData::begin
Iterator begin()
Obtain a mutable iterator corresponding to the start of the blob.
Definition NiftiImage.h:581
RNifti::NiftiImageData::init
void init(void *data, const size_t length, const int datatype, const double slope, const double intercept, const bool alloc=true)
Initialiser method, used by constructors.
Definition NiftiImage.h:211
RNifti::NiftiImageData::isEmpty
bool isEmpty() const
Determine whether or not the object is empty.
Definition NiftiImage.h:528
RNifti::NiftiImageData::blob
void * blob() const
Return an opaque pointer to the blob.
Definition NiftiImage.h:513
RNifti::NiftiImageData::calibrateFrom
void calibrateFrom(const NiftiImageData &data)
Update the slope and intercept to cover the range of another data object.
Definition NiftiImage.h:237
RNifti::NiftiImageData::isComplex
bool isComplex() const
Determine whether the datatype is complex.
Definition NiftiImage.h:541
RNifti::NiftiImageData::dataPtr
void * dataPtr
Opaque pointer to the underlying data blob.
Definition NiftiImage.h:195
RNifti::NiftiImageData::TypeHandler
Abstract inner class defining the type-specific functions required in concrete subclasses.
Definition NiftiImage.h:76
RNifti::NiftiImageData::ConcreteTypeHandler
Concrete inner class template defining behaviour specific to individual data types.
Definition NiftiImage.h:96
RNifti::NiftiImageData::Element
Inner class representing a single element in the data blob.
Definition NiftiImage.h:262
RNifti::NiftiImageData::Element::Element
Element(const NiftiImageData &parent, void *ptr=NULL)
Primary constructor.
Definition NiftiImage.h:274
RNifti::NiftiImageData::Element::operator=
Element & operator=(const SourceType &value)
Copy assignment operator.
RNifti::NiftiImageData::Iterator
Iterator type for NiftiImageData, with Element as its value type.
Definition NiftiImage.h:349
RNifti::NiftiImageData::Iterator::Iterator
Iterator(const NiftiImageData *parent=NULL, void *ptr=NULL, const size_t step=0)
Primary constructor.
Definition NiftiImage.h:373
RNifti::NiftiImageData::Iterator::Iterator
Iterator(const Iterator &other)
Copy constructor.
Definition NiftiImage.h:384
RNifti::Vector
A simple object-oriented wrapper around a fixed-length array.
Definition NiftiImage.h:633
RNifti::Vector::Vector
Vector(const ElementType *source)
Initialise from a C-style array of the appropriate type and length.
Definition NiftiImage.h:649
RNifti::Vector::operator-
Vector< ElementType, Length > operator-() const
Unary negation operator, which reverses the signs of all elements.
Definition NiftiImage.h:657
RNifti::Vector::Vector
Vector(const ElementType value=0.0)
Initialise with a fixed element value, defaulting to zero.
Definition NiftiImage.h:641
RNifti::SquareMatrix
Class representing a numeric square matrix of a fixed order.
Definition NiftiImage.h:679
RNifti::SquareMatrix::SquareMatrix
SquareMatrix(const ElementType value=0.0)
Initialise with a fixed element value, defaulting to zero.
Definition NiftiImage.h:707
RNifti::SquareMatrix::elements
ElementType elements[Order *Order]
The underlying raw data elements, stored row-major for consistency with niftilib.
Definition NiftiImage.h:681
RNifti::SquareMatrix::begin
const ElementType * begin() const
Return a pointer/iterator to the beginning of the data.
Definition NiftiImage.h:762
RNifti::SquareMatrix::inverse
MatrixType inverse() const
Matrix inverse.
RNifti::SquareMatrix::SquareMatrix
SquareMatrix(const ElementType *source)
Initialise from a C-style array of the appropriate type and length.
Definition NiftiImage.h:715
RNifti::SquareMatrix::polar
MatrixType polar() const
Polar decomposition, as implemented in niftilib (Order 3 only)
RNifti::SquareMatrix::end
ElementType * end()
Return a pointer/iterator to the end of the data.
Definition NiftiImage.h:778
RNifti::SquareMatrix::VectorType
Vector< ElementType, Order > VectorType
Type of vectors for which this matrix is a linear operator.
Definition NiftiImage.h:702
RNifti::SquareMatrix::end
const ElementType * end() const
Return a pointer/iterator to the end of the data.
Definition NiftiImage.h:773
RNifti::SquareMatrix::NativeType
NiftiType NativeType
The niftilib structure type corresponding to this matrix.
Definition NiftiImage.h:700
RNifti::SquareMatrix::multiply
MatrixType multiply(const MatrixType &other) const
Matrix-matrix multiplication.
RNifti::SquareMatrix::rownorm
ElementType rownorm() const
Maximum row norm, as implemented in niftilib (Order 3 only)
RNifti::SquareMatrix::operator()
const ElementType & operator()(const int i, const int j) const
Indexing operator.
Definition NiftiImage.h:805
RNifti::SquareMatrix::colnorm
ElementType colnorm() const
Maximum column norm, as implemented in niftilib (Order 3 only)
RNifti::SquareMatrix::niftiCopy
NiftiType niftiCopy() const
Copy the data elements into a new NIfTI-style mat44 or dmat44.
Definition NiftiImage.h:692
RNifti::SquareMatrix::begin
ElementType * begin()
Return a pointer/iterator to the beginning of the data.
Definition NiftiImage.h:768
RNifti::SquareMatrix::MatrixType
SquareMatrix< NiftiType, ElementType, Order > MatrixType
Type alias for the current specialisation.
Definition NiftiImage.h:701
RNifti::SquareMatrix::SquareMatrix
SquareMatrix(SEXP source)
Initialise from an R object representing a numeric matrix.
Definition NiftiImage.h:733
RNifti::SquareMatrix::determ
ElementType determ() const
Matrix determinant, as implemented in niftilib (Order 3 only)
RNifti::SquareMatrix::multiply
VectorType multiply(const VectorType &vec) const
Matrix-vector multiplication.
RNifti::SquareMatrix::eye
static MatrixType eye()
Construct an identity matrix of the appropriate size.
Definition NiftiImage.h:783
RNifti::SquareMatrix::operator*
MatrixType operator*(const MatrixType &other) const
Matrix-matrix multiplication (infix shorthand)
Definition NiftiImage.h:799
RNifti::SquareMatrix::SquareMatrix
SquareMatrix(const NiftiType &source)
Initialise from the appropriate niftilib type.
Definition NiftiImage.h:723
RNifti::SquareMatrix::niftiPointer
NiftiType * niftiPointer() const
Obtain a pointer to a NIfTI-style mat44 or dmat44 encapsulating the same data as this object.
Definition NiftiImage.h:687
RNifti::NiftiImage::release
void release()
Release the currently wrapped pointer, if it is not NULL, decrementing the reference count and releas...
RNifti::NiftiImage::reorient
NiftiImage & reorient(const std::string &orientation)
Reorient the image by permuting dimensions and potentially reversing some.
RNifti::NiftiImage::initFromMriImage
void initFromMriImage(const Rcpp::RObject &object, const bool copyData=true)
Initialise the object from a reference object of class "MriImage".
RNifti::NiftiImage::replaceData
NiftiImage & replaceData(const NiftiImageData &data)
Replace the pixel data in the image with the contents of a NiftiImageData object.
RNifti::NiftiImage::extensions
std::list< Extension > extensions(const int code=-1) const
Return a list of the extensions associated with the image.
Definition NiftiImage.h:1874
RNifti::NiftiImage::NiftiImage
NiftiImage(const NiftiImage &source, const bool copy=true)
Copy constructor.
Definition NiftiImage.h:1378
RNifti::NiftiImage::isDataScaled
bool isDataScaled() const
Determine whether nontrivial scale and slope parameters are set.
Definition NiftiImage.h:1584
RNifti::NiftiImage::update
NiftiImage & update(const Rcpp::RObject &object)
Update the image from an R array.
RNifti::NiftiImage::setPixunits
void setPixunits(const std::vector< std::string > &pixunits)
Modify the pixel dimension units.
RNifti::NiftiImage::toFile
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.
RNifti::NiftiImage::xform
const Xform xform(const bool preferQuaternion=true) const
Obtain an xform matrix, indicating the orientation of the image.
RNifti::NiftiImage::acquire
void acquire(const NiftiImage &source)
Acquire the same pointer as another NiftiImage, incrementing the shared reference count.
Definition NiftiImage.h:1284
RNifti::NiftiImage::fileVersion
static int fileVersion(const std::string &path)
Get the NIfTI format version used by the file at the specified path.
RNifti::NiftiImage::updatePixdim
void updatePixdim(const std::vector< pixdim_t > &pixdim)
Modify the pixel dimensions, and potentially the xform matrices to match.
RNifti::NiftiImage::replaceData
NiftiImage & replaceData(const std::vector< SourceType > &data, const int datatype=DT_NONE)
Replace the pixel data in the image with the contents of a vector.
RNifti::NiftiImage::rescale
NiftiImage & rescale(const std::vector< pixdim_t > &scales)
Rescale the image, changing its image dimensions and pixel dimensions.
RNifti::NiftiImage::pixdim
std::vector< pixdim_t > pixdim() const
Return the dimensions of the pixels or voxels in the image.
Definition NiftiImage.h:1614
RNifti::NiftiImage::nExtensions
int nExtensions() const
Return the number of extensions associated with the image.
Definition NiftiImage.h:1866
RNifti::NiftiImage::sform
Xform sform()
Access the sform matrix.
Definition NiftiImage.h:1781
RNifti::NiftiImage::reorient
NiftiImage & reorient(const int i, const int j, const int k)
Reorient the image by permuting dimensions and potentially reversing some.
RNifti::NiftiImage::isNull
bool isNull() const
Determine whether or not the wrapped pointer is NULL.
Definition NiftiImage.h:1563
RNifti::NiftiImage::~NiftiImage
virtual ~NiftiImage()
Destructor which decrements the reference counter, and releases the wrapped pointer if the counter dr...
Definition NiftiImage.h:1501
RNifti::NiftiImage::NiftiImage
NiftiImage(const Block &source)
Initialise from a block, copying in the data.
Definition NiftiImage.h:1394
RNifti::NiftiImage::operator->
const nifti_image * operator->() const
Allows a NiftiImage object to be treated as a pointer to a const nifti_image.
Definition NiftiImage.h:1516
RNifti::NiftiImage::nChannels
int nChannels() const
Return the number of colour channels used by the image.
Definition NiftiImage.h:1840
RNifti::NiftiImage::NiftiImage
NiftiImage(const std::vector< dim_t > &dim, const int datatype)
Initialise from basic metadata, allocating and zeroing pixel data.
RNifti::NiftiImage::NiftiImage
NiftiImage(const std::vector< dim_t > &dim, const std::string &datatype)
Initialise from basic metadata, allocating and zeroing pixel data.
RNifti::NiftiImage::dropExtensions
NiftiImage & dropExtensions()
Remove any extensions from the image.
Definition NiftiImage.h:1924
RNifti::NiftiImage::initFromNiftiS4
void initFromNiftiS4(const Rcpp::RObject &object, const bool copyData=true)
Initialise the object from an S4 object of class "nifti".
RNifti::NiftiImage::data
const NiftiImageData data() const
Obtain the pixel data within the image.
Definition NiftiImage.h:1642
RNifti::NiftiImage::dim
std::vector< dim_t > dim() const
Return the dimensions of the image.
Definition NiftiImage.h:1602
RNifti::NiftiImage::isShared
bool isShared() const
Determine whether the wrapped pointer is shared with another NiftiImage.
Definition NiftiImage.h:1569
RNifti::NiftiImage::nBlocks
dim_t nBlocks() const
Return the number of blocks in the image.
Definition NiftiImage.h:1787
RNifti::NiftiImage::getData
std::vector< TargetType > getData(const bool useSlope=true) const
Extract a vector of data from the image, casting it to any required element type.
RNifti::NiftiImage::image
nifti_image * image
The wrapped nifti_image pointer.
Definition NiftiImage.h:1269
RNifti::NiftiImage::block
const Block block(const int i) const
Extract a block from the image.
Definition NiftiImage.h:1796
RNifti::NiftiImage::sexpTypeToNiftiType
static int sexpTypeToNiftiType(const int sexpType)
Convert between R SEXP object type and nifti_image datatype codes.
Definition NiftiImage.h:1246
RNifti::NiftiImage::refCount
int * refCount
A reference counter, shared with other objects wrapping the same pointer.
Definition NiftiImage.h:1270
RNifti::NiftiImage::operator=
NiftiImage & operator=(const NiftiImage &source)
Copy assignment operator, which copies from its argument.
Definition NiftiImage.h:1527
RNifti::NiftiImage::isPersistent
bool isPersistent() const
Determine whether or not the image is marked as persistent.
Definition NiftiImage.h:1577
RNifti::NiftiImage::block
Block block(const int i)
Extract a block from the image.
Definition NiftiImage.h:1805
RNifti::NiftiImage::replaceExtensions
NiftiImage & replaceExtensions(const std::list< Extension > extensions)
Replace all extensions with new ones.
Definition NiftiImage.h:1912
RNifti::NiftiImage::toPointer
Rcpp::RObject toPointer(const std::string label) const
Create an internal image to pass back to R.
RNifti::NiftiImage::NiftiImage
NiftiImage(const SEXP object, const bool readData=true, const bool readOnly=false)
Initialise from an R object, retrieving an existing image from an external pointer attribute if avail...
RNifti::NiftiImage::slice
Block slice(const int i)
Extract a slice block from a 3D image.
Definition NiftiImage.h:1819
RNifti::NiftiImage::dropData
NiftiImage & dropData()
Drop the data from the image, retaining only the metadata.
Definition NiftiImage.h:1704
RNifti::NiftiImage::changeDatatype
NiftiImage & changeDatatype(const std::string &datatype, const bool useSlope=false)
Change the datatype of the image, casting the pixel data if present.
RNifti::NiftiImage::toArrayOrPointer
Rcpp::RObject toArrayOrPointer(const bool internal, const std::string label) const
A conditional method that calls either toArray or toPointer.
RNifti::NiftiImage::copy
void copy(const NiftiImage &source)
Copy the contents of another NiftiImage to create a new image, acquiring a new pointer.
RNifti::NiftiImage::changeDatatype
NiftiImage & changeDatatype(const int datatype, const bool useSlope=false)
Change the datatype of the image, casting the pixel data if present.
RNifti::NiftiImage::data
NiftiImageData data()
Obtain the pixel data within the image.
Definition NiftiImage.h:1648
RNifti::NiftiImage::toArray
Rcpp::RObject toArray() const
Create an R array from the image.
RNifti::NiftiImage::nDims
int nDims() const
Return the number of dimensions in the image.
Definition NiftiImage.h:1590
RNifti::NiftiImage::NiftiImage
NiftiImage(nifti_image *const image, const bool copy=false)
Initialise using an existing nifti_image pointer.
Definition NiftiImage.h:1409
RNifti::NiftiImage::volume
Block volume(const int i)
Extract a volume block from a 4D image.
Definition NiftiImage.h:1833
RNifti::NiftiImage::acquire
void acquire(nifti_image *const image)
Acquire the specified pointer to a nifti_image struct, taking (possibly shared) responsibility for fr...
RNifti::NiftiImage::NiftiImage
NiftiImage(const std::string &path, const std::vector< dim_t > &volumes)
Initialise using a path string and sequence of required volumes.
RNifti::NiftiImage::volume
const Block volume(const int i) const
Extract a volume block from a 4D image.
Definition NiftiImage.h:1826
RNifti::NiftiImage::toFile
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.
RNifti::NiftiImage::initFromArray
void initFromArray(const Rcpp::RObject &object, const bool copyData=true)
Initialise the object from an R array.
RNifti::NiftiImage::copy
void copy(const Block &source)
Copy the contents of a Block to create a new image, acquiring a new pointer.
RNifti::NiftiImage::nVoxels
size_t nVoxels() const
Return the number of voxels in the image.
Definition NiftiImage.h:1860
RNifti::NiftiImage::qform
Xform qform()
Access the qform matrix.
Definition NiftiImage.h:1769
RNifti::NiftiImage::slice
const Block slice(const int i) const
Extract a slice block from a 3D image.
Definition NiftiImage.h:1812
RNifti::NiftiImage::sform
const Xform sform() const
Access the sform matrix.
Definition NiftiImage.h:1775
RNifti::NiftiImage::drop
NiftiImage & drop()
Drop unitary dimensions.
Definition NiftiImage.h:1628
RNifti::NiftiImage::setPersistence
NiftiImage & setPersistence(const bool persistent)
Mark the image as persistent, so that it can be passed back to R.
Definition NiftiImage.h:1557
RNifti::NiftiImage::copy
void copy(const nifti_image *source)
Copy the contents of a nifti_image to create a new image, acquiring the new pointer.
RNifti::NiftiImage::NiftiImage
NiftiImage()
Default constructor.
Definition NiftiImage.h:1369
RNifti::NiftiImage::initFromList
void initFromList(const Rcpp::RObject &object)
Initialise the object from an R list with named elements, which can only contain metadata.
RNifti::NiftiImage::addExtension
NiftiImage & addExtension(const Extension &extension)
Add an extension to the image.
Definition NiftiImage.h:1896
RNifti::NiftiImage::NiftiImage
NiftiImage(const nifti_1_header &header)
Initialise using a NIfTI-1 header.
Definition NiftiImage.h:1425
RNifti::NiftiImage::initFromDims
void initFromDims(const std::vector< dim_t > &dim, const int datatype)
Initialise an empty object from basic metadata.
RNifti::NiftiImage::NiftiImage
NiftiImage(const std::string &path, const bool readData=true)
Initialise using a path string.
RNifti::NiftiImage::qform
const Xform qform() const
Access the qform matrix.
Definition NiftiImage.h:1763
RNifti::NiftiImage::Block
Inner class referring to a subset of an image.
Definition NiftiImage.h:858
RNifti::NiftiImage::Block::data
NiftiImageData data() const
Obtain the data within the block.
Definition NiftiImage.h:908
RNifti::NiftiImage::Block::image
const NiftiImage & image
The parent image.
Definition NiftiImage.h:859
RNifti::NiftiImage::Block::index
const dim_t index
The location along dimension.
Definition NiftiImage.h:861
RNifti::NiftiImage::Block::Block
Block(const NiftiImage &image, const int dimension, const dim_t index)
Standard constructor for this class.
Definition NiftiImage.h:870
RNifti::NiftiImage::Block::dimension
const int dimension
The dimension along which the block applies (which should be the last)
Definition NiftiImage.h:860
RNifti::NiftiImage::Block::operator=
Block & operator=(const NiftiImage &source)
Copy assignment operator, which allows a block in one image to be replaced with the contents of anoth...
Definition NiftiImage.h:885
RNifti::NiftiImage::Block::getData
std::vector< TargetType > getData(const bool useSlope=true) const
Extract a vector of data from a block, casting it to any required element type.
RNifti::NiftiImage::Extension
Inner class wrapping a NIfTI extension, a weakly-specified standard for attaching additional metadata...
Definition NiftiImage.h:937
RNifti::NiftiImage::Extension::copy
void copy(const nifti1_extension *source)
Copy an existing nifti1_extension structure into the object.
RNifti::NiftiImage::Extension::Extension
Extension(const SourceType *data, const size_t length, const int code)
Construct the object from its constituent parts.
Definition NiftiImage.h:994
RNifti::NiftiImage::Extension::Extension
Extension(const Extension &source)
Copy constructor.
Definition NiftiImage.h:982
RNifti::NiftiImage::Extension::copy
void copy(const SourceType *data, const size_t length, const int code)
Copy the specified data buffer into the object.
RNifti::NiftiImage::Extension::Extension
Extension(SEXP source, int code=-1)
Construct the object from an atomic R object, copying the data into a new extension.
Definition NiftiImage.h:1007
RNifti::NiftiImage::Extension::code
int code() const
Return the code associated with the extension.
Definition NiftiImage.h:1037
RNifti::NiftiImage::Extension::length
size_t length() const
Return the length of the data array.
Definition NiftiImage.h:1049
RNifti::NiftiImage::Extension::Extension
Extension()
Default constructor, wrapping NULL.
Definition NiftiImage.h:960
RNifti::NiftiImage::Extension::Extension
Extension(nifti1_extension *const extension, const bool copy=false)
Initialise from an existing nifti1_extension (which is used by both NIfTI-1 and NIfTI-2 images),...
Definition NiftiImage.h:970
RNifti::NiftiImage::Extension::size
size_t size() const
Return the length of the data array.
Definition NiftiImage.h:1055
RNifti::NiftiImage::Extension::data
const char * data() const
Return the data blob associated with the extension.
Definition NiftiImage.h:1043
RNifti::NiftiImage::Extension::ext
nifti1_extension * ext
The wrapped extension structure.
Definition NiftiImage.h:939
RNifti::NiftiImage::Xform
Inner class representing an xform matrix, which indicates the orientation and other spatial propertie...
Definition NiftiImage.h:1083
RNifti::NiftiImage::Xform::operator=
Xform & operator=(const Xform &source)
Copy assignment operator, taking an Xform and replacing linked data.
Definition NiftiImage.h:1165
RNifti::NiftiImage::Xform::matrix
const Matrix & matrix() const
Access the xform matrix as an immutable SquareMatrix object.
Definition NiftiImage.h:1194
RNifti::NiftiImage::Xform::Xform
Xform()
Default constructor.
Definition NiftiImage.h:1113
RNifti::NiftiImage::Xform::Xform
Xform(Matrix::NativeType &source, Matrix::NativeType &inverse, Element *qparams=NULL)
Initialise from forward and backward matrices, and optionally quaternion parameters.
Definition NiftiImage.h:1139
RNifti::NiftiImage::Xform::spacing
Vector3 spacing() const
Obtain the pixel spacing of the image in each spatial dimension.
RNifti::NiftiImage::Xform::Xform
Xform(const Matrix &source)
Initialise from a 4x4 SquareMatrix.
Definition NiftiImage.h:1119
RNifti::NiftiImage::Xform::rotation
Submatrix rotation() const
Obtain the 3x3 rotation matrix from the xform matrix, with scale and skew components removed.
RNifti::NiftiImage::Xform::Xform
Xform(Matrix::NativeType &source)
Initialise from a NIfTI mat44 or dmat44.
Definition NiftiImage.h:1132
RNifti::NiftiImage::Xform::replace
void replace(const Matrix &source)
Replace the current matrix with a new one.
RNifti::NiftiImage::Xform::mat
Matrix mat
The full xform matrix underpinning this object.
Definition NiftiImage.h:1101
RNifti::NiftiImage::Xform::submatrix
Submatrix submatrix() const
Obtain the upper left 3x3 submatrix from the xform matrix.
RNifti::NiftiImage::Xform::handedness
Element handedness() const
Returns the qfac value, which should be 1 where the xform matrix represents a right-handed coordinate...
RNifti::NiftiImage::Xform::Xform
Xform(SEXP source)
Initialise from an R numeric matrix object.
Definition NiftiImage.h:1146
RNifti::NiftiImage::Xform::quaternion
Vector4 quaternion() const
Obtain the quaternion representation of the xform's rotation component.
RNifti::NiftiImage::Xform::orientation
std::string orientation() const
Obtain the approximate orientation of the image's coordinate frame, as a three-character string consi...
RNifti::NiftiImage::Xform::Xform
Xform(const Matrix::NativeType &source)
Initialise from a constant NIfTI mat44 or dmat44.
Definition NiftiImage.h:1125
RNifti::NiftiImage::Xform::qparams
Element * qparams
Pointers to linked C-style arrays.
Definition NiftiImage.h:1100
RNifti::NiftiImage::Xform::offset
Vector3 offset() const
Obtain the translation component of the xform matrix.