@niivue/niivue
Version:
minimal webgl2 nifti image viewer
3,818 lines (3,807 loc) • 1.5 MB
JavaScript
var __defProp = Object.defineProperty;
var __typeError = (msg) => {
throw TypeError(msg);
};
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
// src/niivue/index.ts
import { mat4 as mat418, vec2, vec3 as vec324, vec4 as vec417 } from "gl-matrix";
// package.json
var package_default = {
name: "@niivue/niivue",
version: "0.69.0",
description: "minimal webgl2 nifti image viewer",
types: "./build/niivue/index.d.ts",
main: "./build/niivue/index.js",
type: "module",
unpkg: "./dist/index.min.js",
module: "./build/niivue/index.js",
exports: {
".": {
import: "./build/niivue/index.js",
types: "./build/niivue/index.d.ts"
},
"./drawing": {
import: "./build/drawing/index.js",
types: "./build/drawing/index.d.ts"
},
"./utils": {
import: "./build/utils/index.js",
types: "./build/utils/index.d.ts"
},
"./min": {
import: "./build/index.min.js"
}
},
scripts: {
dev: "vite",
"build:umd": "vite build --config vite.config.js --base=./ && vite build --config vite.config_inject.js --base=./",
build: "tsup --config tsup.config.ts && npm run build:forTests && npm run build:min && npm run build:umd",
"build:forTests": "tsup --config tsup.config.tests.ts && npm run build:mindemos",
"build:min": "node bundle.js",
"build:mindemos": "node bundleForDemos.js",
demo: "npm run build:forTests && rm -rf demos/dist && cp -r dist demos/dist && npx http-server demos/ --cors",
"demo-win": "npm run build && npx http-server demos/",
test: "npm run build:forTests && npm run test:unit && jest --maxWorkers=1",
"test-win": "npm run build-win && jest",
"test-playwright": 'npx playwright test --grep-invert "niivue demo file:"',
"test-demos": "npx playwright test playwright/e2e/test.demos.spec.ts",
docs: "typedoc && rm -rf ../docs/docs/api && cp -r devdocs ../docs/docs/api",
"test:unit": "vitest --run --coverage",
"serve-docs": "npx http-server devdocs",
pub: "npm run build && npm publish --access public",
lint: "eslint . --ext .ts",
"lint:ts": "tsc --noEmit",
"lint:fix": "eslint --fix . --ext .ts",
"lint:debug": "DEBUG=eslint:cli-engine eslint . --ext .ts",
"pretest-playwright": "npm run build:forTests && node preplaywrighttest.cjs && tsc --incremental -p playwright/e2e/tsconfig.json",
"pretest-demos": "npm run build:forTests && node preplaywrighttest.cjs && tsc --incremental -p playwright/e2e/tsconfig.json"
},
files: [
"src",
"build",
"dist"
],
repository: {
type: "git",
url: "git+https://github.com/niivue/niivue.git"
},
keywords: [
"niivue",
"webgl2",
"nifti",
"image",
"viewer"
],
author: "niivue authors",
license: "BSD-2-Clause",
bugs: {
url: "https://github.com/niivue/niivue/issues"
},
homepage: "https://github.com/niivue/niivue#readme",
dependencies: {
"@lukeed/uuid": "^2.0.1",
"@ungap/structured-clone": "^1.2.0",
"array-equal": "^1.0.2",
fflate: "^0.8.2",
"gl-matrix": "^3.4.3",
"nifti-reader-js": "^0.8.0",
zarrita: "^0.5.0"
},
devDependencies: {
"@playwright/test": "^1.45.2",
"@rollup/plugin-commonjs": "^26.0.1",
"@types/array-equal": "^1.0.2",
"@types/node": "^20.14.11",
"@types/ungap__structured-clone": "^1.2.0",
"@typescript-eslint/eslint-plugin": "^7.16.1",
"@typescript-eslint/parser": "^7.16.1",
"@vitest/coverage-v8": "^3.1.3",
esbuild: "^0.25.12",
eslint: "^8.57.0",
"eslint-config-prettier": "^9.1.0",
"eslint-config-standard": "^17.1.0",
"eslint-plugin-prettier": "^5.2.1",
"eslint-plugin-tsdoc": "^0.3.0",
express: "^4.19.2",
"happy-dom": "^20.0.11",
"http-server": "^14.1.1",
prettier: "^3.3.3",
"regenerator-runtime": "^0.14.1",
terser: "^5.31.3",
tsup: "^8.1.2",
typedoc: "^0.28.5",
"typedoc-docusaurus-theme": "^1.4.0",
"typedoc-plugin-markdown": "^4.7.0",
typescript: "^5.5.3",
vite: "^7.2.7",
vitest: "^3.1.3"
},
optionalDependencies: {
"@rollup/rollup-linux-x64-gnu": "^4.18.1"
}
};
// src/niivue/texture-constants.ts
var TEXTURE_CONSTANTS = {
TEXTURE0_BACK_VOL: 33984,
TEXTURE1_COLORMAPS: 33985,
TEXTURE2_OVERLAY_VOL: 33986,
TEXTURE3_FONT: 33987,
TEXTURE5_MATCAP: 33989,
TEXTURE6_GRADIENT: 33990,
TEXTURE7_DRAW: 33991,
TEXTURE8_PAQD: 33992,
TEXTURE10_DRAW_SMOOTH: 33994,
// subsequent textures only used transiently
_TEXTURE8_GRADIENT_TEMP: 33992,
TEXTURE9_ORIENT: 33993,
TEXTURE11_GC_BACK: 33995,
TEXTURE12_GC_STRENGTH0: 33996,
TEXTURE13_GC_STRENGTH1: 33997,
TEXTURE14_GC_LABEL0: 33998,
TEXTURE15_GC_LABEL1: 33999
};
// src/orientCube.ts
var orientCube = new Float32Array([
-1,
-1,
-1,
0.28,
0.28,
0.28,
-1,
-1,
-1,
0.28,
0.28,
0.28,
-1,
1,
-1,
0.28,
0.28,
0.28,
1,
-1,
-1,
0.28,
0.28,
0.28,
1,
1,
-1,
0.28,
0.28,
0.28,
1,
1,
-1,
0.28,
0.28,
0.28,
-1,
-1,
1,
0.8,
0.8,
0.8,
-1,
-1,
1,
0.8,
0.8,
0.8,
1,
-1,
1,
0.8,
0.8,
0.8,
-1,
1,
1,
0.8,
0.8,
0.8,
1,
1,
1,
0.8,
0.8,
0.8,
1,
1,
1,
0.8,
0.8,
0.8,
-1,
1,
-1,
0,
0,
0.74,
-1,
1,
-1,
0,
0,
0.74,
-1,
1,
1,
0,
0,
0.74,
1,
1,
-1,
0,
0,
0.74,
1,
1,
1,
0,
0,
0.74,
1,
1,
1,
0,
0,
0.74,
-1,
-1,
-1,
0.42,
0,
0.42,
-1,
-1,
-1,
0.42,
0,
0.42,
1,
-1,
-1,
0.42,
0,
0.42,
-1,
-1,
1,
0.42,
0,
0.42,
1,
-1,
1,
0.42,
0,
0.42,
1,
-1,
1,
0.42,
0,
0.42,
-1,
-1,
-1,
0.64,
0,
0,
-1,
-1,
-1,
0.64,
0,
0,
-1,
-1,
1,
0.64,
0,
0,
-1,
1,
-1,
0.64,
0,
0,
-1,
1,
1,
0.64,
0,
0,
-1,
1,
1,
0.64,
0,
0,
1,
-1,
-1,
0,
0.5,
0,
1,
-1,
-1,
0,
0.5,
0,
1,
1,
-1,
0,
0.5,
0,
1,
-1,
1,
0,
0.5,
0,
1,
1,
1,
0,
0.5,
0,
1,
1,
1,
0,
0.5,
0,
// P
-0.45,
1,
-0.8,
0,
0,
0,
-0.45,
1,
-0.8,
0,
0,
0,
-0.45,
1,
0.8,
0,
0,
0,
-0.25,
1,
-0.8,
0,
0,
0,
-0.25,
1,
0.8,
0,
0,
0,
-0.25,
1,
0.8,
0,
0,
0,
-0.25,
1,
0.6,
0,
0,
0,
-0.25,
1,
0.6,
0,
0,
0,
-0.25,
1,
0.8,
0,
0,
0,
0.45,
1,
0.6,
0,
0,
0,
0.25,
1,
0.8,
0,
0,
0,
0.25,
1,
0.8,
0,
0,
0,
0.25,
1,
0.1,
0,
0,
0,
0.25,
1,
0.1,
0,
0,
0,
0.25,
1,
0.6,
0,
0,
0,
0.45,
1,
0.1,
0,
0,
0,
0.45,
1,
0.6,
0,
0,
0,
0.45,
1,
0.6,
0,
0,
0,
-0.25,
1,
-0.1,
0,
0,
0,
-0.25,
1,
-0.1,
0,
0,
0,
-0.25,
1,
0.1,
0,
0,
0,
0.25,
1,
-0.1,
0,
0,
0,
0.45,
1,
0.1,
0,
0,
0,
0.45,
1,
0.1,
0,
0,
0,
// A
0.45,
-1,
-0.8,
0,
0,
0,
0.45,
-1,
-0.8,
0,
0,
0,
0.05,
-1,
0.8,
0,
0,
0,
0.25,
-1,
-0.8,
0,
0,
0,
-0.15,
-1,
0.8,
0,
0,
0,
-0.15,
-1,
0.8,
0,
0,
0,
-0.25,
-1,
-0.8,
0,
0,
0,
-0.25,
-1,
-0.8,
0,
0,
0,
0.05,
-1,
0.8,
0,
0,
0,
-0.45,
-1,
-0.8,
0,
0,
0,
-0.15,
-1,
0.8,
0,
0,
0,
-0.15,
-1,
0.8,
0,
0,
0,
0.13,
-1,
-0.3,
0,
0,
0,
0.13,
-1,
-0.3,
0,
0,
0,
0.07,
-1,
-0.1,
0,
0,
0,
-0.33,
-1,
-0.3,
0,
0,
0,
-0.27,
-1,
-0.1,
0,
0,
0,
-0.27,
-1,
-0.1,
0,
0,
0,
// S
-0.45,
0.6,
1,
0,
0,
0,
-0.45,
0.6,
1,
0,
0,
0,
-0.45,
0.4,
1,
0,
0,
0,
-0.25,
0.8,
1,
0,
0,
0,
-0.25,
0.4,
1,
0,
0,
0,
-0.25,
0.4,
1,
0,
0,
0,
-0.25,
0.8,
1,
0,
0,
0,
-0.25,
0.8,
1,
0,
0,
0,
-0.25,
0.6,
1,
0,
0,
0,
0.25,
0.8,
1,
0,
0,
0,
0.45,
0.6,
1,
0,
0,
0,
0.45,
0.6,
1,
0,
0,
0,
0.25,
0.8,
1,
0,
0,
0,
0.25,
0.8,
1,
0,
0,
0,
0.25,
-0.1,
1,
0,
0,
0,
0.45,
0.6,
1,
0,
0,
0,
0.45,
0.1,
1,
0,
0,
0,
0.45,
0.1,
1,
0,
0,
0,
-0.25,
0.1,
1,
0,
0,
0,
-0.25,
0.1,
1,
0,
0,
0,
-0.45,
-0.1,
1,
0,
0,
0,
0.25,
0.1,
1,
0,
0,
0,
0.25,
-0.1,
1,
0,
0,
0,
0.25,
-0.1,
1,
0,
0,
0,
-0.45,
-0.1,
1,
0,
0,
0,
-0.45,
-0.1,
1,
0,
0,
0,
-0.45,
-0.6,
1,
0,
0,
0,
-0.25,
-0.1,
1,
0,
0,
0,
-0.25,
-0.8,
1,
0,
0,
0,
-0.25,
-0.8,
1,
0,
0,
0,
-0.25,
-0.6,
1,
0,
0,
0,
-0.25,
-0.6,
1,
0,
0,
0,
-0.25,
-0.8,
1,
0,
0,
0,
0.45,
-0.6,
1,
0,
0,
0,
0.25,
-0.8,
1,
0,
0,
0,
0.25,
-0.8,
1,
0,
0,
0,
0.25,
-0.4,
1,
0,
0,
0,
0.25,
-0.4,
1,
0,
0,
0,
0.25,
-0.6,
1,
0,
0,
0,
0.45,
-0.4,
1,
0,
0,
0,
0.45,
-0.6,
1,
0,
0,
0,
0.45,
-0.6,
1,
0,
0,
0,
// I
-0.1,
-0.8,
-1,
0,
0,
0,
-0.1,
-0.8,
-1,
0,
0,
0,
-0.1,
0.8,
-1,
0,
0,
0,
0.1,
-0.8,
-1,
0,
0,
0,
0.1,
0.8,
-1,
0,
0,
0,
0.1,
0.8,
-1,
0,
0,
0,
// L
-1,
-0.45,
-0.8,
0,
0,
0,
-1,
-0.45,
-0.8,
0,
0,
0,
-1,
-0.45,
0.8,
0,
0,
0,
-1,
-0.25,
-0.8,
0,
0,
0,
-1,
-0.25,
0.8,
0,
0,
0,
-1,
-0.25,
0.8,
0,
0,
0,
-1,
-0.25,
-0.8,
0,
0,
0,
-1,
-0.25,
-0.8,
0,
0,
0,
-1,
-0.25,
-0.6,
0,
0,
0,
-1,
0.45,
-0.8,
0,
0,
0,
-1,
0.45,
-0.6,
0,
0,
0,
-1,
0.45,
-0.6,
0,
0,
0,
// R
1,
0.45,
-0.8,
0,
0,
0,
1,
0.45,
-0.8,
0,
0,
0,
1,
0.45,
0.8,
0,
0,
0,
1,
0.25,
-0.8,
0,
0,
0,
1,
0.25,
0.8,
0,
0,
0,
1,
0.25,
0.8,
0,
0,
0,
1,
0.25,
0.6,
0,
0,
0,
1,
0.25,
0.6,
0,
0,
0,
1,
0.25,
0.8,
0,
0,
0,
1,
-0.45,
0.6,
0,
0,
0,
1,
-0.25,
0.8,
0,
0,
0,
1,
-0.25,
0.8,
0,
0,
0,
1,
-0.25,
0.1,
0,
0,
0,
1,
-0.25,
0.1,
0,
0,
0,
1,
-0.25,
0.6,
0,
0,
0,
1,
-0.45,
0.1,
0,
0,
0,
1,
-0.45,
0.6,
0,
0,
0,
1,
-0.45,
0.6,
0,
0,
0,
1,
0.25,
-0.1,
0,
0,
0,
1,
0.25,
-0.1,
0,
0,
0,
1,
0.25,
0.1,
0,
0,
0,
1,
-0.25,
-0.1,
0,
0,
0,
1,
-0.45,
0.1,
0,
0,
0,
1,
-0.45,
0.1,
0,
0,
0,
1,
-0.25,
-0.8,
0,
0,
0,
1,
-0.25,
-0.8,
0,
0,
0,
1,
-0.05,
-0.1,
0,
0,
0,
1,
-0.45,
-0.8,
0,
0,
0,
1,
-0.25,
-0.1,
0,
0,
0,
1,
-0.25,
-0.1,
0,
0,
0
]);
// src/niivue-object3D.ts
import { mat4, vec3 } from "gl-matrix";
var _NiivueObject3D = class _NiivueObject3D {
constructor(id, vertexBuffer, mode, indexCount, indexBuffer = null, vao = null) {
__publicField(this, "sphereIdx", []);
__publicField(this, "sphereVtx", []);
__publicField(this, "renderShaders", []);
__publicField(this, "isVisible", true);
__publicField(this, "isPickable", true);
__publicField(this, "vertexBuffer");
__publicField(this, "indexCount");
__publicField(this, "indexBuffer");
__publicField(this, "vao");
__publicField(this, "mode");
__publicField(this, "glFlags", 0);
__publicField(this, "id");
__publicField(this, "colorId");
__publicField(this, "modelMatrix", mat4.create());
__publicField(this, "scale", [1, 1, 1]);
__publicField(this, "position", [0, 0, 0]);
__publicField(this, "rotation", [0, 0, 0]);
__publicField(this, "rotationRadians", 0);
__publicField(this, "extentsMin", []);
__publicField(this, "extentsMax", []);
// TODO needed through NVImage
__publicField(this, "furthestVertexFromOrigin");
__publicField(this, "originNegate");
__publicField(this, "fieldOfViewDeObliqueMM");
// TODO needed through crosshairs in NiiVue
__publicField(this, "mm");
this.vertexBuffer = vertexBuffer;
this.indexCount = indexCount;
this.indexBuffer = indexBuffer;
this.vao = vao;
this.mode = mode;
this.id = id;
this.colorId = [(id >> 0 & 255) / 255, (id >> 8 & 255) / 255, (id >> 16 & 255) / 255, (id >> 24 & 255) / 255];
}
};
__publicField(_NiivueObject3D, "BLEND", 1);
__publicField(_NiivueObject3D, "CULL_FACE", 2);
__publicField(_NiivueObject3D, "CULL_FRONT", 4);
__publicField(_NiivueObject3D, "CULL_BACK", 8);
__publicField(_NiivueObject3D, "ENABLE_DEPTH_TEST", 16);
__publicField(_NiivueObject3D, "generateCrosshairs", function(gl, id, xyzMM, xyzMin, xyzMax, radius, sides = 20, gap = 0) {
const geometry = _NiivueObject3D.generateCrosshairsGeometry(gl, xyzMM, xyzMin, xyzMax, radius, sides, gap);
return new _NiivueObject3D(id, geometry.vertexBuffer, gl.TRIANGLES, geometry.indexCount, geometry.indexBuffer, geometry.vao);
});
// not included in public docs
__publicField(_NiivueObject3D, "generateCrosshairsGeometry", function(gl, xyzMM, xyzMin, xyzMax, radius, sides = 20, gap = 0) {
const vertices = [];
const indices = [];
const gapX = radius * gap;
if (gapX <= 0) {
let start = vec3.fromValues(xyzMin[0], xyzMM[1], xyzMM[2]);
let dest = vec3.fromValues(xyzMax[0], xyzMM[1], xyzMM[2]);
_NiivueObject3D.makeCylinder(vertices, indices, start, dest, radius, sides);
start = vec3.fromValues(xyzMM[0], xyzMin[1], xyzMM[2]);
dest = vec3.fromValues(xyzMM[0], xyzMax[1], xyzMM[2]);
_NiivueObject3D.makeCylinder(vertices, indices, start, dest, radius, sides);
start = vec3.fromValues(xyzMM[0], xyzMM[1], xyzMin[2]);
dest = vec3.fromValues(xyzMM[0], xyzMM[1], xyzMax[2]);
_NiivueObject3D.makeCylinder(vertices, indices, start, dest, radius, sides);
} else {
let start = vec3.fromValues(xyzMin[0], xyzMM[1], xyzMM[2]);
let dest = vec3.fromValues(xyzMM[0] - gapX, xyzMM[1], xyzMM[2]);
_NiivueObject3D.makeCylinder(vertices, indices, start, dest, radius, sides, false);
start = vec3.fromValues(xyzMM[0] + gapX, xyzMM[1], xyzMM[2]);
dest = vec3.fromValues(xyzMax[0], xyzMM[1], xyzMM[2]);
_NiivueObject3D.makeCylinder(vertices, indices, start, dest, radius, sides, false);
start = vec3.fromValues(xyzMM[0], xyzMin[1], xyzMM[2]);
dest = vec3.fromValues(xyzMM[0], xyzMM[1] - gapX, xyzMM[2]);
_NiivueObject3D.makeCylinder(vertices, indices, start, dest, radius, sides, false);
start = vec3.fromValues(xyzMM[0], xyzMM[1] + gapX, xyzMM[2]);
dest = vec3.fromValues(xyzMM[0], xyzMax[1], xyzMM[2]);
_NiivueObject3D.makeCylinder(vertices, indices, start, dest, radius, sides, false);
start = vec3.fromValues(xyzMM[0], xyzMM[1], xyzMin[2]);
dest = vec3.fromValues(xyzMM[0], xyzMM[1], xyzMM[2] - gapX);
_NiivueObject3D.makeCylinder(vertices, indices, start, dest, radius, sides, false);
start = vec3.fromValues(xyzMM[0], xyzMM[1], xyzMM[2] + gapX);
dest = vec3.fromValues(xyzMM[0], xyzMM[1], xyzMax[2]);
_NiivueObject3D.makeCylinder(vertices, indices, start, dest, radius, sides, false);
}
const vertexBuffer = gl.createBuffer();
if (vertexBuffer === null) {
throw new Error("could not instantiate vertex buffer");
}
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
const indexBuffer = gl.createBuffer();
if (indexBuffer === null) {
throw new Error("could not instantiate index buffer");
}
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint32Array(indices), gl.STATIC_DRAW);
const vao = gl.createVertexArray();
gl.bindVertexArray(vao);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.enableVertexAttribArray(0);
gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
gl.bindVertexArray(null);
return {
vertexBuffer,
indexBuffer,
indexCount: indices.length,
vao
};
});
__publicField(_NiivueObject3D, "getFirstPerpVector", function(v1) {
const v2 = vec3.fromValues(0, 0, 0);
if (v1[0] === 0) {
v2[0] = 1;
} else if (v1[1] === 0) {
v2[1] = 1;
} else if (v1[2] === 0) {
v2[2] = 1;
} else {
v2[0] = v1[2];
v2[1] = v1[2];
v2[2] = -(v1[0] + v1[1]);
vec3.normalize(v2, v2);
}
return v2;
});
__publicField(_NiivueObject3D, "subdivide", function(verts, faces) {
let nv = verts.length / 3;
let nf = faces.length / 3;
const n = nf;
const vNew = vec3.create();
const nNew = vec3.create();
for (let faceIndex = 0; faceIndex < n; faceIndex++) {
const fx = faces[faceIndex * 3 + 0];
const fy = faces[faceIndex * 3 + 1];
const fz = faces[faceIndex * 3 + 2];
const vx = vec3.fromValues(verts[fx * 3 + 0], verts[fx * 3 + 1], verts[fx * 3 + 2]);
const vy = vec3.fromValues(verts[fy * 3 + 0], verts[fy * 3 + 1], verts[fy * 3 + 2]);
const vz = vec3.fromValues(verts[fz * 3 + 0], verts[fz * 3 + 1], verts[fz * 3 + 2]);
vec3.add(vNew, vx, vy);
vec3.normalize(nNew, vNew);
verts.push(...nNew);
vec3.add(vNew, vy, vz);
vec3.normalize(nNew, vNew);
verts.push(...nNew);
vec3.add(vNew, vx, vz);
vec3.normalize(nNew, vNew);
verts.push(...nNew);
let face = [nv, nv + 1, nv + 2];
faces.push(...face);
face = [fx, nv, nv + 2];
faces.push(...face);
face = [nv, fy, nv + 1];
faces.push(...face);
faces[faceIndex * 3 + 0] = nv + 2;
faces[faceIndex * 3 + 1] = nv + 1;
faces[faceIndex * 3 + 2] = fz;
nf = nf + 3;
nv = nv + 3;
}
});
__publicField(_NiivueObject3D, "weldVertices", function(verts, faces) {
const nv = verts.length / 3;
let nUnique = 0;
const remap = new Int32Array(nv);
for (let i = 0; i < nv - 1; i++) {
if (remap[i] !== 0) {
continue;
}
remap[i] = nUnique;
let v = i * 3;
const x = verts[v];
const y = verts[v + 1];
const z = verts[v + 2];
for (let j = i + 1; j < nv; j++) {
v += 3;
if (x === verts[v] && y === verts[v + 1] && z === verts[v + 2]) {
remap[j] = nUnique;
}
}
nUnique++;
}
if (nUnique === nv) {
return verts;
}
const nf = faces.length;
for (let f = 0; f < nf; f++) {
faces[f] = remap[faces[f]];
}
const vtx = verts.slice(0, nUnique * 3 - 1);
for (let i = 0; i < nv - 1; i++) {
const v = i * 3;
const r = remap[i] * 3;
vtx[r] = verts[v];
vtx[r + 1] = verts[v + 1];
vtx[r + 2] = verts[v + 2];
}
return vtx;
});
__publicField(_NiivueObject3D, "makeSphere", function(vertices, indices, radius, origin = [0, 0, 0]) {
let vtx = [
0,
0,
1,
0.894,
0,
0.447,
0.276,
0.851,
0.447,
-0.724,
0.526,
0.447,
-0.724,
-0.526,
0.447,
0.276,
-0.851,
0.447,
0.724,
0.526,
-0.447,
-0.276,
0.851,
-0.447,
-0.894,
0,
-0.447,
-0.276,
-0.851,
-0.447,
0.724,
-0.526,
-0.447,
0,
0,
-1
];
const idx2 = [
0,
1,
2,
0,
2,
3,
0,
3,
4,
0,
4,
5,
0,
5,
1,
7,
6,
11,
8,
7,
11,
9,
8,
11,
10,
9,
11,
6,
10,
11,
6,
2,
1,
7,
3,
2,
8,
4,
3,
9,
5,
4,
10,
1,
5,
6,
7,
2,
7,
8,
3,
8,
9,
4,
9,
10,
5,
10,
6,
1
];
_NiivueObject3D.subdivide(vtx, idx2);
_NiivueObject3D.subdivide(vtx, idx2);
vtx = _NiivueObject3D.weldVertices(vtx, idx2);
for (let i = 0; i < vtx.length; i++) {
vtx[i] = vtx[i] * radius;
}
const nvtx = vtx.length / 3;
let j = 0;
for (let i = 0; i < nvtx; i++) {
vtx[j] = vtx[j] + origin[0];
j++;
vtx[j] = vtx[j] + origin[1];
j++;
vtx[j] = vtx[j] + origin[2];
j++;
}
const idx0 = Math.floor(vertices.length / 3);
for (let i = 0; i < idx2.length; i++) {
idx2[i] = idx2[i] + idx0;
}
indices.push(...idx2);
vertices.push(...vtx);
});
__publicField(_NiivueObject3D, "makeCylinder", function(vertices, indices, start, dest, radius, sides = 20, endcaps = true) {
if (sides < 3) {
sides = 3;
}
const v1 = vec3.create();
vec3.subtract(v1, dest, start);
vec3.normalize(v1, v1);
const v2 = _NiivueObject3D.getFirstPerpVector(v1);
const v3 = vec3.create();
vec3.cross(v3, v1, v2);
vec3.normalize(v3, v3);
let num_v = 2 * sides;
let num_f = 2 * sides;
if (endcaps) {
num_f += 2 * sides;
num_v += 2;
}
const idx0 = Math.floor(vertices.length / 3);
const idx2 = new Uint32Array(num_f * 3);
const vtx = new Float32Array(num_v * 3);
function setV(i, vec325) {
vtx[i * 3 + 0] = vec325[0];
vtx[i * 3 + 1] = vec325[1];
vtx[i * 3 + 2] = vec325[2];
}
function setI(i, a, b, c) {
idx2[i * 3 + 0] = a + idx0;
idx2[i * 3 + 1] = b + idx0;
idx2[i * 3 + 2] = c + idx0;
}
const startPole = 2 * sides;
const destPole = startPole + 1;
if (endcaps) {
setV(startPole, start);
setV(destPole, dest);
}
const pt1 = vec3.create();
const pt2 = vec3.create();
for (let i = 0; i < sides; i++) {
const c = Math.cos(i / sides * 2 * Math.PI);
const s = Math.sin(i / sides * 2 * Math.PI);
pt1[0] = radius * (c * v2[0] + s * v3[0]);
pt1[1] = radius * (c * v2[1] + s * v3[1]);
pt1[2] = radius * (c * v2[2] + s * v3[2]);
vec3.add(pt2, start, pt1);
setV(i, pt2);
vec3.add(pt2, dest, pt1);
setV(i + sides, pt2);
let nxt = 0;
if (i < sides - 1) {
nxt = i + 1;
}
setI(i * 2, i, nxt, i + sides);
setI(i * 2 + 1, nxt, nxt + sides, i + sides);
if (endcaps) {
setI(sides * 2 + i, i, startPole, nxt);
setI(sides * 2 + i + sides, destPole, i + sides, nxt + sides);
}
}
indices.push(...idx2);
vertices.push(...vtx);
});
__publicField(_NiivueObject3D, "makeColoredCylinder", function(vertices, indices, colors, start, dest, radius, rgba255 = [192, 0, 0, 255], sides = 20, endcaps = false) {
let nv = vertices.length / 3;
_NiivueObject3D.makeCylinder(vertices, indices, start, dest, radius, sides, endcaps);
nv = vertices.length / 3 - nv;
const clrs = [];
for (let i = 0; i < nv * 4 - 1; i += 4) {
clrs[i] = rgba255[0];
clrs[i + 1] = rgba255[1];
clrs[i + 2] = rgba255[2];
clrs[i + 3] = rgba255[3];
}
colors.push(...clrs);
});
__publicField(_NiivueObject3D, "makeColoredSphere", function(vertices, indices, colors, radius, origin = [0, 0, 0], rgba255 = [0, 0, 192, 255]) {
let nv = vertices.length / 3;
_NiivueObject3D.makeSphere(vertices, indices, radius, origin);
nv = vertices.length / 3 - nv;
const clrs = [];
for (let i = 0; i < nv * 4 - 1; i += 4) {
clrs[i] = rgba255[0];
clrs[i + 1] = rgba255[1];
clrs[i + 2] = rgba255[2];
clrs[i + 3] = rgba255[3];
}
colors.push(...clrs);
});
var NiivueObject3D = _NiivueObject3D;
// src/nvmesh.ts
import { vec3 as vec35, vec4 as vec44 } from "gl-matrix";
import { v4 as uuidv4 } from "@lukeed/uuid";
// src/logger.ts
var _Log = class _Log {
constructor({ name = "niivue", level = "info" } = {}) {
__publicField(this, "level");
__publicField(this, "name");
this.name = `${name}`;
this.level = level;
}
debug(...args) {
if (_Log.levels[this.level] > _Log.levels.debug) {
return;
}
console.debug(`${this.name}-debug`, ...args);
}
info(...args) {
if (_Log.levels[this.level] > _Log.levels.info) {
return;
}
console.info(`${this.name}-info`, ...args);
}
warn(...args) {
if (_Log.levels[this.level] > _Log.levels.warn) {
return;
}
console.warn(`${this.name}-warn`, ...args);
}
error(...args) {
if (_Log.levels[this.level] > _Log.levels.error) {
return;
}
console.error(`${this.name}-error`, ...args);
}
fatal(...args) {
if (_Log.levels[this.level] > _Log.levels.fatal) {
return;
}
console.error(`${this.name}-fatal`, ...args);
}
setLogLevel(level) {
this.level = level;
}
setName(name) {
this.name = name;
}
};
// map 'debug' 'info' 'warn' 'error' 'fatal' 'silent' to numbers
// for comparison
__publicField(_Log, "levels", {
debug: 0,
info: 1,
warn: 2,
error: 3,
fatal: 4,
silent: Infinity
});
var Log = _Log;
var log = new Log({ name: "niivue", level: "info" });
// src/cmaps/index.ts
var cmaps_exports = {};
__export(cmaps_exports, {
$itksnap: () => itksnap_default,
$slicer3d: () => slicer3d_default,
actc: () => actc_default,
afni_blues_inv: () => afni_blues_inv_default,
afni_reds_inv: () => afni_reds_inv_default,
batlow: () => batlow_default,
bcgwhw: () => bcgwhw_default,
bcgwhw_dark: () => bcgwhw_dark_default,
blue: () => blue_default,
blue2cyan: () => blue2cyan_default,
blue2magenta: () => blue2magenta_default,
blue2red: () => blue2red_default,
bluegrn: () => bluegrn_default,
bone: () => bone_default,
bronze: () => bronze_default,
cet_l17: () => cet_l17_default,
cividis: () => cividis_default,
cool: () => cool_default,
copper: () => copper_default,
copper2: () => copper2_default,
ct_airways: () => ct_airways_default,
ct_artery: () => ct_artery_default,
ct_bones: () => ct_bones_default,
ct_brain: () => ct_brain_default,
ct_brain_gray: () => ct_brain_gray_default,
ct_cardiac: () => ct_cardiac_default,
ct_head: () => ct_head_default,
ct_kidneys: () => ct_kidneys_default,
ct_liver: () => ct_liver_default,
ct_muscles: () => ct_muscles_default,
ct_scalp: () => ct_scalp_default,
ct_skull: () => ct_skull_default,
ct_soft: () => ct_soft_default,
ct_soft_tissue: () => ct_soft_tissue_default,
ct_surface: () => ct_surface_default,
ct_vessels: () => ct_vessels_default,
ct_w_contrast: () => ct_w_contrast_default,
cubehelix: () => cubehelix_default,
electric_blue: () => electric_blue_default,
freesurfer: () => freesurfer_default,
ge_color: () => ge_color_default,
gold: () => gold_default,
gray: () => gray_default,
green: () => green_default,
green2cyan: () => green2cyan_default,
green2orange: () => green2orange_default,
hot: () => hot_default,
hotiron: () => hotiron_default,
hsv: () => hsv_default,
inferno: () => inferno_default,
jet: () => jet_default,
kry: () => kry_default,
linspecer: () => linspecer_default,
lipari: () => lipari_default,
magma: () => magma_default,
mako: () => mako_default,
navia: () => navia_default,
nih: () => nih_default,
plasma: () => plasma_default,
random: () => random_default,
red: () => red_default,
redyell: () => redyell_default,
rocket: () => rocket_default,
roi_i256: () => roi_i256_default,
surface: () => surface_default,
thermal: () => thermal_default,
turbo: () => turbo_default,
violet: () => violet_default,
viridis: () => viridis_default,
warm: () => warm_default,
winter: () => winter_default,
x_rain: () => x_rain_default
});
// src/cmaps/_itksnap.json
var itksnap_default = {
R: [
0,
255,
0,
0,
255,
0,
255,
255,
0,
205,
210,
102,
0,
0,
46,
255,
106,
221,
233,
165,
255,
147,
218,
75,
255,
60,
255,
255,
218,
0,
188,
255,
255,
222,
127,
139,
124,
255,
70,
0,
238,
238,
240,
245,
184,
32,
255,
25,
112,
34,
248,
245,
255,
144,
173,
65,
255,
250,
128,
50,
244,
255,
123,
255,
173,
255,
127,
255,
143,
220,
253,
255,
0,
0,
128,
255,
250,
148,
178,
255,
135,
100,
240,
250,
255,
107,
135,
0,
139,
245,
186,
255,
255,
0,
210,
255,
47,
72,
175,
128,
176,
255,
139,
240,
255,
216,
119,
219,
72,
255,
199,
154,
189,
240,
230,
0,
85,
64,
153,
205,
250,
95,
0,
255,
224,
176,
138,
30,
240,
152,
160
],
G: [
0,
0,
255,
0,
255,
255,
0,
239,
0,
133,
180,
205,
0,
139,
139,
228,
90,
160,
150,
42,
250,
112,
112,
0,
182,
179,
235,
228,
165,
128,
143,
105,
218,
184,
255,
69,
252,
255,
130,
100,
130,
232,
255,
222,
134,
178,
20,
25,
128,
139,
248,
255,
160,
238,
255,
105,
99,
240,
0,
205,
164,
255,
104,
165,
216,
192,
255,
140,
188,
20,
245,
250,
206,
255,
0,
250,
128,
0,
34,
127,
206,
149,
230,
235,
245,
142,
206,
0,
0,
245,
85,
228,
222,
191,
105,
248,
79,
61,
238,
128,
224,
240,
0,
255,
215,
191,
136,
112,
209,
0,
21,
205,
183,
248,
230,
250,
107,
224,
50,
92,
250,
158,
128,
69,
255,
196,
43,
144,
128,
251,
82
],
B: [
0,
0,
0,
255,
0,
255,
255,
213,
205,
63,
140,
170,
128,
139,
87,
225,
205,
221,
122,
42,
250,
219,
214,
130,
193,
113,
205,
196,
32,
128,
143,
180,
185,
135,
0,
19,
0,
224,
180,
0,
238,
170,
240,
179,
11,
170,
147,
112,
144,
34,
255,
250,
122,
144,
47,
225,
71,
230,
0,
50,
96,
240,
238,
0,
230,
203,
212,
0,
143,
60,
230,
240,
209,
127,
128,
205,
114,
211,
34,
80,
235,
237,
140,
215,
238,
35,
250,
139,
139,
220,
211,
181,
173,
255,
30,
220,
79,
139,
238,
0,
230,
245,
0,
255,
0,
216,
153,
147,
204,
255,
133,
50,
107,
255,
250,
154,
47,
208,
204,
92,
210,
160,
0,
0,
255,
222,
226,
255,
128,
152,
45
],
A: [
0,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255
],
I: [
0,
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
31,
32,
33,
34,
35,
36,
37,
38,
39,
40,
41,
42,
43,
44,
45,
46,
47,
48,
49,
50,
51,
52,
53,
54,
55,
56,
57,
58,
59,
60,
61,
62,
63,
64,
65,
66,
67,
68,
69,
70,
71,
72,
73,
74,
75,
76,
77,
78,
79,
80,
81,
82,
83,
84,
85,
86,
87,
88,
89,
90,
91,
92,
93,
94,
95,
96,
97,
98,
99,
100,
101,
102,
103,
104,
105,
106,
107,
108,
109,
110,
111,
112,
113,
114,
115,
116,
117,
118,
119,
120,
121,
122,
123,
124,
125,
126,
127,
128,
129,
130
]
};
// src/cmaps/_slicer3d.json
var slicer3d_default = {
labels: [
"background",
"tissue",
"bone",
"skin",
"connective tissue",
"blood",
"organ",
"mass",
"muscle",
"foreign object",
"waste",
"teeth",
"fat",
"gray matter",
"white matter",
"nerve",
"vein",
"artery",
"capillary",
"ligament",
"tendon",
"cartilage",
"meniscus",
"lymph node",
"lymphatic vessel",
"cerebro-spinal fluid",
"bile",
"urine",
"feces",
"gas",
"fluid",
"edema",
"bleeding",
"necrosis",
"clot",
"embolism",
"head",
"central nervous system",
"brain",
"gray matter of brain",
"telencephalon",
"cerebral cortex",
"right frontal lobe",
"left frontal lobe",
"right temporal lobe",
"left temporal lobe",
"right parietal lobe",
"left parietal lobe",
"right occipital lobe",
"left occipital lobe",
"right insular lobe",
"left insular lobe",
"right limbic lobe",
"left limbic lobe",
"right striatum",
"left striatum",
"right caudate nucleus",
"left caudate nucleus",
"right putamen",
"left putamen",
"right pallidum",
"left pallidum",
"right amygdaloid complex",
"left amygdaloid complex",
"diencephalon",
"thalamus",
"right thalamus",
"left thalamus",
"pineal gland",
"midbrain",
"substantia nigra",
"right substantia nigra",
"left substantia nigra",
"cerebral white matter",
"right superior longitudinal fasciculus",
"left superior longitudinal fasciculus",
"right inferior longitudinal fasciculus",
"left inferior longitudinal fasciculus",
"right arcuate fasciculus",
"left arcuate fasciculus",
"right uncinate fasciculus",
"left uncinate fasciculus",
"right cingulum bundle",
"left cingulum bundle",
"projection fibers",
"right corticospinal tract",
"left corticospinal tract",
"right optic radiation",
"left optic radiation",
"right medial lemniscus",
"left medial lemniscus",
"right superior cerebellar peduncle",
"left superior cerebellar peduncle",
"right middle cerebellar peduncle",
"left middle cerebellar peduncle",
"right inferior cerebellar peduncle",
"left inferior cerebellar peduncle",
"optic chiasm",
"right optic tract",
"left optic tract",
"right fornix",
"left fornix",
"commissural fibers",
"corpus callosum",
"posterior commissure",
"cerebellar white matter",
"CSF space",
"ventricles of brain",
"right lateral ventricle",
"left lateral ventricle",
"right third ventricle",
"left third ventricle",
"cerebral aqueduct",
"fourth ventricle",
"subarachnoid space",
"spinal cord",
"gray matter of spinal cord",
"white matter of spinal cord",
"endocrine system of brain",
"pituitary gland",
"adenohypophysis",
"neurohypophysis",
"meninges",
"dura mater",
"arachnoid",
"pia mater",
"muscles of head",
"salivary glands",
"lips",
"nose",
"tongue",
"soft palate",
"right inner ear",
"left inner ear",
"right external ear",
"left external ear",
"right middle ear",
"left middle ear",
"right eyeball",
"left eyeball",
"skull",
"right frontal bone",
"left frontal bone",
"right parietal bone",
"left parietal bone",
"right temporal bone",
"left temporal bone",
"right sphenoid bone",
"left sphenoid bone",
"right ethmoid bone",
"left ethmoid bone",
"occipital bone",
"maxilla",
"right zygomatic bone",
"right lacrimal bone",
"vomer bone",
"right palatine bone",
"left palatine bone",
"mandible",
"neck",
"muscles of neck",
"pharynx",
"larynx",
"thyroid gland",
"right parathyroid glands",
"left parathyroid glands",
"skeleton of neck",
"hyoid bone",
"cervical vertebral column",
"thorax",
"trachea",
"bronchi",
"right lung",
"left lung",
"superior lobe of right lung",
"superior lobe of left lung",
"middle lobe of right lung",
"inferior lobe of right lung",
"inferior lobe of left lung",
"pleura",
"heart",
"right atrium",
"left atrium",
"atrial septum",
"ventricular septum",
"right ventricle of heart",
"left ventricle of heart",
"mitral valve",
"tricuspid valve",
"aortic valve",
"pulmonary valve",
"aorta",
"pericardium",
"pericardial cavity",
"esophagus",
"thymus",
"mediastinum",
"skin of thoracic wall",
"muscles of thoracic wall",
"skeleton of thorax",
"thoracic vertebral column",
"ribs",
"sternum",
"right clavicle",
"left clavicle",
"abdominal cavity",
"abdomen",
"peritoneum",
"omentum",
"peritoneal cavity",
"retroperitoneal space",
"stomach",
"duodenum",
"small bowel",
"colon",
"anus",
"liver",
"biliary tree",
"gallbladder",
"pancreas",
"spleen",
"urinary system",
"right kidney",
"left kidney",
"right ureter",
"left ureter",
"urinary bladder",
"urethra",
"right adrenal gland",
"left adrenal gland",
"female internal genitalia",
"uterus",
"right fallopian tube",
"left fallopian tube",
"right ovary",
"left ovary",
"vagina",
"male internal genitalia",
"prostate",
"right seminal vesicle",
"left seminal vesicle",
"right deferent duct",
"left deferent duct",
"skin of abdominal wall",
"muscles of abdominal wall",
"skeleton of abdomen",
"lumbar vertebral column",
"female external genitalia",
"male external genitalia",
"skeleton of upper limb",
"muscles of upper limb",
"right upper limb",
"left upper limb",
"right shoulder",
"left shoulder",
"right arm"
],
R: [
0,
128,
241,
177,
111,
216,
221,
144,
192,
220,
78,
255,
230,
200,
250,
244,
0,
216,
183,
183,
152,
111,
178,
68,
111,
85,
0,
214,
78,
218,
170,
140,
188,
216,
145,
150,
177,
244,
250,
200,
68,
128,
83,
83,
162,
162,
141,
141,
182,
182,
188,
188,
154,
154,
177,
177,
30,
30,
210,
210,
48,
48,
98,
98,
69,
166,
122,
122,
253,
145,
46,
0,
0,
250,
127,
127,
159,
159,
125,
125,
106,
106,
154,
154,
126,
201,
201,
78,
78,
174,
174,
139,
139,
148,
148,
186,
186,
99,
156,
156,
64,
64,
138,
97,
126,
194,
85,
88,
88,
88,
88,
88,
88,
88,
88,
244,
200,
250,
82,
57,
60,
92,
255,
255,
255,
255,
201,
70,
188,
177,
166,
182,
229,
229,
174,
174,
201,
201,
194,
194,
241,
203,
203,
229,
229,
255,
255,
209,
209,
248,
248,
255,
196,
255,
255,
255,
242,
242,
222,
177,
213,
184,
150,
62,
62,
62,
242,
250,
255,
177,
182,
175,
197,
197,
172,
172,
202,
224,
224,
255,
206,
210,
203,
233,
195,
181,
152,
159,
166,
218,
225,
224,
255,
184,
211,
47,
255,
173,
188,
255,
226,
253,
244,
205,
205,
186,
177,
255,
234,
204,
180,
216,
255,
205,
204,
255,
221,
0,
139,
249,
157,
203,
185,
185,
247,
247,
222,
124,
249,
249,
244,
255,
255,
227,
213,
213,
193,
216,
230,
245,
245,
241,
241,
177,
171,
217,
212,
185,
185,
198,
194,
177,
177,
177,
177,
177
],
G: [
0,
174,
214,
122,
184,
101,
130,
238,
104,
245,
63,
250,
220,
200,
250,
214,
151,
101,
156,
214,
189,
184,
212,
172,
197,
188,
145,
230,
63,
255,
250,
224,
65,
191,
60,
98,
122,
214,
250,
200,
131,
174,
146,
146,
115,
115,
93,
93,
166,
166,
135,
135,
150,
150,
140,
140,
111,
111,
157,
157,
129,
129,
153,
153,
110,
113,
101,
101,
135,
92,
101,
108,
108,
250,
150,
150,
116,
116,
102,
102,
174,
174,
146,
146,
126,
160,
160,
152,
152,
140,
140,
126,
126,
120,
120,
135,
135,
106,
171,
171,
123,
123,
95,
113,
161,
195,
188,
106,
106,
106,
106,
106,
106,
106,
106,
214,
200,
250,
174,
157,
143,
162,
244,
244,
244,
244,
121,
163,
91,
122,
84,
105,
147,
147,
122,
122,
112,
112,
142,
142,
213,
179,
179,
204,
204,
243,
243,
185,
185,
223,
223,
230,
172,
255,
250,
237,
217,
217,
198,
122,
124,
105,
208,
162,
162,
162,
206,
210,
255,
122,
228,
216,
165,
165,
138,
138,
164,
186,
186,
245,
110,
115,
108,
138,
100,
85,
55,
63,
70,
123,
130,
97,
244,
122,
171,
150,
244,
121,
95,
239,
202,
232,
217,
179,
179,
124,
122,
255,
234,
142,
119,
132,
253,
167,
168,
224,
130,
145,
150,
180,
108,
136,
102,
102,
182,
182,
154,
186,
186,
186,
170,
181,
190,
153,
141,
141,
123,
146,
158,
172,
172,
172,
172,
124,
85,
198,
188,
135,
135,
175,
98,
122,
122,
122,
122,
122
],
B: [
0,
128,
145,
101,
210,
79,
101,
144,
88,
20,
0,
220,
70,
235,
210,
49,
206,
79,
220,
211,
207,
210,
242,
100,
131,
255,
30,
130,
0,
255,
250,
228,
28,
216,
66,
83,
101,
49,
225,
215,
98,
128,
164,
164,
105,
105,
137,
137,
110,
110,
166,
166,
201,
201,
190,
190,
85,
85,
166,
166,
126,
126,
112,
112,
53,
137,
38,
38,
192,
109,
131,
112,
112,
225,
88,
88,
163,
163,
154,
154,
155,
155,
83,
83,
55,
133,
133,
141,
141,
103,
103,
177,
177,
72,
72,
135,
135,
24,
108,
108,
147,
147,
74,
158,
197,
164,
255,
215,
215,
215,
215,
215,
215,
215,
215,
49,
215,
225,
128,
110,
83,
109,
209,
209,
209,
209,
77,
117,
95,
101,
94,
107,
118,
118,
90,
90,
73,
73,
0,
0,
144,
77,
77,
109,
109,
152,
152,
85,
85,
131,
131,
138,
68,
167,
160,
145,
123,
123,
101,
101,
109,
108,
243,
114,
114,
114,
142,
139,
207,
101,
255,
244,
145,
145,
115,
115,
140,
162,
162,
217,
84,
89,
81,
112,
73,
57,
13,
27,
38,
97,
104,
76,
209,
154,
143,
103,
209,
88,
76,
172,
134,
158,
154,
108,
108,
161,
101,
220,
194,
178,
153,
105,
229,
142,
143,
199,
101,
30,
98,
111,
162,
116,
83,
83,
164,
164,
132,
223,
150,
150,
147,
158,
165,
130,
113,
113,
103,
127,
140,
147,
147,
151,
151,
92,
68,
131,
102,
134,
134,
125,
79,
101,
101,
101,
101,
101
],
A: [
0,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255,
255
],
I: [
0,
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
31,
32,
33,
34,
35,
36,
37,
38,
39,
40,
41,
42,
43,
44,
45,
46,
47,
48,
49,
50,
51,
52,
53,
54,
55,
56,
57,
58,
59,
60,
61,
62,
63,
64,
65,
66,
67,
68,
69,
70,
71,
72,
73,
74,
75,
76,
77,
78,
79,
80,
81,
82,
83,
84,
85,
86,
87,
88,
89,
90,
91,
92,
93,
94,
95,
96,
97,
98,
99,
100,
101,
102,
103,
104,
105,
106,
107,
108,
109,
110,
111,
112,
113,
114,
115,
116,
117,
118,
119,
120,
121,
122,
123,
124,
125,
126,
127,
128,
129,
130,