@radicalimaging/static-wado-creator 1.6.10 → 1.6.12
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/dist/index.js +84817 -54902
- package/lib/DeleteStudy.js +9 -14
- package/lib/RejectInstance.js +4 -15
- package/lib/StaticWado.js +92 -147
- package/lib/createMain.js +3 -3
- package/lib/createPart10.js +19 -23
- package/lib/createThumbnail.js +27 -45
- package/lib/deleteMain.js +2 -2
- package/lib/groupMain.js +2 -2
- package/lib/index.js +6 -6
- package/lib/indexMain.js +2 -2
- package/lib/instanceMain.js +2 -2
- package/lib/metadataMain.js +2 -2
- package/lib/mkdicomwebConfig.js +157 -165
- package/lib/model/TagLists.js +5 -17
- package/lib/model/uids.js +29 -29
- package/lib/operation/InstanceDeduplicate.js +14 -19
- package/lib/operation/ScanStudy.js +11 -18
- package/lib/operation/StudyData.js +87 -156
- package/lib/operation/ThumbnailService.js +29 -54
- package/lib/operation/adapter/decodeImage.js +2 -2
- package/lib/operation/adapter/getImageInfo.js +7 -8
- package/lib/operation/adapter/transcodeImage.js +95 -146
- package/lib/operation/extractImageFrames.js +13 -17
- package/lib/operation/getDataSet.js +9 -43
- package/lib/operation/getEncapsulatedImageFrame.js +7 -19
- package/lib/operation/getNumberOfFrames.js +2 -2
- package/lib/operation/getUncompressedImageFrame.js +2 -10
- package/lib/operation/getVR.js +5 -5
- package/lib/operation/getValue.js +42 -65
- package/lib/operation/validateMetadata.js +4 -4
- package/lib/program/index.js +2 -5
- package/lib/rejectMain.js +2 -2
- package/lib/serverMain.js +8 -14
- package/lib/util/IdCreator.js +8 -17
- package/lib/util/adaptProgramOpts.js +2 -2
- package/lib/util/compressionOptionParser.js +5 -14
- package/lib/util/resultsReport.ts +67 -68
- package/lib/writer/CompleteStudyWriter.js +24 -37
- package/lib/writer/DeduplicateWriter.js +7 -8
- package/lib/writer/ExpandUriPath.js +3 -5
- package/lib/writer/HashDataWriter.js +18 -18
- package/lib/writer/ImageFrameWriter.js +20 -33
- package/lib/writer/MultipartHeader.js +1 -1
- package/lib/writer/RawDicomWriter.js +12 -13
- package/lib/writer/ThumbnailWriter.js +2 -2
- package/lib/writer/VideoWriter.js +23 -34
- package/lib/writer/WriteMultipart.js +4 -6
- package/lib/writer/WriteStream.js +14 -20
- package/package.json +1 -1
- package/lib/writer/static-dicomweb.code-workspace +0 -8
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
const path = require(
|
|
2
|
-
const glob = require(
|
|
3
|
-
const fs = require(
|
|
4
|
-
const { Tags, execSpawn, Stats } = require(
|
|
5
|
-
const { shouldThumbUseTranscoded } = require(
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const glob = require('glob');
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const { Tags, execSpawn, Stats } = require('@radicalimaging/static-wado-util');
|
|
5
|
+
const { shouldThumbUseTranscoded } = require('./adapter/transcodeImage');
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Return the middle index of given list
|
|
@@ -46,7 +46,7 @@ class ThumbnailService {
|
|
|
46
46
|
constructor() {
|
|
47
47
|
this.framesThumbnailObj = [];
|
|
48
48
|
this.favoriteThumbnailObj = {};
|
|
49
|
-
this.thumbFileName =
|
|
49
|
+
this.thumbFileName = 'thumbnail';
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
/**
|
|
@@ -56,12 +56,9 @@ class ThumbnailService {
|
|
|
56
56
|
* @param {Object} programOpts
|
|
57
57
|
*/
|
|
58
58
|
queueThumbnail(thumbObjWrapper, programOpts) {
|
|
59
|
-
const { id, imageFrame, transcodedId, transcodedImageFrame, frameIndex } =
|
|
60
|
-
thumbObjWrapper;
|
|
59
|
+
const { id, imageFrame, transcodedId, transcodedImageFrame, frameIndex } = thumbObjWrapper;
|
|
61
60
|
const getThumbContent = (originalContent, trancodedContent) =>
|
|
62
|
-
shouldThumbUseTranscoded(id, programOpts)
|
|
63
|
-
? trancodedContent
|
|
64
|
-
: originalContent;
|
|
61
|
+
shouldThumbUseTranscoded(id, programOpts) ? trancodedContent : originalContent;
|
|
65
62
|
|
|
66
63
|
const thumbObj = {
|
|
67
64
|
imageFrame: getThumbContent(imageFrame, transcodedImageFrame),
|
|
@@ -81,17 +78,15 @@ class ThumbnailService {
|
|
|
81
78
|
}
|
|
82
79
|
|
|
83
80
|
ffmpeg(input, output) {
|
|
84
|
-
execSpawn(
|
|
85
|
-
`ffmpeg -i "${input}" -y -f image2 -frames:v 1 -update true "${output}"`,
|
|
86
|
-
);
|
|
81
|
+
execSpawn(`ffmpeg -i "${input}" -y -f image2 -frames:v 1 -update true "${output}"`);
|
|
87
82
|
}
|
|
88
83
|
|
|
89
84
|
dcm2jpg(input, output, options) {
|
|
90
|
-
const script = [
|
|
85
|
+
const script = ['dcm2jpg', `"${input}" "${output}"`];
|
|
91
86
|
if (options?.format) {
|
|
92
|
-
script.push(
|
|
87
|
+
script.push('-F', options.format);
|
|
93
88
|
}
|
|
94
|
-
execSpawn(script.join(
|
|
89
|
+
execSpawn(script.join(' '));
|
|
95
90
|
}
|
|
96
91
|
|
|
97
92
|
/** Generates a rendered copy of this, assuming --rendered is set.
|
|
@@ -102,8 +97,8 @@ class ThumbnailService {
|
|
|
102
97
|
return null;
|
|
103
98
|
}
|
|
104
99
|
const { id } = this.favoriteThumbnailObj;
|
|
105
|
-
const rendered = id.imageFrameRootPath.replace(/frames/,
|
|
106
|
-
return this.dcm2jpg(id.filename, rendered, { format:
|
|
100
|
+
const rendered = id.imageFrameRootPath.replace(/frames/, 'rendered');
|
|
101
|
+
return this.dcm2jpg(id.filename, rendered, { format: 'png' });
|
|
107
102
|
}
|
|
108
103
|
|
|
109
104
|
/**
|
|
@@ -121,21 +116,18 @@ class ThumbnailService {
|
|
|
121
116
|
const pixelData = metadata[Tags.PixelData];
|
|
122
117
|
if (pixelData) {
|
|
123
118
|
const { BulkDataURI } = pixelData;
|
|
124
|
-
if (BulkDataURI?.indexOf(
|
|
119
|
+
if (BulkDataURI?.indexOf('mp4')) {
|
|
125
120
|
fs.mkdirSync(`${itemId.sopInstanceRootPath}/rendered`, {
|
|
126
121
|
recursive: true,
|
|
127
122
|
});
|
|
128
|
-
const mp4Path = path.join(
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
);
|
|
132
|
-
const thumbPath = path.join(itemId.sopInstanceRootPath, "thumbnail");
|
|
133
|
-
console.verbose("MP4 - converting video format", mp4Path);
|
|
123
|
+
const mp4Path = path.join(itemId.sopInstanceRootPath, 'rendered/index.mp4');
|
|
124
|
+
const thumbPath = path.join(itemId.sopInstanceRootPath, 'thumbnail');
|
|
125
|
+
console.verbose('MP4 - converting video format', mp4Path);
|
|
134
126
|
this.ffmpeg(mp4Path, thumbPath);
|
|
135
127
|
return thumbPath;
|
|
136
128
|
}
|
|
137
129
|
} else {
|
|
138
|
-
console.verbose(
|
|
130
|
+
console.verbose('Series is of other type...', metadata[Tags.Modality]);
|
|
139
131
|
}
|
|
140
132
|
return null;
|
|
141
133
|
}
|
|
@@ -145,11 +137,7 @@ class ThumbnailService {
|
|
|
145
137
|
}
|
|
146
138
|
|
|
147
139
|
if (options.dcm2jpg) {
|
|
148
|
-
return this.dcm2jpg(
|
|
149
|
-
id.filename,
|
|
150
|
-
id.imageFrameRootPath.replace(/frames/, "thumbnail"),
|
|
151
|
-
{},
|
|
152
|
-
);
|
|
140
|
+
return this.dcm2jpg(id.filename, id.imageFrameRootPath.replace(/frames/, 'thumbnail'), {});
|
|
153
141
|
}
|
|
154
142
|
|
|
155
143
|
await callback.internalGenerateImage(
|
|
@@ -157,28 +145,20 @@ class ThumbnailService {
|
|
|
157
145
|
dataSet,
|
|
158
146
|
metadata,
|
|
159
147
|
id.transferSyntaxUid,
|
|
160
|
-
async
|
|
148
|
+
async thumbBuffer => {
|
|
161
149
|
try {
|
|
162
150
|
if (thumbBuffer) {
|
|
163
|
-
await callback.thumbWriter(
|
|
164
|
-
id.sopInstanceRootPath,
|
|
165
|
-
this.thumbFileName,
|
|
166
|
-
thumbBuffer,
|
|
167
|
-
);
|
|
151
|
+
await callback.thumbWriter(id.sopInstanceRootPath, this.thumbFileName, thumbBuffer);
|
|
168
152
|
|
|
169
153
|
this.copySyncThumbnail(id.sopInstanceRootPath, id.seriesRootPath);
|
|
170
154
|
this.copySyncThumbnail(id.seriesRootPath, id.studyPath);
|
|
171
|
-
Stats.StudyStats.add(
|
|
172
|
-
"Thumbnail Write",
|
|
173
|
-
`Write thumbnail ${this.thumbFileName}`,
|
|
174
|
-
100,
|
|
175
|
-
);
|
|
155
|
+
Stats.StudyStats.add('Thumbnail Write', `Write thumbnail ${this.thumbFileName}`, 100);
|
|
176
156
|
}
|
|
177
157
|
return this.thumbFileName;
|
|
178
158
|
} catch (e) {
|
|
179
159
|
console.log("Couldn't generate thumbnail", this.thumbFileName, e);
|
|
180
160
|
}
|
|
181
|
-
}
|
|
161
|
+
}
|
|
182
162
|
);
|
|
183
163
|
}
|
|
184
164
|
|
|
@@ -192,16 +172,14 @@ class ThumbnailService {
|
|
|
192
172
|
* @returns
|
|
193
173
|
*/
|
|
194
174
|
async copySyncThumbnail(sourceFolderPath, targetFolderPath) {
|
|
195
|
-
const parentPathLevel = path.join(sourceFolderPath,
|
|
196
|
-
const thumbFilesPath = glob.sync(
|
|
197
|
-
`${parentPathLevel}*/${this.thumbFileName}`,
|
|
198
|
-
);
|
|
175
|
+
const parentPathLevel = path.join(sourceFolderPath, '../');
|
|
176
|
+
const thumbFilesPath = glob.sync(`${parentPathLevel}*/${this.thumbFileName}`);
|
|
199
177
|
|
|
200
178
|
const thumbIndex = getThumbIndex(thumbFilesPath.length);
|
|
201
179
|
const thumbFilePath = thumbFilesPath[thumbIndex];
|
|
202
180
|
|
|
203
181
|
if (!fs.existsSync(thumbFilePath)) {
|
|
204
|
-
console.verbose(
|
|
182
|
+
console.verbose('Thumbnail to copy does not exists');
|
|
205
183
|
return;
|
|
206
184
|
}
|
|
207
185
|
|
|
@@ -210,12 +188,9 @@ class ThumbnailService {
|
|
|
210
188
|
throw new Error(`Target path: ${targetFolderPath} is not a directory`);
|
|
211
189
|
}
|
|
212
190
|
|
|
213
|
-
fs.copyFileSync(
|
|
214
|
-
thumbFilePath,
|
|
215
|
-
`${targetFolderPath}/${this.thumbFileName}`,
|
|
216
|
-
);
|
|
191
|
+
fs.copyFileSync(thumbFilePath, `${targetFolderPath}/${this.thumbFileName}`);
|
|
217
192
|
} catch (e) {
|
|
218
|
-
console.verbose(
|
|
193
|
+
console.verbose('The file could not be copied', e);
|
|
219
194
|
}
|
|
220
195
|
}
|
|
221
196
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
const dicomCodec = require(
|
|
2
|
-
const getImageInfo = require(
|
|
1
|
+
const dicomCodec = require('@cornerstonejs/dicom-codec');
|
|
2
|
+
const getImageInfo = require('./getImageInfo');
|
|
3
3
|
|
|
4
4
|
function decodeImage(imageFrame, dataset, instance, transferSyntaxUid) {
|
|
5
5
|
const imageInfo = getImageInfo(dataset, instance);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const { Tags } = require(
|
|
1
|
+
const { Tags } = require('@radicalimaging/static-wado-util');
|
|
2
2
|
/**
|
|
3
3
|
* Minimum image info data to be used on transcode process by dicom-codec api.
|
|
4
4
|
*/
|
|
@@ -8,8 +8,7 @@ function getImageInfo(dataSet, instance) {
|
|
|
8
8
|
const columns = Tags.getValue(instance, Tags.Columns);
|
|
9
9
|
const bitsAllocated = Tags.getValue(instance, Tags.BitsAllocated);
|
|
10
10
|
const samplesPerPixel = Tags.getValue(instance, Tags.SamplesPerPixel);
|
|
11
|
-
const pixelRepresentation =
|
|
12
|
-
Tags.getValue(instance, Tags.PixelRepresentation) || 0; // not yet being used.
|
|
11
|
+
const pixelRepresentation = Tags.getValue(instance, Tags.PixelRepresentation) || 0; // not yet being used.
|
|
13
12
|
|
|
14
13
|
return {
|
|
15
14
|
bitsAllocated,
|
|
@@ -20,11 +19,11 @@ function getImageInfo(dataSet, instance) {
|
|
|
20
19
|
pixelRepresentation,
|
|
21
20
|
};
|
|
22
21
|
}
|
|
23
|
-
const rows = dataSet.uint16(
|
|
24
|
-
const columns = dataSet.uint16(
|
|
25
|
-
const bitsAllocated = dataSet.uint16(
|
|
26
|
-
const samplesPerPixel = dataSet.uint16(
|
|
27
|
-
const pixelRepresentation = dataSet.uint16(
|
|
22
|
+
const rows = dataSet.uint16('x00280010');
|
|
23
|
+
const columns = dataSet.uint16('x00280011');
|
|
24
|
+
const bitsAllocated = dataSet.uint16('x00280100');
|
|
25
|
+
const samplesPerPixel = dataSet.uint16('x00280002');
|
|
26
|
+
const pixelRepresentation = dataSet.uint16('x00280103') || 0; // not yet being used.
|
|
28
27
|
|
|
29
28
|
return {
|
|
30
29
|
bitsAllocated,
|