@cornerstonejs/nifti-volume-loader 2.0.0-beta.2 → 2.0.0-beta.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/NiftiImageVolume.d.ts +3 -3
- package/dist/esm/NiftiImageVolume.js +0 -1
- package/dist/esm/constants/index.js +0 -1
- package/dist/esm/constants/niftiLoaderScheme.js +0 -1
- package/dist/esm/cornerstoneNiftiImageLoader.js +0 -1
- package/dist/esm/enums/Events.js +0 -1
- package/dist/esm/enums/index.js +0 -1
- package/dist/esm/helpers/affineUtilities.js +0 -1
- package/dist/esm/helpers/convert.d.ts +1 -1
- package/dist/esm/helpers/convert.js +3 -2
- package/dist/esm/helpers/fetchAndAllocateNiftiVolume.d.ts +0 -1
- package/dist/esm/helpers/fetchAndAllocateNiftiVolume.js +9 -78
- package/dist/esm/helpers/index.js +0 -1
- package/dist/esm/helpers/makeVolumeMetadata.d.ts +5 -1
- package/dist/esm/helpers/makeVolumeMetadata.js +41 -28
- package/dist/esm/helpers/modalityScaleNifti.d.ts +5 -1
- package/dist/esm/helpers/modalityScaleNifti.js +143 -7
- package/dist/esm/helpers/niftiConstants.js +0 -1
- package/dist/esm/index.js +0 -1
- package/dist/umd/index.js +1 -1
- package/dist/umd/index.js.LICENSE.txt +3 -1
- package/dist/umd/index.js.map +1 -1
- package/package.json +13 -5
- package/dist/esm/NiftiImageVolume.js.map +0 -1
- package/dist/esm/constants/index.js.map +0 -1
- package/dist/esm/constants/niftiLoaderScheme.js.map +0 -1
- package/dist/esm/cornerstoneNiftiImageLoader.js.map +0 -1
- package/dist/esm/enums/Events.js.map +0 -1
- package/dist/esm/enums/index.js.map +0 -1
- package/dist/esm/helpers/affineUtilities.js.map +0 -1
- package/dist/esm/helpers/convert.js.map +0 -1
- package/dist/esm/helpers/fetchAndAllocateNiftiVolume.js.map +0 -1
- package/dist/esm/helpers/index.js.map +0 -1
- package/dist/esm/helpers/makeVolumeMetadata.js.map +0 -1
- package/dist/esm/helpers/modalityScaleNifti.js.map +0 -1
- package/dist/esm/helpers/niftiConstants.js.map +0 -1
- package/dist/esm/index.js.map +0 -1
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import { ImageVolume } from '@cornerstonejs/core';
|
|
2
2
|
import type { Types } from '@cornerstonejs/core';
|
|
3
|
-
|
|
3
|
+
type LoadStatus = {
|
|
4
4
|
loaded: boolean;
|
|
5
5
|
loading: boolean;
|
|
6
6
|
callbacks: Array<(...args: unknown[]) => void>;
|
|
7
7
|
};
|
|
8
|
-
|
|
8
|
+
type NiftiImageProperties = {
|
|
9
9
|
loadStatus: LoadStatus;
|
|
10
10
|
controller: AbortController;
|
|
11
11
|
};
|
|
12
12
|
export default class NiftiImageVolume extends ImageVolume {
|
|
13
13
|
loadStatus: LoadStatus;
|
|
14
14
|
controller: AbortController;
|
|
15
|
-
constructor(imageVolumeProperties: Types.
|
|
15
|
+
constructor(imageVolumeProperties: Types.ImageVolumeProps, streamingProperties: NiftiImageProperties);
|
|
16
16
|
cancelLoading: () => void;
|
|
17
17
|
clearLoadCallbacks(): void;
|
|
18
18
|
load: (callback: (...args: unknown[]) => void, priority?: number) => void;
|
package/dist/esm/enums/Events.js
CHANGED
package/dist/esm/enums/index.js
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
|
+
import { getShouldUseSharedArrayBuffer } from '@cornerstonejs/core';
|
|
1
2
|
import { parseAffineMatrix } from './affineUtilities';
|
|
2
3
|
const invertDataPerFrame = (dimensions, imageDataArray) => {
|
|
3
4
|
let TypedArrayConstructor;
|
|
4
5
|
let bytesPerVoxel;
|
|
5
6
|
if (imageDataArray instanceof Uint8Array ||
|
|
6
7
|
imageDataArray instanceof ArrayBuffer ||
|
|
7
|
-
|
|
8
|
+
(getShouldUseSharedArrayBuffer() &&
|
|
9
|
+
imageDataArray instanceof SharedArrayBuffer)) {
|
|
8
10
|
TypedArrayConstructor = Uint8Array;
|
|
9
11
|
bytesPerVoxel = 1;
|
|
10
12
|
}
|
|
@@ -80,4 +82,3 @@ function lpsToRas(header) {
|
|
|
80
82
|
};
|
|
81
83
|
}
|
|
82
84
|
export { lpsToRas, rasToLps, invertDataPerFrame };
|
|
83
|
-
//# sourceMappingURL=convert.js.map
|
|
@@ -1,4 +1,3 @@
|
|
|
1
1
|
import NiftiImageVolume from '../NiftiImageVolume';
|
|
2
2
|
export declare const urlsMap: Map<any, any>;
|
|
3
|
-
export declare const getTypedNiftiArray: (datatypeCode: any, niftiImageBuffer: any) => Float32Array | Int16Array | Uint8Array;
|
|
4
3
|
export default function fetchAndAllocateNiftiVolume(volumeId: string): Promise<NiftiImageVolume>;
|
|
@@ -1,14 +1,11 @@
|
|
|
1
1
|
import * as NiftiReader from 'nifti-reader-js';
|
|
2
|
-
import {
|
|
3
|
-
import { vec3 } from 'gl-matrix';
|
|
4
|
-
import makeVolumeMetadata from './makeVolumeMetadata';
|
|
2
|
+
import { eventTarget, triggerEvent } from '@cornerstonejs/core';
|
|
5
3
|
import NiftiImageVolume from '../NiftiImageVolume';
|
|
6
|
-
import
|
|
7
|
-
import { invertDataPerFrame, rasToLps } from './convert';
|
|
8
|
-
import modalityScaleNifti from './modalityScaleNifti';
|
|
4
|
+
import { rasToLps } from './convert';
|
|
9
5
|
import Events from '../enums/Events';
|
|
10
6
|
import { NIFTI_LOADER_SCHEME } from '../constants';
|
|
11
|
-
|
|
7
|
+
import makeVolumeMetadata from './makeVolumeMetadata';
|
|
8
|
+
import modalityScaleNifti from './modalityScaleNifti';
|
|
12
9
|
export const urlsMap = new Map();
|
|
13
10
|
function fetchArrayBuffer(url, onProgress, signal, onload) {
|
|
14
11
|
return new Promise((resolve, reject) => {
|
|
@@ -45,18 +42,6 @@ function fetchArrayBuffer(url, onProgress, signal, onload) {
|
|
|
45
42
|
xhr.send();
|
|
46
43
|
});
|
|
47
44
|
}
|
|
48
|
-
export const getTypedNiftiArray = (datatypeCode, niftiImageBuffer) => {
|
|
49
|
-
switch (datatypeCode) {
|
|
50
|
-
case NIFTICONSTANTS.NIFTI_TYPE_UINT8:
|
|
51
|
-
return new Uint8Array(niftiImageBuffer);
|
|
52
|
-
case NIFTICONSTANTS.NIFTI_TYPE_FLOAT32:
|
|
53
|
-
return new Float32Array(niftiImageBuffer);
|
|
54
|
-
case NIFTICONSTANTS.NIFTI_TYPE_INT16:
|
|
55
|
-
return new Int16Array(niftiImageBuffer);
|
|
56
|
-
default:
|
|
57
|
-
throw new Error(`datatypeCode ${datatypeCode} is not yet supported`);
|
|
58
|
-
}
|
|
59
|
-
};
|
|
60
45
|
export default async function fetchAndAllocateNiftiVolume(volumeId) {
|
|
61
46
|
const niftiURL = volumeId.substring(NIFTI_LOADER_SCHEME.length + 1);
|
|
62
47
|
const progress = (loaded, total) => {
|
|
@@ -85,63 +70,10 @@ export default async function fetchAndAllocateNiftiVolume(volumeId) {
|
|
|
85
70
|
niftiHeader = NiftiReader.readHeader(niftiBuffer);
|
|
86
71
|
niftiImage = NiftiReader.readImage(niftiHeader, niftiBuffer);
|
|
87
72
|
}
|
|
88
|
-
const
|
|
73
|
+
const { scalarData, pixelRepresentation } = modalityScaleNifti(niftiHeader, niftiImage);
|
|
89
74
|
const { orientation, origin, spacing } = rasToLps(niftiHeader);
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
const volumeMetadata = makeVolumeMetadata(niftiHeader, orientation, typedNiftiArray);
|
|
93
|
-
const scanAxisNormal = vec3.create();
|
|
94
|
-
vec3.set(scanAxisNormal, orientation[6], orientation[7], orientation[8]);
|
|
95
|
-
const { BitsAllocated, PixelRepresentation, PhotometricInterpretation, ImageOrientationPatient, Columns, Rows, } = volumeMetadata;
|
|
96
|
-
const rowCosineVec = vec3.fromValues(ImageOrientationPatient[0], ImageOrientationPatient[1], ImageOrientationPatient[2]);
|
|
97
|
-
const colCosineVec = vec3.fromValues(ImageOrientationPatient[3], ImageOrientationPatient[4], ImageOrientationPatient[5]);
|
|
98
|
-
const { dims } = niftiHeader;
|
|
99
|
-
const numFrames = dims[3];
|
|
100
|
-
const dimensions = [Columns, Rows, numFrames];
|
|
101
|
-
const direction = new Float32Array([
|
|
102
|
-
rowCosineVec[0],
|
|
103
|
-
rowCosineVec[1],
|
|
104
|
-
rowCosineVec[2],
|
|
105
|
-
colCosineVec[0],
|
|
106
|
-
colCosineVec[1],
|
|
107
|
-
colCosineVec[2],
|
|
108
|
-
scanAxisNormal[0],
|
|
109
|
-
scanAxisNormal[1],
|
|
110
|
-
scanAxisNormal[2],
|
|
111
|
-
]);
|
|
112
|
-
const signed = PixelRepresentation === 1;
|
|
113
|
-
let bytesPerVoxel = 1;
|
|
114
|
-
if (BitsAllocated === 16 || BitsAllocated === 32) {
|
|
115
|
-
bytesPerVoxel = 4;
|
|
116
|
-
}
|
|
117
|
-
const sizeInBytesPerComponent = bytesPerVoxel * dimensions[0] * dimensions[1] * dimensions[2];
|
|
118
|
-
let numComponents = 1;
|
|
119
|
-
if (PhotometricInterpretation === 'RGB') {
|
|
120
|
-
numComponents = 3;
|
|
121
|
-
}
|
|
122
|
-
const sizeInBytes = sizeInBytesPerComponent * numComponents;
|
|
123
|
-
const isCacheable = cache.isCacheable(sizeInBytes);
|
|
124
|
-
if (!isCacheable) {
|
|
125
|
-
throw new Error(Enums.Events.CACHE_SIZE_EXCEEDED);
|
|
126
|
-
}
|
|
127
|
-
cache.decacheIfNecessaryUntilBytesAvailable(sizeInBytes);
|
|
128
|
-
let scalarData;
|
|
129
|
-
switch (BitsAllocated) {
|
|
130
|
-
case 8:
|
|
131
|
-
if (signed) {
|
|
132
|
-
throw new Error('8 Bit signed images are not yet supported by this plugin.');
|
|
133
|
-
}
|
|
134
|
-
else {
|
|
135
|
-
scalarData = createUint8SharedArray(dimensions[0] * dimensions[1] * dimensions[2]);
|
|
136
|
-
}
|
|
137
|
-
break;
|
|
138
|
-
case 16:
|
|
139
|
-
case 32:
|
|
140
|
-
scalarData = createFloat32SharedArray(dimensions[0] * dimensions[1] * dimensions[2]);
|
|
141
|
-
break;
|
|
142
|
-
}
|
|
143
|
-
scalarData.set(typedNiftiArray);
|
|
144
|
-
const niftiImageVolume = new NiftiImageVolume({
|
|
75
|
+
const { volumeMetadata, dimensions, direction } = makeVolumeMetadata(niftiHeader, orientation, scalarData, pixelRepresentation);
|
|
76
|
+
return new NiftiImageVolume({
|
|
145
77
|
volumeId,
|
|
146
78
|
metadata: volumeMetadata,
|
|
147
79
|
dimensions,
|
|
@@ -149,7 +81,8 @@ export default async function fetchAndAllocateNiftiVolume(volumeId) {
|
|
|
149
81
|
origin,
|
|
150
82
|
direction,
|
|
151
83
|
scalarData,
|
|
152
|
-
sizeInBytes,
|
|
84
|
+
sizeInBytes: scalarData.byteLength,
|
|
85
|
+
imageIds: [],
|
|
153
86
|
}, {
|
|
154
87
|
loadStatus: {
|
|
155
88
|
loaded: false,
|
|
@@ -158,6 +91,4 @@ export default async function fetchAndAllocateNiftiVolume(volumeId) {
|
|
|
158
91
|
},
|
|
159
92
|
controller,
|
|
160
93
|
});
|
|
161
|
-
return niftiImageVolume;
|
|
162
94
|
}
|
|
163
|
-
//# sourceMappingURL=fetchAndAllocateNiftiVolume.js.map
|
|
@@ -2,4 +2,3 @@ import makeVolumeMetadata from './makeVolumeMetadata';
|
|
|
2
2
|
import modalityScaleNifti from './modalityScaleNifti';
|
|
3
3
|
import fetchAndAllocateNiftiVolume from './fetchAndAllocateNiftiVolume';
|
|
4
4
|
export { modalityScaleNifti, makeVolumeMetadata, fetchAndAllocateNiftiVolume };
|
|
5
|
-
//# sourceMappingURL=index.js.map
|
|
@@ -1,2 +1,6 @@
|
|
|
1
1
|
import { Types } from '@cornerstonejs/core';
|
|
2
|
-
export default function makeVolumeMetadata(niftiHeader: any, orientation: any, scalarData: any):
|
|
2
|
+
export default function makeVolumeMetadata(niftiHeader: any, orientation: any, scalarData: any, pixelRepresentation: any): {
|
|
3
|
+
volumeMetadata: Types.Metadata;
|
|
4
|
+
dimensions: Types.Point3;
|
|
5
|
+
direction: Types.Mat3;
|
|
6
|
+
};
|
|
@@ -1,17 +1,12 @@
|
|
|
1
|
+
import { utilities } from '@cornerstonejs/core';
|
|
1
2
|
import { vec3 } from 'gl-matrix';
|
|
2
|
-
|
|
3
|
+
const { windowLevel } = utilities;
|
|
4
|
+
export default function makeVolumeMetadata(niftiHeader, orientation, scalarData, pixelRepresentation) {
|
|
3
5
|
const { numBitsPerVoxel, littleEndian, pixDims, dims } = niftiHeader;
|
|
4
|
-
const rowCosines = vec3.create();
|
|
5
|
-
const columnCosines = vec3.create();
|
|
6
|
-
vec3.set(rowCosines, orientation[0], orientation[1], orientation[2]);
|
|
7
|
-
vec3.set(columnCosines, orientation[3], orientation[4], orientation[5]);
|
|
8
6
|
let min = Infinity;
|
|
9
7
|
let max = -Infinity;
|
|
10
|
-
const
|
|
11
|
-
const
|
|
12
|
-
const zDim = dims[3];
|
|
13
|
-
const frameLength = xDim * yDim;
|
|
14
|
-
const middleFrameIndex = Math.floor(zDim / 2);
|
|
8
|
+
const frameLength = dims[1] * dims[2];
|
|
9
|
+
const middleFrameIndex = Math.floor(dims[3] / 2);
|
|
15
10
|
const offset = frameLength * middleFrameIndex;
|
|
16
11
|
for (let voxelIndex = offset; voxelIndex < offset + frameLength; voxelIndex++) {
|
|
17
12
|
const voxelValue = scalarData[voxelIndex];
|
|
@@ -22,30 +17,48 @@ export default function makeVolumeMetadata(niftiHeader, orientation, scalarData)
|
|
|
22
17
|
min = voxelValue;
|
|
23
18
|
}
|
|
24
19
|
}
|
|
25
|
-
const windowCenter = (max
|
|
26
|
-
const
|
|
20
|
+
const { windowWidth, windowCenter } = windowLevel.toWindowLevel(min, max);
|
|
21
|
+
const rowCosines = vec3.create();
|
|
22
|
+
const columnCosines = vec3.create();
|
|
23
|
+
const scanAxisNormal = vec3.create();
|
|
24
|
+
vec3.set(rowCosines, orientation[0], orientation[1], orientation[2]);
|
|
25
|
+
vec3.set(columnCosines, orientation[3], orientation[4], orientation[5]);
|
|
26
|
+
vec3.set(scanAxisNormal, orientation[6], orientation[7], orientation[8]);
|
|
27
27
|
return {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
28
|
+
volumeMetadata: {
|
|
29
|
+
BitsAllocated: numBitsPerVoxel,
|
|
30
|
+
BitsStored: numBitsPerVoxel,
|
|
31
|
+
SamplesPerPixel: 1,
|
|
32
|
+
HighBit: littleEndian ? numBitsPerVoxel - 1 : 1,
|
|
33
|
+
PhotometricInterpretation: 'MONOCHROME2',
|
|
34
|
+
PixelRepresentation: pixelRepresentation,
|
|
35
|
+
ImageOrientationPatient: [
|
|
36
|
+
rowCosines[0],
|
|
37
|
+
rowCosines[1],
|
|
38
|
+
rowCosines[2],
|
|
39
|
+
columnCosines[0],
|
|
40
|
+
columnCosines[1],
|
|
41
|
+
columnCosines[2],
|
|
42
|
+
],
|
|
43
|
+
PixelSpacing: [pixDims[1], pixDims[2]],
|
|
44
|
+
Columns: dims[1],
|
|
45
|
+
Rows: dims[2],
|
|
46
|
+
voiLut: [{ windowCenter, windowWidth }],
|
|
47
|
+
FrameOfReferenceUID: '1.2.3',
|
|
48
|
+
Modality: 'MR',
|
|
49
|
+
VOILUTFunction: 'LINEAR',
|
|
50
|
+
},
|
|
51
|
+
dimensions: [dims[1], dims[2], dims[3]],
|
|
52
|
+
direction: new Float32Array([
|
|
35
53
|
rowCosines[0],
|
|
36
54
|
rowCosines[1],
|
|
37
55
|
rowCosines[2],
|
|
38
56
|
columnCosines[0],
|
|
39
57
|
columnCosines[1],
|
|
40
58
|
columnCosines[2],
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
voiLut: [{ windowCenter, windowWidth }],
|
|
46
|
-
FrameOfReferenceUID: '1.2.3',
|
|
47
|
-
Modality: 'MR',
|
|
48
|
-
VOILUTFunction: 'LINEAR',
|
|
59
|
+
scanAxisNormal[0],
|
|
60
|
+
scanAxisNormal[1],
|
|
61
|
+
scanAxisNormal[2],
|
|
62
|
+
]),
|
|
49
63
|
};
|
|
50
64
|
}
|
|
51
|
-
//# sourceMappingURL=makeVolumeMetadata.js.map
|
|
@@ -1 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
import { Types } from '@cornerstonejs/core';
|
|
2
|
+
export default function modalityScaleNifti(niftiHeader: any, niftiImageBuffer: any): {
|
|
3
|
+
scalarData: Types.PixelDataTypedArray;
|
|
4
|
+
pixelRepresentation: number;
|
|
5
|
+
};
|
|
@@ -1,11 +1,147 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { cache, Enums, getShouldUseSharedArrayBuffer, utilities, } from '@cornerstonejs/core';
|
|
2
|
+
import * as NIFTICONSTANTS from './niftiConstants';
|
|
3
|
+
const { createFloat32SharedArray, createInt16SharedArray, createUint8SharedArray, createUint16SharedArray, } = utilities;
|
|
4
|
+
export default function modalityScaleNifti(niftiHeader, niftiImageBuffer) {
|
|
5
|
+
const { datatypeCode, scl_slope, scl_inter } = niftiHeader;
|
|
6
|
+
let slope = scl_slope;
|
|
7
|
+
let inter = scl_inter;
|
|
4
8
|
if (!scl_slope || scl_slope === 0 || Number.isNaN(scl_slope)) {
|
|
5
|
-
|
|
9
|
+
slope = 1;
|
|
6
10
|
}
|
|
7
|
-
|
|
8
|
-
|
|
11
|
+
if (!scl_inter || Number.isNaN(scl_inter)) {
|
|
12
|
+
inter = 0;
|
|
9
13
|
}
|
|
14
|
+
const hasNegativeRescale = inter < 0 || slope < 0;
|
|
15
|
+
const hasFloatRescale = inter % 1 !== 0 || slope % 1 !== 0;
|
|
16
|
+
let niiBuffer;
|
|
17
|
+
let scalarData;
|
|
18
|
+
let pixelRepresentation = 1;
|
|
19
|
+
switch (datatypeCode) {
|
|
20
|
+
case NIFTICONSTANTS.NIFTI_TYPE_UINT8:
|
|
21
|
+
niiBuffer = new Uint8Array(niftiImageBuffer);
|
|
22
|
+
if (hasFloatRescale) {
|
|
23
|
+
scalarData = allocateScalarData('Float32Array', niiBuffer);
|
|
24
|
+
}
|
|
25
|
+
else if (hasNegativeRescale) {
|
|
26
|
+
scalarData = allocateScalarData('Int16Array', niiBuffer);
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
pixelRepresentation = 0;
|
|
30
|
+
scalarData = allocateScalarData('Uint8Array', niiBuffer);
|
|
31
|
+
}
|
|
32
|
+
break;
|
|
33
|
+
case NIFTICONSTANTS.NIFTI_TYPE_INT16:
|
|
34
|
+
niiBuffer = new Int16Array(niftiImageBuffer);
|
|
35
|
+
if (hasFloatRescale) {
|
|
36
|
+
scalarData = allocateScalarData('Float32Array', niiBuffer);
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
scalarData = allocateScalarData('Int16Array', niiBuffer);
|
|
40
|
+
}
|
|
41
|
+
break;
|
|
42
|
+
case NIFTICONSTANTS.NIFTI_TYPE_INT32:
|
|
43
|
+
niiBuffer = new Int32Array(niftiImageBuffer);
|
|
44
|
+
scalarData = allocateScalarData('Float32Array', niiBuffer);
|
|
45
|
+
break;
|
|
46
|
+
case NIFTICONSTANTS.NIFTI_TYPE_FLOAT32: {
|
|
47
|
+
niiBuffer = new Float32Array(niftiImageBuffer);
|
|
48
|
+
scalarData = allocateScalarData('Float32Array', niiBuffer);
|
|
49
|
+
break;
|
|
50
|
+
}
|
|
51
|
+
case NIFTICONSTANTS.NIFTI_TYPE_INT8:
|
|
52
|
+
niiBuffer = new Int8Array(niftiImageBuffer);
|
|
53
|
+
if (hasFloatRescale) {
|
|
54
|
+
scalarData = allocateScalarData('Float32Array', niiBuffer);
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
scalarData = allocateScalarData('Int8Array', niiBuffer);
|
|
58
|
+
}
|
|
59
|
+
break;
|
|
60
|
+
case NIFTICONSTANTS.NIFTI_TYPE_UINT16:
|
|
61
|
+
niiBuffer = new Uint16Array(niftiImageBuffer);
|
|
62
|
+
if (hasFloatRescale || hasNegativeRescale) {
|
|
63
|
+
scalarData = allocateScalarData('Float32Array', niiBuffer);
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
pixelRepresentation = 0;
|
|
67
|
+
scalarData = allocateScalarData('Uint16Array', niiBuffer);
|
|
68
|
+
}
|
|
69
|
+
break;
|
|
70
|
+
case NIFTICONSTANTS.NIFTI_TYPE_UINT32:
|
|
71
|
+
niiBuffer = new Uint32Array(niftiImageBuffer);
|
|
72
|
+
scalarData = allocateScalarData('Float32Array', niiBuffer);
|
|
73
|
+
break;
|
|
74
|
+
default:
|
|
75
|
+
throw new Error(`NIFTI datatypeCode ${datatypeCode} is not yet supported`);
|
|
76
|
+
}
|
|
77
|
+
const nVox = scalarData.length;
|
|
78
|
+
if (slope !== 1 && inter !== 0) {
|
|
79
|
+
for (let i = 0; i < nVox; i++) {
|
|
80
|
+
scalarData[i] = intensityRaw2Scaled(scalarData[i], slope, inter);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
niftiHeader.numBitsPerVoxel = (scalarData.byteLength / scalarData.length) * 8;
|
|
84
|
+
return {
|
|
85
|
+
scalarData,
|
|
86
|
+
pixelRepresentation,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
function intensityRaw2Scaled(raw, scl_slope, scl_inter) {
|
|
90
|
+
return raw * scl_slope + scl_inter;
|
|
91
|
+
}
|
|
92
|
+
function checkCacheAvailable(bitsAllocated, length) {
|
|
93
|
+
const sizeInBytes = (bitsAllocated / 8) * length;
|
|
94
|
+
const isCacheable = cache.isCacheable(sizeInBytes);
|
|
95
|
+
if (!isCacheable) {
|
|
96
|
+
throw new Error(Enums.Events.CACHE_SIZE_EXCEEDED);
|
|
97
|
+
}
|
|
98
|
+
cache.decacheIfNecessaryUntilBytesAvailable(sizeInBytes);
|
|
99
|
+
return sizeInBytes;
|
|
100
|
+
}
|
|
101
|
+
function allocateScalarData(types, niiBuffer) {
|
|
102
|
+
let bitsAllocated;
|
|
103
|
+
let scalarData;
|
|
104
|
+
const useSharedArrayBuffer = getShouldUseSharedArrayBuffer();
|
|
105
|
+
const nVox = niiBuffer.length;
|
|
106
|
+
switch (types) {
|
|
107
|
+
case 'Float32Array':
|
|
108
|
+
bitsAllocated = 32;
|
|
109
|
+
checkCacheAvailable(bitsAllocated, nVox);
|
|
110
|
+
scalarData = useSharedArrayBuffer
|
|
111
|
+
? createFloat32SharedArray(nVox)
|
|
112
|
+
: new Float32Array(nVox);
|
|
113
|
+
break;
|
|
114
|
+
case 'Int16Array':
|
|
115
|
+
bitsAllocated = 16;
|
|
116
|
+
checkCacheAvailable(bitsAllocated, nVox);
|
|
117
|
+
scalarData = useSharedArrayBuffer
|
|
118
|
+
? createInt16SharedArray(nVox)
|
|
119
|
+
: new Int16Array(nVox);
|
|
120
|
+
break;
|
|
121
|
+
case 'Int8Array':
|
|
122
|
+
bitsAllocated = 8;
|
|
123
|
+
checkCacheAvailable(bitsAllocated, nVox);
|
|
124
|
+
scalarData = useSharedArrayBuffer
|
|
125
|
+
? createInt16SharedArray(nVox)
|
|
126
|
+
: new Int16Array(nVox);
|
|
127
|
+
break;
|
|
128
|
+
case 'Uint16Array':
|
|
129
|
+
bitsAllocated = 16;
|
|
130
|
+
checkCacheAvailable(bitsAllocated, nVox);
|
|
131
|
+
scalarData = useSharedArrayBuffer
|
|
132
|
+
? createUint16SharedArray(nVox)
|
|
133
|
+
: new Uint16Array(nVox);
|
|
134
|
+
break;
|
|
135
|
+
case 'Uint8Array':
|
|
136
|
+
bitsAllocated = 8;
|
|
137
|
+
checkCacheAvailable(bitsAllocated, nVox);
|
|
138
|
+
scalarData = useSharedArrayBuffer
|
|
139
|
+
? createUint8SharedArray(nVox)
|
|
140
|
+
: new Uint8Array(nVox);
|
|
141
|
+
break;
|
|
142
|
+
default:
|
|
143
|
+
throw new Error(`TypedArray ${types} is not yet supported`);
|
|
144
|
+
}
|
|
145
|
+
scalarData.set(niiBuffer);
|
|
146
|
+
return scalarData;
|
|
10
147
|
}
|
|
11
|
-
//# sourceMappingURL=modalityScaleNifti.js.map
|
|
@@ -41,4 +41,3 @@ const NIFTI1_HEADER_ENDOFFILE_STRING = '0000';
|
|
|
41
41
|
const NIFTI1_ALIGNED_ANAT = 2;
|
|
42
42
|
const NIFTI1_XYZT_UNITS_UNKNOWN = 0;
|
|
43
43
|
export { NIFTI_TYPE_UINT8, NIFTI_TYPE_INT16, NIFTI_TYPE_INT32, NIFTI_TYPE_FLOAT32, NIFTI_TYPE_COMPLEX64, NIFTI_TYPE_FLOAT64, NIFTI_TYPE_RGB24, NIFTI_TYPE_INT8, NIFTI_TYPE_UINT16, NIFTI_TYPE_UINT32, NIFTI_TYPE_INT64, NIFTI_TYPE_UINT64, NIFTI_TYPE_FLOAT128, NIFTI_TYPE_COMPLEX128, NIFTI_TYPE_COMPLEX256, NIFTI_TYPE_RGBA32, NIFTI2_HEADER_TOTAL_LENGTH_BYTES, NIFTI2_HEADER_TOTAL_LENGTH_BITS, NIFTI2_HEADER_MAGIC_LENGTH_BYTES, NIFTI2_HEADER_DESCRIPTION_LENGTH_BYTES, NIFTI2_HEADER_AUX_FILE_LENGTH_BYTES, NIFTI2_HEADER_INTENT_NAME_LENGTH_BYTES, NIFTI2_HEADER_DIM_INFO_LENGTH_BYTES, NIFTI2_HEADER_ENDOFFILE_LENGTH_BYTES, NIFTI2_VOX_OFFSET_BYTES, NIFTI2_HEADER_MAGIC_STRING, NIFTI2_HEADER_ENDOFFILE_STRING, NIFTI2_ALIGNED_ANAT, NIFTI2_XYZT_UNITS_UNKNOWN, NIFTI1_HEADER_TOTAL_LENGTH_BYTES, NIFTI1_HEADER_TOTAL_LENGTH_BITS, NIFTI1_HEADER_MAGIC_LENGTH_BYTES, NIFTI1_HEADER_DESCRIPTION_LENGTH_BYTES, NIFTI1_HEADER_AUX_FILE_LENGTH_BYTES, NIFTI1_HEADER_INTENT_NAME_LENGTH_BYTES, NIFTI1_HEADER_DIM_INFO_LENGTH_BYTES, NIFTI1_HEADER_ENDOFFILE_LENGTH_BYTES, NIFTI1_VOX_OFFSET_BYTES, NIFTI1_HEADER_MAGIC_STRING, NIFTI1_HEADER_ENDOFFILE_STRING, NIFTI1_ALIGNED_ANAT, NIFTI1_XYZT_UNITS_UNKNOWN, };
|
|
44
|
-
//# sourceMappingURL=niftiConstants.js.map
|
package/dist/esm/index.js
CHANGED