123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580 |
- % Save back to the original image with a portion of slices that was
- % loaded by "load_untouch_nii". You can process those slices matrix
- % in any way, as long as their dimension is not altered.
- %
- % Usage: save_untouch_slice(slice, filename, ...
- % slice_idx, [img_idx], [dim5_idx], [dim6_idx], [dim7_idx])
- %
- % slice - a portion of slices that was loaded by "load_untouch_nii".
- % This should be a numeric matrix (i.e. only the .img field in the
- % loaded structure)
- %
- % filename - NIfTI or ANALYZE file name.
- %
- % slice_idx (depending on slice size) - a numerical array of image
- % slice indices, which should be the same as that you entered
- % in "load_untouch_nii" command.
- %
- % img_idx (depending on slice size) - a numerical array of image
- % volume indices, which should be the same as that you entered
- % in "load_untouch_nii" command.
- %
- % dim5_idx (depending on slice size) - a numerical array of 5th
- % dimension indices, which should be the same as that you entered
- % in "load_untouch_nii" command.
- %
- % dim6_idx (depending on slice size) - a numerical array of 6th
- % dimension indices, which should be the same as that you entered
- % in "load_untouch_nii" command.
- %
- % dim7_idx (depending on slice size) - a numerical array of 7th
- % dimension indices, which should be the same as that you entered
- % in "load_untouch_nii" command.
- %
- % Example:
- % nii = load_nii('avg152T1_LR_nifti.nii');
- % save_nii(nii, 'test.nii');
- % view_nii(nii);
- % nii = load_untouch_nii('test.nii','','','','','',[40 51:53]);
- % nii.img = ones(91,109,4)*122;
- % save_untouch_slice(nii.img, 'test.nii', [40 51:52]);
- % nii = load_nii('test.nii');
- % view_nii(nii);
- %
- % - Jimmy Shen (jimmy@rotman-baycrest.on.ca)
- %
- function save_untouch_slice(slice, filename, slice_idx, img_idx, dim5_idx, dim6_idx, dim7_idx)
- if ~exist('slice','var') | ~isnumeric(slice)
- msg = [char(10) '"slice" argument should be a portion of slices that was loaded' char(10)];
- msg = [msg 'by "load_untouch_nii.m". This should be a numeric matrix (i.e.' char(10)];
- msg = [msg 'only the .img field in the loaded structure).'];
- error(msg);
- end
- if ~exist('filename','var') | ~exist(filename,'file')
- error('In order to save back, original NIfTI or ANALYZE file must exist.');
- end
- if ~exist('slice_idx','var') | isempty(slice_idx) | ~isequal(size(slice,3),length(slice_idx))
- msg = [char(10) '"slice_idx" is a numerical array of image slice indices, which' char(10)];
- msg = [msg 'should be the same as that you entered in "load_untouch_nii.m"' char(10)];
- msg = [msg 'command.'];
- error(msg);
- end
- if ~exist('img_idx','var') | isempty(img_idx)
- img_idx = [];
- if ~isequal(size(slice,4),1)
- msg = [char(10) '"img_idx" is a numerical array of image volume indices, which' char(10)];
- msg = [msg 'should be the same as that you entered in "load_untouch_nii.m"' char(10)];
- msg = [msg 'command.'];
- error(msg);
- end
- elseif ~isequal(size(slice,4),length(img_idx))
- msg = [char(10) '"img_idx" is a numerical array of image volume indices, which' char(10)];
- msg = [msg 'should be the same as that you entered in "load_untouch_nii.m"' char(10)];
- msg = [msg 'command.'];
- error(msg);
- end
- if ~exist('dim5_idx','var') | isempty(dim5_idx)
- dim5_idx = [];
- if ~isequal(size(slice,5),1)
- msg = [char(10) '"dim5_idx" is a numerical array of 5th dimension indices, which' char(10)];
- msg = [msg 'should be the same as that you entered in "load_untouch_nii.m"' char(10)];
- msg = [msg 'command.'];
- error(msg);
- end
- elseif ~isequal(size(slice,5),length(img_idx))
- msg = [char(10) '"img_idx" is a numerical array of 5th dimension indices, which' char(10)];
- msg = [msg 'should be the same as that you entered in "load_untouch_nii.m"' char(10)];
- msg = [msg 'command.'];
- error(msg);
- end
- if ~exist('dim6_idx','var') | isempty(dim6_idx)
- dim6_idx = [];
- if ~isequal(size(slice,6),1)
- msg = [char(10) '"dim6_idx" is a numerical array of 6th dimension indices, which' char(10)];
- msg = [msg 'should be the same as that you entered in "load_untouch_nii.m"' char(10)];
- msg = [msg 'command.'];
- error(msg);
- end
- elseif ~isequal(size(slice,6),length(img_idx))
- msg = [char(10) '"img_idx" is a numerical array of 6th dimension indices, which' char(10)];
- msg = [msg 'should be the same as that you entered in "load_untouch_nii.m"' char(10)];
- msg = [msg 'command.'];
- error(msg);
- end
- if ~exist('dim7_idx','var') | isempty(dim7_idx)
- dim7_idx = [];
- if ~isequal(size(slice,7),1)
- msg = [char(10) '"dim7_idx" is a numerical array of 7th dimension indices, which' char(10)];
- msg = [msg 'should be the same as that you entered in "load_untouch_nii.m"' char(10)];
- msg = [msg 'command.'];
- error(msg);
- end
- elseif ~isequal(size(slice,7),length(img_idx))
- msg = [char(10) '"img_idx" is a numerical array of 7th dimension indices, which' char(10)];
- msg = [msg 'should be the same as that you entered in "load_untouch_nii.m"' char(10)];
- msg = [msg 'command.'];
- error(msg);
- end
- v = version;
- % Check file extension. If .gz, unpack it into temp folder
- %
- if length(filename) > 2 & strcmp(filename(end-2:end), '.gz')
- if ~strcmp(filename(end-6:end), '.img.gz') & ...
- ~strcmp(filename(end-6:end), '.hdr.gz') & ...
- ~strcmp(filename(end-6:end), '.nii.gz')
- error('Please check filename.');
- end
- if str2num(v(1:3)) < 7.1 | ~usejava('jvm')
- error('Please use MATLAB 7.1 (with java) and above, or run gunzip outside MATLAB.');
- elseif strcmp(filename(end-6:end), '.img.gz')
- filename1 = filename;
- filename2 = filename;
- filename2(end-6:end) = '';
- filename2 = [filename2, '.hdr.gz'];
- tmpDir = tempname;
- mkdir(tmpDir);
- gzFileName = filename;
- filename1 = gunzip(filename1, tmpDir);
- filename2 = gunzip(filename2, tmpDir);
- filename = char(filename1); % convert from cell to string
- elseif strcmp(filename(end-6:end), '.hdr.gz')
- filename1 = filename;
- filename2 = filename;
- filename2(end-6:end) = '';
- filename2 = [filename2, '.img.gz'];
- tmpDir = tempname;
- mkdir(tmpDir);
- gzFileName = filename;
- filename1 = gunzip(filename1, tmpDir);
- filename2 = gunzip(filename2, tmpDir);
- filename = char(filename1); % convert from cell to string
- elseif strcmp(filename(end-6:end), '.nii.gz')
- tmpDir = tempname;
- mkdir(tmpDir);
- gzFileName = filename;
- filename = gunzip(filename, tmpDir);
- filename = char(filename); % convert from cell to string
- end
- end
- % Read the dataset header
- %
- [nii.hdr,nii.filetype,nii.fileprefix,nii.machine] = load_nii_hdr(filename);
- if nii.filetype == 0
- nii.hdr = load_untouch0_nii_hdr(nii.fileprefix,nii.machine);
- else
- nii.hdr = load_untouch_nii_hdr(nii.fileprefix,nii.machine,nii.filetype);
- end
- % Clean up after gunzip
- %
- if exist('gzFileName', 'var')
- % fix fileprefix so it doesn't point to temp location
- %
- nii.fileprefix = gzFileName(1:end-7);
- % rmdir(tmpDir,'s');
- end
- [p,f] = fileparts(filename);
- fileprefix = fullfile(p, f);
- % fileprefix = nii.fileprefix;
- filetype = nii.filetype;
- if ~isequal( nii.hdr.dime.dim(2:3), [size(slice,1),size(slice,2)] )
- msg = [char(10) 'The first two dimensions of slice matrix should be the same as' char(10)];
- msg = [msg 'the first two dimensions of image loaded by "load_untouch_nii".'];
- error(msg);
- end
- % Save the dataset body
- %
- save_untouch_slice_img(slice, nii.hdr, filetype, fileprefix, ...
- nii.machine, slice_idx,img_idx,dim5_idx,dim6_idx,dim7_idx);
- % gzip output file if requested
- %
- if exist('gzFileName', 'var')
- [p,f] = fileparts(gzFileName);
- if filetype == 1
- gzip([fileprefix, '.img']);
- delete([fileprefix, '.img']);
- movefile([fileprefix, '.img.gz']);
- gzip([fileprefix, '.hdr']);
- delete([fileprefix, '.hdr']);
- movefile([fileprefix, '.hdr.gz']);
- elseif filetype == 2
- gzip([fileprefix, '.nii']);
- delete([fileprefix, '.nii']);
- movefile([fileprefix, '.nii.gz']);
- end;
- rmdir(tmpDir,'s');
- end;
- return % save_untouch_slice
- %--------------------------------------------------------------------------
- function save_untouch_slice_img(slice,hdr,filetype,fileprefix,machine,slice_idx,img_idx,dim5_idx,dim6_idx,dim7_idx)
- if ~exist('hdr','var') | ~exist('filetype','var') | ~exist('fileprefix','var') | ~exist('machine','var')
- error('Usage: save_untouch_slice_img(slice,hdr,filetype,fileprefix,machine,slice_idx,[img_idx],[dim5_idx],[dim6_idx],[dim7_idx]);');
- end
- if ~exist('slice_idx','var') | isempty(slice_idx) | hdr.dime.dim(4)<1
- slice_idx = [];
- end
- if ~exist('img_idx','var') | isempty(img_idx) | hdr.dime.dim(5)<1
- img_idx = [];
- end
- if ~exist('dim5_idx','var') | isempty(dim5_idx) | hdr.dime.dim(6)<1
- dim5_idx = [];
- end
- if ~exist('dim6_idx','var') | isempty(dim6_idx) | hdr.dime.dim(7)<1
- dim6_idx = [];
- end
- if ~exist('dim7_idx','var') | isempty(dim7_idx) | hdr.dime.dim(8)<1
- dim7_idx = [];
- end
- % check img_idx
- %
- if ~isempty(img_idx) & ~isnumeric(img_idx)
- error('"img_idx" should be a numerical array.');
- end
- if length(unique(img_idx)) ~= length(img_idx)
- error('Duplicate image index in "img_idx"');
- end
- if ~isempty(img_idx) & (min(img_idx) < 1 | max(img_idx) > hdr.dime.dim(5))
- max_range = hdr.dime.dim(5);
- if max_range == 1
- error(['"img_idx" should be 1.']);
- else
- range = ['1 ' num2str(max_range)];
- error(['"img_idx" should be an integer within the range of [' range '].']);
- end
- end
- % check dim5_idx
- %
- if ~isempty(dim5_idx) & ~isnumeric(dim5_idx)
- error('"dim5_idx" should be a numerical array.');
- end
- if length(unique(dim5_idx)) ~= length(dim5_idx)
- error('Duplicate index in "dim5_idx"');
- end
- if ~isempty(dim5_idx) & (min(dim5_idx) < 1 | max(dim5_idx) > hdr.dime.dim(6))
- max_range = hdr.dime.dim(6);
- if max_range == 1
- error(['"dim5_idx" should be 1.']);
- else
- range = ['1 ' num2str(max_range)];
- error(['"dim5_idx" should be an integer within the range of [' range '].']);
- end
- end
- % check dim6_idx
- %
- if ~isempty(dim6_idx) & ~isnumeric(dim6_idx)
- error('"dim6_idx" should be a numerical array.');
- end
- if length(unique(dim6_idx)) ~= length(dim6_idx)
- error('Duplicate index in "dim6_idx"');
- end
- if ~isempty(dim6_idx) & (min(dim6_idx) < 1 | max(dim6_idx) > hdr.dime.dim(7))
- max_range = hdr.dime.dim(7);
- if max_range == 1
- error(['"dim6_idx" should be 1.']);
- else
- range = ['1 ' num2str(max_range)];
- error(['"dim6_idx" should be an integer within the range of [' range '].']);
- end
- end
- % check dim7_idx
- %
- if ~isempty(dim7_idx) & ~isnumeric(dim7_idx)
- error('"dim7_idx" should be a numerical array.');
- end
- if length(unique(dim7_idx)) ~= length(dim7_idx)
- error('Duplicate index in "dim7_idx"');
- end
- if ~isempty(dim7_idx) & (min(dim7_idx) < 1 | max(dim7_idx) > hdr.dime.dim(8))
- max_range = hdr.dime.dim(8);
- if max_range == 1
- error(['"dim7_idx" should be 1.']);
- else
- range = ['1 ' num2str(max_range)];
- error(['"dim7_idx" should be an integer within the range of [' range '].']);
- end
- end
- % check slice_idx
- %
- if ~isempty(slice_idx) & ~isnumeric(slice_idx)
- error('"slice_idx" should be a numerical array.');
- end
- if length(unique(slice_idx)) ~= length(slice_idx)
- error('Duplicate index in "slice_idx"');
- end
- if ~isempty(slice_idx) & (min(slice_idx) < 1 | max(slice_idx) > hdr.dime.dim(4))
- max_range = hdr.dime.dim(4);
- if max_range == 1
- error(['"slice_idx" should be 1.']);
- else
- range = ['1 ' num2str(max_range)];
- error(['"slice_idx" should be an integer within the range of [' range '].']);
- end
- end
- write_image(slice,hdr,filetype,fileprefix,machine,slice_idx,img_idx,dim5_idx,dim6_idx,dim7_idx);
- return % save_untouch_slice_img
- %---------------------------------------------------------------------
- function write_image(slice,hdr,filetype,fileprefix,machine,slice_idx,img_idx,dim5_idx,dim6_idx,dim7_idx)
- if filetype == 2
- fid = fopen(sprintf('%s.nii',fileprefix),'r+');
- if fid < 0,
- msg = sprintf('Cannot open file %s.nii.',fileprefix);
- error(msg);
- end
- else
- fid = fopen(sprintf('%s.img',fileprefix),'r+');
- if fid < 0,
- msg = sprintf('Cannot open file %s.img.',fileprefix);
- error(msg);
- end
- end
- % Set bitpix according to datatype
- %
- % /*Acceptable values for datatype are*/
- %
- % 0 None (Unknown bit per voxel) % DT_NONE, DT_UNKNOWN
- % 1 Binary (ubit1, bitpix=1) % DT_BINARY
- % 2 Unsigned char (uchar or uint8, bitpix=8) % DT_UINT8, NIFTI_TYPE_UINT8
- % 4 Signed short (int16, bitpix=16) % DT_INT16, NIFTI_TYPE_INT16
- % 8 Signed integer (int32, bitpix=32) % DT_INT32, NIFTI_TYPE_INT32
- % 16 Floating point (single or float32, bitpix=32) % DT_FLOAT32, NIFTI_TYPE_FLOAT32
- % 32 Complex, 2 float32 (Use float32, bitpix=64) % DT_COMPLEX64, NIFTI_TYPE_COMPLEX64
- % 64 Double precision (double or float64, bitpix=64) % DT_FLOAT64, NIFTI_TYPE_FLOAT64
- % 128 uint8 RGB (Use uint8, bitpix=24) % DT_RGB24, NIFTI_TYPE_RGB24
- % 256 Signed char (schar or int8, bitpix=8) % DT_INT8, NIFTI_TYPE_INT8
- % 511 Single RGB (Use float32, bitpix=96) % DT_RGB96, NIFTI_TYPE_RGB96
- % 512 Unsigned short (uint16, bitpix=16) % DT_UNINT16, NIFTI_TYPE_UNINT16
- % 768 Unsigned integer (uint32, bitpix=32) % DT_UNINT32, NIFTI_TYPE_UNINT32
- % 1024 Signed long long (int64, bitpix=64) % DT_INT64, NIFTI_TYPE_INT64
- % 1280 Unsigned long long (uint64, bitpix=64) % DT_UINT64, NIFTI_TYPE_UINT64
- % 1536 Long double, float128 (Unsupported, bitpix=128) % DT_FLOAT128, NIFTI_TYPE_FLOAT128
- % 1792 Complex128, 2 float64 (Use float64, bitpix=128) % DT_COMPLEX128, NIFTI_TYPE_COMPLEX128
- % 2048 Complex256, 2 float128 (Unsupported, bitpix=256) % DT_COMPLEX128, NIFTI_TYPE_COMPLEX128
- %
- switch hdr.dime.datatype
- case 2,
- hdr.dime.bitpix = 8; precision = 'uint8';
- case 4,
- hdr.dime.bitpix = 16; precision = 'int16';
- case 8,
- hdr.dime.bitpix = 32; precision = 'int32';
- case 16,
- hdr.dime.bitpix = 32; precision = 'float32';
- case 64,
- hdr.dime.bitpix = 64; precision = 'float64';
- case 128,
- hdr.dime.bitpix = 24; precision = 'uint8';
- case 256
- hdr.dime.bitpix = 8; precision = 'int8';
- case 511
- hdr.dime.bitpix = 96; precision = 'float32';
- case 512
- hdr.dime.bitpix = 16; precision = 'uint16';
- case 768
- hdr.dime.bitpix = 32; precision = 'uint32';
- case 1024
- hdr.dime.bitpix = 64; precision = 'int64';
- case 1280
- hdr.dime.bitpix = 64; precision = 'uint64';
- otherwise
- error('This datatype is not supported');
- end
- hdr.dime.dim(find(hdr.dime.dim < 1)) = 1;
- % move pointer to the start of image block
- %
- switch filetype
- case {0, 1}
- fseek(fid, 0, 'bof');
- case 2
- fseek(fid, hdr.dime.vox_offset, 'bof');
- end
- if hdr.dime.datatype == 1 | isequal(hdr.dime.dim(4:8),ones(1,5)) | ...
- (isempty(img_idx) & isempty(dim5_idx) & isempty(dim6_idx) & isempty(dim7_idx) & isempty(slice_idx))
- msg = [char(10) char(10) ' "save_untouch_slice" is used to save back to the original image a' char(10)];
- msg = [msg ' portion of slices that were loaded by "load_untouch_nii". You can' char(10)];
- msg = [msg ' process those slices matrix in any way, as long as their dimension' char(10)];
- msg = [msg ' is not changed.'];
- error(msg);
- else
- d1 = hdr.dime.dim(2);
- d2 = hdr.dime.dim(3);
- d3 = hdr.dime.dim(4);
- d4 = hdr.dime.dim(5);
- d5 = hdr.dime.dim(6);
- d6 = hdr.dime.dim(7);
- d7 = hdr.dime.dim(8);
- if isempty(slice_idx)
- slice_idx = 1:d3;
- end
- if isempty(img_idx)
- img_idx = 1:d4;
- end
- if isempty(dim5_idx)
- dim5_idx = 1:d5;
- end
- if isempty(dim6_idx)
- dim6_idx = 1:d6;
- end
- if isempty(dim7_idx)
- dim7_idx = 1:d7;
- end
-
- %ROMAN: begin
- roman = 1;
- if(roman)
- % compute size of one slice
- %
- img_siz = prod(hdr.dime.dim(2:3));
- % For complex float32 or complex float64, voxel values
- % include [real, imag]
- %
- if hdr.dime.datatype == 32 | hdr.dime.datatype == 1792
- img_siz = img_siz * 2;
- end
- %MPH: For RGB24, voxel values include 3 separate color planes
- %
- if hdr.dime.datatype == 128 | hdr.dime.datatype == 511
- img_siz = img_siz * 3;
- end
- end; %if(roman)
- % ROMAN: end
- for i7=1:length(dim7_idx)
- for i6=1:length(dim6_idx)
- for i5=1:length(dim5_idx)
- for t=1:length(img_idx)
- for s=1:length(slice_idx)
- % Position is seeked in bytes. To convert dimension size
- % to byte storage size, hdr.dime.bitpix/8 will be
- % applied.
- %
- pos = sub2ind([d1 d2 d3 d4 d5 d6 d7], 1, 1, slice_idx(s), ...
- img_idx(t), dim5_idx(i5),dim6_idx(i6),dim7_idx(i7)) -1;
- pos = pos * hdr.dime.bitpix/8;
- % ROMAN: begin
- if(roman)
- % do nothing
- else
- img_siz = prod(hdr.dime.dim(2:3));
- % For complex float32 or complex float64, voxel values
- % include [real, imag]
- %
- if hdr.dime.datatype == 32 | hdr.dime.datatype == 1792
- img_siz = img_siz * 2;
- end
- %MPH: For RGB24, voxel values include 3 separate color planes
- %
- if hdr.dime.datatype == 128 | hdr.dime.datatype == 511
- img_siz = img_siz * 3;
- end
- end; % if (roman)
- % ROMAN: end
-
- if filetype == 2
- fseek(fid, pos + hdr.dime.vox_offset, 'bof');
- else
- fseek(fid, pos, 'bof');
- end
- % For each frame, fwrite will write precision of value
- % in img_siz times
- %
- fwrite(fid, slice(:,:,s,t,i5,i6,i7), sprintf('*%s',precision));
-
- end
- end
- end
- end
- end
- end
- fclose(fid);
- return % write_image
|