UNPKG

three-stdlib

Version:

stand-alone library of threejs examples

404 lines (403 loc) 11.8 kB
"use strict"; Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" }); const THREE = require("three"); const fflate = require("fflate"); const Volume = require("../misc/Volume.cjs"); class NRRDLoader extends THREE.Loader { constructor(manager) { super(manager); } load(url, onLoad, onProgress, onError) { const scope = this; const loader = new THREE.FileLoader(scope.manager); loader.setPath(scope.path); loader.setResponseType("arraybuffer"); loader.setRequestHeader(scope.requestHeader); loader.setWithCredentials(scope.withCredentials); loader.load( url, function(data) { try { onLoad(scope.parse(data)); } catch (e) { if (onError) { onError(e); } else { console.error(e); } scope.manager.itemError(url); } }, onProgress, onError ); } parse(data) { let _data = data; let _dataPointer = 0; const _nativeLittleEndian = new Int8Array(new Int16Array([1]).buffer)[0] > 0; const _littleEndian = true; const headerObject = {}; function scan(type, chunks) { if (chunks === void 0 || chunks === null) { chunks = 1; } let _chunkSize = 1; let _array_type = Uint8Array; switch (type) { case "uchar": break; case "schar": _array_type = Int8Array; break; case "ushort": _array_type = Uint16Array; _chunkSize = 2; break; case "sshort": _array_type = Int16Array; _chunkSize = 2; break; case "uint": _array_type = Uint32Array; _chunkSize = 4; break; case "sint": _array_type = Int32Array; _chunkSize = 4; break; case "float": _array_type = Float32Array; _chunkSize = 4; break; case "complex": _array_type = Float64Array; _chunkSize = 8; break; case "double": _array_type = Float64Array; _chunkSize = 8; break; } let _bytes2 = new _array_type(_data.slice(_dataPointer, _dataPointer += chunks * _chunkSize)); if (_nativeLittleEndian != _littleEndian) { _bytes2 = flipEndianness(_bytes2, _chunkSize); } if (chunks == 1) { return _bytes2[0]; } return _bytes2; } function flipEndianness(array, chunkSize) { const u8 = new Uint8Array(array.buffer, array.byteOffset, array.byteLength); for (let i2 = 0; i2 < array.byteLength; i2 += chunkSize) { for (let j = i2 + chunkSize - 1, k = i2; j > k; j--, k++) { const tmp = u8[k]; u8[k] = u8[j]; u8[j] = tmp; } } return array; } function parseHeader(header) { let data2, field, fn, i2, l, m, _i, _len; const lines = header.split(/\r?\n/); for (_i = 0, _len = lines.length; _i < _len; _i++) { l = lines[_i]; if (l.match(/NRRD\d+/)) { headerObject.isNrrd = true; } else if (l.match(/^#/)) ; else if (m = l.match(/(.*):(.*)/)) { field = m[1].trim(); data2 = m[2].trim(); fn = _fieldFunctions[field]; if (fn) { fn.call(headerObject, data2); } else { headerObject[field] = data2; } } } if (!headerObject.isNrrd) { throw new Error("Not an NRRD file"); } if (headerObject.encoding === "bz2" || headerObject.encoding === "bzip2") { throw new Error("Bzip is not supported"); } if (!headerObject.vectors) { headerObject.vectors = [new THREE.Vector3(1, 0, 0), new THREE.Vector3(0, 1, 0), new THREE.Vector3(0, 0, 1)]; if (headerObject.spacings) { for (i2 = 0; i2 <= 2; i2++) { if (!isNaN(headerObject.spacings[i2])) { headerObject.vectors[i2].multiplyScalar(headerObject.spacings[i2]); } } } } } function parseDataAsText(data2, start, end) { let number = ""; start = start || 0; end = end || data2.length; let value; const lengthOfTheResult = headerObject.sizes.reduce(function(previous, current) { return previous * current; }, 1); let base = 10; if (headerObject.encoding === "hex") { base = 16; } const result = new headerObject.__array(lengthOfTheResult); let resultIndex = 0; let parsingFunction = parseInt; if (headerObject.__array === Float32Array || headerObject.__array === Float64Array) { parsingFunction = parseFloat; } for (let i2 = start; i2 < end; i2++) { value = data2[i2]; if ((value < 9 || value > 13) && value !== 32) { number += String.fromCharCode(value); } else { if (number !== "") { result[resultIndex] = parsingFunction(number, base); resultIndex++; } number = ""; } } if (number !== "") { result[resultIndex] = parsingFunction(number, base); resultIndex++; } return result; } const _bytes = scan("uchar", data.byteLength); const _length = _bytes.length; let _header = null; let _data_start = 0; let i; for (i = 1; i < _length; i++) { if (_bytes[i - 1] == 10 && _bytes[i] == 10) { _header = this.parseChars(_bytes, 0, i - 2); _data_start = i + 1; break; } } parseHeader(_header); _data = _bytes.subarray(_data_start); if (headerObject.encoding.substring(0, 2) === "gz") { _data = fflate.gunzipSync(new Uint8Array(_data)); } else if (headerObject.encoding === "ascii" || headerObject.encoding === "text" || headerObject.encoding === "txt" || headerObject.encoding === "hex") { _data = parseDataAsText(_data); } else if (headerObject.encoding === "raw") { const _copy = new Uint8Array(_data.length); for (let i2 = 0; i2 < _data.length; i2++) { _copy[i2] = _data[i2]; } _data = _copy; } _data = _data.buffer; const volume = new Volume.Volume(); volume.header = headerObject; volume.data = new headerObject.__array(_data); const min_max = volume.computeMinMax(); const min = min_max[0]; const max = min_max[1]; volume.windowLow = min; volume.windowHigh = max; volume.dimensions = [headerObject.sizes[0], headerObject.sizes[1], headerObject.sizes[2]]; volume.xLength = volume.dimensions[0]; volume.yLength = volume.dimensions[1]; volume.zLength = volume.dimensions[2]; const spacingX = new THREE.Vector3( headerObject.vectors[0][0], headerObject.vectors[0][1], headerObject.vectors[0][2] ).length(); const spacingY = new THREE.Vector3( headerObject.vectors[1][0], headerObject.vectors[1][1], headerObject.vectors[1][2] ).length(); const spacingZ = new THREE.Vector3( headerObject.vectors[2][0], headerObject.vectors[2][1], headerObject.vectors[2][2] ).length(); volume.spacing = [spacingX, spacingY, spacingZ]; volume.matrix = new THREE.Matrix4(); let _spaceX = 1; let _spaceY = 1; const _spaceZ = 1; if (headerObject.space == "left-posterior-superior") { _spaceX = -1; _spaceY = -1; } else if (headerObject.space === "left-anterior-superior") { _spaceX = -1; } if (!headerObject.vectors) { volume.matrix.set(_spaceX, 0, 0, 0, 0, _spaceY, 0, 0, 0, 0, _spaceZ, 0, 0, 0, 0, 1); } else { const v = headerObject.vectors; volume.matrix.set( _spaceX * v[0][0], _spaceX * v[1][0], _spaceX * v[2][0], 0, _spaceY * v[0][1], _spaceY * v[1][1], _spaceY * v[2][1], 0, _spaceZ * v[0][2], _spaceZ * v[1][2], _spaceZ * v[2][2], 0, 0, 0, 0, 1 ); } volume.inverseMatrix = new THREE.Matrix4(); volume.inverseMatrix.copy(volume.matrix).invert(); volume.RASDimensions = new THREE.Vector3(volume.xLength, volume.yLength, volume.zLength).applyMatrix4(volume.matrix).round().toArray().map(Math.abs); if (volume.lowerThreshold === -Infinity) { volume.lowerThreshold = min; } if (volume.upperThreshold === Infinity) { volume.upperThreshold = max; } return volume; } parseChars(array, start, end) { if (start === void 0) { start = 0; } if (end === void 0) { end = array.length; } let output = ""; let i = 0; for (i = start; i < end; ++i) { output += String.fromCharCode(array[i]); } return output; } } const _fieldFunctions = { type: function(data) { switch (data) { case "uchar": case "unsigned char": case "uint8": case "uint8_t": this.__array = Uint8Array; break; case "signed char": case "int8": case "int8_t": this.__array = Int8Array; break; case "short": case "short int": case "signed short": case "signed short int": case "int16": case "int16_t": this.__array = Int16Array; break; case "ushort": case "unsigned short": case "unsigned short int": case "uint16": case "uint16_t": this.__array = Uint16Array; break; case "int": case "signed int": case "int32": case "int32_t": this.__array = Int32Array; break; case "uint": case "unsigned int": case "uint32": case "uint32_t": this.__array = Uint32Array; break; case "float": this.__array = Float32Array; break; case "double": this.__array = Float64Array; break; default: throw new Error("Unsupported NRRD data type: " + data); } return this.type = data; }, endian: function(data) { return this.endian = data; }, encoding: function(data) { return this.encoding = data; }, dimension: function(data) { return this.dim = parseInt(data, 10); }, sizes: function(data) { let i; return this.sizes = function() { const _ref = data.split(/\s+/); const _results = []; for (let _i = 0, _len = _ref.length; _i < _len; _i++) { i = _ref[_i]; _results.push(parseInt(i, 10)); } return _results; }(); }, space: function(data) { return this.space = data; }, "space origin": function(data) { return this.space_origin = data.split("(")[1].split(")")[0].split(","); }, "space directions": function(data) { let f, v; const parts = data.match(/\(.*?\)/g); return this.vectors = function() { const _results = []; for (let _i = 0, _len = parts.length; _i < _len; _i++) { v = parts[_i]; _results.push( function() { const _ref = v.slice(1, -1).split(/,/); const _results2 = []; for (let _j = 0, _len2 = _ref.length; _j < _len2; _j++) { f = _ref[_j]; _results2.push(parseFloat(f)); } return _results2; }() ); } return _results; }(); }, spacings: function(data) { let f; const parts = data.split(/\s+/); return this.spacings = function() { const _results = []; for (let _i = 0, _len = parts.length; _i < _len; _i++) { f = parts[_i]; _results.push(parseFloat(f)); } return _results; }(); } }; exports.NRRDLoader = NRRDLoader; //# sourceMappingURL=NRRDLoader.cjs.map