reslice_nii.m 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. % The basic application of the 'reslice_nii.m' program is to perform
  2. % any 3D affine transform defined by a NIfTI format image.
  3. %
  4. % In addition, the 'reslice_nii.m' program can also be applied to
  5. % generate an isotropic image from either a NIfTI format image or
  6. % an ANALYZE format image.
  7. %
  8. % The resliced NIfTI file will always be in RAS orientation.
  9. %
  10. % This program only supports real integer or floating-point data type.
  11. % For other data type, the program will exit with an error message
  12. % "Transform of this NIFTI data is not supported by the program".
  13. %
  14. % Usage: reslice_nii(old_fn, new_fn, [voxel_size], [verbose], [bg], ...
  15. % [method], [img_idx], [preferredForm]);
  16. %
  17. % old_fn - filename for original NIfTI file
  18. %
  19. % new_fn - filename for resliced NIfTI file
  20. %
  21. % voxel_size (optional) - size of a voxel in millimeter along x y z
  22. % direction for resliced NIfTI file. 'voxel_size' will use
  23. % the minimum voxel_size in original NIfTI header,
  24. % if it is default or empty.
  25. %
  26. % verbose (optional) - 1, 0
  27. % 1: show transforming progress in percentage
  28. % 2: progress will not be displayed
  29. % 'verbose' is 1 if it is default or empty.
  30. %
  31. % bg (optional) - background voxel intensity in any extra corner that
  32. % is caused by 3D interpolation. 0 in most cases. 'bg'
  33. % will be the average of two corner voxel intensities
  34. % in original image volume, if it is default or empty.
  35. %
  36. % method (optional) - 1, 2, or 3
  37. % 1: for Trilinear interpolation
  38. % 2: for Nearest Neighbor interpolation
  39. % 3: for Fischer's Bresenham interpolation
  40. % 'method' is 1 if it is default or empty.
  41. %
  42. % img_idx (optional) - a numerical array of image volume indices. Only
  43. % the specified volumes will be loaded. All available image
  44. % volumes will be loaded, if it is default or empty.
  45. %
  46. % The number of images scans can be obtained from get_nii_frame.m,
  47. % or simply: hdr.dime.dim(5).
  48. %
  49. % preferredForm (optional) - selects which transformation from voxels
  50. % to RAS coordinates; values are s,q,S,Q. Lower case s,q indicate
  51. % "prefer sform or qform, but use others if preferred not present".
  52. % Upper case indicate the program is forced to use the specificied
  53. % tranform or fail loading. 'preferredForm' will be 's', if it is
  54. % default or empty. - Jeff Gunter
  55. %
  56. % NIFTI data format can be found on: http://nifti.nimh.nih.gov
  57. %
  58. % - Jimmy Shen (jshen@research.baycrest.org)
  59. %
  60. function reslice_nii(old_fn, new_fn, voxel_size, verbose, bg, method, img_idx, preferredForm)
  61. if ~exist('old_fn','var') | ~exist('new_fn','var')
  62. error('Usage: reslice_nii(old_fn, new_fn, [voxel_size], [verbose], [bg], [method], [img_idx])');
  63. end
  64. if ~exist('method','var') | isempty(method)
  65. method = 1;
  66. end
  67. if ~exist('img_idx','var') | isempty(img_idx)
  68. img_idx = [];
  69. end
  70. if ~exist('verbose','var') | isempty(verbose)
  71. verbose = 1;
  72. end
  73. if ~exist('preferredForm','var') | isempty(preferredForm)
  74. preferredForm= 's'; % Jeff
  75. end
  76. nii = load_nii_no_xform(old_fn, img_idx, 0, preferredForm);
  77. if ~ismember(nii.hdr.dime.datatype, [2,4,8,16,64,256,512,768])
  78. error('Transform of this NIFTI data is not supported by the program.');
  79. end
  80. if ~exist('voxel_size','var') | isempty(voxel_size)
  81. voxel_size = abs(min(nii.hdr.dime.pixdim(2:4)))*ones(1,3);
  82. elseif length(voxel_size) < 3
  83. voxel_size = abs(voxel_size(1))*ones(1,3);
  84. end
  85. if ~exist('bg','var') | isempty(bg)
  86. bg = mean([nii.img(1) nii.img(end)]);
  87. end
  88. old_M = nii.hdr.hist.old_affine;
  89. if nii.hdr.dime.dim(5) > 1
  90. for i = 1:nii.hdr.dime.dim(5)
  91. if verbose
  92. fprintf('Reslicing %d of %d volumes.\n', i, nii.hdr.dime.dim(5));
  93. end
  94. [img(:,:,:,i) M] = ...
  95. affine(nii.img(:,:,:,i), old_M, voxel_size, verbose, bg, method);
  96. end
  97. else
  98. [img M] = affine(nii.img, old_M, voxel_size, verbose, bg, method);
  99. end
  100. new_dim = size(img);
  101. nii.img = img;
  102. nii.hdr.dime.dim(2:4) = new_dim(1:3);
  103. nii.hdr.dime.datatype = 16;
  104. nii.hdr.dime.bitpix = 32;
  105. nii.hdr.dime.pixdim(2:4) = voxel_size(:)';
  106. nii.hdr.dime.glmax = max(img(:));
  107. nii.hdr.dime.glmin = min(img(:));
  108. nii.hdr.hist.qform_code = 0;
  109. nii.hdr.hist.sform_code = 1;
  110. nii.hdr.hist.srow_x = M(1,:);
  111. nii.hdr.hist.srow_y = M(2,:);
  112. nii.hdr.hist.srow_z = M(3,:);
  113. nii.hdr.hist.new_affine = M;
  114. save_nii(nii, new_fn);
  115. return; % reslice_nii
  116. %--------------------------------------------------------------------
  117. function [nii] = load_nii_no_xform(filename, img_idx, old_RGB, preferredForm)
  118. if ~exist('filename','var'),
  119. error('Usage: [nii] = load_nii(filename, [img_idx], [old_RGB])');
  120. end
  121. if ~exist('img_idx','var'), img_idx = []; end
  122. if ~exist('old_RGB','var'), old_RGB = 0; end
  123. if ~exist('preferredForm','var'), preferredForm= 's'; end % Jeff
  124. v = version;
  125. % Check file extension. If .gz, unpack it into temp folder
  126. %
  127. if length(filename) > 2 & strcmp(filename(end-2:end), '.gz')
  128. if ~strcmp(filename(end-6:end), '.img.gz') & ...
  129. ~strcmp(filename(end-6:end), '.hdr.gz') & ...
  130. ~strcmp(filename(end-6:end), '.nii.gz')
  131. error('Please check filename.');
  132. end
  133. if str2num(v(1:3)) < 7.1 | ~usejava('jvm')
  134. error('Please use MATLAB 7.1 (with java) and above, or run gunzip outside MATLAB.');
  135. elseif strcmp(filename(end-6:end), '.img.gz')
  136. filename1 = filename;
  137. filename2 = filename;
  138. filename2(end-6:end) = '';
  139. filename2 = [filename2, '.hdr.gz'];
  140. tmpDir = tempname;
  141. mkdir(tmpDir);
  142. gzFileName = filename;
  143. filename1 = gunzip(filename1, tmpDir);
  144. filename2 = gunzip(filename2, tmpDir);
  145. filename = char(filename1); % convert from cell to string
  146. elseif strcmp(filename(end-6:end), '.hdr.gz')
  147. filename1 = filename;
  148. filename2 = filename;
  149. filename2(end-6:end) = '';
  150. filename2 = [filename2, '.img.gz'];
  151. tmpDir = tempname;
  152. mkdir(tmpDir);
  153. gzFileName = filename;
  154. filename1 = gunzip(filename1, tmpDir);
  155. filename2 = gunzip(filename2, tmpDir);
  156. filename = char(filename1); % convert from cell to string
  157. elseif strcmp(filename(end-6:end), '.nii.gz')
  158. tmpDir = tempname;
  159. mkdir(tmpDir);
  160. gzFileName = filename;
  161. filename = gunzip(filename, tmpDir);
  162. filename = char(filename); % convert from cell to string
  163. end
  164. end
  165. % Read the dataset header
  166. %
  167. [nii.hdr,nii.filetype,nii.fileprefix,nii.machine] = load_nii_hdr(filename);
  168. % Read the header extension
  169. %
  170. % nii.ext = load_nii_ext(filename);
  171. % Read the dataset body
  172. %
  173. [nii.img,nii.hdr] = ...
  174. load_nii_img(nii.hdr,nii.filetype,nii.fileprefix,nii.machine,img_idx,'','','',old_RGB);
  175. % Perform some of sform/qform transform
  176. %
  177. % nii = xform_nii(nii, preferredForm);
  178. % Clean up after gunzip
  179. %
  180. if exist('gzFileName', 'var')
  181. % fix fileprefix so it doesn't point to temp location
  182. %
  183. nii.fileprefix = gzFileName(1:end-7);
  184. rmdir(tmpDir,'s');
  185. end
  186. hdr = nii.hdr;
  187. % NIFTI can have both sform and qform transform. This program
  188. % will check sform_code prior to qform_code by default.
  189. %
  190. % If user specifys "preferredForm", user can then choose the
  191. % priority. - Jeff
  192. %
  193. useForm=[]; % Jeff
  194. if isequal(preferredForm,'S')
  195. if isequal(hdr.hist.sform_code,0)
  196. error('User requires sform, sform not set in header');
  197. else
  198. useForm='s';
  199. end
  200. end % Jeff
  201. if isequal(preferredForm,'Q')
  202. if isequal(hdr.hist.qform_code,0)
  203. error('User requires sform, sform not set in header');
  204. else
  205. useForm='q';
  206. end
  207. end % Jeff
  208. if isequal(preferredForm,'s')
  209. if hdr.hist.sform_code > 0
  210. useForm='s';
  211. elseif hdr.hist.qform_code > 0
  212. useForm='q';
  213. end
  214. end % Jeff
  215. if isequal(preferredForm,'q')
  216. if hdr.hist.qform_code > 0
  217. useForm='q';
  218. elseif hdr.hist.sform_code > 0
  219. useForm='s';
  220. end
  221. end % Jeff
  222. if isequal(useForm,'s')
  223. R = [hdr.hist.srow_x(1:3)
  224. hdr.hist.srow_y(1:3)
  225. hdr.hist.srow_z(1:3)];
  226. T = [hdr.hist.srow_x(4)
  227. hdr.hist.srow_y(4)
  228. hdr.hist.srow_z(4)];
  229. nii.hdr.hist.old_affine = [ [R;[0 0 0]] [T;1] ];
  230. elseif isequal(useForm,'q')
  231. b = hdr.hist.quatern_b;
  232. c = hdr.hist.quatern_c;
  233. d = hdr.hist.quatern_d;
  234. if 1.0-(b*b+c*c+d*d) < 0
  235. if abs(1.0-(b*b+c*c+d*d)) < 1e-5
  236. a = 0;
  237. else
  238. error('Incorrect quaternion values in this NIFTI data.');
  239. end
  240. else
  241. a = sqrt(1.0-(b*b+c*c+d*d));
  242. end
  243. qfac = hdr.dime.pixdim(1);
  244. i = hdr.dime.pixdim(2);
  245. j = hdr.dime.pixdim(3);
  246. k = qfac * hdr.dime.pixdim(4);
  247. R = [a*a+b*b-c*c-d*d 2*b*c-2*a*d 2*b*d+2*a*c
  248. 2*b*c+2*a*d a*a+c*c-b*b-d*d 2*c*d-2*a*b
  249. 2*b*d-2*a*c 2*c*d+2*a*b a*a+d*d-c*c-b*b];
  250. T = [hdr.hist.qoffset_x
  251. hdr.hist.qoffset_y
  252. hdr.hist.qoffset_z];
  253. nii.hdr.hist.old_affine = [ [R * diag([i j k]);[0 0 0]] [T;1] ];
  254. elseif nii.filetype == 0 & exist([nii.fileprefix '.mat'],'file')
  255. load([nii.fileprefix '.mat']); % old SPM affine matrix
  256. R=M(1:3,1:3);
  257. T=M(1:3,4);
  258. T=R*ones(3,1)+T;
  259. M(1:3,4)=T;
  260. nii.hdr.hist.old_affine = M;
  261. else
  262. M = diag(hdr.dime.pixdim(2:5));
  263. M(1:3,4) = -M(1:3,1:3)*(hdr.hist.originator(1:3)-1)';
  264. M(4,4) = 1;
  265. nii.hdr.hist.old_affine = M;
  266. end
  267. return % load_nii_no_xform