@abasb75/dicom-parser
Version:
a javascript powerfull dicom parser
318 lines (317 loc) • 12.1 kB
JavaScript
import Dataset from "./Dataset";
import Tag from "./Tag";
import Value from "./Value";
import * as pako from "pako";
var Parser = /** @class */ (function () {
function Parser(arrayBuffer) {
Object.defineProperty(this, "start", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "end", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "arrayBuffer", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "offset", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "startOfset", {
enumerable: true,
configurable: true,
writable: true,
value: 132
});
Object.defineProperty(this, "dataView", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "tags", {
enumerable: true,
configurable: true,
writable: true,
value: {}
});
Object.defineProperty(this, "dataSet", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "EXEPTED", {
enumerable: true,
configurable: true,
writable: true,
value: ["OB", "OW", "SQ", "UN", "UT", "OF", "UC", "OD"]
});
Object.defineProperty(this, "VRS", {
enumerable: true,
configurable: true,
writable: true,
value: ["AE", "AS", "AT", "CS", "DA", "DS", "DT", "FL", "FD", "IS", "LO", "LT", "OB", "OD", "OF", "OW", "PN", "SH", "SL", "SS", "ST", "TM", "UI", "UL", "UN", "US", "UT", "UC"]
});
Object.defineProperty(this, "IMPLICT_TRANSFER_SYNTAXES", {
enumerable: true,
configurable: true,
writable: true,
value: ["1.2.840.10008.1.2"]
});
Object.defineProperty(this, "BIG_ENDIAN_TRANSFER_SYNTAXES", {
enumerable: true,
configurable: true,
writable: true,
value: ["1.2.840.10008.1.2.2"]
});
Object.defineProperty(this, "DEFLATED_TRANSFER_SYNTAXES", {
enumerable: true,
configurable: true,
writable: true,
value: ["1.2.840.10008.1.2.1.99"]
});
Object.defineProperty(this, "littleEndian", {
enumerable: true,
configurable: true,
writable: true,
value: true
});
Object.defineProperty(this, "implicit", {
enumerable: true,
configurable: true,
writable: true,
value: false
});
Object.defineProperty(this, "transferSyntaxUID", {
enumerable: true,
configurable: true,
writable: true,
value: ""
});
// private UNDEFIENED_LEN:number = 0xffffffff;
Object.defineProperty(this, "inflated", {
enumerable: true,
configurable: true,
writable: true,
value: false
});
Object.defineProperty(this, "concatArrayBuffers", {
enumerable: true,
configurable: true,
writable: true,
value: function (buffer1, buffer2) {
var tmp = new Uint8Array(buffer1.byteLength + buffer2.byteLength);
tmp.set(new Uint8Array(buffer1), 0);
tmp.set(new Uint8Array(buffer2), buffer1.byteLength);
return tmp.buffer;
}
});
this.start = Date.now();
this.offset = 0;
this.arrayBuffer = arrayBuffer;
this.dataView = new DataView(arrayBuffer);
if (this.arrayBuffer.byteLength < 132) {
return;
}
var prefix = Value.getString(new Uint8Array(arrayBuffer, 128, 4));
if (prefix === 'DICM') {
this.offset = 132;
}
else {
this.offset = 0;
while (Value.getString(this.dataView.buffer.slice(this.offset, this.offset + 1)) === "") {
this.offset++;
}
this.startOfset = this.offset;
}
this.parse();
}
Object.defineProperty(Parser.prototype, "parse", {
enumerable: false,
configurable: true,
writable: true,
value: function () {
this.tags = this.getElements();
this.end = Date.now();
this.dataSet = new Dataset(this.tags, this.dataView, this.littleEndian, this.start, this.end);
this.dataSet.transferSyntaxUID = this.transferSyntaxUID;
return this.dataSet;
}
});
Object.defineProperty(Parser.prototype, "getDataset", {
enumerable: false,
configurable: true,
writable: true,
value: function () {
return this.dataSet;
}
});
Object.defineProperty(Parser.prototype, "getElements", {
enumerable: false,
configurable: true,
writable: true,
value: function (sqLen) {
var tags = {};
var targetOfset = (sqLen !== undefined)
? (this.offset + sqLen) : this.arrayBuffer.byteLength;
while (this.offset < targetOfset) {
var _a = this.getNextGroupAndElement(), group = _a.group, element = _a.element;
if (!group && !element) {
break;
}
if (sqLen && group === 0xFFFE && (element === 0xE00D || element === 0xE0DD)) {
this.offset += 4;
return tags;
}
if (group === 0xFFFE && (element === 0xE0DD || element === 0xE00D || element === 0xE000)) {
this.offset += 4;
continue;
}
if (!this.implicit && group !== 0x0002 && this.IMPLICT_TRANSFER_SYNTAXES.includes(this.transferSyntaxUID)) {
this.implicit = true;
}
if (this.littleEndian && group !== 0x0002
&& this.BIG_ENDIAN_TRANSFER_SYNTAXES.includes(this.transferSyntaxUID)) {
this.littleEndian = false;
}
if (!this.inflated && group !== 0x0002 && this.DEFLATED_TRANSFER_SYNTAXES.includes(this.transferSyntaxUID)) {
this.offset -= 4;
var meta = this.dataView.buffer.slice(0, this.offset);
var body = this.dataView.buffer.slice(this.offset);
var infaltedBody = pako.inflateRaw(body);
this.arrayBuffer = this.concatArrayBuffers(meta, infaltedBody);
this.dataView = new DataView(this.arrayBuffer);
this.inflated = true;
return this.getElements();
}
var vr = this.getNextVR(group, element);
var len = 0;
if (this.implicit) {
len = this.dataView.getUint32(this.offset, this.littleEndian);
this.offset += 4;
}
else if (this.EXEPTED.includes(vr)) {
this.offset += 2; // skip 2 byte reserved
len = this.dataView.getUint32(this.offset, this.littleEndian);
this.offset += 4;
}
else if (this.VRS.includes(vr)) {
len = this.dataView.getUint16(this.offset, this.littleEndian);
this.offset += 2;
}
else if ((!vr || !vr.match(/^[A-Z]{2}$/)) && group === 0x0002 && element === 0x0000) {
this.offset = this.startOfset;
this.tags = {};
this.implicit = true;
continue;
}
else {
this.offset -= 6;
this.implicit = true;
continue;
}
if (group === 0x0002 && element === 0x0010) {
this.transferSyntaxUID = (Value.getString(new Uint8Array(this.arrayBuffer, this.offset, len))).replace('\0', '');
}
// find dataset thats may be as big endian dicom.
// if(
// this.littleEndian
// && Object.keys(tags)?.length===0
// && len > this.dataView.byteLength
// ){
// console.log({group,element,len,vr});
// this.littleEndian =false;
// this.offset = this.startOfset;
// return this.getElements();
// }else{
// console.log({group,element,len,vr});
// return tags;
// }
var tag = new Tag(group, element, vr, len, this.offset);
if (len === 0xFFFFFFFF && group === 0x7FE0 && element === 0x0010) {
var _b = this.getNextGroupAndElement(), group_1 = _b.group, element_1 = _b.element;
while (true) {
if (group_1 === 0xFFFE && element_1 === 0xE000) {
var len_1 = this.dataView.getUint32(this.offset, this.littleEndian);
this.offset += 4;
var t = this.getNextGroupAndElement();
group_1 = t.group;
element_1 = t.element;
this.offset += len_1;
}
else {
break;
}
}
this.offset -= 4;
}
if (vr === "SQ") {
tag.value = this.getElements(len);
}
else {
this.offset += len;
}
var key = tag.generateKey();
tags[key] = tag;
}
return tags;
}
});
Object.defineProperty(Parser.prototype, "getValue", {
enumerable: false,
configurable: true,
writable: true,
value: function (len) {
var value = this.arrayBuffer.slice(this.offset, len);
this.offset += len;
return value;
}
});
Object.defineProperty(Parser.prototype, "getNextGroupAndElement", {
enumerable: false,
configurable: true,
writable: true,
value: function () {
try {
var group = this.dataView.getUint16(this.offset, this.littleEndian);
this.offset += 2;
var element = this.dataView.getUint16(this.offset, this.littleEndian);
this.offset += 2;
return { group: group, element: element };
}
catch (_a) {
return { group: 0, element: 0 };
}
}
});
Object.defineProperty(Parser.prototype, "getNextVR", {
enumerable: false,
configurable: true,
writable: true,
value: function (groupInt, elementInt) {
if (this.offset >= this.dataView.byteLength) {
return "";
}
if (this.implicit) {
return Tag.getTagVRFromDictionary(groupInt, elementInt) || "AA";
}
var vr = Value.getString(new Uint8Array(this.arrayBuffer, this.offset, 2));
this.offset += 2;
return vr;
}
});
return Parser;
}());
export default Parser;