@abasb75/dicom-parser 0.0.0-test

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/Dataset.d.ts ADDED
@@ -0,0 +1,11 @@
1
+ import { Tags } from "./types";
2
+ declare class Dataset {
3
+ tags: Tags;
4
+ arrayBuffer: ArrayBuffer;
5
+ transferSyntaxUID: string;
6
+ constructor(tags: Tags, arrayBuffer: ArrayBuffer);
7
+ getValue(element: number | string, elementId?: number | string, vr?: string): "" | undefined;
8
+ private _getValue;
9
+ private _reformatToString;
10
+ }
11
+ export default Dataset;
package/Dataset.js ADDED
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const Tag_1 = require("./Tag");
4
+ const Value_1 = require("./Value");
5
+ class Dataset {
6
+ constructor(tags, arrayBuffer) {
7
+ Object.defineProperty(this, "tags", {
8
+ enumerable: true,
9
+ configurable: true,
10
+ writable: true,
11
+ value: void 0
12
+ });
13
+ Object.defineProperty(this, "arrayBuffer", {
14
+ enumerable: true,
15
+ configurable: true,
16
+ writable: true,
17
+ value: void 0
18
+ });
19
+ Object.defineProperty(this, "transferSyntaxUID", {
20
+ enumerable: true,
21
+ configurable: true,
22
+ writable: true,
23
+ value: "1.2.840.10008.1.2"
24
+ });
25
+ this.tags = tags;
26
+ this.arrayBuffer = arrayBuffer;
27
+ }
28
+ getValue(element, elementId, vr) {
29
+ var _a;
30
+ if (!element && !elementId) {
31
+ return "";
32
+ }
33
+ let _group, _element = "";
34
+ if (typeof element === 'string' && element.length >= 8) {
35
+ const el = element.replace(/^0[xX]/, '');
36
+ if (el.length !== 8) {
37
+ return "";
38
+ }
39
+ _group = el.slice(0, 3);
40
+ _element = el.slice(4, 7);
41
+ }
42
+ else if (typeof element === 'number' && element > 0xffff) {
43
+ const el = Tag_1.default.intTo4digitString(element);
44
+ _group = el.slice(0, 3);
45
+ _element = el.slice(4, 7);
46
+ }
47
+ else {
48
+ _group = this._reformatToString(element);
49
+ _element = this._reformatToString(elementId);
50
+ if (!_group || _element)
51
+ return "";
52
+ }
53
+ const key = `0x${_group}${_element}`;
54
+ if (!this.tags[key]) {
55
+ return "";
56
+ }
57
+ const _vr = vr || ((_a = this.tags[key]) === null || _a === void 0 ? void 0 : _a.vr) || Tag_1.default.getTagVRFromDictionary(_group, _element) || "AA";
58
+ return this._getValue(this.tags[key], _vr);
59
+ }
60
+ _getValue(tag, vr = "AA") {
61
+ const offset = tag.offset;
62
+ if (!offset)
63
+ return "";
64
+ const len = tag.valueLength;
65
+ const value = this.arrayBuffer.slice(offset, len);
66
+ const formedValue = Value_1.default.byVr(value, vr);
67
+ tag.value = formedValue;
68
+ }
69
+ _reformatToString(input) {
70
+ if (!input)
71
+ return "";
72
+ if (typeof input === "string") {
73
+ return input.replace(/^0[xX]/, '');
74
+ }
75
+ return Tag_1.default.intTo4digitString(input);
76
+ }
77
+ }
78
+ exports.default = Dataset;
package/Loader.d.ts ADDED
@@ -0,0 +1,8 @@
1
+ declare class Loader {
2
+ private dicomSrc;
3
+ private xhr;
4
+ constructor(dicomSrc?: string);
5
+ load(dicomSrc?: string | File): Promise<ArrayBuffer | undefined>;
6
+ cancel(): void;
7
+ }
8
+ export default Loader;
package/Loader.js ADDED
@@ -0,0 +1,65 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ class Loader {
13
+ constructor(dicomSrc) {
14
+ Object.defineProperty(this, "dicomSrc", {
15
+ enumerable: true,
16
+ configurable: true,
17
+ writable: true,
18
+ value: void 0
19
+ });
20
+ Object.defineProperty(this, "xhr", {
21
+ enumerable: true,
22
+ configurable: true,
23
+ writable: true,
24
+ value: void 0
25
+ });
26
+ this.dicomSrc = dicomSrc;
27
+ this.xhr = new XMLHttpRequest();
28
+ }
29
+ load(dicomSrc) {
30
+ return __awaiter(this, void 0, void 0, function* () {
31
+ if (typeof dicomSrc === "string") {
32
+ const dicom = dicomSrc || this.dicomSrc;
33
+ if (!dicom)
34
+ return;
35
+ return new Promise((resolve, reject) => {
36
+ this.xhr.onload = () => {
37
+ resolve(this.xhr.response);
38
+ };
39
+ this.xhr.onerror = () => {
40
+ reject(this.xhr);
41
+ };
42
+ this.xhr.responseType = 'arraybuffer';
43
+ this.xhr.open('GET', dicom, true);
44
+ this.xhr.send();
45
+ });
46
+ }
47
+ else if (dicomSrc instanceof File) {
48
+ return new Promise((resolve, reject) => {
49
+ dicomSrc.arrayBuffer().then((arrayBuffer) => {
50
+ resolve(arrayBuffer);
51
+ }).catch(reason => reject(reason));
52
+ });
53
+ }
54
+ return new Promise((resolve, reject) => {
55
+ if (false)
56
+ resolve(new ArrayBuffer(1));
57
+ reject("dicom source is not valid");
58
+ });
59
+ });
60
+ }
61
+ cancel() {
62
+ this.xhr.abort();
63
+ }
64
+ }
65
+ exports.default = Loader;
package/Parser.d.ts ADDED
@@ -0,0 +1,29 @@
1
+ import Dataset from "./Dataset";
2
+ declare class Parser {
3
+ private arrayBuffer;
4
+ private offset;
5
+ private dataView;
6
+ private tags;
7
+ private dataSet;
8
+ private EXEPTED;
9
+ private VRS;
10
+ private IMPLICT_TRANSFER_SYNTAXES;
11
+ private BIG_ENDIAN_TRANSFER_SYNTAXES;
12
+ private DEFLATED_TRANSFER_SYNTAXES;
13
+ private littleEndian;
14
+ private implicit;
15
+ private transferSyntaxUID;
16
+ private inflated;
17
+ constructor(arrayBuffer: ArrayBuffer);
18
+ parse(): Dataset;
19
+ getDataset(): Dataset | undefined;
20
+ getNextTag(): void;
21
+ getValue(len: number): ArrayBuffer;
22
+ getNextGroupAndElement(): {
23
+ group: number;
24
+ element: number;
25
+ };
26
+ getNextVR(groupInt: number, elementInt: number): string;
27
+ concatArrayBuffers: (buffer1: ArrayBuffer, buffer2: ArrayBuffer) => ArrayBufferLike;
28
+ }
29
+ export default Parser;
package/Parser.js ADDED
@@ -0,0 +1,225 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const Dataset_1 = require("./Dataset");
4
+ const Tag_1 = require("./Tag");
5
+ const Value_1 = require("./Value");
6
+ const pako_1 = require("pako");
7
+ class Parser {
8
+ constructor(arrayBuffer) {
9
+ Object.defineProperty(this, "arrayBuffer", {
10
+ enumerable: true,
11
+ configurable: true,
12
+ writable: true,
13
+ value: void 0
14
+ });
15
+ Object.defineProperty(this, "offset", {
16
+ enumerable: true,
17
+ configurable: true,
18
+ writable: true,
19
+ value: void 0
20
+ });
21
+ Object.defineProperty(this, "dataView", {
22
+ enumerable: true,
23
+ configurable: true,
24
+ writable: true,
25
+ value: void 0
26
+ });
27
+ Object.defineProperty(this, "tags", {
28
+ enumerable: true,
29
+ configurable: true,
30
+ writable: true,
31
+ value: {}
32
+ });
33
+ Object.defineProperty(this, "dataSet", {
34
+ enumerable: true,
35
+ configurable: true,
36
+ writable: true,
37
+ value: void 0
38
+ });
39
+ Object.defineProperty(this, "EXEPTED", {
40
+ enumerable: true,
41
+ configurable: true,
42
+ writable: true,
43
+ value: ["OB", "OW", "SQ", "UN"]
44
+ });
45
+ Object.defineProperty(this, "VRS", {
46
+ enumerable: true,
47
+ configurable: true,
48
+ writable: true,
49
+ 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"]
50
+ });
51
+ Object.defineProperty(this, "IMPLICT_TRANSFER_SYNTAXES", {
52
+ enumerable: true,
53
+ configurable: true,
54
+ writable: true,
55
+ value: ["1.2.840.10008.1.2"]
56
+ });
57
+ Object.defineProperty(this, "BIG_ENDIAN_TRANSFER_SYNTAXES", {
58
+ enumerable: true,
59
+ configurable: true,
60
+ writable: true,
61
+ value: ["1.2.840.10008.1.2.2"]
62
+ });
63
+ Object.defineProperty(this, "DEFLATED_TRANSFER_SYNTAXES", {
64
+ enumerable: true,
65
+ configurable: true,
66
+ writable: true,
67
+ value: ["1.2.840.10008.1.2.1.99"]
68
+ });
69
+ Object.defineProperty(this, "littleEndian", {
70
+ enumerable: true,
71
+ configurable: true,
72
+ writable: true,
73
+ value: true
74
+ });
75
+ Object.defineProperty(this, "implicit", {
76
+ enumerable: true,
77
+ configurable: true,
78
+ writable: true,
79
+ value: false
80
+ });
81
+ Object.defineProperty(this, "transferSyntaxUID", {
82
+ enumerable: true,
83
+ configurable: true,
84
+ writable: true,
85
+ value: ""
86
+ });
87
+ // private UNDEFIENED_LEN:number = 0xffffffff;
88
+ Object.defineProperty(this, "inflated", {
89
+ enumerable: true,
90
+ configurable: true,
91
+ writable: true,
92
+ value: false
93
+ });
94
+ Object.defineProperty(this, "concatArrayBuffers", {
95
+ enumerable: true,
96
+ configurable: true,
97
+ writable: true,
98
+ value: function (buffer1, buffer2) {
99
+ var tmp = new Uint8Array(buffer1.byteLength + buffer2.byteLength);
100
+ tmp.set(new Uint8Array(buffer1), 0);
101
+ tmp.set(new Uint8Array(buffer2), buffer1.byteLength);
102
+ return tmp.buffer;
103
+ }
104
+ });
105
+ this.offset = 0;
106
+ this.arrayBuffer = arrayBuffer;
107
+ this.dataView = new DataView(arrayBuffer);
108
+ if (this.arrayBuffer.byteLength < 132) {
109
+ console.error("is not valid dicom file");
110
+ return;
111
+ }
112
+ const prefix = Value_1.default.getString(new Uint8Array(arrayBuffer, 128, 4));
113
+ if (prefix !== 'DICM') {
114
+ console.error("is not valid dicom file");
115
+ return;
116
+ }
117
+ this.offset = 132;
118
+ this.parse();
119
+ }
120
+ parse() {
121
+ this.getNextTag();
122
+ this.dataSet = new Dataset_1.default(this.tags, this.arrayBuffer);
123
+ console.log(this.dataSet);
124
+ this.dataSet.transferSyntaxUID = this.transferSyntaxUID;
125
+ return this.dataSet;
126
+ }
127
+ getDataset() {
128
+ return this.dataSet;
129
+ }
130
+ getNextTag() {
131
+ if (this.offset >= this.arrayBuffer.byteLength) {
132
+ return;
133
+ }
134
+ const { group, element } = this.getNextGroupAndElement();
135
+ if (!group && !element) {
136
+ return;
137
+ }
138
+ if (group === 0xFFFE && (element === 0xE0DD || element === 0xE00D || element === 0xE000)) {
139
+ this.offset += 4;
140
+ return this.getNextTag();
141
+ }
142
+ if (!this.implicit && group !== 0x0002 && this.IMPLICT_TRANSFER_SYNTAXES.includes(this.transferSyntaxUID)) {
143
+ this.implicit = true;
144
+ }
145
+ if (this.littleEndian && group !== 0x0002 && this.BIG_ENDIAN_TRANSFER_SYNTAXES.includes(this.transferSyntaxUID)) {
146
+ this.littleEndian = false;
147
+ }
148
+ if (!this.inflated && group !== 0x0002 && this.DEFLATED_TRANSFER_SYNTAXES.includes(this.transferSyntaxUID)) {
149
+ this.offset -= 4;
150
+ const meta = this.dataView.buffer.slice(0, this.offset);
151
+ const body = this.dataView.buffer.slice(this.offset);
152
+ const infaltedBody = pako_1.default.inflateRaw(body);
153
+ this.arrayBuffer = this.concatArrayBuffers(meta, infaltedBody);
154
+ this.dataView = new DataView(this.arrayBuffer);
155
+ this.inflated = true;
156
+ return this.getNextTag();
157
+ }
158
+ const vr = this.getNextVR(group, element);
159
+ let len = 0;
160
+ if (this.implicit) {
161
+ len = this.dataView.getUint32(this.offset, this.littleEndian);
162
+ this.offset += 4;
163
+ }
164
+ else if (this.EXEPTED.includes(vr)) {
165
+ this.offset += 2; // skip 2 byte reserved
166
+ len = this.dataView.getUint32(this.offset, this.littleEndian);
167
+ this.offset += 4;
168
+ }
169
+ else if (this.VRS.includes(vr)) {
170
+ len = this.dataView.getUint16(this.offset, this.littleEndian);
171
+ this.offset += 2;
172
+ }
173
+ else if ((!vr || !vr.match(/^[A-Z]{2}$/)) && group === 0x0002 && element === 0x0000) {
174
+ console.log("pyz");
175
+ this.offset = 132;
176
+ this.tags = {};
177
+ this.implicit = true;
178
+ return this.getNextTag();
179
+ }
180
+ else {
181
+ console.log("ended", vr);
182
+ return;
183
+ }
184
+ if (group === 0x0002 && element === 0x0010) {
185
+ console.log("transfer syntax uid", this.transferSyntaxUID);
186
+ this.transferSyntaxUID = (Value_1.default.getString(new Uint8Array(this.arrayBuffer, this.offset, len))).replace('\0', '');
187
+ }
188
+ const tag = new Tag_1.default(group, element, vr, len, this.offset);
189
+ const key = tag.generateKey();
190
+ this.tags[key] = tag;
191
+ if (vr === "SQ") {
192
+ this.getNextTag();
193
+ }
194
+ else {
195
+ this.offset += len;
196
+ this.getNextTag();
197
+ }
198
+ }
199
+ getValue(len) {
200
+ const value = this.arrayBuffer.slice(this.offset, len);
201
+ this.offset += len;
202
+ return value;
203
+ }
204
+ getNextGroupAndElement() {
205
+ try {
206
+ const group = this.dataView.getUint16(this.offset, this.littleEndian);
207
+ this.offset += 2;
208
+ const element = this.dataView.getUint16(this.offset, this.littleEndian);
209
+ this.offset += 2;
210
+ return { group, element };
211
+ }
212
+ catch (_a) {
213
+ return { group: 0, element: 0 };
214
+ }
215
+ }
216
+ getNextVR(groupInt, elementInt) {
217
+ if (this.implicit) {
218
+ return Tag_1.default.getTagVRFromDictionary(groupInt, elementInt) || "AA";
219
+ }
220
+ const vr = Value_1.default.getString(new Uint8Array(this.arrayBuffer, this.offset, 2));
221
+ this.offset += 2;
222
+ return vr;
223
+ }
224
+ }
225
+ exports.default = Parser;
package/README.md ADDED
@@ -0,0 +1,68 @@
1
+ # @abasb75/dicom-parser
2
+
3
+ ```sh
4
+ npm i @abasb75/dicom-parser --save
5
+ ```
6
+
7
+
8
+ #Usage
9
+
10
+ 1. For Download dicom and parse from url:
11
+
12
+ ```javascript
13
+ import { loadAndParseFromUrl } from "@abasb75/dicom-parser";
14
+
15
+ ...
16
+ const url = "....dcm";
17
+ loadAndParseFromUrl(url)
18
+ .then(dataset=>{
19
+ console.log(dataset);
20
+ })
21
+ .catch(err=>{
22
+ console.log(error);
23
+ })
24
+
25
+ ```
26
+
27
+
28
+ 2. For parse dataset from local files:
29
+
30
+ ```javascript
31
+ import { loadAndParseFromFiles } from "@abasb75/dicom-parser";
32
+
33
+ ...
34
+
35
+ loadAndParseFromFiles(file)
36
+ .then(dataset=>{
37
+ console.log(dataset);
38
+ })
39
+ .catch(err=>{
40
+ console.log(error);
41
+ });
42
+
43
+ ```
44
+
45
+ 3. For parsing arrayBuffer:
46
+
47
+ ```javascript
48
+ import { parse } from "@abasb75/dicom-parser";
49
+
50
+ ...
51
+
52
+ const dataset = parse(arrayBuffer);
53
+
54
+ ```
55
+
56
+
57
+ 4. Getting value for dicom tag
58
+
59
+ ```javascript
60
+
61
+ ...
62
+
63
+ const transferSyntaxUID = dataset.get(0x0002,0x0010);
64
+ const transferSyntaxUID = dataset.string(0x0002,0x0010);
65
+
66
+ ...
67
+
68
+ ```
package/Tag.d.ts ADDED
@@ -0,0 +1,17 @@
1
+ declare class Tag {
2
+ name: string;
3
+ vr: string;
4
+ group: number;
5
+ element: number;
6
+ value: unknown;
7
+ valueLength: number;
8
+ offset: number;
9
+ constructor(group: number, element: number, vr: string, valueLength: number, offset: number, value?: ArrayBuffer, name?: string | null);
10
+ generateKey(): string;
11
+ static getTagNameFromDictionary(groupInt: number, elementInt: number): string;
12
+ static getTagVRFromDictionary(group: number | string, element: number | string): string;
13
+ static intTo4digitString(int: number): string;
14
+ static int8digitString(int: number): string;
15
+ getValue(): void;
16
+ }
17
+ export default Tag;
package/Tag.js ADDED
@@ -0,0 +1,99 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const TagsDictionary_1 = require("./enums/TagsDictionary");
4
+ class Tag {
5
+ constructor(group, element, vr, valueLength, offset, value, name) {
6
+ Object.defineProperty(this, "name", {
7
+ enumerable: true,
8
+ configurable: true,
9
+ writable: true,
10
+ value: void 0
11
+ });
12
+ Object.defineProperty(this, "vr", {
13
+ enumerable: true,
14
+ configurable: true,
15
+ writable: true,
16
+ value: void 0
17
+ });
18
+ Object.defineProperty(this, "group", {
19
+ enumerable: true,
20
+ configurable: true,
21
+ writable: true,
22
+ value: void 0
23
+ });
24
+ Object.defineProperty(this, "element", {
25
+ enumerable: true,
26
+ configurable: true,
27
+ writable: true,
28
+ value: void 0
29
+ });
30
+ Object.defineProperty(this, "value", {
31
+ enumerable: true,
32
+ configurable: true,
33
+ writable: true,
34
+ value: void 0
35
+ });
36
+ Object.defineProperty(this, "valueLength", {
37
+ enumerable: true,
38
+ configurable: true,
39
+ writable: true,
40
+ value: void 0
41
+ });
42
+ Object.defineProperty(this, "offset", {
43
+ enumerable: true,
44
+ configurable: true,
45
+ writable: true,
46
+ value: void 0
47
+ });
48
+ this.group = group;
49
+ this.element = element;
50
+ this.vr = vr;
51
+ this.name = name || Tag.getTagNameFromDictionary(this.group, this.element) || '';
52
+ this.value = value || undefined;
53
+ this.valueLength = valueLength;
54
+ this.offset = offset;
55
+ if (this.name === '') {
56
+ }
57
+ }
58
+ generateKey() {
59
+ const group = Tag.intTo4digitString(this.group);
60
+ const element = Tag.intTo4digitString(this.element);
61
+ return `0x${group}${element}`;
62
+ }
63
+ static getTagNameFromDictionary(groupInt, elementInt) {
64
+ const group = Tag.intTo4digitString(groupInt);
65
+ const element = Tag.intTo4digitString(elementInt);
66
+ const groupItems = TagsDictionary_1.default[group];
67
+ if (!groupItems)
68
+ return "";
69
+ const elementItem = groupItems[element];
70
+ if (!elementItem)
71
+ return "";
72
+ return elementItem[1];
73
+ }
74
+ static getTagVRFromDictionary(group, element) {
75
+ let _group, _element;
76
+ if (typeof group === "number") {
77
+ _group = Tag.intTo4digitString(group);
78
+ }
79
+ if (typeof element === "number") {
80
+ _element = Tag.intTo4digitString(element);
81
+ }
82
+ const groupItems = TagsDictionary_1.default[_group || group];
83
+ if (!groupItems)
84
+ return "";
85
+ const elementItem = groupItems[_element || element];
86
+ if (!elementItem)
87
+ return "";
88
+ return elementItem[0];
89
+ }
90
+ static intTo4digitString(int) {
91
+ return ('0000' + int.toString(16).toUpperCase()).slice(-4);
92
+ }
93
+ static int8digitString(int) {
94
+ return ('00000000' + int.toString(16).toUpperCase()).slice(-8);
95
+ }
96
+ getValue() {
97
+ }
98
+ }
99
+ exports.default = Tag;
package/Value.d.ts ADDED
@@ -0,0 +1,5 @@
1
+ declare class Value {
2
+ static byVr(arrayBuffer: ArrayBuffer, vr: string): string;
3
+ static getString(bytes: Uint8Array | Int8Array | ArrayBuffer): string;
4
+ }
5
+ export default Value;
package/Value.js ADDED
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ class Value {
4
+ static byVr(arrayBuffer, vr) {
5
+ switch (vr) {
6
+ case "UL":
7
+ default:
8
+ return Value.getString(arrayBuffer);
9
+ }
10
+ }
11
+ static getString(bytes) {
12
+ const decoder = new TextDecoder();
13
+ return decoder.decode(bytes);
14
+ }
15
+ }
16
+ exports.default = Value;
package/dic.d.ts ADDED
@@ -0,0 +1,8 @@
1
+ export declare const dict: {
2
+ "6": string;
3
+ Tag: string;
4
+ Name: string;
5
+ Keyword: string;
6
+ VR: string;
7
+ VM: string;
8
+ }[];