Skip to content

Commit d590fb3

Browse files
committed
add jnii2nii to convert jnii back to nii for compatibility
1 parent c3aa8bf commit d590fb3

4 files changed

Lines changed: 326 additions & 0 deletions

File tree

gzipdecode.m

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
function varargout = gzipdecode(varargin)
2+
%
3+
% output = gzipdecode(input)
4+
% or
5+
% output = gzipdecode(input,info)
6+
%
7+
% Decompressing a GZIP-compressed byte-stream to recover the original data
8+
% This function depends on JVM in MATLAB or, can optionally use the ZMat
9+
% toolbox (http://github.com/fangq/zmat)
10+
%
11+
% Copyright (c) 2012, Kota Yamaguchi
12+
% URL: https://www.mathworks.com/matlabcentral/fileexchange/39526-byte-encoding-utilities
13+
%
14+
% Modified by: Qianqian Fang (q.fang <at> neu.edu)
15+
%
16+
% input:
17+
% input: a string, int8/uint8 vector or numerical array to store the GZIP-compressed data
18+
% info (optional): a struct produced by the zmat/lz4hcencode function during
19+
% compression; if not given, the inputs/outputs will be treated as a
20+
% 1-D vector
21+
%
22+
% output:
23+
% output: the decompressed byte stream stored in a uint8 vector; if info is
24+
% given, output will restore the original data's type and dimensions
25+
%
26+
% examples:
27+
% [bytes, info]=gzipencode(eye(10));
28+
% orig=gzipdecode(bytes,info);
29+
%
30+
% license:
31+
% BSD or GPL version 3, see LICENSE_{BSD,GPLv3}.txt files for details
32+
%
33+
% -- this function is part of JSONLab toolbox (http://iso2mesh.sf.net/cgi-bin/index.cgi?jsonlab)
34+
%
35+
36+
if(nargin==0)
37+
error('you must provide at least 1 input');
38+
end
39+
if(exist('zmat','file')==2 || exist('zmat','file')==3)
40+
if(nargin>1)
41+
[varargout{1:nargout}]=zmat(varargin{1},varargin{2:end});
42+
else
43+
[varargout{1:nargout}]=zmat(varargin{1},0,'gzip',varargin{2:end});
44+
end
45+
return;
46+
elseif(isoctavemesh)
47+
error('You must install the ZMat toolbox (http://github.com/fangq/zmat) to use this function in Octave');
48+
end
49+
error(javachk('jvm'));
50+
51+
if(ischar(varargin{1}))
52+
varargin{1}=uint8(varargin{1});
53+
end
54+
55+
input=typecast(varargin{1}(:)','uint8');
56+
57+
gzip = java.util.zip.GZIPInputStream(java.io.ByteArrayInputStream(input));
58+
buffer = java.io.ByteArrayOutputStream();
59+
org.apache.commons.io.IOUtils.copy(gzip, buffer);
60+
gzip.close();
61+
62+
if(nargout>0)
63+
varargout{1} = typecast(buffer.toByteArray(), 'uint8')';
64+
if(nargin>1 && isstruct(varargin{2}) && isfield(varargin{2},'type'))
65+
inputinfo=varargin{2};
66+
varargout{1}=typecast(varargout{1},inputinfo.type);
67+
varargout{1}=reshape(varargout{1},inputinfo.size);
68+
end
69+
end

gzipencode.m

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
function varargout = gzipencode(varargin)
2+
%
3+
% output = gzipencode(input)
4+
% or
5+
% [output, info] = gzipencode(input)
6+
%
7+
% Compress a string or numerical array using the GZIP-compression
8+
%
9+
% This function depends on JVM in MATLAB or, can optionally use the ZMat
10+
% toolbox (http://github.com/fangq/zmat)
11+
%
12+
% Copyright (c) 2012, Kota Yamaguchi
13+
% URL: https://www.mathworks.com/matlabcentral/fileexchange/39526-byte-encoding-utilities
14+
%
15+
% Modified by: Qianqian Fang (q.fang <at> neu.edu)
16+
%
17+
% input:
18+
% input: the original data, can be a string, a numerical vector or array
19+
%
20+
% output:
21+
% output: the decompressed byte stream stored in a uint8 vector; if info is
22+
% given, output will restore the original data's type and dimensions
23+
%
24+
% examples:
25+
% [bytes, info]=gzipencode(eye(10));
26+
% orig=gzipdecode(bytes,info);
27+
%
28+
% license:
29+
% BSD or GPL version 3, see LICENSE_{BSD,GPLv3}.txt files for details
30+
%
31+
% -- this function is part of JSONLab toolbox (http://iso2mesh.sf.net/cgi-bin/index.cgi?jsonlab)
32+
%
33+
34+
35+
if(nargin==0)
36+
error('you must provide at least 1 input');
37+
end
38+
39+
if(exist('zmat','file')==2 || exist('zmat','file')==3)
40+
[varargout{1:nargout}]=zmat(varargin{1},1,'gzip');
41+
return;
42+
elseif(isoctavemesh)
43+
error('You must install the ZMat toolbox (http://github.com/fangq/zmat) to use this function in Octave');
44+
end
45+
46+
error(javachk('jvm'));
47+
48+
if(ischar(varargin{1}))
49+
varargin{1}=uint8(varargin{1});
50+
end
51+
52+
input=typecast(varargin{1}(:)','uint8');
53+
54+
buffer = java.io.ByteArrayOutputStream();
55+
gzip = java.util.zip.GZIPOutputStream(buffer);
56+
gzip.write(input, 0, numel(input));
57+
gzip.close();
58+
59+
varargout{1} = typecast(buffer.toByteArray(), 'uint8')';
60+
61+
if(nargout>1)
62+
varargout{2}=struct('type',class(varargin{1}),'size',size(varargin{1}),'method','gzip','status',0);
63+
end

jnii2nii.m

Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
function nii=jnii2nii(jnii, varargin)
2+
%
3+
% nii=jnii2nii(jnii)
4+
% or
5+
% nii=jnii2nii(jniifile)
6+
% jnii2nii(jniifile, niifile)
7+
%
8+
% Covert a JNIfTI file or data structure to a NIfTI-1/2 structure or file
9+
%
10+
% This function is compatible with both MATLAB and GNU Octave.
11+
% It accepts .jnii and .bnii input files
12+
%
13+
% author: Qianqian Fang (q.fang <at> neu.edu)
14+
%
15+
% input:
16+
% jnii: a JNIfTI data structure (a struct with NIFTIHeader and NIFTIData fields);
17+
% if jnii is a string, it represents a JNIfTI file (.jnii/.bnii)
18+
% niifile: if the 2nd parameter is given as a file name, the converted nifti data
19+
% will be save as a nii file with filename specified by niifile.
20+
% if the filename in niifile contains .gz, the file will be compressed using
21+
% the zmat toolbox.
22+
%
23+
% output:
24+
% nii: is the converted nifti-1/2 data structure, it contains the below subfields
25+
% nii.img: the data volume read from the nii file
26+
% nii.hdr: extended raw file header, a structure that is byte-wise compatible with a
27+
% nifti-1 - in this case, typecast(nii.hdr,'uint8') must be 348+4=352 bytes,
28+
% including the raw nifti-1 hdr header (348 bytes) plus the 4-byte
29+
% extension flags), or
30+
% nifti-2 - in this case, typecast(nii.hdr,'uint8') must be 540+4=544 bytes,
31+
% including the raw nifti-2 hdr header (540 bytes) plus the 4-byte
32+
% extension flags)
33+
% if one run nii.hdr.extension=[]; the resulting struct is 348/540-byte in length
34+
% nii.hdr key subfileds include
35+
%
36+
% sizeof_hdr: must be 348 (for NIFTI-1) or 540 (for NIFTI-2)
37+
% dim: short array, dim(2: dim(1)+1) defines the array size
38+
% datatype: the type of data stored in each voxel
39+
% bitpix: total bits per voxel
40+
% magic: must be 'ni1\0' or 'n+1\0' for NIFTI-1 data, and 'ni2\0' or 'n+2\0' for NIFTI-2 data
41+
%
42+
% For the detailed nii header, please see
43+
% https://nifti.nimh.nih.gov/pub/dist/src/niftilib/nifti1.h
44+
%
45+
% dependency:
46+
%
47+
% To load a JNIfTI file with compression or niifile ends with (.nii.gz/.hdr.gz/.img.gz),
48+
% one must install the ZMat Toolbox (http://github.com/fangq/zmat) and
49+
% JSONLab Toolbox (http://github.com/fangq/jsonlab);
50+
%
51+
% this file is part of JNIfTI specification: https://github.com/fangq/jnifti
52+
%
53+
% License: Apache 2.0, see https://github.com/fangq/jnifti for details
54+
%
55+
56+
if(nargin<=0)
57+
help jnii2nii
58+
return;
59+
end
60+
61+
if(~isstruct(jnii))
62+
jnii=loadjnifti(jnii);
63+
end
64+
65+
if(~(isfield(jnii,'NIFTIHeader') && isfield(jnii,'NIFTIData')))
66+
error('input must be a valid JNIfTI structure (needs both NIFTIHeader and NIFTIData subfields)');
67+
end
68+
69+
niiformat='nifti1';
70+
71+
if((isfield(jnii.NIFTIHeader,'NIIFormat') && ismember(jnii.NIFTIHeader.NIIFormat(1:3),{'ni2','n+2'})) || max(jnii.NIFTIHeader.Dim)>=2^32)
72+
niiformat='nifti2';
73+
end
74+
75+
nii.hdr=nifticreate(jnii.NIFTIData, niiformat);
76+
nii.img=jnii.NIFTIData;
77+
78+
if(isfield(jnii.NIFTIHeader,'NIIHeaderSize'))
79+
nii.hdr.sizeof_hdr =bytematch(jnii.NIFTIHeader, 'NIIHeaderSize', nii.hdr.sizeof_hdr);
80+
end
81+
if(isfield(nii.hdr,'data_type'))
82+
nii.hdr.data_type =bytematch(jnii.NIFTIHeader, 'A75DataTypeName', nii.hdr.data_type);
83+
nii.hdr.db_name =bytematch(jnii.NIFTIHeader, 'A75DBName', nii.hdr.db_name);
84+
nii.hdr.extents =bytematch(jnii.NIFTIHeader, 'A75Extends', nii.hdr.extents);
85+
nii.hdr.session_error =bytematch(jnii.NIFTIHeader, 'A75SessionError', nii.hdr.session_error);
86+
nii.hdr.regular =bytematch(jnii.NIFTIHeader, 'A75Regular', nii.hdr.regular);
87+
end
88+
89+
dim_info=bitor(uint8(jnii.NIFTIHeader.DimInfo.Freq),bitshift(uint8(jnii.NIFTIHeader.DimInfo.Phase),3));
90+
dim_info=bitor(dim_info,bitshift(uint8(jnii.NIFTIHeader.DimInfo.Slice),6));
91+
nii.hdr.dim_info=cast(dim_info, class(nii.hdr.dim_info));
92+
93+
nii.hdr.dim(1)=cast(length(jnii.NIFTIHeader.Dim),class(nii.hdr.dim));
94+
nii.hdr.dim(2:1+length(jnii.NIFTIHeader.Dim)) =bytematch(jnii.NIFTIHeader, 'Dim', nii.hdr.dim(2:1+length(jnii.NIFTIHeader.Dim)));
95+
nii.hdr.intent_p1 =bytematch(jnii.NIFTIHeader, 'Param1', nii.hdr.intent_p1);
96+
nii.hdr.intent_p2 =bytematch(jnii.NIFTIHeader, 'Param2', nii.hdr.intent_p2);
97+
nii.hdr.intent_p3 =bytematch(jnii.NIFTIHeader, 'Param3', nii.hdr.intent_p3);
98+
99+
if(ischar(jnii.NIFTIHeader.Intent))
100+
jnii.NIFTIHeader.Intent=niicodemap('intent',jnii.NIFTIHeader.Intent);
101+
end
102+
nii.hdr.intent_code =bytematch(jnii.NIFTIHeader, 'Intent', nii.hdr.intent_code);
103+
if(ischar(jnii.NIFTIHeader.DataType))
104+
jnii.NIFTIHeader.DataType=niicodemap('datatype',jnii.NIFTIHeader.DataType);
105+
end
106+
107+
nii.hdr.datatype =bytematch(jnii.NIFTIHeader, 'DataType', nii.hdr.datatype);
108+
nii.hdr.bitpix =bytematch(jnii.NIFTIHeader, 'BitDepth', nii.hdr.bitpix);
109+
nii.hdr.slice_start =bytematch(jnii.NIFTIHeader, 'FirstSliceID', nii.hdr.slice_start);
110+
nii.hdr.pixdim(1)=cast(length(jnii.NIFTIHeader.VoxelSize),class(nii.hdr.pixdim));
111+
nii.hdr.pixdim(2:2+nii.hdr.dim(1)-1) =bytematch(jnii.NIFTIHeader, 'VoxelSize', nii.hdr.pixdim(2:2+nii.hdr.dim(1)-1));
112+
nii.hdr.vox_offset =bytematch(jnii.NIFTIHeader, 'NIIByteOffset', nii.hdr.vox_offset);
113+
nii.hdr.scl_slope =bytematch(jnii.NIFTIHeader, 'ScaleSlope', nii.hdr.scl_slope);
114+
nii.hdr.scl_inter =bytematch(jnii.NIFTIHeader, 'ScaleOffset', nii.hdr.scl_inter);
115+
nii.hdr.slice_end =bytematch(jnii.NIFTIHeader, 'LastSliceID', nii.hdr.slice_end);
116+
117+
if(ischar(jnii.NIFTIHeader.SliceType))
118+
jnii.NIFTIHeader.SliceType=niicodemap('slicetype',jnii.NIFTIHeader.SliceType);
119+
end
120+
nii.hdr.slice_code =bytematch(jnii.NIFTIHeader, 'SliceType', nii.hdr.slice_code);
121+
if(ischar(jnii.NIFTIHeader.Unit.L))
122+
jnii.NIFTIHeader.Unit.L=niicodemap('unit',jnii.NIFTIHeader.Unit.L);
123+
end
124+
if(ischar(jnii.NIFTIHeader.Unit.T))
125+
jnii.NIFTIHeader.Unit.T=niicodemap('unit',jnii.NIFTIHeader.Unit.T);
126+
end
127+
128+
xyzt_units=bitor(uint8(jnii.NIFTIHeader.Unit.L),uint8(jnii.NIFTIHeader.Unit.T));
129+
nii.hdr.xyzt_units=cast(xyzt_units, class(nii.hdr.xyzt_units));
130+
131+
nii.hdr.cal_max =bytematch(jnii.NIFTIHeader, 'MaxIntensity', nii.hdr.cal_max);
132+
nii.hdr.cal_min =bytematch(jnii.NIFTIHeader, 'MinIntensity', nii.hdr.cal_min);
133+
nii.hdr.slice_duration =bytematch(jnii.NIFTIHeader, 'SliceTime', nii.hdr.slice_duration);
134+
nii.hdr.toffset =bytematch(jnii.NIFTIHeader, 'TimeOffset', nii.hdr.toffset);
135+
if(isfield(nii.hdr,'glmax'))
136+
nii.hdr.glmax =bytematch(jnii.NIFTIHeader, 'A75GlobalMax', nii.hdr.glmax);
137+
nii.hdr.glmin =bytematch(jnii.NIFTIHeader, 'A75GlobalMin', nii.hdr.glmin);
138+
end
139+
140+
nii.hdr.descrip =bytematch(jnii.NIFTIHeader, 'Description', nii.hdr.descrip);
141+
nii.hdr.aux_file =bytematch(jnii.NIFTIHeader, 'AuxFile', nii.hdr.aux_file);
142+
143+
nii.hdr.qform_code =bytematch(jnii.NIFTIHeader, 'QForm', nii.hdr.qform_code);
144+
nii.hdr.sform_code =bytematch(jnii.NIFTIHeader, 'SForm', nii.hdr.sform_code);
145+
nii.hdr.quatern_b =bytematch(jnii.NIFTIHeader, 'Quatern.b', nii.hdr.quatern_b);
146+
nii.hdr.quatern_c =bytematch(jnii.NIFTIHeader, 'Quatern.c', nii.hdr.quatern_c);
147+
nii.hdr.quatern_d =bytematch(jnii.NIFTIHeader, 'Quatern.d', nii.hdr.quatern_d);
148+
nii.hdr.qoffset_x =bytematch(jnii.NIFTIHeader, 'QuaternOffset.x', nii.hdr.qoffset_x);
149+
nii.hdr.qoffset_y =bytematch(jnii.NIFTIHeader, 'QuaternOffset.y', nii.hdr.qoffset_y);
150+
nii.hdr.qoffset_z =bytematch(jnii.NIFTIHeader, 'QuaternOffset.z', nii.hdr.qoffset_z);
151+
nii.hdr.srow_x =cast(jnii.NIFTIHeader.Affine(1,:), class(nii.hdr.srow_x));
152+
nii.hdr.srow_y =cast(jnii.NIFTIHeader.Affine(2,:), class(nii.hdr.srow_y));
153+
nii.hdr.srow_z =cast(jnii.NIFTIHeader.Affine(3,:), class(nii.hdr.srow_z));
154+
155+
nii.hdr.intent_name =bytematch(jnii.NIFTIHeader, 'Name', nii.hdr.intent_name);
156+
%nii.hdr.magic =bytematch(jnii.NIFTIHeader, 'NIIFormat', nii.hdr.magic);
157+
158+
if(isfield(jnii.NIFTIHeader,'NIIExtender'))
159+
nii.hdr.extension =bytematch(jnii.NIFTIHeader, 'NIIExtender', nii.hdr.extension);
160+
end
161+
if(isfield(jnii.NIFTIHeader,'NIIQfac_'))
162+
nii.hdr.pixdim(1) =bytematch(jnii.NIFTIHeader, 'NIIQfac_', nii.hdr.pixdim(1));
163+
end
164+
if(isfield(jnii.NIFTIHeader,'NIIUnused_'))
165+
nii.hdr.reserved =bytematch(jnii.NIFTIHeader, 'NIIUnused_', nii.hdr.reserved);
166+
end
167+
168+
if(isfield(jnii,'NIFTIExtension') && iscell(jnii.NIFTIExtension))
169+
nii.extension=jnii.NIFTIExtension;
170+
if(nii.hdr.extension(1)~=length(jnii.NIFTIExtension))
171+
nii.hdr.extension(1)=length(jnii.NIFTIExtension);
172+
warning('header extension count does not match the extension data, force update');
173+
end
174+
end
175+
176+
if(nargin>=2 && ischar(varargin{1}))
177+
savenifti(nii.img, varargin{1}, nii.hdr);
178+
end
179+
180+
%---------------------------------------------------------------------------
181+
182+
function dat=bytematch(jobj, key, orig)
183+
dtype=class(orig);
184+
dat=orig;
185+
if(isfield(jobj,key))
186+
dat=cast(jobj.(key),dtype);
187+
else
188+
dat=cast(0,dtype);
189+
end
190+
if(length(dat)<length(orig))
191+
dat(length(orig))=cast(0,dtype);
192+
end
193+
dat=dat(1:length(orig));

nifticreate.m

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
header=memmapstream(uint8(zeros(1,headerlen+4)),niiformat(format));
3636
header.sizeof_hdr=cast(headerlen, class(header.sizeof_hdr));
3737
header.datatype=cast(datatype.(class(img)), class(header.datatype));
38+
header.dim(1:end)=cast(1,class(header.dim));
3839
header.dim(1:ndims(img)+1)=cast([ndims(img),size(img)], class(header.dim));
3940
header.pixdim(1:ndims(img)+1)=cast(1, class(header.pixdim));
4041
header.vox_offset=cast(headerlen+4, class(header.vox_offset));

0 commit comments

Comments
 (0)