Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(NiftiVolumeLoader): enable the nifti-volume-loader to read nifti file with datatype such as int32, float64, int8, uint16 and uint32. Because there is something wrong with function ‘createInt16SharedArray’ and ‘createUint16SharedArray’(window.crossOriginIsolated is false), Float32SharedArray is used for representing datatypes except for uint8. #1033

Closed
2 changes: 1 addition & 1 deletion common/reviews/api/nifti-volume-loader.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ export { helpers }
function makeVolumeMetadata(niftiHeader: any, orientation: any, scalarData: any): Types.Metadata;

// @public (undocumented)
function modalityScaleNifti(array: Float32Array | Int16Array | Uint8Array, niftiHeader: any): void;
function modalityScaleNifti(array: Uint8Array | Int16Array | Int32Array | Float32Array | Float64Array | Int8Array | Uint16Array | Uint32Array, niftiHeader: any): void;

// @public (undocumented)
export class NiftiImageVolume extends ImageVolume {
Expand Down
19 changes: 17 additions & 2 deletions packages/nifti-volume-loader/src/helpers/convert.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,33 @@ const invertDataPerFrame = (dimensions, imageDataArray) => {
} else if (imageDataArray instanceof Int16Array) {
TypedArrayConstructor = Int16Array;
bytesPerVoxel = 2;
} else if (imageDataArray instanceof Int32Array) {
TypedArrayConstructor = Int32Array;
bytesPerVoxel = 4;
} else if (imageDataArray instanceof Float32Array) {
TypedArrayConstructor = Float32Array;
bytesPerVoxel = 4;
} else if (imageDataArray instanceof Float64Array) {
TypedArrayConstructor = Float64Array;
bytesPerVoxel = 8;
} else if (imageDataArray instanceof Int8Array) {
TypedArrayConstructor = Int8Array;
bytesPerVoxel = 1;
} else if (imageDataArray instanceof Uint16Array) {
TypedArrayConstructor = Uint16Array;
bytesPerVoxel = 2;
} else if (imageDataArray instanceof Uint32Array) {
TypedArrayConstructor = Uint32Array;
bytesPerVoxel = 4;
} else {
throw new Error(
'imageDataArray needs to be a Uint8Array, Int16Array or Float32Array.'
'imageDataArray needs to be a Uint8Array, Int16Array, Int32Array, Float32Array, Float64Array, Int8Array, Uint16Array or Uint32Array.'
);
}

// Make a copy of the data first using the browser native fast TypedArray.set().
const newImageDataArray = new TypedArrayConstructor(
imageDataArray.byteLength
imageDataArray.byteLength / bytesPerVoxel
);

const view = new TypedArrayConstructor(imageDataArray);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,20 @@ export const getTypedNiftiArray = (datatypeCode, niftiImageBuffer) => {
switch (datatypeCode) {
case NIFTICONSTANTS.NIFTI_TYPE_UINT8:
return new Uint8Array(niftiImageBuffer);
case NIFTICONSTANTS.NIFTI_TYPE_FLOAT32:
return new Float32Array(niftiImageBuffer);
case NIFTICONSTANTS.NIFTI_TYPE_INT16:
return new Int16Array(niftiImageBuffer);
case NIFTICONSTANTS.NIFTI_TYPE_INT32:
return new Int32Array(niftiImageBuffer);
case NIFTICONSTANTS.NIFTI_TYPE_FLOAT32:
return new Float32Array(niftiImageBuffer);
case NIFTICONSTANTS.NIFTI_TYPE_FLOAT64:
return new Float64Array(niftiImageBuffer);
case NIFTICONSTANTS.NIFTI_TYPE_INT8:
return new Int8Array(niftiImageBuffer);
case NIFTICONSTANTS.NIFTI_TYPE_UINT16:
return new Uint16Array(niftiImageBuffer);
case NIFTICONSTANTS.NIFTI_TYPE_UINT32:
return new Uint32Array(niftiImageBuffer);
default:
throw new Error(`datatypeCode ${datatypeCode} is not yet supported`);
}
Expand Down Expand Up @@ -149,7 +159,6 @@ export default async function fetchAndAllocateNiftiVolume(

const {
BitsAllocated,
PixelRepresentation,
PhotometricInterpretation,
ImageOrientationPatient,
Columns,
Expand Down Expand Up @@ -184,7 +193,6 @@ export default async function fetchAndAllocateNiftiVolume(
scanAxisNormal[1],
scanAxisNormal[2],
]) as Types.Mat3;
const signed = PixelRepresentation === 1;

// Check if it fits in the cache before we allocate data
// TODO Improve this when we have support for more types
Expand Down Expand Up @@ -213,22 +221,15 @@ export default async function fetchAndAllocateNiftiVolume(

let scalarData;

switch (BitsAllocated) {
case 8:
if (signed) {
throw new Error(
'8 Bit signed images are not yet supported by this plugin.'
);
} else {
scalarData = createUint8SharedArray(
dimensions[0] * dimensions[1] * dimensions[2]
);
}
switch (niftiHeader.datatypeCode) {
case NIFTICONSTANTS.NIFTI_TYPE_UINT8:
scalarData = createUint8SharedArray(
dimensions[0] * dimensions[1] * dimensions[2]
);

break;

case 16:
case 32:
default:
scalarData = createFloat32SharedArray(
dimensions[0] * dimensions[1] * dimensions[2]
);
Expand Down
10 changes: 9 additions & 1 deletion packages/nifti-volume-loader/src/helpers/modalityScaleNifti.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,15 @@
* @returns The array being scaled
*/
export default function modalityScaleNifti(
array: Float32Array | Int16Array | Uint8Array,
array:
| Uint8Array
| Int16Array
| Int32Array
| Float32Array
| Float64Array
| Int8Array
| Uint16Array
| Uint32Array,
niftiHeader
): void {
const arrayLength = array.length;
Expand Down