dcmjs 0.24.1 → 0.24.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dcmjs",
3
- "version": "0.24.1",
3
+ "version": "0.24.2",
4
4
  "description": "Javascript implementation of DICOM manipulation",
5
5
  "main": "build/dcmjs.js",
6
6
  "module": "build/dcmjs.es.js",
@@ -0,0 +1,237 @@
1
+ import "regenerator-runtime/runtime.js";
2
+
3
+ import dcmjs from "../src/index.js";
4
+ import fs from "fs";
5
+ import path from "path";
6
+ import os from "os";
7
+ import followRedirects from "follow-redirects";
8
+ const { https } = followRedirects;
9
+ import { promisify } from "util";
10
+ import unzipper from "unzipper";
11
+ import fsPromises from "fs/promises";
12
+
13
+ const {
14
+ DicomMetaDictionary,
15
+ DicomDict,
16
+ DicomMessage,
17
+ ReadBufferStream
18
+ } = dcmjs.data;
19
+
20
+ function downloadToFile(url, filePath) {
21
+ return new Promise((resolve, reject) => {
22
+ const fileStream = fs.createWriteStream(filePath);
23
+ https
24
+ .get(url, response => {
25
+ response.pipe(fileStream);
26
+ fileStream.on("finish", () => {
27
+ resolve(filePath);
28
+ });
29
+ })
30
+ .on("error", reject);
31
+ });
32
+ }
33
+
34
+ const areEqual = (first, second) =>
35
+ first.byteLength === second.byteLength &&
36
+ first.every((value, index) => value === second[index]);
37
+
38
+ it("test_untilTag", () => {
39
+ const buffer = fs.readFileSync("test/sample-dicom.dcm");
40
+ console.time("readFile");
41
+ const fullData = DicomMessage.readFile(buffer.buffer);
42
+ console.timeEnd("readFile");
43
+
44
+ console.time("readFile without untilTag");
45
+ const dicomData = DicomMessage.readFile(buffer.buffer, {
46
+ untilTag: "7FE00010",
47
+ includeUntilTagValue: false
48
+ });
49
+ console.timeEnd("readFile without untilTag");
50
+
51
+ console.time("readFile with untilTag");
52
+ const dicomData2 = DicomMessage.readFile(buffer.buffer, {
53
+ untilTag: "7FE00010",
54
+ includeUntilTagValue: true
55
+ });
56
+ console.timeEnd("readFile with untilTag");
57
+
58
+ const full_dataset = DicomMetaDictionary.naturalizeDataset(fullData.dict);
59
+ full_dataset._meta = DicomMetaDictionary.namifyDataset(fullData.meta);
60
+
61
+ const dataset = DicomMetaDictionary.naturalizeDataset(dicomData.dict);
62
+ dataset._meta = DicomMetaDictionary.namifyDataset(dicomData.meta);
63
+
64
+ const dataset2 = DicomMetaDictionary.naturalizeDataset(dicomData2.dict);
65
+ dataset2._meta = DicomMetaDictionary.namifyDataset(dicomData2.meta);
66
+
67
+ expect(full_dataset.PixelData).toEqual(dataset2.PixelData);
68
+ expect(dataset.PixelData).toEqual(0);
69
+ });
70
+
71
+ it("noCopy multiframe DICOM which has trailing padding", async () => {
72
+ const dicomUrl =
73
+ "https://github.com/dcmjs-org/data/releases/download/binary-parsing-stressors/multiframe-ultrasound.dcm";
74
+ const dicomPath = path.join(os.tmpdir(), "multiframe-ultrasound.dcm");
75
+
76
+ await downloadToFile(dicomUrl, dicomPath);
77
+
78
+ const dicomDictNoCopy = DicomMessage.readFile(
79
+ fs.readFileSync(dicomPath).buffer,
80
+ {
81
+ noCopy: true
82
+ }
83
+ );
84
+
85
+ const dicomDict = DicomMessage.readFile(fs.readFileSync(dicomPath).buffer, {
86
+ noCopy: false
87
+ });
88
+
89
+ Object.keys(dicomDict.dict).map(key => {
90
+ const value = dicomDict.dict[key].Value;
91
+ if (value[0] instanceof ArrayBuffer) {
92
+ value.map((e, idx) => {
93
+ const noCopyValue = dicomDictNoCopy.dict[key].Value[idx];
94
+ const copyValue = new Uint8Array(e);
95
+ expect(areEqual(noCopyValue, copyValue)).toEqual(true);
96
+ });
97
+ }
98
+ });
99
+ });
100
+
101
+ it("noCopy multiframe DICOM with large private tags before and after the image data", async () => {
102
+ const dicomUrl =
103
+ "https://github.com/dcmjs-org/data/releases/download/binary-parsing-stressors/large-private-tags.dcm";
104
+ const dicomPath = path.join(os.tmpdir(), "large-private-tags.dcm");
105
+
106
+ await downloadToFile(dicomUrl, dicomPath);
107
+
108
+ const dicomDictNoCopy = DicomMessage.readFile(
109
+ fs.readFileSync(dicomPath).buffer,
110
+ {
111
+ noCopy: true
112
+ }
113
+ );
114
+
115
+ const dicomDict = DicomMessage.readFile(fs.readFileSync(dicomPath).buffer, {
116
+ noCopy: false
117
+ });
118
+
119
+ Object.keys(dicomDict.dict).map(key => {
120
+ const value = dicomDict.dict[key].Value;
121
+ if (value[0] instanceof ArrayBuffer) {
122
+ value.map((e, idx) => {
123
+ const noCopyValue = dicomDictNoCopy.dict[key].Value[idx];
124
+ const copyValue = new Uint8Array(e);
125
+ expect(areEqual(noCopyValue, copyValue)).toEqual(true);
126
+ });
127
+ }
128
+ });
129
+ });
130
+
131
+ it("noCopy binary data into an ArrayBuffer", async () => {
132
+ const dicomUrl =
133
+ "https://github.com/dcmjs-org/data/releases/download/binary-tag/binary-tag.dcm";
134
+ const dicomPath = path.join(os.tmpdir(), "binary-tag.dcm");
135
+
136
+ await downloadToFile(dicomUrl, dicomPath);
137
+ const fileData = await promisify(fs.readFile)(dicomPath);
138
+
139
+ const dicomDictNoCopy = DicomMessage.readFile(fileData.buffer, {
140
+ noCopy: true
141
+ });
142
+
143
+ const dicomDict = DicomMessage.readFile(fileData.buffer, {
144
+ noCopy: false
145
+ });
146
+
147
+ Object.keys(dicomDict.dict).map(key => {
148
+ const value = dicomDict.dict[key].Value;
149
+ if (value[0] instanceof ArrayBuffer) {
150
+ value.map((e, idx) => {
151
+ const noCopyValue = dicomDictNoCopy.dict[key].Value[idx];
152
+ const copyValue = new Uint8Array(e);
153
+ expect(areEqual(noCopyValue, copyValue)).toEqual(true);
154
+ });
155
+ }
156
+ });
157
+ });
158
+
159
+ it("noCopy test_multiframe_1", async () => {
160
+ const url =
161
+ "https://github.com/dcmjs-org/data/releases/download/MRHead/MRHead.zip";
162
+ const zipFilePath = path.join(os.tmpdir(), "MRHead.zip");
163
+ const unzipPath = path.join(os.tmpdir(), "test_multiframe_1");
164
+
165
+ await downloadToFile(url, zipFilePath);
166
+
167
+ await new Promise(resolve => {
168
+ fs.createReadStream(zipFilePath).pipe(
169
+ unzipper.Extract({ path: unzipPath }).on("close", resolve)
170
+ );
171
+ });
172
+
173
+ const mrHeadPath = path.join(unzipPath, "MRHead");
174
+ const fileNames = await fsPromises.readdir(mrHeadPath);
175
+
176
+ const datasets = [];
177
+ fileNames.forEach(fileName => {
178
+ const arrayBuffer = fs.readFileSync(path.join(mrHeadPath, fileName))
179
+ .buffer;
180
+ const dicomDictNoCopy = DicomMessage.readFile(arrayBuffer, {
181
+ noCopy: true
182
+ });
183
+ const dicomDict = DicomMessage.readFile(arrayBuffer, {
184
+ noCopy: false
185
+ });
186
+
187
+ Object.keys(dicomDict.dict).map(key => {
188
+ const value = dicomDict.dict[key].Value;
189
+ if (value[0] instanceof ArrayBuffer) {
190
+ value.map((e, idx) => {
191
+ const noCopyValue = dicomDictNoCopy.dict[key].Value[idx];
192
+ const copyValue = new Uint8Array(e);
193
+ expect(areEqual(noCopyValue, copyValue)).toEqual(true);
194
+ });
195
+ }
196
+ });
197
+ });
198
+ });
199
+
200
+ it("noCopy test_fragment_multiframe", async () => {
201
+ const url =
202
+ "https://github.com/dcmjs-org/data/releases/download/encapsulation/encapsulation-fragment-multiframe.dcm";
203
+ const dcmPath = path.join(
204
+ os.tmpdir(),
205
+ "encapsulation-fragment-multiframe.dcm"
206
+ );
207
+
208
+ await downloadToFile(url, dcmPath);
209
+ const file = fs.readFileSync(dcmPath);
210
+
211
+ const dicomDict = dcmjs.data.DicomMessage.readFile(file.buffer, {
212
+ // ignoreErrors: true,
213
+ });
214
+
215
+ const dicomDictNoCopy = DicomMessage.readFile(file.buffer, {
216
+ noCopy: true
217
+ });
218
+
219
+ Object.keys(dicomDict.dict).map(key => {
220
+ const value = dicomDict.dict[key].Value;
221
+ if (value[0] instanceof ArrayBuffer) {
222
+ value.map((e, idx) => {
223
+ const noCopyValue = dicomDictNoCopy.dict[key].Value[idx];
224
+ const copyValue = new Uint8Array(e);
225
+ const areEqual = (first, second) =>
226
+ first.every((value, index) => value === second[index]);
227
+
228
+ const totalSize = noCopyValue.reduce(
229
+ (sum, arr) => sum + arr.byteLength,
230
+ 0
231
+ );
232
+ expect(totalSize).toEqual(copyValue.length);
233
+ expect(areEqual(noCopyValue[0], copyValue)).toEqual(true);
234
+ });
235
+ }
236
+ });
237
+ });
package/test/data.test.js CHANGED
@@ -17,8 +17,12 @@ import minimalDataset from "./mocks/minimal_fields_dataset.json";
17
17
  import arrayItem from "./arrayItem.json";
18
18
  import { rawTags } from "./rawTags";
19
19
 
20
- const { DicomMetaDictionary, DicomDict, DicomMessage, ReadBufferStream } =
21
- dcmjs.data;
20
+ const {
21
+ DicomMetaDictionary,
22
+ DicomDict,
23
+ DicomMessage,
24
+ ReadBufferStream
25
+ } = dcmjs.data;
22
26
 
23
27
  const EXPLICIT_LITTLE_ENDIAN = "1.2.840.10008.1.2.1";
24
28
 
@@ -171,8 +175,9 @@ it("test_json_1", () => {
171
175
  //
172
176
  // make a natural version of a dataset with sequence tags and confirm it has correct values
173
177
  //
174
- const naturalSequence =
175
- DicomMetaDictionary.naturalizeDataset(sequenceMetadata);
178
+ const naturalSequence = DicomMetaDictionary.naturalizeDataset(
179
+ sequenceMetadata
180
+ );
176
181
 
177
182
  // The match object needs to be done on the actual element, not the proxied value
178
183
  expect(naturalSequence.ProcedureCodeSequence[0]).toMatchObject({
@@ -234,17 +239,17 @@ it("test_multiframe_1", async () => {
234
239
 
235
240
  const datasets = [];
236
241
  fileNames.forEach(fileName => {
237
- const arrayBuffer = fs.readFileSync(
238
- path.join(mrHeadPath, fileName)
239
- ).buffer;
242
+ const arrayBuffer = fs.readFileSync(path.join(mrHeadPath, fileName))
243
+ .buffer;
240
244
  const dicomDict = DicomMessage.readFile(arrayBuffer);
241
245
  const dataset = DicomMetaDictionary.naturalizeDataset(dicomDict.dict);
242
246
 
243
247
  datasets.push(dataset);
244
248
  });
245
249
 
246
- const multiframe =
247
- dcmjs.normalizers.Normalizer.normalizeToDataset(datasets);
250
+ const multiframe = dcmjs.normalizers.Normalizer.normalizeToDataset(
251
+ datasets
252
+ );
248
253
  const spacing =
249
254
  multiframe.SharedFunctionalGroupsSequence.PixelMeasuresSequence
250
255
  .SpacingBetweenSlices;
@@ -280,9 +285,8 @@ it("test_oneslice_seg", async () => {
280
285
 
281
286
  const datasets = [];
282
287
  fileNames.forEach(fileName => {
283
- const arrayBuffer = fs.readFileSync(
284
- path.join(ctPelvisPath, fileName)
285
- ).buffer;
288
+ const arrayBuffer = fs.readFileSync(path.join(ctPelvisPath, fileName))
289
+ .buffer;
286
290
  const dicomDict = DicomMessage.readFile(arrayBuffer);
287
291
  const dataset = DicomMetaDictionary.naturalizeDataset(dicomDict.dict);
288
292
  datasets.push(dataset);
@@ -308,8 +312,9 @@ it("test_oneslice_seg", async () => {
308
312
  });
309
313
 
310
314
  it("test_normalizer_smaller", () => {
311
- const naturalizedTags =
312
- dcmjs.data.DicomMetaDictionary.naturalizeDataset(rawTags);
315
+ const naturalizedTags = dcmjs.data.DicomMetaDictionary.naturalizeDataset(
316
+ rawTags
317
+ );
313
318
 
314
319
  const rawTagsLen = JSON.stringify(rawTags).length;
315
320
  const naturalizedTagsLen = JSON.stringify(naturalizedTags).length;
@@ -452,39 +457,6 @@ it("test_invalid_vr_length", () => {
452
457
  }
453
458
  });
454
459
 
455
- it("test_untiltag", () => {
456
- const buffer = fs.readFileSync("test/sample-dicom.dcm");
457
- console.time("readFile");
458
- const fullData = DicomMessage.readFile(buffer.buffer);
459
- console.timeEnd("readFile");
460
-
461
- console.time("readFile without untilTag");
462
- const dicomData = DicomMessage.readFile(buffer.buffer, {
463
- untilTag: "7FE00010",
464
- includeUntilTagValue: false
465
- });
466
- console.timeEnd("readFile without untilTag");
467
-
468
- console.time("readFile with untilTag");
469
- const dicomData2 = DicomMessage.readFile(buffer.buffer, {
470
- untilTag: "7FE00010",
471
- includeUntilTagValue: true
472
- });
473
- console.timeEnd("readFile with untilTag");
474
-
475
- const full_dataset = DicomMetaDictionary.naturalizeDataset(fullData.dict);
476
- full_dataset._meta = DicomMetaDictionary.namifyDataset(fullData.meta);
477
-
478
- const dataset = DicomMetaDictionary.naturalizeDataset(dicomData.dict);
479
- dataset._meta = DicomMetaDictionary.namifyDataset(dicomData.meta);
480
-
481
- const dataset2 = DicomMetaDictionary.naturalizeDataset(dicomData2.dict);
482
- dataset2._meta = DicomMetaDictionary.namifyDataset(dicomData2.meta);
483
-
484
- expect(full_dataset.PixelData).toEqual(dataset2.PixelData);
485
- expect(dataset.PixelData).toEqual(0);
486
- });
487
-
488
460
  it("test_encapsulation", async () => {
489
461
  const url =
490
462
  "https://github.com/dcmjs-org/data/releases/download/encapsulation/encapsulation.dcm";
@@ -531,10 +503,10 @@ it("test_encapsulation", async () => {
531
503
  throw new Error("Invalid a dicom file");
532
504
  }
533
505
 
534
- const el = DicomMessage.readTag(stream, useSyntax),
506
+ const el = DicomMessage._readTag(stream, useSyntax),
535
507
  metaLength = el.values[0]; //read header buffer
536
508
  const metaStream = stream.more(metaLength);
537
- const metaHeader = DicomMessage.read(metaStream, useSyntax, false); //get the syntax
509
+ const metaHeader = DicomMessage._read(metaStream, useSyntax); //get the syntax
538
510
  let mainSyntax = metaHeader["00020010"].Value[0];
539
511
 
540
512
  mainSyntax = DicomMessage._normalizeSyntax(mainSyntax);
@@ -565,7 +537,7 @@ it("test_encapsulation", async () => {
565
537
  lengths.push(length);
566
538
  }
567
539
 
568
- DicomMessage.readTag(stream, mainSyntax, null, false);
540
+ DicomMessage._readTag(stream, mainSyntax);
569
541
  }
570
542
 
571
543
  // then
@@ -1,44 +0,0 @@
1
- import dcmjs from "../src/index.js";
2
- import fs from "fs";
3
-
4
- it("test_untilTag", () => {
5
- const buffer = fs.readFileSync("test/sample-dicom.dcm");
6
-
7
- const { DicomMessage, DicomMetaDictionary } = dcmjs.data;
8
-
9
- console.time("readFile");
10
- const fullData = DicomMessage.readFile(buffer.buffer);
11
- console.timeEnd("readFile");
12
-
13
- console.time("readFile without untilTag");
14
- const dicomData = DicomMessage.readFile(buffer.buffer, {
15
- untilTag: "7FE00010",
16
- includeUntilTagValue: false
17
- });
18
- console.timeEnd("readFile without untilTag");
19
-
20
- console.time("readFile with untilTag");
21
- const dicomData2 = DicomMessage.readFile(buffer.buffer, {
22
- untilTag: "7FE00010",
23
- includeUntilTagValue: true
24
- });
25
- console.timeEnd("readFile with untilTag");
26
-
27
- const full_dataset = DicomMetaDictionary.naturalizeDataset(fullData.dict);
28
- full_dataset._meta = DicomMetaDictionary.namifyDataset(fullData.meta);
29
-
30
- // console.log(full_dataset.PixelData);
31
-
32
- const dataset = DicomMetaDictionary.naturalizeDataset(dicomData.dict);
33
- dataset._meta = DicomMetaDictionary.namifyDataset(dicomData.meta);
34
-
35
- // console.log(dataset.PixelData);
36
-
37
- const dataset2 = DicomMetaDictionary.naturalizeDataset(dicomData2.dict);
38
- dataset2._meta = DicomMetaDictionary.namifyDataset(dicomData2.meta);
39
-
40
- // console.log(dataset2.PixelData);
41
-
42
- expect(full_dataset.PixelData).toEqual(dataset2.PixelData);
43
- expect(dataset.PixelData).toEqual(0);
44
- });