@radicalimaging/static-wado-creator 0.6.5 → 1.1.0

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/CHANGELOG.md ADDED
@@ -0,0 +1,67 @@
1
+ # Change Log
2
+
3
+ All notable changes to this project will be documented in this file.
4
+ See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
+
6
+ ## [0.6.4](https://github.com/OHIF/static-wado/compare/@radicalimaging/static-wado-creator@0.6.3...@radicalimaging/static-wado-creator@0.6.4) (2022-04-04)
7
+
8
+ **Note:** Version bump only for package @radicalimaging/static-wado-creator
9
+
10
+
11
+
12
+
13
+
14
+ ## [0.6.3](https://github.com/OHIF/static-wado/compare/@radicalimaging/static-wado-creator@0.6.2...@radicalimaging/static-wado-creator@0.6.3) (2022-03-14)
15
+
16
+ **Note:** Version bump only for package @radicalimaging/static-wado-creator
17
+
18
+
19
+
20
+
21
+
22
+ ## [0.6.2](https://github.com/OHIF/static-wado/compare/@radicalimaging/static-wado-creator@0.6.1...@radicalimaging/static-wado-creator@0.6.2) (2022-03-04)
23
+
24
+ **Note:** Version bump only for package @radicalimaging/static-wado-creator
25
+
26
+
27
+
28
+
29
+
30
+ ## [0.6.1](https://github.com/OHIF/static-wado/compare/@radicalimaging/static-wado-creator@0.6.0...@radicalimaging/static-wado-creator@0.6.1) (2022-03-04)
31
+
32
+ **Note:** Version bump only for package @radicalimaging/static-wado-creator
33
+
34
+
35
+
36
+
37
+
38
+ # [0.6.0](https://github.com/OHIF/static-wado/compare/@radicalimaging/static-wado-creator@0.5.1...@radicalimaging/static-wado-creator@0.6.0) (2022-03-03)
39
+
40
+
41
+ ### Bug Fixes
42
+
43
+ * **static-wado:** make the various constructors use a straight configuration without using the program data ([1997d9f](https://github.com/OHIF/static-wado/commit/1997d9f0fe2e0a084d31edeb475494bcec78fd77))
44
+
45
+
46
+ ### Features
47
+
48
+ * **static-wado:** qido series fallback to retrieve from proxyAe ([#8](https://github.com/OHIF/static-wado/issues/8)) ([47b5550](https://github.com/OHIF/static-wado/commit/47b55503732e25be08b215bdc201593f64de52e6))
49
+
50
+
51
+
52
+
53
+
54
+ ## 0.5.1 (2022-02-16)
55
+
56
+
57
+ ### Bug Fixes
58
+
59
+ * **pencil:** add more files to lint, increase test config and README ([89b667c](https://github.com/OHIF/static-wado/commit/89b667c83d324ab9fa540cda0c037af8fe088f72))
60
+ * **pencil:** adding must package and minor test changes ([9194f3f](https://github.com/OHIF/static-wado/commit/9194f3f1bb52da57e20bb8bb9f07262bcebdffbf))
61
+ * **pencil:** code review.lint ([fa1a58a](https://github.com/OHIF/static-wado/commit/fa1a58a0c62015503575fbeb172b71810c6833de))
62
+ * **pencil:** fix format ([68fbc9b](https://github.com/OHIF/static-wado/commit/68fbc9bf5a3e9bf85e3fbcddfb3e0759e79b769d))
63
+ * **pencil:** fix lint and add pre-commit restr ([deec345](https://github.com/OHIF/static-wado/commit/deec34524531d5a8595a775bac414f63f60e9f23))
64
+ * **pencil:** lint/prettier ([d6ecbc6](https://github.com/OHIF/static-wado/commit/d6ecbc6b5961e03e8a557f4fcc78af53549132cd))
65
+ * **pencil:** moving from wado-js to wado repo ([5916aec](https://github.com/OHIF/static-wado/commit/5916aecd7c77dbc4882681877e2b51210976427f))
66
+ * **pencil:** readme link name ([40408ab](https://github.com/OHIF/static-wado/commit/40408ab6b4e97c8656e30b1dd2c30b92440b9f90))
67
+ * **pencil:** unit tests migration ([d9d56dd](https://github.com/OHIF/static-wado/commit/d9d56dd619fb1f41ed1d5ad85f7f804e013c6527))
package/README.md CHANGED
@@ -158,11 +158,13 @@ There is currently no notification of what studies have been updated between sta
158
158
  ### To Serve Instances As a Web Server
159
159
  ```
160
160
  cd ~/dicomweb
161
- npx http-server -p 5000 -g --cors
161
+ npx http-server -p 5000 -g --cors -e json
162
162
  ```
163
163
 
164
164
  The -g option serves up compressed files ending in .gz as compressed http streams.
165
165
 
166
+ The -e option will mark json files as the default extension, so when requesting `GET dicomweb/studies/` the `./studies/index.json.gz` file will be served.
167
+
166
168
  ### To Create DICOM part 10 from DICOMweb files
167
169
  TODO
168
170
 
@@ -1,6 +1,6 @@
1
1
  const { JSONReader } = require("@radicalimaging/static-wado-util");
2
- const JSONWriter = require("./writer/JSONWriter");
3
- const Tags = require("./dictionary/Tags");
2
+ const { JSONWriter } = require("@radicalimaging/static-wado-util");
3
+ const { Tags } = require("@radicalimaging/static-wado-util");
4
4
 
5
5
  module.exports = (options) =>
6
6
  async function (studyInstanceUid) {
package/lib/StaticWado.js CHANGED
@@ -3,9 +3,7 @@ const { Stats, handleHomeRelative } = require("@radicalimaging/static-wado-util"
3
3
  const dicomParser = require("dicom-parser");
4
4
  const fs = require("fs");
5
5
  const path = require("path");
6
- const { dirScanner } = require("@radicalimaging/static-wado-util");
7
- const { JSONReader } = require("@radicalimaging/static-wado-util");
8
- const asyncIterableToBuffer = require("@radicalimaging/static-wado-util/lib/asyncIterableToBuffer");
6
+ const { dirScanner, JSONReader, JSONWriter, asyncIterableToBuffer } = require("@radicalimaging/static-wado-util");
9
7
  const getDataSet = require("./operation/getDataSet");
10
8
  const InstanceDeduplicate = require("./operation/InstanceDeduplicate");
11
9
  const DeduplicateWriter = require("./writer/DeduplicateWriter");
@@ -20,7 +18,7 @@ const ThumbnailWriter = require("./writer/ThumbnailWriter");
20
18
  const ThumbnailService = require("./operation/ThumbnailService");
21
19
  const DeleteStudy = require("./DeleteStudy");
22
20
  const RejectInstance = require("./RejectInstance");
23
- const JSONWriter = require("./writer/JSONWriter");
21
+ const RawDicomWriter = require("./writer/RawDicomWriter");
24
22
 
25
23
  function setStudyData(studyData) {
26
24
  this.studyData = studyData;
@@ -53,6 +51,7 @@ class StaticWado {
53
51
  reject: RejectInstance(this.options),
54
52
  delete: DeleteStudy(this.options),
55
53
  setStudyData,
54
+ rawDicomWriter: RawDicomWriter(this.options),
56
55
  };
57
56
  }
58
57
 
@@ -176,6 +175,8 @@ class StaticWado {
176
175
  // convert to DICOMweb MetaData and BulkData
177
176
  const result = await getDataSet(dataSet, generator, this.options);
178
177
 
178
+ await this.callback.rawDicomWriter?.(id, result, buffer);
179
+
179
180
  const transcodedMeta = transcodeMetadata(result.metadata, id, this.options);
180
181
  thumbnailService.generateThumbnails(id, dataSet, transcodedMeta, this.callback);
181
182
 
package/lib/index.js CHANGED
@@ -4,5 +4,6 @@ const StaticWado = require("./StaticWado");
4
4
  StaticWado.mkdicomwebConfig = mkdicomwebConfig;
5
5
  StaticWado.createMain = require("./createMain");
6
6
  StaticWado.deleteMain = require("./deleteMain");
7
+ StaticWado.adaptProgramOpts = require("./util/adaptProgramOpts");
7
8
 
8
9
  module.exports = StaticWado;
@@ -25,6 +25,11 @@ const { mkdicomwebConfig } = ConfigPoint.register({
25
25
  description: "Clean the outputs before generating/starting to write new values.",
26
26
  defaultValue: false,
27
27
  },
28
+ {
29
+ key: "-d, --deployments <listvalue...>",
30
+ description: "List of deployments from configuration to deploy to. Separated by space.",
31
+ defaultValue: undefined,
32
+ },
28
33
  {
29
34
  key: "-v, --verbose",
30
35
  description: "Write verbose output",
@@ -32,10 +37,14 @@ const { mkdicomwebConfig } = ConfigPoint.register({
32
37
  },
33
38
  {
34
39
  key: "-t, --content-type <type>",
35
- description: 'Destination type to compress to (choices: "jls", "lei", "jls-lossy" or DICOM Transfer Syntax UID - default: "jls")',
36
- defaultValue: "jls",
40
+ description: 'Destination type to compress to (choices: "jls", "lei", "jls-lossy", "jhc", "jxl" or DICOM Transfer Syntax UID - default: "jls")',
41
+ defaultValue: "jhc",
37
42
  customParser: compressionOptionParser,
38
43
  },
44
+ {
45
+ key: "-e, --no-encapsulated-image-frame",
46
+ description: "Avoid encapsulating the image frame. Writes with the extension and without multipart",
47
+ },
39
48
  {
40
49
  key: "-m, --maximum-inline-public-length <value>",
41
50
  description: "Maximum length of public binary data",
@@ -49,8 +58,8 @@ const { mkdicomwebConfig } = ConfigPoint.register({
49
58
  {
50
59
  key: "-r, --recompress <listvalue...>",
51
60
  description: "List of types to recompress separated by space",
52
- defaultValue: ["uncompressed", "jp2"],
53
- choices: ["uncompressed", "jp2", "jpeglossless", "rle", "none"],
61
+ defaultValue: ["uncompressed", "jp2", "jls", "jll"],
62
+ choices: ["uncompressed", "jp2", "jpeglossless", "rle", "jph", "jls", "true", "none"],
54
63
  },
55
64
  {
56
65
  key: "--recompress-thumb <listvalue...>",
@@ -1,5 +1,5 @@
1
1
  const hashFactory = require("node-object-hash");
2
- const Tags = require("../dictionary/Tags");
2
+ const { Tags } = require("@radicalimaging/static-wado-util");
3
3
 
4
4
  /* eslint "no-param-reassign": "off" */
5
5
 
package/lib/model/uids.js CHANGED
@@ -12,7 +12,7 @@ const jpeg = "image/jpeg";
12
12
  const jls = "image/jls";
13
13
  const jll = "image/jll";
14
14
  const jxl = "image/x-jxl";
15
- const htj2k = "image/x-htj2k";
15
+ const htj2k = "image/jphc";
16
16
  const jp2 = "image/jp2";
17
17
  const rle = "image/dicom-rle";
18
18
 
@@ -21,20 +21,19 @@ const uids = {
21
21
  "1.2.840.10008.1.2.1": uncompressed,
22
22
  "1.2.840.10008.1.2.1.99": uncompressed,
23
23
  "1.2.840.10008.1.2.2": uncompressed,
24
- "1.2.840.10008.1.2.4.50": { contentType: jpeg, lossy: true },
24
+ "1.2.840.10008.1.2.4.50": { contentType: jpeg, lossy: true, extension: ".jpeg" },
25
25
  "1.2.840.10008.1.2.4.51": { contentType: jpeg, lossy: true },
26
26
  "1.2.840.10008.1.2.4.57": { contentType: jpeg },
27
- "1.2.840.10008.1.2.4.70": { contentType: jll },
28
- "1.2.840.10008.1.2.4.140": { contentType: jxl },
27
+ "1.2.840.10008.1.2.4.70": { contentType: jll, extension: ".jll" },
28
+ "1.2.840.10008.1.2.4.140": { contentType: jxl, extension: ".jxl" },
29
+ // Lossy, original JPEG reconstruction mode
29
30
  "1.2.840.10008.1.2.4.141": { contentType: jxl, lossy: true },
30
- "1.2.840.10008.1.2.4.80": { contentType: jls },
31
+ "1.2.840.10008.1.2.4.142": { contentType: jxl, lossy: true },
32
+ "1.2.840.10008.1.2.4.80": { contentType: jls, extension: ".jls" },
31
33
  "1.2.840.10008.1.2.4.81": { contentType: jls, lossy: true },
32
- "1.2.840.10008.1.2.4.90": { contentType: jp2 },
34
+ "1.2.840.10008.1.2.4.90": { contentType: jp2, extension: ".jp2" },
33
35
  "1.2.840.10008.1.2.4.91": { contentType: jp2 },
34
- // From JPEG original data, lossless to JXL
35
- "1.2.840.10008.1.2.4.142": { contentType: jxl, lossy: true },
36
- "1.2.840.10008.1.2.4.150": { contentType: htj2k },
37
- // **
36
+ "3.2.840.10008.1.2.4.96": { contentType: htj2k, extension: ".jhc" },
38
37
  "1.2.840.10008.1.2.5": { contentType: rle },
39
38
  default: {},
40
39
  };
@@ -1,7 +1,7 @@
1
1
  // TODO review returning type of some methods
2
- const JSONWriter = require("../writer/JSONWriter");
2
+ const { JSONWriter } = require("@radicalimaging/static-wado-util");
3
+ const { Tags } = require("@radicalimaging/static-wado-util");
3
4
  const TagLists = require("../model/TagLists");
4
- const Tags = require("../dictionary/Tags");
5
5
 
6
6
  const { getValue, setValue } = Tags;
7
7
 
@@ -1,10 +1,9 @@
1
1
  const path = require("path");
2
2
  const fs = require("fs");
3
3
  const hashFactory = require("node-object-hash");
4
- const { JSONReader } = require("@radicalimaging/static-wado-util");
5
- const Tags = require("../dictionary/Tags");
4
+ const { JSONReader, JSONWriter } = require("@radicalimaging/static-wado-util");
5
+ const { Tags } = require("@radicalimaging/static-wado-util");
6
6
  const TagLists = require("../model/TagLists");
7
- const JSONWriter = require("../writer/JSONWriter");
8
7
 
9
8
  const { getValue, setValue, getList, setList } = Tags;
10
9
  const hasher = hashFactory();
@@ -4,10 +4,10 @@ const dicomCodec = require("@cornerstonejs/dicom-codec");
4
4
  const staticCS = require("@radicalimaging/static-cs-lite");
5
5
  const fs = require("fs");
6
6
  const { exec } = require("child_process");
7
+ const { Tags } = require("@radicalimaging/static-wado-util");
7
8
  const decodeImage = require("./adapter/decodeImage");
8
9
  const { shouldThumbUseTranscoded } = require("./adapter/transcodeImage");
9
10
  const { isVideo } = require("../writer/VideoWriter");
10
- const Tags = require("../dictionary/Tags");
11
11
 
12
12
  /**
13
13
  * Return the middle index of given list
@@ -1,5 +1,5 @@
1
1
  const dicomCodec = require("@cornerstonejs/dicom-codec");
2
- const Tags = require("../../dictionary/Tags");
2
+ const { Tags } = require("@radicalimaging/static-wado-util");
3
3
  const getImageInfo = require("./getImageInfo");
4
4
 
5
5
  const transcodeOp = {
@@ -33,6 +33,10 @@ const transcodeDestinationMap = {
33
33
  transferSyntaxUid: "1.2.840.10008.1.2.4.91",
34
34
  transcodeOp: transcodeOp.encode,
35
35
  },
36
+ jhc: {
37
+ transferSyntaxUid: "3.2.840.10008.1.2.4.96",
38
+ transcodeOp: transcodeOp.encode,
39
+ },
36
40
  };
37
41
 
38
42
  const transcodeSourceMap = {
@@ -50,11 +54,11 @@ const transcodeSourceMap = {
50
54
  },
51
55
  "1.2.840.10008.1.2.4.57": {
52
56
  transcodeOp: transcodeOp.decode,
53
- alias: "jpeglossless",
57
+ alias: "jls",
54
58
  },
55
59
  "1.2.840.10008.1.2.4.70": {
56
60
  transcodeOp: transcodeOp.decode,
57
- alias: "jpeglossless",
61
+ alias: "jls",
58
62
  },
59
63
  "1.2.840.10008.1.2.4.90": {
60
64
  transcodeOp: transcodeOp.decode,
@@ -64,6 +68,10 @@ const transcodeSourceMap = {
64
68
  transcodeOp: transcodeOp.decode,
65
69
  alias: "jp2",
66
70
  },
71
+ "3.2.840.10008.1.2.4.96": {
72
+ transcodeOp: transcodeOp.decode,
73
+ alias: "jhc",
74
+ },
67
75
  "1.2.840.10008.1.2.5": {
68
76
  transcodeOp: transcodeOp.decode,
69
77
  alias: "rle",
@@ -92,7 +100,7 @@ function getDestinationTranscoder(id) {
92
100
  */
93
101
  function getTranscoder(transferSyntaxUid, { contentType, verbose }) {
94
102
  if (verbose) {
95
- console.log(`getTranscoder for ${transferSyntaxUid}`);
103
+ console.log('getTranscoder for', transferSyntaxUid, 'source to', contentType);
96
104
  }
97
105
  const sourceTranscoder = transcodeSourceMap[transferSyntaxUid];
98
106
  const destinationTranscoder = getDestinationTranscoder(contentType);
@@ -113,17 +121,23 @@ function getTranscoder(transferSyntaxUid, { contentType, verbose }) {
113
121
  * @param {*} options runner options
114
122
  */
115
123
  function shouldTranscodeImageFrame(id, options) {
116
- if (!options.recompress) {
124
+ const { recompress } = options;
125
+ if (!recompress) {
126
+ if( options.verbose ) console.log("Not transcoding because recompress not set");
117
127
  return false;
118
128
  }
119
129
 
120
130
  function isValidTranscoder() {
121
131
  const { transferSyntaxUid } = id;
122
132
  const transcoder = getTranscoder(transferSyntaxUid, options);
123
- return transcoder && transcoder.transferSyntaxUid && options.recompress.includes(transcoder.alias);
133
+ return transcoder && transcoder.transferSyntaxUid && (recompress.includes("true") || recompress.includes(transcoder.alias));
124
134
  }
125
135
 
126
- return isValidTranscoder();
136
+ const ret = isValidTranscoder();
137
+ if( !ret && options.verbose ) {
138
+ console.log("Not transcoding");
139
+ }
140
+ return ret;
127
141
  }
128
142
 
129
143
  /**
@@ -170,6 +184,7 @@ async function transcodeImageFrame(id, targetIdSrc, imageFrame, dataSet, options
170
184
  let result = {};
171
185
 
172
186
  if (!shouldTranscodeImageFrame(id, options)) {
187
+ console.log("Shouldn't transcode");
173
188
  return {
174
189
  id,
175
190
  imageFrame,
@@ -181,6 +196,7 @@ async function transcodeImageFrame(id, targetIdSrc, imageFrame, dataSet, options
181
196
 
182
197
  // last chance to prevent transcoding
183
198
  if (targetId.transferSyntaxUid !== transcoder.transferSyntaxUid) {
199
+ console.log("Image is already in", targetId.transferSyntaxUid, "not transcoding");
184
200
  return {
185
201
  id,
186
202
  imageFrame,
@@ -188,9 +204,8 @@ async function transcodeImageFrame(id, targetIdSrc, imageFrame, dataSet, options
188
204
  };
189
205
  }
190
206
 
191
- if (options.verbose) {
192
- console.log("Transcoding to", transcoder.transferSyntaxUid);
193
- }
207
+ if( options.verbose ) console.log("Transcoding to", transcoder.transferSyntaxUid);
208
+
194
209
  const imageInfo = getImageInfo(dataSet);
195
210
  let done = false;
196
211
  let processResultMsg = "";
@@ -289,6 +304,9 @@ function transcodeMetadata(metadata, id, options) {
289
304
 
290
305
  if (result[Tags.AvailableTransferSyntaxUID]) {
291
306
  Tags.setValue(result, Tags.AvailableTransferSyntaxUID, transcodedId.transferSyntaxUid);
307
+ if( this.verbose ) {
308
+ console.log("Apply available tsuid", transcodeId.transferSyntaxUid);
309
+ }
292
310
  }
293
311
 
294
312
  return result;
@@ -1,6 +1,6 @@
1
+ const { Tags } = require("@radicalimaging/static-wado-util");
1
2
  const getVR = require("./getVR");
2
3
  const getValue = require("./getValue");
3
- const Tags = require("../dictionary/Tags");
4
4
 
5
5
  /**
6
6
  * Get dataset.
@@ -1,4 +1,4 @@
1
- const dataDictionary = require("../dictionary/dataDictionary");
1
+ const { dataDictionary } = require("@radicalimaging/static-wado-util");
2
2
 
3
3
  const getVR = (attr) => {
4
4
  if (attr.vr) {
@@ -29,6 +29,7 @@ module.exports = function adaptProgramOpts(programOpts, defaults) {
29
29
  prependBulkDataUri,
30
30
  expandBulkDataUri,
31
31
  verbose,
32
+ scpPort,
32
33
  } = programOpts;
33
34
 
34
35
  return assignDefined(
@@ -50,6 +51,7 @@ module.exports = function adaptProgramOpts(programOpts, defaults) {
50
51
  pathInstances,
51
52
  removeDeduplicatedInstances,
52
53
  storeMultipartBulkData,
54
+ scpPort,
53
55
  prependBulkDataUri,
54
56
  expandBulkDataUri,
55
57
  verbose,
@@ -1,8 +1,6 @@
1
- const { Stats } = require("@radicalimaging/static-wado-util");
2
- const { JSONReader } = require("@radicalimaging/static-wado-util");
3
- const JSONWriter = require("./JSONWriter");
1
+ const { JSONReader, JSONWriter, Stats } = require("@radicalimaging/static-wado-util");
2
+ const { Tags } = require("@radicalimaging/static-wado-util");
4
3
  const StudyData = require("../operation/StudyData");
5
- const Tags = require("../dictionary/Tags");
6
4
 
7
5
  /**
8
6
  * CompleteStudyWriter takes the deduplicated data values, all loaded into the study parameter,
@@ -1,8 +1,8 @@
1
1
  const hashFactory = require("node-object-hash");
2
2
 
3
3
  const hasher = hashFactory();
4
- const JSONWriter = require("./JSONWriter");
5
- const Tags = require("../dictionary/Tags");
4
+ const { JSONWriter } = require("@radicalimaging/static-wado-util");
5
+ const { Tags } = require("@radicalimaging/static-wado-util");
6
6
  const TagLists = require("../model/TagLists");
7
7
 
8
8
  async function writeDeduplicatedFile(dir, data, hashValueSrc) {
@@ -2,7 +2,7 @@ const hashFactory = require("node-object-hash");
2
2
 
3
3
  const hasher = hashFactory();
4
4
  const path = require("path");
5
- const Tags = require("../dictionary/Tags");
5
+ const { Tags } = require("@radicalimaging/static-wado-util");
6
6
  const WriteStream = require("./WriteStream");
7
7
  const WriteMultipart = require("./WriteMultipart");
8
8
  const ExpandUriPath = require("./ExpandUriPath");
@@ -5,24 +5,43 @@ const ExpandUriPath = require("./ExpandUriPath");
5
5
  const { MultipartHeader, MultipartAttribute } = require("./MultipartHeader");
6
6
 
7
7
  const ImageFrameWriter = (options) => {
8
- const { verbose } = options;
8
+ const { verbose, encapsulatedImageFrame = true } = options;
9
9
 
10
10
  return async (id, index, imageFrame) => {
11
11
  const { transferSyntaxUid } = id;
12
12
  const type = uids[transferSyntaxUid] || uids.default;
13
- const writeStream = WriteStream(id.imageFrameRootPath, `${1 + index}`, {
14
- gzip: type.gzip,
15
- mkdir: true,
16
- });
13
+ const extension = type.extension;
17
14
  let content;
18
15
  if (imageFrame instanceof Uint8Array) {
19
16
  content = imageFrame;
20
17
  } else {
21
18
  content = Buffer.from(imageFrame.buffer);
22
19
  }
23
- await WriteMultipart(writeStream, [new MultipartHeader("Content-Type", type.contentType, [new MultipartAttribute("transfer-syntax", transferSyntaxUid)])], content);
24
- await writeStream.close();
25
- if (verbose) console.log("Wrote image frame", id.sopInstanceUid, index + 1);
20
+
21
+ if (encapsulatedImageFrame || !extension) {
22
+ const writeStream = WriteStream(id.imageFrameRootPath, `${1 + index}`, {
23
+ gzip: type.gzip,
24
+ mkdir: true,
25
+ });
26
+ await WriteMultipart(
27
+ writeStream,
28
+ [new MultipartHeader("Content-Type", type.contentType, [new MultipartAttribute("transfer-syntax", transferSyntaxUid)])],
29
+ content
30
+ );
31
+ writeStream.close();
32
+ if (verbose) {
33
+ console.log("Wrote encapsulated image frame", id.sopInstanceUid, index + 1, type.contentType);
34
+ }
35
+ }
36
+ if (extension) {
37
+ const writeStreamSingle = WriteStream(id.imageFrameRootPath, `${1 + index}${extension}`, {
38
+ gzip: type.gzip,
39
+ mkdir: true,
40
+ });
41
+ await writeStreamSingle.write(content);
42
+ writeStreamSingle.close();
43
+ if (verbose) console.log("Wrote single part image frame", id.sopInstanceUid, index + 1, extension);
44
+ }
26
45
  const includeSeries = true;
27
46
  return ExpandUriPath(id, `instances/${id.sopInstanceUid}/frames`, { includeSeries, ...options });
28
47
  };
@@ -0,0 +1,36 @@
1
+ const { Tags } = require("@radicalimaging/static-wado-util");
2
+ const WriteStream = require("./WriteStream");
3
+ const WriteMultipart = require("./WriteMultipart");
4
+ const { MultipartHeader } = require("./MultipartHeader");
5
+
6
+ const modalitiesToRawWrite = ["SEG", "SR"];
7
+
8
+ const defaultSelector = (instance) => {
9
+ const modality = instance.metadata[Tags.Modality]?.Value?.[0];
10
+ return modalitiesToRawWrite.indexOf(modality) !== -1;
11
+ };
12
+
13
+ /** Writes out raw DICOM files, encapsulated in multipart and gzipped - currently just DICOM SR and SEG */
14
+ const RawDicomWriter =
15
+ () =>
16
+ async (id, instance, content, options = { gzip: true }) => {
17
+ if (!instance) {
18
+ return undefined;
19
+ }
20
+ const selector = options.selector || defaultSelector;
21
+ if (!selector(instance)) {
22
+ return undefined;
23
+ }
24
+ const contentType = options.contentType || "application/dicom";
25
+ const writeStream = WriteStream(id.sopInstanceRootPath, "index.mht", {
26
+ gzip: options.gzip,
27
+ mkdir: true,
28
+ });
29
+ const { length } = content;
30
+ const buffer = content.slice(0, length);
31
+ await WriteMultipart(writeStream, [new MultipartHeader("Content-Type", contentType, [])], buffer);
32
+ await writeStream.close();
33
+ };
34
+ RawDicomWriter.defaultSelector = defaultSelector;
35
+
36
+ module.exports = RawDicomWriter;
@@ -1,5 +1,5 @@
1
1
  /** Write raw video file */
2
- const Tags = require("../dictionary/Tags");
2
+ const { Tags } = require("@radicalimaging/static-wado-util");
3
3
  const WriteStream = require("./WriteStream");
4
4
 
5
5
  const MPEG2 = "mpg";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@radicalimaging/static-wado-creator",
3
- "version": "0.6.5",
3
+ "version": "1.1.0",
4
4
  "description": "Library to convert DICOMP10 to DICOMweb format. Original upstream: https://github.com/chafey/dicomp10-to-dicomweb-js",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -60,11 +60,11 @@
60
60
  },
61
61
  "dependencies": {
62
62
  "@cornerstonejs/dicom-codec": "^0.1.3",
63
- "@radicalimaging/static-cs-lite": "^0.0.2",
63
+ "@radicalimaging/static-cs-lite": "^0.0.3",
64
64
  "@radicalimaging/static-wado-util": "^0.6.2",
65
65
  "canvas": "^2.9.1",
66
- "config-point": "0.5.1",
67
- "dcmjs": "^0.27.0",
66
+ "config-point": "^0.5.1",
67
+ "dcmjs": "^0.28.0",
68
68
  "dicom-parser": "^1.8.13",
69
69
  "glob": "^7.2.0",
70
70
  "node-object-hash": "^2.3.10",