dicom-microscopy-viewer-changed
Version:
Interactive web-based viewer for DICOM Microscopy Images
1,720 lines (1,433 loc) • 1.51 MB
JavaScript
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
(global = global || self, factory(global.dcmjs = {}));
}(this, (function (exports) { 'use strict';
var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
function createCommonjsModule(fn, module) {
return module = { exports: {} }, fn(module, module.exports), module.exports;
}
/*
Copyright © 2018 Andrew Powell
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/.
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of this Source Code Form.
*/
const noop = () => {};
const levels = Symbol('log-levels');
const instance = Symbol('log-instance');
var MethodFactory_1 = class MethodFactory {
constructor(logger) {
this[instance] = logger;
this[levels] = {
TRACE: 0,
DEBUG: 1,
INFO: 2,
WARN: 3,
ERROR: 4,
SILENT: 5
};
}
get levels() {
return this[levels];
}
get logger() {
return this[instance];
}
set logger(logger) {
this[instance] = logger;
}
get methods() {
return Object.keys(this.levels)
.map((key) => key.toLowerCase())
.filter((key) => key !== 'silent');
}
// eslint-disable-next-line class-methods-use-this
bindMethod(obj, methodName) {
const method = obj[methodName];
if (typeof method.bind === 'function') {
return method.bind(obj);
}
try {
return Function.prototype.bind.call(method, obj);
} catch (e) {
// Missing bind shim or IE8 + Modernizr, fallback to wrapping
return function result() {
// eslint-disable-next-line prefer-rest-params
return Function.prototype.apply.apply(method, [obj, arguments]);
};
}
}
distillLevel(level) {
let result = level;
if (typeof result === 'string' && typeof this.levels[result.toUpperCase()] !== 'undefined') {
result = this.levels[result.toUpperCase()];
}
if (this.levelValid(result)) {
return result;
}
return false;
}
levelValid(level) {
if (typeof level === 'number' && level >= 0 && level <= this.levels.SILENT) {
return true;
}
return false;
}
/**
* Build the best logging method possible for this env
* Wherever possible we want to bind, not wrap, to preserve stack traces.
* Since we're targeting modern browsers, there's no need to wait for the
* console to become available.
*/
// eslint-disable-next-line class-methods-use-this
make(methodName) {
if (methodName === 'debug') {
// eslint-disable-next-line no-param-reassign
methodName = 'log';
}
/* eslint-disable no-console */
if (typeof console[methodName] !== 'undefined') {
return this.bindMethod(console, methodName);
} else if (typeof console.log !== 'undefined') {
return this.bindMethod(console, 'log');
}
/* eslint-enable no-console */
return noop;
}
replaceMethods(logLevel) {
const level = this.distillLevel(logLevel);
if (level == null) {
throw new Error(`loglevelnext: replaceMethods() called with invalid level: ${logLevel}`);
}
if (!this.logger || this.logger.type !== 'LogLevel') {
throw new TypeError(
'loglevelnext: Logger is undefined or invalid. Please specify a valid Logger instance.'
);
}
this.methods.forEach((methodName) => {
const { [methodName.toUpperCase()]: methodLevel } = this.levels;
this.logger[methodName] = methodLevel < level ? noop : this.make(methodName);
});
// Define log.log as an alias for log.debug
this.logger.log = this.logger.debug;
}
};
/*
Copyright © 2018 Andrew Powell
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/.
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of this Source Code Form.
*/
const defaults = {
level: (opts) => `[${opts.level}]`,
name: (opts) => opts.logger.name,
template: '{{time}} {{level}} ',
time: () => new Date().toTimeString().split(' ')[0]
};
var PrefixFactory_1 = class PrefixFactory extends MethodFactory_1 {
constructor(logger, options) {
super(logger);
this.options = Object.assign({}, defaults, options);
}
interpolate(level) {
return this.options.template.replace(/{{([^{}]*)}}/g, (stache, prop) => {
const fn = this.options[prop];
if (fn) {
return fn({ level, logger: this.logger });
}
return stache;
});
}
make(methodName) {
const og = super.make(methodName);
return (...args) => {
const output = this.interpolate(methodName);
const [first] = args;
if (typeof first === 'string') {
// eslint-disable-next-line no-param-reassign
args[0] = output + first;
} else {
args.unshift(output);
}
og(...args);
};
}
};
/*
Copyright © 2018 Andrew Powell
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/.
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of this Source Code Form.
*/
const defaults$1 = {
factory: null,
level: 'warn',
name: +new Date(),
prefix: null
};
var LogLevel_1 = class LogLevel {
constructor(options) {
// implement for some _very_ loose type checking. avoids getting into a
// circular require between MethodFactory and LogLevel
this.type = 'LogLevel';
this.options = Object.assign({}, defaults$1, options);
this.methodFactory = options.factory;
if (!this.methodFactory) {
const factory = options.prefix
? new PrefixFactory_1(this, options.prefix)
: new MethodFactory_1(this);
this.methodFactory = factory;
}
if (!this.methodFactory.logger) {
this.methodFactory.logger = this;
}
this.name = options.name || '<unknown>';
// this.level is a setter, do this after setting up the factory
this.level = this.options.level;
}
get factory() {
return this.methodFactory;
}
set factory(factory) {
// eslint-disable-next-line no-param-reassign
factory.logger = this;
this.methodFactory = factory;
this.methodFactory.replaceMethods(this.level);
}
disable() {
this.level = this.levels.SILENT;
}
enable() {
this.level = this.levels.TRACE;
}
get level() {
return this.currentLevel;
}
set level(logLevel) {
const level = this.methodFactory.distillLevel(logLevel);
if (level === false || level == null) {
throw new RangeError(`loglevelnext: setLevel() called with invalid level: ${logLevel}`);
}
this.currentLevel = level;
this.methodFactory.replaceMethods(level);
if (typeof console === 'undefined' && level < this.levels.SILENT) {
// eslint-disable-next-line no-console
console.warn('loglevelnext: console is undefined. The log will produce no output.');
}
}
get levels() {
// eslint-disable-line class-methods-use-this
return this.methodFactory.levels;
}
};
var lib = createCommonjsModule(function (module) {
/*
Copyright © 2018 Andrew Powell
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/.
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of this Source Code Form.
*/
const factories = Symbol('log-factories');
class DefaultLogger extends LogLevel_1 {
constructor() {
super({ name: 'default' });
this.cache = { default: this };
this[factories] = { MethodFactory: MethodFactory_1, PrefixFactory: PrefixFactory_1 };
}
get factories() {
return this[factories];
}
get loggers() {
return this.cache;
}
create(opts) {
let options;
if (typeof opts === 'string') {
options = { name: opts };
} else {
options = Object.assign({}, opts);
}
if (!options.id) {
options.id = options.name;
}
const { name, id } = options;
const defaults = { level: this.level };
if (typeof name !== 'string' || !name || !name.length) {
throw new TypeError('You must supply a name when creating a logger.');
}
let logger = this.cache[id];
if (!logger) {
logger = new LogLevel_1(Object.assign({}, defaults, options));
this.cache[id] = logger;
}
return logger;
}
}
module.exports = new DefaultLogger();
// TypeScript fix
module.exports.default = module.exports;
});
var log = lib.create("dcmjs");
/* eslint no-bitwise: 0 */
var BitArray = {
getBytesForBinaryFrame: getBytesForBinaryFrame,
pack: pack,
unpack: unpack
};
function getBytesForBinaryFrame(numPixels) {
// Check whether the 1-bit pixels exactly fit into bytes
var remainder = numPixels % 8; // Number of bytes that work on an exact fit
var bytesRequired = Math.floor(numPixels / 8); // Add one byte if we have a remainder
if (remainder > 0) {
bytesRequired++;
}
return bytesRequired;
}
function pack(pixelData) {
var numPixels = pixelData.length;
log.log("numPixels: " + numPixels);
var length = getBytesForBinaryFrame(numPixels); //log.log('getBytesForBinaryFrame: ' + length);
var bitPixelData = new Uint8Array(length);
var bytePos = 0;
for (var i = 0; i < numPixels; i++) {
// Compute byte position
bytePos = Math.floor(i / 8);
var pixValue = pixelData[i] !== 0; //log.log('i: ' + i);
//log.log('pixValue: ' + pixValue);
//log.log('bytePos: ' + bytePos);
var bitPixelValue = pixValue << i % 8; //log.log('current bitPixelData: ' + bitPixelData[bytePos]);
//log.log('this bitPixelValue: ' + bitPixelValue);
bitPixelData[bytePos] |= bitPixelValue; //log.log('new bitPixelValue: ' + bitPixelData[bytePos]);
}
return bitPixelData;
} // convert a packed bitwise pixel array into a byte-per-pixel
// array with 255 corresponding to each set bit in the bit array
function unpack(bitPixelArray) {
var bitArray = new Uint8Array(bitPixelArray);
var byteArray = new Uint8Array(8 * bitArray.length);
for (var byteIndex = 0; byteIndex < byteArray.length; byteIndex++) {
var bitIndex = byteIndex % 8;
var bitByteIndex = Math.floor(byteIndex / 8);
byteArray[byteIndex] = 255 * ((bitArray[bitByteIndex] & 1 << bitIndex) >> bitIndex);
}
return byteArray;
}
function ownKeys(object, enumerableOnly) {
var keys = Object.keys(object);
if (Object.getOwnPropertySymbols) {
var symbols = Object.getOwnPropertySymbols(object);
enumerableOnly && (symbols = symbols.filter(function (sym) {
return Object.getOwnPropertyDescriptor(object, sym).enumerable;
})), keys.push.apply(keys, symbols);
}
return keys;
}
function _objectSpread2(target) {
for (var i = 1; i < arguments.length; i++) {
var source = null != arguments[i] ? arguments[i] : {};
i % 2 ? ownKeys(Object(source), !0).forEach(function (key) {
_defineProperty(target, key, source[key]);
}) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) {
Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
});
}
return target;
}
function _typeof(obj) {
"@babel/helpers - typeof";
return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) {
return typeof obj;
} : function (obj) {
return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
}, _typeof(obj);
}
function _classCallCheck(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
function _defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
function _createClass(Constructor, protoProps, staticProps) {
if (protoProps) _defineProperties(Constructor.prototype, protoProps);
if (staticProps) _defineProperties(Constructor, staticProps);
Object.defineProperty(Constructor, "prototype", {
writable: false
});
return Constructor;
}
function _defineProperty(obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
}
function _inherits(subClass, superClass) {
if (typeof superClass !== "function" && superClass !== null) {
throw new TypeError("Super expression must either be null or a function");
}
subClass.prototype = Object.create(superClass && superClass.prototype, {
constructor: {
value: subClass,
writable: true,
configurable: true
}
});
Object.defineProperty(subClass, "prototype", {
writable: false
});
if (superClass) _setPrototypeOf(subClass, superClass);
}
function _getPrototypeOf(o) {
_getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) {
return o.__proto__ || Object.getPrototypeOf(o);
};
return _getPrototypeOf(o);
}
function _setPrototypeOf(o, p) {
_setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
o.__proto__ = p;
return o;
};
return _setPrototypeOf(o, p);
}
function _isNativeReflectConstruct() {
if (typeof Reflect === "undefined" || !Reflect.construct) return false;
if (Reflect.construct.sham) return false;
if (typeof Proxy === "function") return true;
try {
Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {}));
return true;
} catch (e) {
return false;
}
}
function _construct(Parent, args, Class) {
if (_isNativeReflectConstruct()) {
_construct = Reflect.construct;
} else {
_construct = function _construct(Parent, args, Class) {
var a = [null];
a.push.apply(a, args);
var Constructor = Function.bind.apply(Parent, a);
var instance = new Constructor();
if (Class) _setPrototypeOf(instance, Class.prototype);
return instance;
};
}
return _construct.apply(null, arguments);
}
function _isNativeFunction(fn) {
return Function.toString.call(fn).indexOf("[native code]") !== -1;
}
function _wrapNativeSuper(Class) {
var _cache = typeof Map === "function" ? new Map() : undefined;
_wrapNativeSuper = function _wrapNativeSuper(Class) {
if (Class === null || !_isNativeFunction(Class)) return Class;
if (typeof Class !== "function") {
throw new TypeError("Super expression must either be null or a function");
}
if (typeof _cache !== "undefined") {
if (_cache.has(Class)) return _cache.get(Class);
_cache.set(Class, Wrapper);
}
function Wrapper() {
return _construct(Class, arguments, _getPrototypeOf(this).constructor);
}
Wrapper.prototype = Object.create(Class.prototype, {
constructor: {
value: Wrapper,
enumerable: false,
writable: true,
configurable: true
}
});
return _setPrototypeOf(Wrapper, Class);
};
return _wrapNativeSuper(Class);
}
function _assertThisInitialized(self) {
if (self === void 0) {
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
}
return self;
}
function _possibleConstructorReturn(self, call) {
if (call && (typeof call === "object" || typeof call === "function")) {
return call;
} else if (call !== void 0) {
throw new TypeError("Derived constructors may only return object or undefined");
}
return _assertThisInitialized(self);
}
function _createSuper(Derived) {
var hasNativeReflectConstruct = _isNativeReflectConstruct();
return function _createSuperInternal() {
var Super = _getPrototypeOf(Derived),
result;
if (hasNativeReflectConstruct) {
var NewTarget = _getPrototypeOf(this).constructor;
result = Reflect.construct(Super, arguments, NewTarget);
} else {
result = Super.apply(this, arguments);
}
return _possibleConstructorReturn(this, result);
};
}
function _superPropBase(object, property) {
while (!Object.prototype.hasOwnProperty.call(object, property)) {
object = _getPrototypeOf(object);
if (object === null) break;
}
return object;
}
function _get() {
if (typeof Reflect !== "undefined" && Reflect.get) {
_get = Reflect.get;
} else {
_get = function _get(target, property, receiver) {
var base = _superPropBase(target, property);
if (!base) return;
var desc = Object.getOwnPropertyDescriptor(base, property);
if (desc.get) {
return desc.get.call(arguments.length < 3 ? target : receiver);
}
return desc.value;
};
}
return _get.apply(this, arguments);
}
function _slicedToArray(arr, i) {
return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest();
}
function _toConsumableArray(arr) {
return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread();
}
function _arrayWithoutHoles(arr) {
if (Array.isArray(arr)) return _arrayLikeToArray(arr);
}
function _arrayWithHoles(arr) {
if (Array.isArray(arr)) return arr;
}
function _iterableToArray(iter) {
if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
}
function _iterableToArrayLimit(arr, i) {
var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"];
if (_i == null) return;
var _arr = [];
var _n = true;
var _d = false;
var _s, _e;
try {
for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) {
_arr.push(_s.value);
if (i && _arr.length === i) break;
}
} catch (err) {
_d = true;
_e = err;
} finally {
try {
if (!_n && _i["return"] != null) _i["return"]();
} finally {
if (_d) throw _e;
}
}
return _arr;
}
function _unsupportedIterableToArray(o, minLen) {
if (!o) return;
if (typeof o === "string") return _arrayLikeToArray(o, minLen);
var n = Object.prototype.toString.call(o).slice(8, -1);
if (n === "Object" && o.constructor) n = o.constructor.name;
if (n === "Map" || n === "Set") return Array.from(o);
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
}
function _arrayLikeToArray(arr, len) {
if (len == null || len > arr.length) len = arr.length;
for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
return arr2;
}
function _nonIterableSpread() {
throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
function _nonIterableRest() {
throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
function _createForOfIteratorHelper(o, allowArrayLike) {
var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"];
if (!it) {
if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") {
if (it) o = it;
var i = 0;
var F = function () {};
return {
s: F,
n: function () {
if (i >= o.length) return {
done: true
};
return {
done: false,
value: o[i++]
};
},
e: function (e) {
throw e;
},
f: F
};
}
throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
var normalCompletion = true,
didErr = false,
err;
return {
s: function () {
it = it.call(o);
},
n: function () {
var step = it.next();
normalCompletion = step.done;
return step;
},
e: function (e) {
didErr = true;
err = e;
},
f: function () {
try {
if (!normalCompletion && it.return != null) it.return();
} finally {
if (didErr) throw err;
}
}
};
}
function toInt(val) {
if (isNaN(val)) {
throw new Error("Not a number: " + val);
} else if (typeof val == "string") {
return parseInt(val);
} else return val;
}
function toFloat(val) {
if (isNaN(val)) {
throw new Error("Not a number: " + val);
} else if (typeof val == "string") {
return parseFloat(val);
} else return val;
}
var BufferStream = /*#__PURE__*/function () {
function BufferStream(sizeOrBuffer, littleEndian) {
_classCallCheck(this, BufferStream);
this.buffer = typeof sizeOrBuffer == "number" ? new ArrayBuffer(sizeOrBuffer) : sizeOrBuffer;
if (!this.buffer) {
this.buffer = new ArrayBuffer(0);
}
this.view = new DataView(this.buffer);
this.offset = 0;
this.isLittleEndian = littleEndian || false;
this.size = 0;
this.encoder = new TextEncoder("utf-8");
}
_createClass(BufferStream, [{
key: "setEndian",
value: function setEndian(isLittle) {
this.isLittleEndian = isLittle;
}
}, {
key: "writeUint8",
value: function writeUint8(value) {
this.checkSize(1);
this.view.setUint8(this.offset, toInt(value));
return this.increment(1);
}
}, {
key: "writeUint8Repeat",
value: function writeUint8Repeat(value, count) {
var v = toInt(value);
this.checkSize(count);
for (var i = 0; i < count; i++) {
this.view.setUint8(this.offset + i, v);
}
return this.increment(count);
}
}, {
key: "writeInt8",
value: function writeInt8(value) {
this.checkSize(1);
this.view.setInt8(this.offset, toInt(value));
return this.increment(1);
}
}, {
key: "writeUint16",
value: function writeUint16(value) {
this.checkSize(2);
this.view.setUint16(this.offset, toInt(value), this.isLittleEndian);
return this.increment(2);
}
}, {
key: "writeTwoUint16s",
value: function writeTwoUint16s(value) {
this.checkSize(4);
var first = value >> 16;
var second = value & 0xffff;
this.view.setUint16(this.offset, toInt(first), this.isLittleEndian);
this.view.setUint16(this.offset + 2, toInt(second), this.isLittleEndian);
return this.increment(4);
}
}, {
key: "writeInt16",
value: function writeInt16(value) {
this.checkSize(2);
this.view.setInt16(this.offset, toInt(value), this.isLittleEndian);
return this.increment(2);
}
}, {
key: "writeUint32",
value: function writeUint32(value) {
this.checkSize(4);
this.view.setUint32(this.offset, toInt(value), this.isLittleEndian);
return this.increment(4);
}
}, {
key: "writeInt32",
value: function writeInt32(value) {
this.checkSize(4);
this.view.setInt32(this.offset, toInt(value), this.isLittleEndian);
return this.increment(4);
}
}, {
key: "writeFloat",
value: function writeFloat(value) {
this.checkSize(4);
this.view.setFloat32(this.offset, toFloat(value), this.isLittleEndian);
return this.increment(4);
}
}, {
key: "writeDouble",
value: function writeDouble(value) {
this.checkSize(8);
this.view.setFloat64(this.offset, toFloat(value), this.isLittleEndian);
return this.increment(8);
}
}, {
key: "writeUTF8String",
value: function writeUTF8String(value) {
var encodedString = this.encoder.encode(value);
this.checkSize(encodedString.byteLength);
new Uint8Array(this.buffer).set(encodedString, this.offset);
return this.increment(encodedString.byteLength);
}
}, {
key: "writeAsciiString",
value: function writeAsciiString(value) {
value = value || "";
var len = value.length;
this.checkSize(len);
var startOffset = this.offset;
for (var i = 0; i < len; i++) {
var charcode = value.charCodeAt(i);
this.view.setUint8(startOffset + i, charcode);
}
return this.increment(len);
}
}, {
key: "readUint32",
value: function readUint32() {
var val = this.view.getUint32(this.offset, this.isLittleEndian);
this.increment(4);
return val;
}
}, {
key: "readUint16",
value: function readUint16() {
var val = this.view.getUint16(this.offset, this.isLittleEndian);
this.increment(2);
return val;
}
}, {
key: "readUint8",
value: function readUint8() {
var val = this.view.getUint8(this.offset);
this.increment(1);
return val;
}
}, {
key: "peekUint8",
value: function peekUint8(offset) {
return this.view.getUint8(this.offset + offset);
}
}, {
key: "readUint8Array",
value: function readUint8Array(length) {
var arr = new Uint8Array(this.buffer, this.offset, length);
this.increment(length);
return arr;
}
}, {
key: "readUint16Array",
value: function readUint16Array(length) {
var sixlen = length / 2,
arr = new Uint16Array(sixlen),
i = 0;
while (i++ < sixlen) {
arr[i] = this.view.getUint16(this.offset, this.isLittleEndian);
this.offset += 2;
}
return arr;
}
}, {
key: "readInt16",
value: function readInt16() {
var val = this.view.getInt16(this.offset, this.isLittleEndian);
this.increment(2);
return val;
}
}, {
key: "readInt32",
value: function readInt32() {
var val = this.view.getInt32(this.offset, this.isLittleEndian);
this.increment(4);
return val;
}
}, {
key: "readFloat",
value: function readFloat() {
var val = this.view.getFloat32(this.offset, this.isLittleEndian);
this.increment(4);
return val;
}
}, {
key: "readDouble",
value: function readDouble() {
var val = this.view.getFloat64(this.offset, this.isLittleEndian);
this.increment(8);
return val;
}
}, {
key: "readAsciiString",
value: function readAsciiString(length) {
var result = "";
var start = this.offset;
var end = this.offset + length;
if (end >= this.buffer.byteLength) {
end = this.buffer.byteLength;
}
for (var i = start; i < end; ++i) {
result += String.fromCharCode(this.view.getUint8(i));
}
this.increment(end - start);
return result;
}
}, {
key: "readVR",
value: function readVR() {
var vr = String.fromCharCode(this.view.getUint8(this.offset)) + String.fromCharCode(this.view.getUint8(this.offset + 1));
this.increment(2);
return vr;
}
}, {
key: "readEncodedString",
value: function readEncodedString(length) {
if (this.offset + length >= this.buffer.byteLength) {
length = this.buffer.byteLength - this.offset;
}
var view = new DataView(this.buffer, this.offset, length);
var result = this.decoder.decode(view);
this.increment(length);
return result;
}
}, {
key: "readHex",
value: function readHex(length) {
var hexString = "";
for (var i = 0; i < length; i++) {
hexString += this.readUint8().toString(16);
}
return hexString;
}
}, {
key: "checkSize",
value: function checkSize(step) {
if (this.offset + step > this.buffer.byteLength) {
//throw new Error("Writing exceeded the size of buffer");
//
// Resize the buffer.
// The idea is that when it is necessary to increase the buffer size,
// there will likely be more bytes which need to be written to the
// buffer in the future. Buffer allocation is costly.
// So we increase the buffer size right now
// by a larger amount than necessary, to reserve space for later
// writes which then can be done much faster. The current size of
// the buffer is the best estimate of the scale by which the size
// should increase.
// So approximately doubling the size of the buffer
// (while ensuring it fits the new data) is a simple but effective strategy.
var dstSize = this.offset + step + this.buffer.byteLength;
var dst = new ArrayBuffer(dstSize);
new Uint8Array(dst).set(new Uint8Array(this.buffer));
this.buffer = dst;
this.view = new DataView(this.buffer);
}
}
}, {
key: "concat",
value: function concat(stream) {
var available = this.buffer.byteLength - this.offset;
if (stream.size > available) {
var newbuf = new ArrayBuffer(this.offset + stream.size);
var int8 = new Uint8Array(newbuf);
int8.set(new Uint8Array(this.getBuffer(0, this.offset)));
int8.set(new Uint8Array(stream.getBuffer(0, stream.size)), this.offset);
this.buffer = newbuf;
this.view = new DataView(this.buffer);
} else {
var _int = new Uint8Array(this.buffer);
_int.set(new Uint8Array(stream.getBuffer(0, stream.size)), this.offset);
}
this.offset += stream.size;
this.size = this.offset;
return this.buffer.byteLength;
}
}, {
key: "increment",
value: function increment(step) {
this.offset += step;
if (this.offset > this.size) {
this.size = this.offset;
}
return step;
}
}, {
key: "getBuffer",
value: function getBuffer(start, end) {
if (!start && !end) {
start = 0;
end = this.size;
}
return this.buffer.slice(start, end);
}
}, {
key: "more",
value: function more(length) {
if (this.offset + length > this.endOffset) {
throw new Error("Request more than currently allocated buffer");
}
var newBuf = new ReadBufferStream(this.buffer, null, {
start: this.offset,
stop: this.offset + length
});
this.increment(length);
return newBuf;
}
}, {
key: "reset",
value: function reset() {
this.offset = 0;
return this;
}
}, {
key: "end",
value: function end() {
return this.offset >= this.buffer.byteLength;
}
}, {
key: "toEnd",
value: function toEnd() {
this.offset = this.buffer.byteLength;
}
}]);
return BufferStream;
}();
var ReadBufferStream = /*#__PURE__*/function (_BufferStream) {
_inherits(ReadBufferStream, _BufferStream);
var _super = _createSuper(ReadBufferStream);
function ReadBufferStream(buffer, littleEndian) {
var _this;
var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {
start: null,
stop: null,
noCopy: false
};
_classCallCheck(this, ReadBufferStream);
_this = _super.call(this, buffer, littleEndian);
_this.offset = options.start || 0;
_this.size = options.stop || _this.buffer.byteLength;
_this.noCopy = options.noCopy;
_this.startOffset = _this.offset;
_this.endOffset = _this.size;
_this.decoder = new TextDecoder("latin1");
return _this;
}
_createClass(ReadBufferStream, [{
key: "setDecoder",
value: function setDecoder(decoder) {
this.decoder = decoder;
}
}, {
key: "getBuffer",
value: function getBuffer(start, end) {
if (this.noCopy) {
return new Uint8Array(this.buffer, start, end - start);
}
if (!start && !end) {
start = 0;
end = this.size;
}
return this.buffer.slice(start, end);
}
}, {
key: "reset",
value: function reset() {
this.offset = this.startOffset;
return this;
}
}, {
key: "end",
value: function end() {
return this.offset >= this.endOffset;
}
}, {
key: "toEnd",
value: function toEnd() {
this.offset = this.endOffset;
}
}, {
key: "writeUint8",
value: function writeUint8(value) {
throw new Error(value, "writeUint8 not implemented");
}
}, {
key: "writeUint8Repeat",
value: function writeUint8Repeat(value, count) {
throw new Error(value, "writeUint8Repeat not implemented");
}
}, {
key: "writeInt8",
value: function writeInt8(value) {
throw new Error(value, "writeInt8 not implemented");
}
}, {
key: "writeUint16",
value: function writeUint16(value) {
throw new Error(value, "writeUint16 not implemented");
}
}, {
key: "writeTwoUint16s",
value: function writeTwoUint16s(value) {
throw new Error(value, "writeTwoUint16s not implemented");
}
}, {
key: "writeInt16",
value: function writeInt16(value) {
throw new Error(value, "writeInt16 not implemented");
}
}, {
key: "writeUint32",
value: function writeUint32(value) {
throw new Error(value, "writeUint32 not implemented");
}
}, {
key: "writeInt32",
value: function writeInt32(value) {
throw new Error(value, "writeInt32 not implemented");
}
}, {
key: "writeFloat",
value: function writeFloat(value) {
throw new Error(value, "writeFloat not implemented");
}
}, {
key: "writeDouble",
value: function writeDouble(value) {
throw new Error(value, "writeDouble not implemented");
}
}, {
key: "writeAsciiString",
value: function writeAsciiString(value) {
throw new Error(value, "writeAsciiString not implemented");
}
}, {
key: "writeUTF8String",
value: function writeUTF8String(value) {
throw new Error(value, "writeUTF8String not implemented");
}
}, {
key: "checkSize",
value: function checkSize(step) {
throw new Error(step, "checkSize not implemented");
}
}, {
key: "concat",
value: function concat(stream) {
throw new Error(stream, "concat not implemented");
}
}]);
return ReadBufferStream;
}(BufferStream);
var WriteBufferStream = /*#__PURE__*/function (_BufferStream2) {
_inherits(WriteBufferStream, _BufferStream2);
var _super2 = _createSuper(WriteBufferStream);
function WriteBufferStream(buffer, littleEndian) {
var _this2;
_classCallCheck(this, WriteBufferStream);
_this2 = _super2.call(this, buffer, littleEndian);
_this2.size = 0;
return _this2;
}
return _createClass(WriteBufferStream);
}(BufferStream);
function rtrim(str) {
return str.replace(/\s*$/g, "");
}
function toWindows(inputArray, size) {
return Array.from({
length: inputArray.length - (size - 1)
}, //get the appropriate length
function (_, index) {
return inputArray.slice(index, index + size);
} //create the windows
);
}
var binaryVRs = ["FL", "FD", "SL", "SS", "UL", "US", "AT"],
explicitVRs = ["OB", "OW", "OF", "SQ", "UC", "UR", "UT", "UN"],
singleVRs = ["SQ", "OF", "OW", "OB", "UN"];
var ValueRepresentation = /*#__PURE__*/function () {
function ValueRepresentation(type) {
_classCallCheck(this, ValueRepresentation);
this.type = type;
this.multi = false;
this._isBinary = binaryVRs.indexOf(this.type) != -1;
this._allowMultiple = !this._isBinary && singleVRs.indexOf(this.type) == -1;
this._isExplicit = explicitVRs.indexOf(this.type) != -1;
}
_createClass(ValueRepresentation, [{
key: "isBinary",
value: function isBinary() {
return this._isBinary;
}
}, {
key: "allowMultiple",
value: function allowMultiple() {
return this._allowMultiple;
}
}, {
key: "isExplicit",
value: function isExplicit() {
return this._isExplicit;
}
}, {
key: "read",
value: function read(stream, length, syntax) {
if (this.fixed && this.maxLength) {
if (!length) return this.defaultValue;
if (this.maxLength != length) log.error("Invalid length for fixed length tag, vr " + this.type + ", length " + this.maxLength + " != " + length);
}
return this.readBytes(stream, length, syntax);
}
}, {
key: "readBytes",
value: function readBytes(stream, length) {
return stream.readAsciiString(length);
}
}, {
key: "readNullPaddedString",
value: function readNullPaddedString(stream, length) {
if (!length) return "";
if (stream.peekUint8(length - 1) !== 0) {
return stream.readAsciiString(length);
} else {
var val = stream.readAsciiString(length - 1);
stream.increment(1);
return val;
}
}
}, {
key: "write",
value: function write(stream, type) {
var args = Array.from(arguments);
if (args[2] === null || args[2] === "" || args[2] === undefined) {
return [stream.writeAsciiString("")];
} else {
var written = [],
valueArgs = args.slice(2),
func = stream["write" + type];
if (Array.isArray(valueArgs[0])) {
if (valueArgs[0].length < 1) {
written.push(0);
} else {
var self = this;
valueArgs[0].forEach(function (v, k) {
if (self.allowMultiple() && k > 0) {
stream.writeUint8(0x5c);
}
var singularArgs = [v].concat(valueArgs.slice(1));
var byteCount = func.apply(stream, singularArgs);
written.push(byteCount);
});
}
} else {
written.push(func.apply(stream, valueArgs));
}
return written;
}
}
}, {
key: "writeBytes",
value: function writeBytes(stream, value, lengths) {
var writeOptions = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {
allowInvalidVRLength: false
};
var allowInvalidVRLength = writeOptions.allowInvalidVRLength;
var valid = true,
valarr = Array.isArray(value) ? value : [value],
total = 0;
for (var i = 0; i < valarr.length; i++) {
var checkValue = valarr[i],
checklen = lengths[i],
isString = false,
displaylen = checklen;
if (checkValue === null || allowInvalidVRLength) {
valid = true;
} else if (this.checkLength) {
valid = this.checkLength(checkValue);
} else if (this.maxCharLength) {
var check = this.maxCharLength; //, checklen = checkValue.length;
valid = checkValue.length <= check;
displaylen = checkValue.length;
isString = true;
} else if (this.maxLength) {
valid = checklen <= this.maxLength;
}
if (!valid) {
var errmsg = "Value exceeds max length, vr: " + this.type + ", value: " + checkValue + ", length: " + displaylen;
if (isString) log.log(errmsg);else throw new Error(errmsg);
}
total += checklen;
}
if (this.allowMultiple()) {
total += valarr.length ? valarr.length - 1 : 0;
} //check for odd
var written = total;
if (total & 1) {
stream.writeUint8(this.padByte);
written++;
}
return written;
}
}], [{
key: "createByTypeString",
value: function createByTypeString(type) {
var vr = VRinstances[type];
if (vr === undefined) {
if (type == "ox") {
// TODO: determine VR based on context (could be 1 byte pixel data)
// https://github.com/dgobbi/vtk-dicom/issues/38
log.error("Invalid vr type " + type + " - using OW");
vr = VRinstances["OW"];
} else if (type == "xs") {
log.error("Invalid vr type " + type + " - using US");
vr = VRinstances["US"];
} else {
log.error("Invalid vr type " + type + " - using UN");
vr = VRinstances["UN"];
}
}
return vr;
}
}]);
return ValueRepresentation;
}();
var AsciiStringRepresentation = /*#__PURE__*/function (_ValueRepresentation) {
_inherits(AsciiStringRepresentation, _ValueRepresentation);
var _super = _createSuper(AsciiStringRepresentation);
function AsciiStringRepresentation(type) {
_classCallCheck(this, AsciiStringRepresentation);
return _super.call(this, type);
}
_createClass(AsciiStringRepresentation, [{
key: "readBytes",
value: function readBytes(stream, length) {
return stream.readAsciiString(length);
}
}, {
key: "writeBytes",
value: function writeBytes(stream, value, writeOptions) {
var written = _get(_getPrototypeOf(AsciiStringRepresentation.prototype), "write", this).call(this, stream, "AsciiString", value);
return _get(_getPrototypeOf(AsciiStringRepresentation.prototype), "writeBytes", this).call(this, stream, value, written, writeOptions);
}
}]);
return AsciiStringRepresentation;
}(ValueRepresentation);
var EncodedStringRepresentation = /*#__PURE__*/function (_ValueRepresentation2) {
_inherits(EncodedStringRepresentation, _ValueRepresentation2);
var _super2 = _createSuper(EncodedStringRepresentation);
function EncodedStringRepresentation(type) {
_classCallCheck(this, EncodedStringRepresentation);
return _super2.call(this, type);
}
_createClass(EncodedStringRepresentation, [{
key: "readBytes",
value: function readBytes(stream, length) {
return stream.readEncodedString(length);
}
}, {
key: "writeBytes",
value: function writeBytes(stream, value, writeOptions) {
var written = _get(_getPrototypeOf(EncodedStringRepresentation.prototype), "write", this).call(this, stream, "UTF8String", value);
return _get(_getPrototypeOf(EncodedStringRepresentation.prototype), "writeBytes", this).call(this, stream, value, written, writeOptions);
}
}]);
return EncodedStringRepresentation;
}(ValueRepresentation);
var BinaryRepresentation = /*#__PURE__*/function (_ValueRepresentation3) {
_inherits(BinaryRepresentation, _ValueRepresentation3);
var _super3 = _createSuper(BinaryRepresentation);
function BinaryRepresentation(type) {
_classCallCheck(this, BinaryRepresentation);
return _super3.call(this, type);
}
_createClass(BinaryRepresentation, [{
key: "writeBytes",
value: function writeBytes(stream, value, syntax, isEncapsulated) {
var writeOptions = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};
var i;
var binaryStream;
var _writeOptions$fragmen = writeOptions.fragmentMultiframe,
fragmentMultiframe = _writeOptions$fragmen === void 0 ? true : _writeOptions$fragmen;
value = value === null || value === undefined ? [] : value;
if (isEncapsulated) {
var fragmentSize = 1024 * 20,
frames = value.length,
startOffset = []; // Calculate a total length for storing binary stream
var bufferLength = 0;
for (i = 0; i < frames; i++) {
var needsPadding = Boolean(value[i].byteLength & 1);
bufferLength += value[i].byteLength + (needsPadding ? 1 : 0);
var _fragmentsLength = 1;
if (fragmentMultiframe) {
_fragmentsLength = Math.ceil(value[i].byteLength / fragmentSize);
} // 8 bytes per fragment are needed to store 0xffff (2 bytes), 0xe000 (2 bytes), and frageStream size (4 bytes)
bufferLength += _fragmentsLength * 8;
}
binaryStream = new WriteBufferStream(bufferLength, stream.isLittleEndian);
for (i = 0; i < frames; i++) {
var _needsPadding = Boolean(value[i].byteLength & 1);
startOffset.push(binaryStream.size);
var frameBuffer = value[i],
frameStream = new ReadBufferStream(frameBuffer);
var fragmentsLength = 1;
if (fragmentMultiframe) {
fragmentsLength = Math.ceil(frameStream.size / fragmentSize);
}
for (var j = 0, fragmentStart = 0; j < fragmentsLength; j++) {
var isFinalFragment = j === fragmentsLength - 1;
var fragmentEnd = fragmentStart + frameStream.size;
if (fragmentMultiframe) {
fragmentEnd = fragmentStart + fragmentSize;
}
if (isFinalFragment) {
fragmentEnd = frameStream.size;
}
var fragStream = new ReadBufferStream(frameStream.getBuffer(fragmentStart, fragmentEnd));
fragmentStart = fragmentEnd;
binaryStream.writeUint16(0xfffe);
binaryStream.writeUint16(0xe000);
var addPaddingByte = isFinalFragment && _needsPadding;
binaryStream.writeUint32(fragStream.size + (addPaddingByte ? 1 : 0));
binaryStream.concat(fragStream);
if (addPaddingByte) {
binaryStream.writeInt8(this.padByte);
}
}
}
stream.writeUint16(0xfffe);
stream.writeUint16(0xe000);
stream.writeUint32(startOffset.length * 4);
for (i = 0; i < startOffset.length; i++) {
stream.writeUint32(startOffset[i]);
}
stream.concat(binaryStream);
stream.writeUint16(0xfffe);
stream.writeUint16(0xe0dd);
stream.writeUint32(0x0);
return 0xffffffff;
} else {
var binaryData = value[0];
binaryStream = new ReadBufferStream(binaryData);
stream.concat(binaryStream);
return _get(_getPrototypeOf(BinaryRepresentation.prototype), "writeBytes", this).call(this, stream, binaryData, [binaryStream.size], writeOptions);
}
}
}, {
key: "readBytes",
value: function readBytes(stream, length) {
if (length == 0xffffffff) {
var itemTagValue = Tag.readTag(stream),
frames = [];
if (itemTagValue.is(0xfffee000)) {
var itemLength = stream.readUint32(),
numOfFrames = 1,
offsets = [];
if (itemLength > 0x0) {
//has frames
numOfFrames = itemLength / 4;
var i = 0;
while (i++ < numOfFrames) {
offsets.push(stream.readUint32());
}
} else {
offsets = [];
}
var SequenceItemTag = 0xfffee000;
var SequenceDelimiterTag = 0xfffee0dd;
var getNextSequenceItemData = function getNextSequenceItemData(stream) {
var nextTag = Tag.readTag(stream);
if (nextTag.is(SequenceItemTag)) {
var _itemLength = stream.readUint32();
var buffer = stream.getBuffer(stream.offset, stream.offset + _itemLength);
stream.increment(_itemLength);
return buffer;
} else if (nextTag.is(SequenceDelimiterTag)) {
// Read SequenceDelimiterItem value for the SequenceDelimiterTag
if (stream.readUint32() !== 0) {
throw Error("SequenceDelimiterItem tag value was not zero");
}
return null;
}
throw Error("Invalid tag in sequence");
}; // If there is an offset table, use that to loop through pixel data sequence
if (offsets.length > 0) {
// make offsets relative to the stream, not tag
offsets = offsets.map(function (e) {
return e + stream.offset;
});
offsets.push(stream.size); // window offsets to an array of [start,stop] locations
frames = toWindows(offsets, 2).map(function (rang