@niivue/niivue 0.12.2 → 0.13.2
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/README.md +4 -2
- package/dist/assets/worker.9df7e894.js +1 -0
- package/dist/niivue.es.js +113 -5
- package/dist/niivue.umd.js +22 -22
- package/package.json +11 -11
- package/src/heap-verifier.js +51 -0
- package/src/index.html +3 -3
- package/src/linear-memory.js +33 -0
- package/src/niivue.js +107 -5
- package/src/nvimage.js +59 -0
- package/src/process-image.wasm +0 -0
- package/src/wasm/core.c +959 -0
- package/src/wasm/core.h +187 -0
- package/src/wasm/core32.c +3 -0
- package/src/wasm/core32.h +17 -0
- package/src/wasm/core64.c +3 -0
- package/src/wasm/core64.h +18 -0
- package/src/wasm/coreFLT.c +6285 -0
- package/src/wasm/nifti2_wasm.c +27 -0
- package/src/wasm/nifti2_wasm.h +76 -0
- package/src/wasm/walloc.c +466 -0
- package/src/worker.js +72 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@niivue/niivue",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.2",
|
|
4
4
|
"description": "minimal webgl2 nifti image viewer",
|
|
5
5
|
"main": "./src/niivue.js",
|
|
6
6
|
"unpkg": "./dist/niivue.umd.js",
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"demo-win": "npm run build-win && npx http-server demos/",
|
|
13
13
|
"copy-test": "cp ./dist/niivue.umd.js ./tests/niivue.umd.js",
|
|
14
14
|
"copy-test-win": "copy .\\dist\\niivue.umd.js .\\tests\\niivue.umd.js",
|
|
15
|
-
"copy-demo": "cp ./dist
|
|
15
|
+
"copy-demo": "cp -r ./dist/* ./demos/",
|
|
16
16
|
"copy-demo-win": "copy .\\dist\\niivue.umd.js .\\demos\\niivue.umd.js",
|
|
17
17
|
"test": "npm run build && jest --maxWorkers=1",
|
|
18
18
|
"test-win": "npm run build-win && jest --maxWorkers=1",
|
|
@@ -42,22 +42,22 @@
|
|
|
42
42
|
},
|
|
43
43
|
"homepage": "https://github.com/niivue/niivue#readme",
|
|
44
44
|
"dependencies": {
|
|
45
|
-
"gl-matrix": "^3.3
|
|
45
|
+
"gl-matrix": "^3.4.3",
|
|
46
46
|
"nifti-reader-js": "^0.5.4",
|
|
47
|
-
"rxjs": "^7.
|
|
47
|
+
"rxjs": "^7.4.0",
|
|
48
48
|
"uuid": "^8.3.2"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
|
-
"clean-jsdoc-theme": "^3.
|
|
52
|
-
"eslint": "^8.
|
|
51
|
+
"clean-jsdoc-theme": "^3.3.1",
|
|
52
|
+
"eslint": "^8.4.1",
|
|
53
53
|
"express": "^4.17.1",
|
|
54
|
-
"http-server": "^0.
|
|
55
|
-
"jest": "^27.
|
|
54
|
+
"http-server": "^14.0.0",
|
|
55
|
+
"jest": "^27.4.4",
|
|
56
56
|
"jest-image-snapshot": "^4.5.1",
|
|
57
|
-
"jest-puppeteer": "^
|
|
57
|
+
"jest-puppeteer": "^6.0.2",
|
|
58
58
|
"jsdoc": "^3.6.7",
|
|
59
|
-
"prettier": "^2.
|
|
59
|
+
"prettier": "^2.5.1",
|
|
60
60
|
"puppeteer": "^9.1.1",
|
|
61
|
-
"vite": "^2.
|
|
61
|
+
"vite": "^2.7.1"
|
|
62
62
|
}
|
|
63
63
|
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
let granule_size = 8;
|
|
2
|
+
let bits_per_byte = 8;
|
|
3
|
+
let bits_per_byte_log2 = 3;
|
|
4
|
+
|
|
5
|
+
function assert(c, msg) {
|
|
6
|
+
if (!c) throw new Error(msg);
|
|
7
|
+
}
|
|
8
|
+
function power_of_two(x) {
|
|
9
|
+
return x && (x & (x - 1)) == 0;
|
|
10
|
+
}
|
|
11
|
+
function assert_power_of_two(x) {
|
|
12
|
+
assert(power_of_two(x), `not power of two: ${x}`);
|
|
13
|
+
}
|
|
14
|
+
function aligned(x, y) {
|
|
15
|
+
assert_power_of_two(y);
|
|
16
|
+
return (x & (y - 1)) == 0;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function assert_aligned(x, y) {
|
|
20
|
+
assert(aligned(x, y), `bad alignment: ${x} % ${y}`);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export class HeapVerifier {
|
|
24
|
+
constructor(maxbytes) {
|
|
25
|
+
this.maxwords = maxbytes / granule_size;
|
|
26
|
+
this.state = new Uint8Array(this.maxwords / bits_per_byte);
|
|
27
|
+
this.allocations = new Map();
|
|
28
|
+
}
|
|
29
|
+
acquire(offset, len) {
|
|
30
|
+
assert_aligned(offset, granule_size);
|
|
31
|
+
for (let i = 0; i < len; i += granule_size) {
|
|
32
|
+
let bit = (offset + i) / granule_size;
|
|
33
|
+
let byte = bit >> bits_per_byte_log2;
|
|
34
|
+
let mask = 1 << (bit & (bits_per_byte - 1));
|
|
35
|
+
assert((this.state[byte] & mask) == 0, "word in use");
|
|
36
|
+
this.state[byte] |= mask;
|
|
37
|
+
}
|
|
38
|
+
this.allocations.set(offset, len);
|
|
39
|
+
}
|
|
40
|
+
release(offset) {
|
|
41
|
+
assert(this.allocations.has(offset));
|
|
42
|
+
let len = this.allocations.get(offset);
|
|
43
|
+
this.allocations.delete(offset);
|
|
44
|
+
for (let i = 0; i < len; i += granule_size) {
|
|
45
|
+
let bit = (offset + i) / granule_size;
|
|
46
|
+
let byte = bit >> bits_per_byte_log2;
|
|
47
|
+
let mask = 1 << (bit & (bits_per_byte - 1));
|
|
48
|
+
this.state[byte] &= ~mask;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
package/src/index.html
CHANGED
|
@@ -51,19 +51,19 @@
|
|
|
51
51
|
<!-- <script type="module" src="./index.js">
|
|
52
52
|
</script> -->
|
|
53
53
|
<script type="module">
|
|
54
|
-
import {Niivue} from './niivue.js'
|
|
54
|
+
import { Niivue } from './niivue.js'
|
|
55
55
|
// console.log(Niivue)
|
|
56
56
|
var volumeList1 = [
|
|
57
57
|
// first item is brackground image
|
|
58
58
|
{
|
|
59
|
-
|
|
60
|
-
url: "https://openneuro.org/crn/datasets/ds002328/snapshots/1.0.0/files/sub-01:anat:sub-01_T1w.nii.gz",
|
|
59
|
+
url: "./mni152.nii.gz",//"./images/RAS.nii.gz", "./images/spm152.nii.gz",
|
|
61
60
|
colorMap: "gray",
|
|
62
61
|
opacity: 1,
|
|
63
62
|
visible: true,
|
|
64
63
|
}
|
|
65
64
|
]
|
|
66
65
|
var nv1 = new Niivue()
|
|
66
|
+
nv1.setRadiologicalConvention(false)
|
|
67
67
|
nv1.attachTo('gl1')
|
|
68
68
|
nv1.loadVolumes(volumeList1)
|
|
69
69
|
nv1.setSliceType(nv1.sliceTypeMultiplanar)
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { HeapVerifier } from "./heap-verifier";
|
|
2
|
+
|
|
3
|
+
export class LinearMemory {
|
|
4
|
+
constructor({ initial = 2048, maximum = 2048 }) {
|
|
5
|
+
this.memory = new WebAssembly.Memory({ initial, maximum });
|
|
6
|
+
this.verifier = new HeapVerifier(maximum * 65536);
|
|
7
|
+
}
|
|
8
|
+
record_malloc(ptr, len) {
|
|
9
|
+
this.verifier.acquire(ptr, len);
|
|
10
|
+
}
|
|
11
|
+
record_free(ptr) {
|
|
12
|
+
this.verifier.release(ptr);
|
|
13
|
+
}
|
|
14
|
+
read_string(offset) {
|
|
15
|
+
let view = new Uint8Array(this.memory.buffer);
|
|
16
|
+
let bytes = [];
|
|
17
|
+
for (let byte = view[offset]; byte; byte = view[++offset]) bytes.push(byte);
|
|
18
|
+
return String.fromCharCode(...bytes);
|
|
19
|
+
}
|
|
20
|
+
log(str) {
|
|
21
|
+
console.log(`wasm log: ${str}`);
|
|
22
|
+
}
|
|
23
|
+
log_i(str, i) {
|
|
24
|
+
console.log(`wasm log: ${str}: ${i}`);
|
|
25
|
+
}
|
|
26
|
+
env() {
|
|
27
|
+
return {
|
|
28
|
+
memory: this.memory,
|
|
29
|
+
wasm_log: (off) => this.log(this.read_string(off)),
|
|
30
|
+
wasm_log_i: (off, i) => this.log_i(this.read_string(off), i),
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
}
|
package/src/niivue.js
CHANGED
|
@@ -29,7 +29,17 @@ import { NVImage } from "./nvimage.js";
|
|
|
29
29
|
export { NVImage } from "./nvimage";
|
|
30
30
|
import defaultFontPNG from "./fonts/Roboto-Regular.png";
|
|
31
31
|
import defaultFontMetrics from "./fonts/Roboto-Regular.json";
|
|
32
|
-
|
|
32
|
+
// import createModule from "./process-image";
|
|
33
|
+
// import init from "./process-image.wasm";
|
|
34
|
+
// import { LinearMemory } from "./linear-memory.js";
|
|
35
|
+
// import workerString from "./worker.js?raw";
|
|
36
|
+
// const workerBlob = new Blob([workerString], { type: "text/javascript" });
|
|
37
|
+
// const workerURL = URL.createObjectURL(workerBlob);
|
|
38
|
+
// const worker = new Worker(workerURL, { type: "classic" });
|
|
39
|
+
import NiiMathWorker from "./worker?worker";
|
|
40
|
+
import { v4 as uuidv4 } from "uuid";
|
|
41
|
+
|
|
42
|
+
var Module;
|
|
33
43
|
/**
|
|
34
44
|
* @class Niivue
|
|
35
45
|
* @description
|
|
@@ -49,6 +59,7 @@ import defaultFontMetrics from "./fonts/Roboto-Regular.json";
|
|
|
49
59
|
* @param {string} [options.clipPlaneHotKey="KeyC"] the keyboard key used to cycle through clip plane orientations. The default is "c"
|
|
50
60
|
* @param {string} [options.viewModeHotKey="KeyV"] the keyboard key used to cycle through view modes. The default is "v"
|
|
51
61
|
* @param {number} [options.keyDebounceTime=50] the keyUp debounce time in milliseconds. The default is 50 ms. You must wait this long before a new hot-key keystroke will be registered by the event listener
|
|
62
|
+
* @param {boolean} [options.isRadiologicalConvention=false] whether or not to use radiological convention in the display
|
|
52
63
|
* @example
|
|
53
64
|
* let niivue = new Niivue({crosshairColor: [0,1,0,0.5], textHeight: 0.5}) // a see-through green crosshair, and larger text labels
|
|
54
65
|
*/
|
|
@@ -67,6 +78,7 @@ export const Niivue = function (options = {}) {
|
|
|
67
78
|
clipPlaneHotKey: "KeyC", // keyboard short cut to activate the clip plane
|
|
68
79
|
viewModeHotKey: "KeyV", // keyboard shortcut to switch view modes
|
|
69
80
|
keyDebounceTime: 50, // default debounce time used in keyup listeners
|
|
81
|
+
isRadiologicalConvention: false,
|
|
70
82
|
};
|
|
71
83
|
|
|
72
84
|
this.canvas = null; // the canvas element on the page
|
|
@@ -117,7 +129,6 @@ export const Niivue = function (options = {}) {
|
|
|
117
129
|
this.volumes = []; // all loaded images. Can add in the ability to push or slice as needed
|
|
118
130
|
this.backTexture = [];
|
|
119
131
|
this.objectsToRender3D = [];
|
|
120
|
-
this.isRadiologicalConvention = false;
|
|
121
132
|
this.volScaleMultiplier = 1;
|
|
122
133
|
this.volScale = [];
|
|
123
134
|
this.vox = [];
|
|
@@ -205,7 +216,6 @@ Niivue.prototype.attachTo = async function (id) {
|
|
|
205
216
|
Niivue.prototype.on = function (event, callback) {
|
|
206
217
|
let knownEvents = Object.keys(this.eventsToSubjects);
|
|
207
218
|
if (knownEvents.indexOf(event) == -1) {
|
|
208
|
-
console.log(`there is no known event ${event}`);
|
|
209
219
|
return;
|
|
210
220
|
}
|
|
211
221
|
let subject = this.eventsToSubjects[event];
|
|
@@ -225,7 +235,6 @@ Niivue.prototype.on = function (event, callback) {
|
|
|
225
235
|
Niivue.prototype.off = function (event) {
|
|
226
236
|
let knownEvents = Object.keys(this.eventsToSubjects);
|
|
227
237
|
if (knownEvents.indexOf(event) == -1) {
|
|
228
|
-
console.log(`there is no known event ${event}`);
|
|
229
238
|
return;
|
|
230
239
|
}
|
|
231
240
|
let nsubs = this.subscriptions.length;
|
|
@@ -779,6 +788,16 @@ Niivue.prototype.dropListener = async function (e) {
|
|
|
779
788
|
}
|
|
780
789
|
};
|
|
781
790
|
|
|
791
|
+
Niivue.prototype.setRadiologicalConvention = function (
|
|
792
|
+
isRadiologicalConvention
|
|
793
|
+
) {
|
|
794
|
+
this.opts.isRadiologicalConvention = isRadiologicalConvention;
|
|
795
|
+
};
|
|
796
|
+
|
|
797
|
+
Niivue.prototype.getRadiologicalConvention = function () {
|
|
798
|
+
return this.opts.isRadiologicalConvention;
|
|
799
|
+
};
|
|
800
|
+
|
|
782
801
|
/**
|
|
783
802
|
* add a new volume to the canvas
|
|
784
803
|
* @param {NVImage} volume the new volume to add to the canvas
|
|
@@ -1343,6 +1362,73 @@ Niivue.prototype.initText = async function () {
|
|
|
1343
1362
|
this.drawLoadingText(this.loadingText);
|
|
1344
1363
|
}; // initText()
|
|
1345
1364
|
|
|
1365
|
+
Niivue.prototype.processImage = function (imageIndex, cmd, isNewLayer = true) {
|
|
1366
|
+
let image = this.volumes[imageIndex].clone();
|
|
1367
|
+
let metadata = image.getImageMetadata();
|
|
1368
|
+
this.worker.postMessage([metadata, image.img.buffer, cmd, isNewLayer]);
|
|
1369
|
+
};
|
|
1370
|
+
|
|
1371
|
+
Niivue.prototype.initWasm = async function () {
|
|
1372
|
+
this.worker = new NiiMathWorker();
|
|
1373
|
+
this.worker.onmessage = (e) => {
|
|
1374
|
+
// find our processed image
|
|
1375
|
+
const id = e.data.id;
|
|
1376
|
+
let processedImage = this.volumes.find((image) => image.id == id);
|
|
1377
|
+
if (!processedImage) {
|
|
1378
|
+
console.log("image not found");
|
|
1379
|
+
return;
|
|
1380
|
+
}
|
|
1381
|
+
|
|
1382
|
+
const isNewLayer = e.data.isNewLayer;
|
|
1383
|
+
if (isNewLayer) {
|
|
1384
|
+
processedImage = processedImage.clone();
|
|
1385
|
+
processedImage.id = uuidv4();
|
|
1386
|
+
}
|
|
1387
|
+
|
|
1388
|
+
let imageBytes = e.data.imageBytes;
|
|
1389
|
+
|
|
1390
|
+
switch (processedImage.hdr.datatypeCode) {
|
|
1391
|
+
case processedImage.DT_UNSIGNED_CHAR:
|
|
1392
|
+
processedImage.img = new Uint8Array(imageBytes);
|
|
1393
|
+
break;
|
|
1394
|
+
case processedImage.DT_SIGNED_SHORT:
|
|
1395
|
+
processedImage.img = new Int16Array(imageBytes);
|
|
1396
|
+
break;
|
|
1397
|
+
case processedImage.DT_FLOAT:
|
|
1398
|
+
processedImage.img = new Float32Array(imageBytes);
|
|
1399
|
+
break;
|
|
1400
|
+
case processedImage.DT_DOUBLE:
|
|
1401
|
+
throw "datatype " + processedImage.hdr.datatypeCode + " not supported";
|
|
1402
|
+
case processedImage.DT_RGB:
|
|
1403
|
+
processedImage.img = new Uint8Array(imageBytes);
|
|
1404
|
+
break;
|
|
1405
|
+
case processedImage.DT_UINT16:
|
|
1406
|
+
processedImage.img = new Uint16Array(imageBytes);
|
|
1407
|
+
break;
|
|
1408
|
+
case processedImage.DT_RGBA32:
|
|
1409
|
+
processedImage.img = new Uint8Array(imageBytes);
|
|
1410
|
+
break;
|
|
1411
|
+
default:
|
|
1412
|
+
throw "datatype " + processedImage.hdr.datatypeCode + " not supported";
|
|
1413
|
+
}
|
|
1414
|
+
|
|
1415
|
+
// recalculate
|
|
1416
|
+
processedImage.trustCalMinMax = false;
|
|
1417
|
+
processedImage.calMinMax();
|
|
1418
|
+
|
|
1419
|
+
let imageIndex = this.volumes.length;
|
|
1420
|
+
if (isNewLayer) {
|
|
1421
|
+
this.setVolume(processedImage, this.volumes.length);
|
|
1422
|
+
} else {
|
|
1423
|
+
imageIndex = this.volumes.indexOf(processedImage);
|
|
1424
|
+
}
|
|
1425
|
+
this.refreshLayers(processedImage, imageIndex, this.volumes.length);
|
|
1426
|
+
this.drawScene();
|
|
1427
|
+
|
|
1428
|
+
this.updateGLVolume();
|
|
1429
|
+
};
|
|
1430
|
+
};
|
|
1431
|
+
|
|
1346
1432
|
// not included in public docs
|
|
1347
1433
|
Niivue.prototype.init = async function () {
|
|
1348
1434
|
//initial setup: only at the startup of the component
|
|
@@ -1353,6 +1439,8 @@ Niivue.prototype.init = async function () {
|
|
|
1353
1439
|
// console.log("gpu vendor: ", vendor);
|
|
1354
1440
|
// console.log("gpu renderer: ", renderer);
|
|
1355
1441
|
// await this.loadFont()
|
|
1442
|
+
await this.initWasm();
|
|
1443
|
+
|
|
1356
1444
|
this.gl.enable(this.gl.CULL_FACE);
|
|
1357
1445
|
this.gl.cullFace(this.gl.FRONT);
|
|
1358
1446
|
this.gl.enable(this.gl.BLEND);
|
|
@@ -1941,6 +2029,20 @@ Niivue.prototype.colorMaps = function (sort = true) {
|
|
|
1941
2029
|
return sort === true ? cm.sort() : cm;
|
|
1942
2030
|
};
|
|
1943
2031
|
|
|
2032
|
+
/**
|
|
2033
|
+
* update the colormap of an image given its ID
|
|
2034
|
+
* @param {string} id the ID of the NVImage
|
|
2035
|
+
* @param {string} colorMap the name of the colorMap to use
|
|
2036
|
+
* @example
|
|
2037
|
+
* niivue = new Niivue()
|
|
2038
|
+
* niivue.setColorMap(someImage.id, 'red')
|
|
2039
|
+
*/
|
|
2040
|
+
Niivue.prototype.setColorMap = function (id, colorMap) {
|
|
2041
|
+
let idx = this.getVolumeIndexByID(id);
|
|
2042
|
+
this.volumes[idx].colorMap = colorMap;
|
|
2043
|
+
this.updateGLVolume();
|
|
2044
|
+
};
|
|
2045
|
+
|
|
1944
2046
|
// not included in public docs
|
|
1945
2047
|
Niivue.prototype.colormapFromKey = function (name) {
|
|
1946
2048
|
let availMaps = this.colorMaps();
|
|
@@ -2342,7 +2444,7 @@ Niivue.prototype.draw2D = function (leftTopWidthHeight, axCorSag) {
|
|
|
2342
2444
|
this.scene.crosshairPos[0],
|
|
2343
2445
|
]; //sagittal: width=j, height=k, slice=i
|
|
2344
2446
|
let isMirrorLR =
|
|
2345
|
-
this.isRadiologicalConvention && axCorSag < this.sliceTypeSagittal;
|
|
2447
|
+
this.opts.isRadiologicalConvention && axCorSag < this.sliceTypeSagittal;
|
|
2346
2448
|
this.sliceShader.use(this.gl);
|
|
2347
2449
|
this.gl.uniform1f(this.sliceShader.uniforms["opacity"], this.backOpacity);
|
|
2348
2450
|
this.gl.uniform1i(this.sliceShader.uniforms["axCorSag"], axCorSag);
|
package/src/nvimage.js
CHANGED
|
@@ -535,6 +535,7 @@ NVImage.loadFromFile = async function (
|
|
|
535
535
|
*/
|
|
536
536
|
NVImage.prototype.clone = function () {
|
|
537
537
|
let clonedImage = new NVImage();
|
|
538
|
+
clonedImage.id = this.id;
|
|
538
539
|
clonedImage.hdr = Object.assign({}, this.hdr);
|
|
539
540
|
clonedImage.img = this.img.slice();
|
|
540
541
|
clonedImage.calculateRAS();
|
|
@@ -552,6 +553,55 @@ NVImage.prototype.zeroImage = function () {
|
|
|
552
553
|
this.img.fill(0);
|
|
553
554
|
};
|
|
554
555
|
|
|
556
|
+
/**
|
|
557
|
+
* Image M.
|
|
558
|
+
* @typedef {Object} NVImage~MetaData
|
|
559
|
+
* @property {uuidv4} id - unique if of image
|
|
560
|
+
* @property {number} datatypeCode - data type
|
|
561
|
+
* @property {number} nx - number of columns
|
|
562
|
+
* @property {number} ny - number of rows
|
|
563
|
+
* @property {number} nz - number of slices
|
|
564
|
+
* @property {number} nt - number of volumes
|
|
565
|
+
* @property {number} dx - space between columns
|
|
566
|
+
* @property {number} dy - space between rows
|
|
567
|
+
* @property {number} dz - space between slices
|
|
568
|
+
* @property {number} dt - time between volumes
|
|
569
|
+
* @property {number} bpx - bits per voxel
|
|
570
|
+
*/
|
|
571
|
+
|
|
572
|
+
/**
|
|
573
|
+
* get nifti specific metadata about the image
|
|
574
|
+
* @returns {NVImage~Metadata} - {@link NVImage~Metadata}
|
|
575
|
+
*/
|
|
576
|
+
NVImage.prototype.getImageMetadata = function () {
|
|
577
|
+
const id = this.id;
|
|
578
|
+
const datatypeCode = this.hdr.datatypeCode;
|
|
579
|
+
const dims = this.hdr.dims;
|
|
580
|
+
const nx = dims[1];
|
|
581
|
+
const ny = dims[2];
|
|
582
|
+
const nz = dims[3];
|
|
583
|
+
const nt = Math.max(1, dims[4]);
|
|
584
|
+
const pixDims = this.hdr.pixDims;
|
|
585
|
+
const dx = pixDims[1];
|
|
586
|
+
const dy = pixDims[2];
|
|
587
|
+
const dz = pixDims[3];
|
|
588
|
+
const dt = pixDims[4];
|
|
589
|
+
const bpv = Math.floor(this.hdr.numBitsPerVoxel / 8);
|
|
590
|
+
|
|
591
|
+
return {
|
|
592
|
+
id,
|
|
593
|
+
datatypeCode,
|
|
594
|
+
nx,
|
|
595
|
+
ny,
|
|
596
|
+
nz,
|
|
597
|
+
nt,
|
|
598
|
+
dx,
|
|
599
|
+
dy,
|
|
600
|
+
dz,
|
|
601
|
+
dt,
|
|
602
|
+
bpv,
|
|
603
|
+
};
|
|
604
|
+
};
|
|
555
605
|
/**
|
|
556
606
|
* a factory function to make a zero filled image given a NVImage as a reference
|
|
557
607
|
* @param {NVImage} nvImage an existing NVImage as a reference
|
|
@@ -565,3 +615,12 @@ NVImage.zerosLike = function (nvImage) {
|
|
|
565
615
|
zeroClone.zeroImage();
|
|
566
616
|
return zeroClone;
|
|
567
617
|
};
|
|
618
|
+
|
|
619
|
+
String.prototype.getBytes = function () {
|
|
620
|
+
let bytes = [];
|
|
621
|
+
for (var i = 0; i < this.length; i++) {
|
|
622
|
+
bytes.push(this.charCodeAt(i));
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
return bytes;
|
|
626
|
+
};
|
|
Binary file
|