load_nii_img.m 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392
  1. % internal function
  2. % - Jimmy Shen (jimmy@rotman-baycrest.on.ca)
  3. function [img,hdr] = load_nii_img(hdr,filetype,fileprefix,machine,img_idx,dim5_idx,dim6_idx,dim7_idx,old_RGB)
  4. if ~exist('hdr','var') | ~exist('filetype','var') | ~exist('fileprefix','var') | ~exist('machine','var')
  5. error('Usage: [img,hdr] = load_nii_img(hdr,filetype,fileprefix,machine,[img_idx],[dim5_idx],[dim6_idx],[dim7_idx],[old_RGB]);');
  6. end
  7. if ~exist('img_idx','var') | isempty(img_idx) | hdr.dime.dim(5)<1
  8. img_idx = [];
  9. end
  10. if ~exist('dim5_idx','var') | isempty(dim5_idx) | hdr.dime.dim(6)<1
  11. dim5_idx = [];
  12. end
  13. if ~exist('dim6_idx','var') | isempty(dim6_idx) | hdr.dime.dim(7)<1
  14. dim6_idx = [];
  15. end
  16. if ~exist('dim7_idx','var') | isempty(dim7_idx) | hdr.dime.dim(8)<1
  17. dim7_idx = [];
  18. end
  19. if ~exist('old_RGB','var') | isempty(old_RGB)
  20. old_RGB = 0;
  21. end
  22. % check img_idx
  23. %
  24. if ~isempty(img_idx) & ~isnumeric(img_idx)
  25. error('"img_idx" should be a numerical array.');
  26. end
  27. if length(unique(img_idx)) ~= length(img_idx)
  28. error('Duplicate image index in "img_idx"');
  29. end
  30. if ~isempty(img_idx) & (min(img_idx) < 1 | max(img_idx) > hdr.dime.dim(5))
  31. max_range = hdr.dime.dim(5);
  32. if max_range == 1
  33. error(['"img_idx" should be 1.']);
  34. else
  35. range = ['1 ' num2str(max_range)];
  36. error(['"img_idx" should be an integer within the range of [' range '].']);
  37. end
  38. end
  39. % check dim5_idx
  40. %
  41. if ~isempty(dim5_idx) & ~isnumeric(dim5_idx)
  42. error('"dim5_idx" should be a numerical array.');
  43. end
  44. if length(unique(dim5_idx)) ~= length(dim5_idx)
  45. error('Duplicate index in "dim5_idx"');
  46. end
  47. if ~isempty(dim5_idx) & (min(dim5_idx) < 1 | max(dim5_idx) > hdr.dime.dim(6))
  48. max_range = hdr.dime.dim(6);
  49. if max_range == 1
  50. error(['"dim5_idx" should be 1.']);
  51. else
  52. range = ['1 ' num2str(max_range)];
  53. error(['"dim5_idx" should be an integer within the range of [' range '].']);
  54. end
  55. end
  56. % check dim6_idx
  57. %
  58. if ~isempty(dim6_idx) & ~isnumeric(dim6_idx)
  59. error('"dim6_idx" should be a numerical array.');
  60. end
  61. if length(unique(dim6_idx)) ~= length(dim6_idx)
  62. error('Duplicate index in "dim6_idx"');
  63. end
  64. if ~isempty(dim6_idx) & (min(dim6_idx) < 1 | max(dim6_idx) > hdr.dime.dim(7))
  65. max_range = hdr.dime.dim(7);
  66. if max_range == 1
  67. error(['"dim6_idx" should be 1.']);
  68. else
  69. range = ['1 ' num2str(max_range)];
  70. error(['"dim6_idx" should be an integer within the range of [' range '].']);
  71. end
  72. end
  73. % check dim7_idx
  74. %
  75. if ~isempty(dim7_idx) & ~isnumeric(dim7_idx)
  76. error('"dim7_idx" should be a numerical array.');
  77. end
  78. if length(unique(dim7_idx)) ~= length(dim7_idx)
  79. error('Duplicate index in "dim7_idx"');
  80. end
  81. if ~isempty(dim7_idx) & (min(dim7_idx) < 1 | max(dim7_idx) > hdr.dime.dim(8))
  82. max_range = hdr.dime.dim(8);
  83. if max_range == 1
  84. error(['"dim7_idx" should be 1.']);
  85. else
  86. range = ['1 ' num2str(max_range)];
  87. error(['"dim7_idx" should be an integer within the range of [' range '].']);
  88. end
  89. end
  90. [img,hdr] = read_image(hdr,filetype,fileprefix,machine,img_idx,dim5_idx,dim6_idx,dim7_idx,old_RGB);
  91. return % load_nii_img
  92. %---------------------------------------------------------------------
  93. function [img,hdr] = read_image(hdr,filetype,fileprefix,machine,img_idx,dim5_idx,dim6_idx,dim7_idx,old_RGB)
  94. switch filetype
  95. case {0, 1}
  96. fn = [fileprefix '.img'];
  97. case 2
  98. fn = [fileprefix '.nii'];
  99. end
  100. fid = fopen(fn,'r',machine);
  101. if fid < 0,
  102. msg = sprintf('Cannot open file %s.',fn);
  103. error(msg);
  104. end
  105. % Set bitpix according to datatype
  106. %
  107. % /*Acceptable values for datatype are*/
  108. %
  109. % 0 None (Unknown bit per voxel) % DT_NONE, DT_UNKNOWN
  110. % 1 Binary (ubit1, bitpix=1) % DT_BINARY
  111. % 2 Unsigned char (uchar or uint8, bitpix=8) % DT_UINT8, NIFTI_TYPE_UINT8
  112. % 4 Signed short (int16, bitpix=16) % DT_INT16, NIFTI_TYPE_INT16
  113. % 8 Signed integer (int32, bitpix=32) % DT_INT32, NIFTI_TYPE_INT32
  114. % 16 Floating point (single or float32, bitpix=32) % DT_FLOAT32, NIFTI_TYPE_FLOAT32
  115. % 32 Complex, 2 float32 (Use float32, bitpix=64) % DT_COMPLEX64, NIFTI_TYPE_COMPLEX64
  116. % 64 Double precision (double or float64, bitpix=64) % DT_FLOAT64, NIFTI_TYPE_FLOAT64
  117. % 128 uint8 RGB (Use uint8, bitpix=24) % DT_RGB24, NIFTI_TYPE_RGB24
  118. % 256 Signed char (schar or int8, bitpix=8) % DT_INT8, NIFTI_TYPE_INT8
  119. % 511 Single RGB (Use float32, bitpix=96) % DT_RGB96, NIFTI_TYPE_RGB96
  120. % 512 Unsigned short (uint16, bitpix=16) % DT_UNINT16, NIFTI_TYPE_UNINT16
  121. % 768 Unsigned integer (uint32, bitpix=32) % DT_UNINT32, NIFTI_TYPE_UNINT32
  122. % 1024 Signed long long (int64, bitpix=64) % DT_INT64, NIFTI_TYPE_INT64
  123. % 1280 Unsigned long long (uint64, bitpix=64) % DT_UINT64, NIFTI_TYPE_UINT64
  124. % 1536 Long double, float128 (Unsupported, bitpix=128) % DT_FLOAT128, NIFTI_TYPE_FLOAT128
  125. % 1792 Complex128, 2 float64 (Use float64, bitpix=128) % DT_COMPLEX128, NIFTI_TYPE_COMPLEX128
  126. % 2048 Complex256, 2 float128 (Unsupported, bitpix=256) % DT_COMPLEX128, NIFTI_TYPE_COMPLEX128
  127. %
  128. switch hdr.dime.datatype
  129. case 1,
  130. hdr.dime.bitpix = 1; precision = 'ubit1';
  131. case 2,
  132. hdr.dime.bitpix = 8; precision = 'uint8';
  133. case 4,
  134. hdr.dime.bitpix = 16; precision = 'int16';
  135. case 8,
  136. hdr.dime.bitpix = 32; precision = 'int32';
  137. case 16,
  138. hdr.dime.bitpix = 32; precision = 'float32';
  139. case 32,
  140. hdr.dime.bitpix = 64; precision = 'float32';
  141. case 64,
  142. hdr.dime.bitpix = 64; precision = 'float64';
  143. case 128,
  144. hdr.dime.bitpix = 24; precision = 'uint8';
  145. case 256
  146. hdr.dime.bitpix = 8; precision = 'int8';
  147. case 511
  148. hdr.dime.bitpix = 96; precision = 'float32';
  149. case 512
  150. hdr.dime.bitpix = 16; precision = 'uint16';
  151. case 768
  152. hdr.dime.bitpix = 32; precision = 'uint32';
  153. case 1024
  154. hdr.dime.bitpix = 64; precision = 'int64';
  155. case 1280
  156. hdr.dime.bitpix = 64; precision = 'uint64';
  157. case 1792,
  158. hdr.dime.bitpix = 128; precision = 'float64';
  159. otherwise
  160. error('This datatype is not supported');
  161. end
  162. hdr.dime.dim(find(hdr.dime.dim < 1)) = 1;
  163. % move pointer to the start of image block
  164. %
  165. switch filetype
  166. case {0, 1}
  167. fseek(fid, 0, 'bof');
  168. case 2
  169. fseek(fid, hdr.dime.vox_offset, 'bof');
  170. end
  171. % Load whole image block for old Analyze format or binary image;
  172. % otherwise, load images that are specified in img_idx, dim5_idx,
  173. % dim6_idx, and dim7_idx
  174. %
  175. % For binary image, we have to read all because pos can not be
  176. % seeked in bit and can not be calculated the way below.
  177. %
  178. if hdr.dime.datatype == 1 | isequal(hdr.dime.dim(5:8),ones(1,4)) | ...
  179. (isempty(img_idx) & isempty(dim5_idx) & isempty(dim6_idx) & isempty(dim7_idx))
  180. % For each frame, precision of value will be read
  181. % in img_siz times, where img_siz is only the
  182. % dimension size of an image, not the byte storage
  183. % size of an image.
  184. %
  185. img_siz = prod(hdr.dime.dim(2:8));
  186. % For complex float32 or complex float64, voxel values
  187. % include [real, imag]
  188. %
  189. if hdr.dime.datatype == 32 | hdr.dime.datatype == 1792
  190. img_siz = img_siz * 2;
  191. end
  192. %MPH: For RGB24, voxel values include 3 separate color planes
  193. %
  194. if hdr.dime.datatype == 128 | hdr.dime.datatype == 511
  195. img_siz = img_siz * 3;
  196. end
  197. img = fread(fid, img_siz, sprintf('*%s',precision));
  198. d1 = hdr.dime.dim(2);
  199. d2 = hdr.dime.dim(3);
  200. d3 = hdr.dime.dim(4);
  201. d4 = hdr.dime.dim(5);
  202. d5 = hdr.dime.dim(6);
  203. d6 = hdr.dime.dim(7);
  204. d7 = hdr.dime.dim(8);
  205. if isempty(img_idx)
  206. img_idx = 1:d4;
  207. end
  208. if isempty(dim5_idx)
  209. dim5_idx = 1:d5;
  210. end
  211. if isempty(dim6_idx)
  212. dim6_idx = 1:d6;
  213. end
  214. if isempty(dim7_idx)
  215. dim7_idx = 1:d7;
  216. end
  217. else
  218. d1 = hdr.dime.dim(2);
  219. d2 = hdr.dime.dim(3);
  220. d3 = hdr.dime.dim(4);
  221. d4 = hdr.dime.dim(5);
  222. d5 = hdr.dime.dim(6);
  223. d6 = hdr.dime.dim(7);
  224. d7 = hdr.dime.dim(8);
  225. if isempty(img_idx)
  226. img_idx = 1:d4;
  227. end
  228. if isempty(dim5_idx)
  229. dim5_idx = 1:d5;
  230. end
  231. if isempty(dim6_idx)
  232. dim6_idx = 1:d6;
  233. end
  234. if isempty(dim7_idx)
  235. dim7_idx = 1:d7;
  236. end
  237. % compute size of one image
  238. %
  239. img_siz = prod(hdr.dime.dim(2:4));
  240. % For complex float32 or complex float64, voxel values
  241. % include [real, imag]
  242. %
  243. if hdr.dime.datatype == 32 | hdr.dime.datatype == 1792
  244. img_siz = img_siz * 2;
  245. end
  246. %MPH: For RGB24, voxel values include 3 separate color planes
  247. %
  248. if hdr.dime.datatype == 128 | hdr.dime.datatype == 511
  249. img_siz = img_siz * 3;
  250. end
  251. % preallocate img
  252. img = zeros(img_siz, length(img_idx)*length(dim5_idx)*length(dim6_idx)*length(dim7_idx) );
  253. currentIndex = 1;
  254. for i7=1:length(dim7_idx)
  255. for i6=1:length(dim6_idx)
  256. for i5=1:length(dim5_idx)
  257. for t=1:length(img_idx)
  258. % Position is seeked in bytes. To convert dimension size
  259. % to byte storage size, hdr.dime.bitpix/8 will be
  260. % applied.
  261. %
  262. pos = sub2ind([d1 d2 d3 d4 d5 d6 d7], 1, 1, 1, ...
  263. img_idx(t), dim5_idx(i5),dim6_idx(i6),dim7_idx(i7)) -1;
  264. pos = pos * hdr.dime.bitpix/8;
  265. if filetype == 2
  266. fseek(fid, pos + hdr.dime.vox_offset, 'bof');
  267. else
  268. fseek(fid, pos, 'bof');
  269. end
  270. % For each frame, fread will read precision of value
  271. % in img_siz times
  272. %
  273. img(:,currentIndex) = fread(fid, img_siz, sprintf('*%s',precision));
  274. currentIndex = currentIndex +1;
  275. end
  276. end
  277. end
  278. end
  279. end
  280. % For complex float32 or complex float64, voxel values
  281. % include [real, imag]
  282. %
  283. if hdr.dime.datatype == 32 | hdr.dime.datatype == 1792
  284. img = reshape(img, [2, length(img)/2]);
  285. img = complex(img(1,:)', img(2,:)');
  286. end
  287. fclose(fid);
  288. % Update the global min and max values
  289. %
  290. hdr.dime.glmax = double(max(img(:)));
  291. hdr.dime.glmin = double(min(img(:)));
  292. % old_RGB treat RGB slice by slice, now it is treated voxel by voxel
  293. %
  294. if old_RGB & hdr.dime.datatype == 128 & hdr.dime.bitpix == 24
  295. % remove squeeze
  296. img = (reshape(img, [hdr.dime.dim(2:3) 3 hdr.dime.dim(4) length(img_idx) length(dim5_idx) length(dim6_idx) length(dim7_idx)]));
  297. img = permute(img, [1 2 4 3 5 6 7 8]);
  298. elseif hdr.dime.datatype == 128 & hdr.dime.bitpix == 24
  299. % remove squeeze
  300. img = (reshape(img, [3 hdr.dime.dim(2:4) length(img_idx) length(dim5_idx) length(dim6_idx) length(dim7_idx)]));
  301. img = permute(img, [2 3 4 1 5 6 7 8]);
  302. elseif hdr.dime.datatype == 511 & hdr.dime.bitpix == 96
  303. img = double(img(:));
  304. img = single((img - min(img))/(max(img) - min(img)));
  305. % remove squeeze
  306. img = (reshape(img, [3 hdr.dime.dim(2:4) length(img_idx) length(dim5_idx) length(dim6_idx) length(dim7_idx)]));
  307. img = permute(img, [2 3 4 1 5 6 7 8]);
  308. else
  309. % remove squeeze
  310. img = (reshape(img, [hdr.dime.dim(2:4) length(img_idx) length(dim5_idx) length(dim6_idx) length(dim7_idx)]));
  311. end
  312. if ~isempty(img_idx)
  313. hdr.dime.dim(5) = length(img_idx);
  314. end
  315. if ~isempty(dim5_idx)
  316. hdr.dime.dim(6) = length(dim5_idx);
  317. end
  318. if ~isempty(dim6_idx)
  319. hdr.dime.dim(7) = length(dim6_idx);
  320. end
  321. if ~isempty(dim7_idx)
  322. hdr.dime.dim(8) = length(dim7_idx);
  323. end
  324. return % read_image