31 #include "Common/AString.h" 33 #include "Common/ByteSwapping.h" 34 #include "Common/BinaryFile.h" 35 #include "Common/CiftiException.h" 36 #include "Common/CiftiMutex.h" 37 #include "Nifti/NiftiHeader.h" 40 #include "Common/MultiDimIterator.h" 53 std::vector<int64_t> m_dims;
54 std::vector<char> m_scratch;
56 int numBytesPerElem();
57 template<
typename TO,
typename FROM>
58 void convertRead(TO* out, FROM* in,
const int64_t& count);
59 template<
typename TO,
typename FROM>
60 void convertWrite(TO* out,
const FROM* in,
const int64_t& count);
62 void openRead(
const AString& filename);
63 void writeNew(
const AString& filename,
const NiftiHeader& header,
const int& version = 1,
const bool& withRead =
false,
const bool& swapEndian =
false);
64 AString getFilename()
const {
return m_file.getFilename(); }
65 void overrideDimensions(
const std::vector<int64_t>& newDims) { m_dims = newDims; }
67 const NiftiHeader& getHeader()
const {
return m_header; }
68 const std::vector<int64_t>& getDimensions()
const {
return m_dims; }
69 int getNumComponents()
const;
73 void readData(T* dataOut,
const int& fullDims,
const std::vector<int64_t>& indexSelect,
const bool& tolerateShortRead =
false);
75 void writeData(
const T* dataIn,
const int& fullDims,
const std::vector<int64_t>& indexSelect);
79 void NiftiIO::readData(T* dataOut,
const int& fullDims,
const std::vector<int64_t>& indexSelect,
const bool& tolerateShortRead)
81 if (fullDims < 0)
throw CiftiException(
"NiftiIO: fulldims must not be negative");
82 if (fullDims > (
int)m_dims.size())
throw CiftiException(
"NiftiIO: fulldims must not be greater than number of dimensions");
83 if ((
size_t)fullDims + indexSelect.size() != m_dims.size())
85 throw CiftiException(
"NiftiIO: fulldims plus length of indexSelect must equal number of dimensions");
87 int64_t numElems = getNumComponents();
89 for (curDim = 0; curDim < fullDims; ++curDim)
91 numElems *= m_dims[curDim];
93 int64_t numDimSkip = numElems, numSkip = 0;
94 for (; curDim < (int)m_dims.size(); ++curDim)
96 if (indexSelect[curDim - fullDims] < 0)
throw CiftiException(
"NiftiIO: indices must not be negative");
97 if (indexSelect[curDim - fullDims] >= m_dims[curDim])
throw CiftiException(
"NiftiIO: index exceeds nifti dimension length");
98 numSkip += indexSelect[curDim - fullDims] * numDimSkip;
99 numDimSkip *= m_dims[curDim];
101 CiftiMutexLocker locked(&m_mutex);
104 m_scratch.resize(numElems * numBytesPerElem());
105 m_file.seek(numSkip * numBytesPerElem() + m_header.getDataOffset());
107 m_file.read(m_scratch.data(), m_scratch.size(), &numRead);
108 if ((numRead != (int64_t)m_scratch.size() && !tolerateShortRead) || numRead < 0)
110 throw CiftiException(
"error while reading from file '" + m_file.getFilename() +
"'");
112 switch (m_header.getDataType())
116 convertRead(dataOut, (uint8_t*)m_scratch.data(), numElems);
119 convertRead(dataOut, (int8_t*)m_scratch.data(), numElems);
122 convertRead(dataOut, (uint16_t*)m_scratch.data(), numElems);
125 convertRead(dataOut, (int16_t*)m_scratch.data(), numElems);
128 convertRead(dataOut, (uint32_t*)m_scratch.data(), numElems);
131 convertRead(dataOut, (int32_t*)m_scratch.data(), numElems);
134 convertRead(dataOut, (uint64_t*)m_scratch.data(), numElems);
137 convertRead(dataOut, (int64_t*)m_scratch.data(), numElems);
141 convertRead(dataOut, (
float*)m_scratch.data(), numElems);
145 convertRead(dataOut, (
double*)m_scratch.data(), numElems);
149 convertRead(dataOut, (
long double*)m_scratch.data(), numElems);
152 throw CiftiException(
"internal error, tell the developers what you just tried to do");
157 void NiftiIO::writeData(
const T* dataIn,
const int& fullDims,
const std::vector<int64_t>& indexSelect)
159 if (fullDims < 0)
throw CiftiException(
"NiftiIO: fulldims must not be negative");
160 if (fullDims > (
int)m_dims.size())
throw CiftiException(
"NiftiIO: fulldims must not be greater than number of dimensions");
161 if ((
size_t)fullDims + indexSelect.size() != m_dims.size())
163 throw CiftiException(
"NiftiIO: fulldims plus length of indexSelect must equal number of dimensions");
165 int64_t numElems = getNumComponents();
167 for (curDim = 0; curDim < fullDims; ++curDim)
169 numElems *= m_dims[curDim];
171 int64_t numDimSkip = numElems, numSkip = 0;
172 for (; curDim < (int)m_dims.size(); ++curDim)
174 if (indexSelect[curDim - fullDims] < 0)
throw CiftiException(
"NiftiIO: indices must not be negative");
175 if (indexSelect[curDim - fullDims] >= m_dims[curDim])
throw CiftiException(
"NiftiIO: index exceeds nifti dimension length");
176 numSkip += indexSelect[curDim - fullDims] * numDimSkip;
177 numDimSkip *= m_dims[curDim];
179 CiftiMutexLocker locked(&m_mutex);
181 m_scratch.resize(numElems * numBytesPerElem());
182 m_file.seek(numSkip * numBytesPerElem() + m_header.getDataOffset());
183 switch (m_header.getDataType())
187 convertWrite((uint8_t*)m_scratch.data(), dataIn, numElems);
190 convertWrite((int8_t*)m_scratch.data(), dataIn, numElems);
193 convertWrite((uint16_t*)m_scratch.data(), dataIn, numElems);
196 convertWrite((int16_t*)m_scratch.data(), dataIn, numElems);
199 convertWrite((uint32_t*)m_scratch.data(), dataIn, numElems);
202 convertWrite((int32_t*)m_scratch.data(), dataIn, numElems);
205 convertWrite((uint64_t*)m_scratch.data(), dataIn, numElems);
208 convertWrite((int64_t*)m_scratch.data(), dataIn, numElems);
212 convertWrite((
float*)m_scratch.data(), dataIn, numElems);
216 convertWrite((
double*)m_scratch.data(), dataIn, numElems);
220 convertWrite((
long double*)m_scratch.data(), dataIn, numElems);
223 throw CiftiException(
"internal error, tell the developers what you just tried to do");
225 m_file.write(m_scratch.data(), m_scratch.size());
228 template<
typename TO,
typename FROM>
229 void NiftiIO::convertRead(TO* out, FROM* in,
const int64_t& count)
231 if (m_header.isSwapped())
233 ByteSwapping::swapArray(in, count);
236 bool doScale = m_header.getDataScaling(mult, offset);
237 if (std::numeric_limits<TO>::is_integer)
241 for (int64_t i = 0; i < count; ++i)
243 out[i] = (TO)floor(0.5 + offset + mult * (
long double)in[i]);
246 for (int64_t i = 0; i < count; ++i)
248 out[i] = (TO)floor(0.5 + in[i]);
254 for (int64_t i = 0; i < count; ++i)
256 out[i] = (TO)(offset + mult * (
long double)in[i]);
259 for (int64_t i = 0; i < count; ++i)
267 template<
typename TO,
typename FROM>
268 void NiftiIO::convertWrite(TO* out,
const FROM* in,
const int64_t& count)
271 bool doScale = m_header.getDataScaling(mult, offset);
272 if (std::numeric_limits<TO>::is_integer)
276 for (int64_t i = 0; i < count; ++i)
278 out[i] = (TO)floor(0.5 + ((
long double)in[i] - offset) / mult);
281 for (int64_t i = 0; i < count; ++i)
283 out[i] = (TO)floor(0.5 + in[i]);
289 for (int64_t i = 0; i < count; ++i)
291 out[i] = (TO)(((
long double)in[i] - offset) / mult);
294 for (int64_t i = 0; i < count; ++i)
300 if (m_header.isSwapped()) ByteSwapping::swapArray(out, count);
305 #endif //__NIFTI_IO_H__ Definition: CiftiException.h:40
namespace for all CiftiLib functionality
Definition: CiftiBrainModelsMap.h:41
const int32_t NIFTI_TYPE_COMPLEX256
Definition: nifti1.h:574
const int32_t NIFTI_TYPE_INT8
Definition: nifti1.h:560
const int32_t NIFTI_TYPE_COMPLEX128
Definition: nifti1.h:572
const int32_t NIFTI_TYPE_UINT64
Definition: nifti1.h:568
const int32_t NIFTI_TYPE_UINT8
Definition: nifti1.h:546
const int32_t NIFTI_TYPE_FLOAT128
Definition: nifti1.h:570
const int32_t NIFTI_TYPE_INT32
Definition: nifti1.h:550
const int32_t NIFTI_TYPE_UINT32
Definition: nifti1.h:564
const int32_t NIFTI_TYPE_INT64
Definition: nifti1.h:566
const int32_t NIFTI_TYPE_FLOAT32
Definition: nifti1.h:552
const int32_t NIFTI_TYPE_RGB24
Definition: nifti1.h:558
const int32_t NIFTI_TYPE_COMPLEX64
Definition: nifti1.h:554
const int32_t NIFTI_TYPE_INT16
Definition: nifti1.h:548
Definition: BinaryFile.h:40
const int32_t NIFTI_TYPE_UINT16
Definition: nifti1.h:562
const int32_t NIFTI_TYPE_FLOAT64
Definition: nifti1.h:556