1 #ifndef _NIFTI_IMAGE_H_ 2 #define _NIFTI_IMAGE_H_ 11 #define MAYBE_SHARED(x) (NAMED(x) > 1) 16 #define R_NegInf -INFINITY 33 #include "niftilib/nifti1_io.h" 65 virtual size_t size ()
const {
return 0; }
66 virtual bool hasNaN ()
const {
return false; }
67 virtual double getDouble (
void *ptr)
const = 0;
68 virtual int getInt (
void *ptr)
const = 0;
69 virtual void setDouble (
void *ptr,
const double value)
const = 0;
70 virtual void setInt (
void *ptr,
const int value)
const = 0;
71 virtual void minmax (
void *ptr,
const size_t length,
double *min,
double *max)
const = 0;
77 template <
typename Type>
80 size_t size ()
const {
return (
sizeof(Type)); }
81 bool hasNaN ()
const {
return std::numeric_limits<Type>::has_quiet_NaN; }
82 double getDouble (
void *ptr)
const {
return static_cast<double>(*static_cast<Type*>(ptr)); }
83 int getInt (
void *ptr)
const {
return static_cast<int>(*static_cast<Type*>(ptr)); }
84 void setDouble (
void *ptr,
const double value)
const { *(static_cast<Type*>(ptr)) = static_cast<Type>(value); }
85 void setInt (
void *ptr,
const int value)
const { *(static_cast<Type*>(ptr)) = static_cast<Type>(value); }
86 void minmax (
void *ptr,
const size_t length,
double *min,
double *max)
const;
113 throw std::runtime_error(
"Unsupported data type (" + std::string(nifti_datatype_string(
_datatype)) +
")");
144 else if (alloc && data == NULL)
166 double dataMin, dataMax, typeMin, typeMax;
167 data.
minmax(&dataMin, &dataMax);
168 handler->minmax(NULL, 0, &typeMin, &typeMax);
171 if (dataMin < typeMin || dataMax > typeMax)
173 slope = (dataMax - dataMin) / (typeMax - typeMin);
199 this->ptr = (ptr == NULL ? parent.
dataPtr : ptr);
209 template <
typename SourceType>
222 template <
typename TargetType>
223 operator TargetType()
const 227 else if (std::numeric_limits<TargetType>::is_integer)
228 return TargetType(parent.
handler->getInt(ptr));
230 return TargetType(parent.
handler->getDouble(ptr));
237 class Iterator :
public std::iterator<std::random_access_iterator_tag, Element>
255 this->ptr = (ptr == NULL ? parent.
dataPtr : ptr);
256 this->step = (step == 0 ? parent.
handler->size() : step);
264 : parent(other.parent), ptr(other.ptr), step(other.step) {}
266 Iterator & operator++ () { ptr = static_cast<char*>(ptr) + step;
return *
this; }
267 Iterator operator++ (
int) {
Iterator copy(*
this); ptr = static_cast<char*>(ptr) + step;
return copy; }
268 Iterator operator+ (ptrdiff_t n)
const 270 void *newptr = static_cast<char*>(ptr) + (n * step);
271 return Iterator(parent, newptr, step);
273 Iterator & operator-- () { ptr = static_cast<char*>(ptr) - step;
return *
this; }
274 Iterator operator-- (
int) {
Iterator copy(*
this); ptr = static_cast<char*>(ptr) - step;
return copy; }
275 Iterator operator- (ptrdiff_t n)
const 277 void *newptr = static_cast<char*>(ptr) - (n * step);
278 return Iterator(parent, newptr, step);
281 ptrdiff_t operator- (
const Iterator &other)
const 283 const ptrdiff_t difference = static_cast<char*>(ptr) - static_cast<char*>(other.ptr);
284 return difference / step;
287 bool operator== (
const Iterator &other)
const {
return (ptr==other.ptr && step==other.step); }
288 bool operator!= (
const Iterator &other)
const {
return (ptr!=other.ptr || step!=other.step); }
289 bool operator> (
const Iterator &other)
const {
return (ptr > other.ptr); }
290 bool operator< (
const Iterator &other)
const {
return (ptr < other.ptr); }
292 const Element operator* ()
const {
return Element(parent, ptr); }
293 Element operator* () {
return Element(parent, ptr); }
294 const Element operator[] (
const size_t i)
const {
return Element(parent, static_cast<char*>(ptr) + (i * step)); }
295 Element operator[] (
const size_t i) {
return Element(parent, static_cast<char*>(ptr) + (i * step)); }
325 init(NULL, 0, DT_NONE, 0.0, 0.0,
false);
327 init(image->data, image->nvox, image->datatype, static_cast<double>(image->scl_slope), static_cast<double>(image->scl_inter),
false);
356 template <
class InputIterator>
359 const size_t length = static_cast<size_t>(std::distance(from, to));
361 std::copy(from, to, this->
begin());
439 bool isRgb ()
const {
return false; }
486 void minmax (
double *min,
double *max)
const 501 inline bool NiftiImageData::ConcreteTypeHandler<int>::hasNaN ()
const {
return true; }
535 throw std::runtime_error(
"Blocks must be along the last dimension in the image");
548 if (source->datatype !=
image->datatype)
549 throw std::runtime_error(
"New data does not have the same datatype as the target block");
550 if (source->scl_slope !=
image->scl_slope || source->scl_inter !=
image->scl_inter)
551 throw std::runtime_error(
"New data does not have the same scale parameters as the target block");
553 size_t blockSize = 1;
557 if (blockSize != source->nvox)
558 throw std::runtime_error(
"New data does not have the same size as the target block");
560 blockSize *=
image->nbyper;
575 size_t blockSize = 1;
589 template <
typename TargetType>
590 std::vector<TargetType>
getData (
const bool useSlope =
true)
const;
600 static int sexpTypeToNiftiType (
const int sexpType)
602 if (sexpType == INTSXP || sexpType == LGLSXP)
604 else if (sexpType == REALSXP)
607 throw std::runtime_error(
"Array elements must be numeric");
666 void copy (
const nifti_image *source);
678 void copy (
const Block &source);
688 void initFromNiftiS4 (
const Rcpp::RObject &
object,
const bool copyData =
true);
695 void initFromMriImage (
const Rcpp::RObject &
object,
const bool copyData =
true);
701 void initFromList (
const Rcpp::RObject &
object);
708 void initFromArray (
const Rcpp::RObject &
object,
const bool copyData =
true);
722 void setPixunits (
const std::vector<std::string> &pixunits);
745 Rc_printf(
"Creating NiftiImage with pointer %p (from NiftiImage)\n", this->image);
758 Rc_printf(
"Creating NiftiImage with pointer %p (from Block)\n", this->image);
776 Rc_printf(
"Creating NiftiImage with pointer %p (from pointer)\n", this->image);
786 NiftiImage (
const std::string &path,
const bool readData =
true)
789 acquire(nifti_image_read(path.c_str(), readData));
791 throw std::runtime_error(
"Failed to read image from path " + path);
793 Rc_printf(
"Creating NiftiImage with pointer %p (from string)\n", this->image);
803 NiftiImage (
const std::string &path,
const std::vector<int> &volumes);
816 NiftiImage (
const SEXP
object,
const bool readData =
true,
const bool readOnly =
false);
828 operator const nifti_image* ()
const {
return image; }
833 operator nifti_image* () {
return image; }
853 Rc_printf(
"Creating NiftiImage with pointer %p (from NiftiImage)\n", this->image);
867 Rc_printf(
"Creating NiftiImage with pointer %p (from Block)\n", this->image);
924 std::vector<int>
dim ()
const 927 return std::vector<int>();
939 return std::vector<float>();
941 return std::vector<float>(
image->pixdim+1,
image->pixdim+
image->ndim+1);
952 int ndim =
image->ndim;
953 while (
image->dim[ndim] < 2)
981 template <
typename TargetType>
982 std::vector<TargetType>
getData (
const bool useSlope =
true)
const;
1010 template <
typename SourceType>
1027 nifti_image_unload(
image);
1065 NiftiImage & update (
const Rcpp::RObject &
object);
1073 mat44
xform (
const bool preferQuaternion =
true)
const;
1138 void toFile (
const std::string fileName,
const int datatype = DT_NONE)
const;
1145 void toFile (
const std::string fileName,
const std::string &datatype)
const;
1153 Rcpp::RObject toArray ()
const;
1160 Rcpp::RObject toPointer (
const std::string label)
const;
1168 Rcpp::RObject toArrayOrPointer (
const bool internal,
const std::string label)
const;
1174 Rcpp::RObject headerToList ()
const;
1181 #include "lib/NiftiImage_impl.h" bool isInteger() const
Determine whether the datatype is an integer type.
Definition: NiftiImage.h:433
NiftiImage()
Default constructor.
Definition: NiftiImage.h:728
const int index
The location along dimension.
Definition: NiftiImage.h:522
static std::string xformToString(const mat44 matrix)
Convert a 4x4 xform matrix to a string describing its canonical axes.
std::vector< int > dim() const
Return the dimensions of the image.
Definition: NiftiImage.h:924
const nifti_image * operator->() const
Allows a NiftiImage object to be treated as a pointer to a const nifti_image.
Definition: NiftiImage.h:838
void init(void *data, const size_t length, const int datatype, const double slope, const double intercept, const bool alloc=true)
Initialiser method, used by constructors.
Definition: NiftiImage.h:133
int datatype() const
Return stored datatype code.
Definition: NiftiImage.h:393
const Iterator begin() const
Obtain a constant iterator corresponding to the start of the blob.
Definition: NiftiImage.h:454
bool isComplex() const
Determine whether the datatype is complex.
Definition: NiftiImage.h:420
NiftiImage & rescale(const std::vector< float > &scales)
Rescale the image, changing its image dimensions and pixel dimensions.
bool isRgb() const
Determine whether the datatype corresponds to an RGB value.
Definition: NiftiImage.h:439
int * refCount
A reference counter, shared with other objects wrapping the same pointer.
Definition: NiftiImage.h:636
Abstract inner class defining the type-specific functions required in concrete subclasses.
Definition: NiftiImage.h:62
const Element operator[](const size_t i) const
Indexing operator, returning a constant element.
Definition: NiftiImage.h:470
Iterator end()
Obtain a mutable iterator corresponding to the end of the blob.
Definition: NiftiImage.h:463
NiftiImage & replaceData(const std::vector< SourceType > &data, const int datatype=DT_NONE)
Replace the pixel data in the image with the contents of a vector.
std::vector< float > pixdim() const
Return the dimensions of the pixels or voxels in the image.
Definition: NiftiImage.h:936
void minmax(double *min, double *max) const
Calculate the minimum and maximum values in the blob, as doubles.
Definition: NiftiImage.h:486
Concrete inner class template defining behaviour specific to individual data types.
Definition: NiftiImage.h:78
NiftiImage(const std::string &path, const bool readData=true)
Initialise using a path string.
Definition: NiftiImage.h:786
size_t size() const
Return the number of elements in the data.
Definition: NiftiImage.h:395
Iterator type for NiftiImageData, with Element as its value type.
Definition: NiftiImage.h:237
double slope
The slope term used to scale data values.
Definition: NiftiImage.h:55
NiftiImage(nifti_image *const image, const bool copy=false)
Initialise using an existing nifti_image pointer.
Definition: NiftiImage.h:768
NiftiImageData(void *data, const size_t length, const int datatype, const double slope=1.0, const double intercept=0.0)
Primary constructor.
Definition: NiftiImage.h:313
Block & operator=(const NiftiImage &source)
Copy assignment operator, which allows a block in one image to be replaced with the contents of anoth...
Definition: NiftiImage.h:546
bool isNull() const
Determine whether or not the wrapped pointer is NULL.
Definition: NiftiImage.h:885
Inner class referring to a subset of an image.
Definition: NiftiImage.h:518
Block slice(const int i)
Extract a slice block from a 3D image.
Definition: NiftiImage.h:1117
const NiftiImageData data() const
Obtain the pixel data within the image.
Definition: NiftiImage.h:964
bool isShared() const
Determine whether the wrapped pointer is shared with another NiftiImage.
Definition: NiftiImage.h:891
void acquire(const NiftiImage &source)
Acquire the same pointer as another NiftiImage, incrementing the shared reference count.
Definition: NiftiImage.h:650
NiftiImageData()
Default constructor, creating an empty data object.
Definition: NiftiImage.h:301
Iterator(const NiftiImageData &parent, void *ptr=NULL, const size_t step=0)
Primary constructor.
Definition: NiftiImage.h:252
void acquire(nifti_image *const image)
Acquire the specified pointer to a nifti_image struct, taking (possibly shared) responsibility for fr...
bool isDataScaled() const
Determine whether nontrivial scale and slope parameters are set.
Definition: NiftiImage.h:906
const Block slice(const int i) const
Extract a slice block from a 3D image.
Definition: NiftiImage.h:1110
NiftiImageData data() const
Obtain the data within the block.
Definition: NiftiImage.h:569
const Block volume(const int i) const
Extract a volume block from a 4D image.
Definition: NiftiImage.h:1124
bool owner
An indicator of whether this object is responsible for cleaning up the data.
Definition: NiftiImage.h:121
bool isPersistent() const
Determine whether or not the image is marked as persistent.
Definition: NiftiImage.h:899
size_t totalBytes() const
Return the total size of the data blob, in bytes.
Definition: NiftiImage.h:401
std::vector< TargetType > getData(const bool useSlope=true) const
Extract a vector of data from a block, casting it to any required element type.
void setPixunits(const std::vector< std::string > &pixunits)
Modify the pixel dimension units.
Element & operator=(const SourceType &value)
Copy assignment operator.
size_t bytesPerPixel() const
Return the number of bytes used per element, or zero if the datatype is undefined or the blob is NULL...
Definition: NiftiImage.h:398
void * blob() const
Return an opaque pointer to the blob.
Definition: NiftiImage.h:392
NiftiImage(const Block &source)
Initialise from a block, copying in the data.
Definition: NiftiImage.h:753
virtual ~NiftiImage()
Destructor which decrements the reference counter, and releases the wrapped pointer if the counter dr...
Definition: NiftiImage.h:823
Thin wrapper around a C-style nifti_image struct that allows C++-style destruction.
Definition: NiftiImage.h:511
virtual ~NiftiImageData()
Destructor which frees the type handler, and the data blob if it is owned by this object.
Definition: NiftiImage.h:367
int _datatype
Datatype code indicating the actual type of the elements.
Definition: NiftiImage.h:118
NiftiImage(const NiftiImage &source, const bool copy=true)
Copy constructor.
Definition: NiftiImage.h:737
NiftiImageData & operator=(const NiftiImageData &source)
Copy assignment operator.
Definition: NiftiImage.h:379
TypeHandler * handler
Type handler, which is created to match the datatype.
Definition: NiftiImage.h:119
int nBlocks() const
Return the number of blocks in the image.
Definition: NiftiImage.h:1079
Inner class representing a single element in the data blob.
Definition: NiftiImage.h:183
void release()
Release the currently wrapped pointer, if it is not NULL, decrementing the reference count and releas...
void calibrateFrom(const NiftiImageData &data)
Update the slope and intercept to cover the range of another data object.
Definition: NiftiImage.h:159
const int dimension
The dimension along which the block applies (which should be the last)
Definition: NiftiImage.h:521
const NiftiImage & image
The parent image.
Definition: NiftiImage.h:520
NiftiImage & operator=(const NiftiImage &source)
Copy assignment operator, which copies from its argument.
Definition: NiftiImage.h:849
NiftiImage & changeDatatype(const int datatype, const bool useSlope=false)
Change the datatype of the image, casting the pixel data if present.
NiftiImageData unscaled() const
Return a similar object to the callee, but with the slope and intercept values reset.
Definition: NiftiImage.h:445
static int fileVersion(const std::string &path)
Get the NIfTI format version used by the file at the specified path.
static mat33 xformToRotation(const mat44 matrix)
Extract the pure rotation part of a 4x4 xform matrix.
void updatePixdim(const std::vector< float > &pixdim)
Modify the pixel dimensions, and potentially the xform matrices to match.
const Block block(const int i) const
Extract a block from the image.
Definition: NiftiImage.h:1094
NiftiImageData(const NiftiImageData &source, const int datatype=DT_NONE)
Copy constructor with optional type conversion.
Definition: NiftiImage.h:337
Element(const NiftiImageData &parent, void *ptr=NULL)
Primary constructor.
Definition: NiftiImage.h:196
bool isScaled() const
Determine whether the object uses data scaling.
Definition: NiftiImage.h:414
NiftiImageData data()
Obtain the pixel data within the image.
Definition: NiftiImage.h:970
NiftiImage & setPersistence(const bool persistent)
Mark the image as persistent, so that it can be passed back to R.
Definition: NiftiImage.h:879
std::vector< TargetType > getData(const bool useSlope=true) const
Extract a vector of data from the image, casting it to any required element type.
Iterator(const Iterator &other)
Copy constructor.
Definition: NiftiImage.h:263
void copy(const nifti_image *source)
Copy the contents of a nifti_image to create a new image, acquiring the new pointer.
mat44 xform(const bool preferQuaternion=true) const
Obtain an xform matrix, indicating the orientation of the image.
nifti_image * image
The wrapped nifti_image pointer.
Definition: NiftiImage.h:635
double intercept
The intercept term used to scale data values.
Definition: NiftiImage.h:56
int nDims() const
Return the number of dimensions in the image.
Definition: NiftiImage.h:912
void * dataPtr
Opaque pointer to the underlying data blob.
Definition: NiftiImage.h:117
TypeHandler * createHandler()
Create a concrete type handler appropriate to the datatype code stored with the data.
Definition: NiftiImage.h:94
size_t _length
The number of data elements in the blob.
Definition: NiftiImage.h:120
Iterator begin()
Obtain a mutable iterator corresponding to the start of the blob.
Definition: NiftiImage.h:460
Block volume(const int i)
Extract a volume block from a 4D image.
Definition: NiftiImage.h:1131
size_t length() const
Return the number of elements in the data.
Definition: NiftiImage.h:394
Wrapper class encapsulating a NIfTI data blob, with responsibility for handling data scaling and poly...
Definition: NiftiImage.h:52
NiftiImage & drop()
Drop unitary dimensions.
Definition: NiftiImage.h:950
NiftiImageData & disown()
Disown the data blob, removing responsibility for freeing it upon destruction.
Definition: NiftiImage.h:451
NiftiImage & reorient(const int i, const int j, const int k)
Reorient the image by permuting dimensions and potentially reversing some.
Block(const NiftiImage &image, const int dimension, const int index)
Standard constructor for this class.
Definition: NiftiImage.h:531
void toFile(const std::string fileName, const int datatype=DT_NONE) const
Write the image to a NIfTI-1 file.
bool isFloatingPoint() const
Determine whether the datatype is floating point.
Definition: NiftiImage.h:427
NiftiImageData(nifti_image *image)
Convenience constructor for a nifti_image.
Definition: NiftiImage.h:322
const Iterator end() const
Obtain a constant iterator corresponding to the end of the blob.
Definition: NiftiImage.h:457
bool isEmpty() const
Determine whether or not the object is empty.
Definition: NiftiImage.h:407
NiftiImageData(InputIterator from, InputIterator to, const int datatype)
Iterator-based constructor.
Definition: NiftiImage.h:357
NiftiImage & dropData()
Drop the data from the image, retaining only the metadata.
Definition: NiftiImage.h:1025
Block block(const int i)
Extract a block from the image.
Definition: NiftiImage.h:1103