@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 +67 -0
- package/README.md +3 -1
- package/lib/DeleteStudy.js +2 -2
- package/lib/StaticWado.js +5 -4
- package/lib/index.js +1 -0
- package/lib/mkdicomwebConfig.js +13 -4
- package/lib/model/TagLists.js +1 -1
- package/lib/model/uids.js +9 -10
- package/lib/operation/InstanceDeduplicate.js +2 -2
- package/lib/operation/StudyData.js +2 -3
- package/lib/operation/ThumbnailService.js +1 -1
- package/lib/operation/adapter/transcodeImage.js +28 -10
- package/lib/operation/getDataSet.js +1 -1
- package/lib/operation/getVR.js +1 -1
- package/lib/util/adaptProgramOpts.js +2 -0
- package/lib/writer/CompleteStudyWriter.js +2 -4
- package/lib/writer/DeduplicateWriter.js +2 -2
- package/lib/writer/HashDataWriter.js +1 -1
- package/lib/writer/ImageFrameWriter.js +27 -8
- package/lib/writer/RawDicomWriter.js +36 -0
- package/lib/writer/VideoWriter.js +1 -1
- package/package.json +4 -4
- package/lib/dictionary/Tags.js +0 -119
- package/lib/dictionary/dataDictionary.js +0 -22268
- package/lib/writer/JSONWriter.js +0 -18
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
|
|
package/lib/DeleteStudy.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const { JSONReader } = require("@radicalimaging/static-wado-util");
|
|
2
|
-
const JSONWriter = require("
|
|
3
|
-
const Tags = require("
|
|
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
|
|
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;
|
package/lib/mkdicomwebConfig.js
CHANGED
|
@@ -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: "
|
|
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...>",
|
package/lib/model/TagLists.js
CHANGED
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/
|
|
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.
|
|
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
|
-
|
|
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("
|
|
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("
|
|
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("
|
|
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: "
|
|
57
|
+
alias: "jls",
|
|
54
58
|
},
|
|
55
59
|
"1.2.840.10008.1.2.4.70": {
|
|
56
60
|
transcodeOp: transcodeOp.decode,
|
|
57
|
-
alias: "
|
|
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(
|
|
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
|
-
|
|
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 &&
|
|
133
|
+
return transcoder && transcoder.transferSyntaxUid && (recompress.includes("true") || recompress.includes(transcoder.alias));
|
|
124
134
|
}
|
|
125
135
|
|
|
126
|
-
|
|
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
|
|
192
|
-
|
|
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;
|
package/lib/operation/getVR.js
CHANGED
|
@@ -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 {
|
|
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("
|
|
5
|
-
const Tags = require("
|
|
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("
|
|
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
|
|
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
|
-
|
|
24
|
-
|
|
25
|
-
|
|
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;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@radicalimaging/static-wado-creator",
|
|
3
|
-
"version": "
|
|
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.
|
|
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.
|
|
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",
|