src_utils_Nifti_viewer_load_untouch_nii_hdr.js
// internal function
//
// - Jimmy Shen (jimmy@rotman-baycrest.on.ca)
//
// This version is ported from original MatLab script into JavaScript by Wirecracker team and distributed under MIT license.
import FILE from "./FILE.js";
export default load_untouch_nii_hdr;
/**
* Loads the header of a NIfTI file.
*
* This function initializes a FILE object to read the binary data of a NIfTI header.
* It then extracts the header information and returns it.
* If the `magic` field in the header is not 'n+1' or 'ni1', `qform_code` and `sform_code` are set to 0.
* @see For function that does not load transformation information: {@link module:nifti_viewer.load_untouch0_nii_hdr load_untouch0_nii_hdr}
*
* @function
* @memberof module:nifti_viewer
* @param {('ieee-le'|'ieee-be')} machine - Byte order used by the machine ('ieee-le' for little-endian, 'ieee-be' for big-endian).
* @param {ArrayBuffer} data - The binary data of the NIfTI file.
* @returns {Object} The parsed NIfTI header object.
*/
function load_untouch_nii_hdr ( machine, data ) {
const fid = new FILE('', machine);
fid.fopen(data);
fid.frewind();
let hdr = read_header(fid);
return hdr
}
function read_header ( fid ) {
let dsr = {};
dsr.hk = header_key(fid);
dsr.dime = image_dimension(fid);
dsr.hist = data_history(fid);
if ( !(dsr.hist.magic === 'n+1') && !(dsr.hist.magic === 'ni1') ) {
dsr.hist.qform_code = 0;
dsr.hist.sform_code = 0;
}
return dsr;
}
function header_key ( fid ) {
fid.frewind();
// Original header structures
// struct header_key /* header key */
// { /* off + size */
// int sizeof_hdr /* 0 + 4 */
// char data_type[10]; /* 4 + 10 */
// char db_name[18]; /* 14 + 18 */
// int extents; /* 32 + 4 */
// short int session_error; /* 36 + 2 */
// char regular; /* 38 + 1 */
// char dim_info; % char hkey_un0; /* 39 + 1 */
// }; /* total=40 bytes */
//
// int sizeof_header Should be 348.
// char regular Must be 'r' to indicate that all images and
// volumes are the same size.
const hk = {};
hk.sizeof_hdr = fid.fread( 1, 'int32'); // should be 348!
hk.data_type = fid.fread(10, 'string');
hk.db_name = fid.fread(18, 'string');
hk.extents = fid.fread( 1, 'int32');
hk.session_error = fid.fread( 1, 'int16');
hk.regular = fid.fread( 1, 'string');
hk.dim_info = fid.fread( 1, 'uchar');
return hk;
}
function image_dimension ( fid ) {
// Original header structures
// struct image_dimension
// { /* off + size */
// short int dim[8]; /* 0 + 16 */
// /*
// dim[0] Number of dimensions in database; usually 4.
// dim[1] Image X dimension; number of *pixels* in an image row.
// dim[2] Image Y dimension; number of *pixel rows* in slice.
// dim[3] Volume Z dimension; number of *slices* in a volume.
// dim[4] Time points; number of volumes in database
// */
// float intent_p1; % char vox_units[4]; /* 16 + 4 */
// float intent_p2; % char cal_units[8]; /* 20 + 4 */
// float intent_p3; % char cal_units[8]; /* 24 + 4 */
// short int intent_code; % short int unused1; /* 28 + 2 */
// short int datatype; /* 30 + 2 */
// short int bitpix; /* 32 + 2 */
// short int slice_start; % short int dim_un0; /* 34 + 2 */
// float pixdim[8]; /* 36 + 32 */
// /*
// pixdim[] specifies the voxel dimensions:
// pixdim[1] - voxel width, mm
// pixdim[2] - voxel height, mm
// pixdim[3] - slice thickness, mm
// pixdim[4] - volume timing, in msec
// ..etc
// */
// float vox_offset; /* 68 + 4 */
// float scl_slope; % float roi_scale; /* 72 + 4 */
// float scl_inter; % float funused1; /* 76 + 4 */
// short slice_end; % float funused2; /* 80 + 2 */
// char slice_code; % float funused2; /* 82 + 1 */
// char xyzt_units; % float funused2; /* 83 + 1 */
// float cal_max; /* 84 + 4 */
// float cal_min; /* 88 + 4 */
// float slice_duration; % int compressed; /* 92 + 4 */
// float toffset; % int verified; /* 96 + 4 */
// int glmax; /* 100 + 4 */
// int glmin; /* 104 + 4 */
// }; /* total=108 bytes */
const dime = {};
dime.dim = fid.fread(8, 'int16');
dime.intent_p1 = fid.fread(1, 'float32');
dime.intent_p2 = fid.fread(1, 'float32');
dime.intent_p3 = fid.fread(1, 'float32');
dime.intent_code = fid.fread(1, 'int16');
dime.datatype = fid.fread(1, 'int16');
dime.bitpix = fid.fread(1, 'int16');
dime.slice_start = fid.fread(1, 'int16');
dime.pixdim = fid.fread(8, 'float32');
dime.vox_offset = fid.fread(1, 'float32');
dime.scl_slope = fid.fread(1, 'float32');
dime.scl_inter = fid.fread(1, 'float32');
dime.slice_end = fid.fread(1, 'int16');
dime.slice_code = fid.fread(1, 'uchar');
dime.xyzt_units = fid.fread(1, 'uchar');
dime.cal_max = fid.fread(1, 'float32');
dime.cal_min = fid.fread(1, 'float32');
dime.slice_duration = fid.fread(1, 'float32');
dime.toffset = fid.fread(1, 'float32');
dime.glmax = fid.fread(1, 'int32');
dime.glmin = fid.fread(1, 'int32');
return dime;
}
function data_history ( fid ) {
// Original header structures
// struct data_history
// { /* off + size */
// char descrip[80]; /* 0 + 80 */
// char aux_file[24]; /* 80 + 24 */
// short int qform_code; /* 104 + 2 */
// short int sform_code; /* 106 + 2 */
// float quatern_b; /* 108 + 4 */
// float quatern_c; /* 112 + 4 */
// float quatern_d; /* 116 + 4 */
// float qoffset_x; /* 120 + 4 */
// float qoffset_y; /* 124 + 4 */
// float qoffset_z; /* 128 + 4 */
// float srow_x[4]; /* 132 + 16 */
// float srow_y[4]; /* 148 + 16 */
// float srow_z[4]; /* 164 + 16 */
// char intent_name[16]; /* 180 + 16 */
// char magic[4]; % int smin; /* 196 + 4 */
// }; /* total=200 bytes */
const hist = {};
hist.descrip = fid.fread(80, 'string');
hist.aux_file = fid.fread(24, 'string');
hist.qform_code = fid.fread( 1, 'int16');
hist.sform_code = fid.fread( 1, 'int16');
hist.quatern_b = fid.fread( 1, 'float32');
hist.quatern_c = fid.fread( 1, 'float32');
hist.quatern_d = fid.fread( 1, 'float32');
hist.qoffset_x = fid.fread( 1, 'float32');
hist.qoffset_y = fid.fread( 1, 'float32');
hist.qoffset_z = fid.fread( 1, 'float32');
hist.srow_x = fid.fread( 4, 'float32');
hist.srow_y = fid.fread( 4, 'float32');
hist.srow_z = fid.fread( 4, 'float32');
hist.intent_name = fid.fread(16, 'string');
hist.magic = fid.fread( 4, 'string');
return hist;
}