@ohif/app 3.0.0 → 3.5.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/dist/151.bundle.07bac9172580a60fae7a.js +2579 -0
- package/dist/192.bundle.62be5f0ef9705a485071.js +894 -0
- package/dist/199.bundle.2286f24cf0a068e7f50c.js +480 -0
- package/dist/205.bundle.39e6c847d618ad2b1b7a.js +62 -0
- package/dist/208.bundle.23748a85dfdc79c05d3a.js +864 -0
- package/dist/270.bundle.abbdb5348274bae3e8bc.js +23906 -0
- package/dist/283.bundle.33f99a75a5e2d9333da2.js +2939 -0
- package/dist/295.bundle.5105ce962be15c92484d.js +48 -0
- package/dist/331.bundle.7ac7b142d249d14fd99e.js +73034 -0
- package/dist/351.bundle.c5d7279ef42e30f61e08.js +1471 -0
- package/dist/351.css +3 -0
- package/dist/36785fbd89b0e17f6099.wasm +0 -0
- package/dist/381.bundle.0905e683605fcbc0895f.js +1009 -0
- package/dist/404.bundle.0f7a500421f246153d89.js +706 -0
- package/dist/50.bundle.4cb103cd20f5ffccf927.js +324 -0
- package/dist/5004fdc02f329ce53b69.wasm +0 -0
- package/dist/531.bundle.1bc152c87c7e2e987d2b.js +5935 -0
- package/dist/55.bundle.a5a215e13a8511f7aee7.js +685 -0
- package/dist/55.css +3 -0
- package/dist/569.bundle.d147c0aa0604f8ea2094.js +514 -0
- package/dist/581.bundle.646c89c5c3e3ee096363.js +508 -0
- package/dist/606.bundle.5d876f5f3dd8287f0a28.js +4939 -0
- package/dist/610.min.worker.js +2 -0
- package/dist/610.min.worker.js.map +1 -0
- package/dist/616.bundle.bec4736d8c9513e62856.js +686 -0
- package/dist/62ab5d58a2bea7b5a1dc.wasm +0 -0
- package/dist/642.bundle.030d908e22c8ff5611f3.js +169 -0
- package/dist/65916ef3def695744bda.wasm +0 -0
- package/dist/664.bundle.4792c88ae0d6d4b5ed13.js +901 -0
- package/dist/707.bundle.0a74aa3e61ed002eb3c6.js +9049 -0
- package/dist/707.css +1 -0
- package/dist/728.bundle.d13856835357400fef82.js +26221 -0
- package/dist/744.bundle.53b07e48e07a11e920ac.js +2355 -0
- package/dist/75788f12450d4c5ed494.wasm +0 -0
- package/dist/75a0c2dfe07b824c7d21.wasm +0 -0
- package/dist/780.bundle.f60ac1906e0ae080dee8.js +4769 -0
- package/dist/790.bundle.b4df2c5d78a2a565b150.js +454 -0
- package/dist/799.bundle.3fff638815e355b0bdfd.js +271 -0
- package/dist/806.css +1 -0
- package/dist/82.bundle.a24015533196e05d190e.js +6104 -0
- package/dist/917.bundle.a094ae9e9de6df4119ae.js +196 -0
- package/dist/926.bundle.dbc9d0e591cb9217fda2.js +72552 -0
- package/dist/935.bundle.deeffff0e4f7b528e3c3.js +1849 -0
- package/dist/945.min.worker.js +2 -0
- package/dist/945.min.worker.js.map +1 -0
- package/dist/953.bundle.c14d9eb6400f697019ee.js +449 -0
- package/dist/973.bundle.4100cf103686b64938d1.js +261 -0
- package/dist/976.bundle.2720eb892514e1818018.js +2725 -0
- package/dist/984.bundle.157fc66ea5040e1364af.js +1842 -0
- package/dist/_headers +6 -0
- package/dist/_redirects +6 -0
- package/dist/app-config.js +215 -0
- package/dist/app.bundle.253eeb2a7ee986e89c50.js +154621 -0
- package/dist/app.bundle.css +21 -0
- package/dist/assets/android-chrome-144x144.png +0 -0
- package/dist/assets/android-chrome-192x192.png +0 -0
- package/dist/assets/android-chrome-256x256.png +0 -0
- package/dist/assets/android-chrome-36x36.png +0 -0
- package/dist/assets/android-chrome-384x384.png +0 -0
- package/dist/assets/android-chrome-48x48.png +0 -0
- package/dist/assets/android-chrome-512x512.png +0 -0
- package/dist/assets/android-chrome-72x72.png +0 -0
- package/dist/assets/android-chrome-96x96.png +0 -0
- package/dist/assets/apple-touch-icon-1024x1024.png +0 -0
- package/dist/assets/apple-touch-icon-114x114.png +0 -0
- package/dist/assets/apple-touch-icon-120x120.png +0 -0
- package/dist/assets/apple-touch-icon-144x144.png +0 -0
- package/dist/assets/apple-touch-icon-152x152.png +0 -0
- package/dist/assets/apple-touch-icon-167x167.png +0 -0
- package/dist/assets/apple-touch-icon-180x180.png +0 -0
- package/dist/assets/apple-touch-icon-57x57.png +0 -0
- package/dist/assets/apple-touch-icon-60x60.png +0 -0
- package/dist/assets/apple-touch-icon-72x72.png +0 -0
- package/dist/assets/apple-touch-icon-76x76.png +0 -0
- package/dist/assets/apple-touch-icon-precomposed.png +0 -0
- package/dist/assets/apple-touch-icon.png +0 -0
- package/dist/assets/apple-touch-startup-image-1182x2208.png +0 -0
- package/dist/assets/apple-touch-startup-image-1242x2148.png +0 -0
- package/dist/assets/apple-touch-startup-image-1496x2048.png +0 -0
- package/dist/assets/apple-touch-startup-image-1536x2008.png +0 -0
- package/dist/assets/apple-touch-startup-image-320x460.png +0 -0
- package/dist/assets/apple-touch-startup-image-640x1096.png +0 -0
- package/dist/assets/apple-touch-startup-image-640x920.png +0 -0
- package/dist/assets/apple-touch-startup-image-748x1024.png +0 -0
- package/dist/assets/apple-touch-startup-image-750x1294.png +0 -0
- package/dist/assets/apple-touch-startup-image-768x1004.png +0 -0
- package/dist/assets/browserconfig.xml +12 -0
- package/dist/assets/coast-228x228.png +0 -0
- package/dist/assets/favicon-16x16.png +0 -0
- package/dist/assets/favicon-32x32.png +0 -0
- package/dist/assets/favicon.ico +0 -0
- package/dist/assets/firefox_app_128x128.png +0 -0
- package/dist/assets/firefox_app_512x512.png +0 -0
- package/dist/assets/firefox_app_60x60.png +0 -0
- package/dist/assets/manifest.webapp +14 -0
- package/dist/assets/mstile-144x144.png +0 -0
- package/dist/assets/mstile-150x150.png +0 -0
- package/dist/assets/mstile-310x150.png +0 -0
- package/dist/assets/mstile-310x310.png +0 -0
- package/dist/assets/mstile-70x70.png +0 -0
- package/dist/assets/yandex-browser-50x50.png +0 -0
- package/dist/assets/yandex-browser-manifest.json +9 -0
- package/dist/b6b803111e2d06a825bd.wasm +0 -0
- package/dist/c22b37c3488e1d6c3aa4.wasm +0 -0
- package/dist/cornerstoneDICOMImageLoader.min.js +2 -0
- package/dist/cornerstoneDICOMImageLoader.min.js.map +1 -0
- package/dist/dicom-microscopy-viewer.bundle.aa60bdf008c32c39cfd7.js +12 -0
- package/dist/dicomMicroscopyViewer.min.js +3 -0
- package/dist/dicomMicroscopyViewer.min.js.LICENSE.txt +29 -0
- package/dist/es6-shim.min.js +12 -0
- package/dist/google.js +75 -0
- package/dist/index.html +1 -0
- package/dist/index.worker.ea71efba2ce63c499055.worker.js +2 -0
- package/dist/index.worker.ea71efba2ce63c499055.worker.js.map +1 -0
- package/dist/index.worker.min.worker.js +2 -0
- package/dist/index.worker.min.worker.js.map +1 -0
- package/dist/init-service-worker.js +59 -0
- package/dist/manifest.json +59 -0
- package/dist/ohif-logo-light.svg +15 -0
- package/dist/ohif-logo.svg +15 -0
- package/dist/oidc-client.min.js +46 -0
- package/dist/polyfill.min.js +1 -0
- package/dist/silent-refresh.html +16 -0
- package/dist/sw.js +56 -0
- package/package.json +24 -23
|
@@ -0,0 +1,1849 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
(globalThis["webpackChunk"] = globalThis["webpackChunk"] || []).push([[935],{
|
|
3
|
+
|
|
4
|
+
/***/ 75935:
|
|
5
|
+
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
6
|
+
|
|
7
|
+
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
8
|
+
/* harmony export */ "api": () => (/* binding */ api)
|
|
9
|
+
/* harmony export */ });
|
|
10
|
+
/* unused harmony exports utils, version */
|
|
11
|
+
function _typeof(obj) {
|
|
12
|
+
"@babel/helpers - typeof";
|
|
13
|
+
|
|
14
|
+
return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) {
|
|
15
|
+
return typeof obj;
|
|
16
|
+
} : function (obj) {
|
|
17
|
+
return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
|
|
18
|
+
}, _typeof(obj);
|
|
19
|
+
}
|
|
20
|
+
function _classCallCheck(instance, Constructor) {
|
|
21
|
+
if (!(instance instanceof Constructor)) {
|
|
22
|
+
throw new TypeError("Cannot call a class as a function");
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
function _defineProperties(target, props) {
|
|
26
|
+
for (var i = 0; i < props.length; i++) {
|
|
27
|
+
var descriptor = props[i];
|
|
28
|
+
descriptor.enumerable = descriptor.enumerable || false;
|
|
29
|
+
descriptor.configurable = true;
|
|
30
|
+
if ("value" in descriptor) descriptor.writable = true;
|
|
31
|
+
Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
function _createClass(Constructor, protoProps, staticProps) {
|
|
35
|
+
if (protoProps) _defineProperties(Constructor.prototype, protoProps);
|
|
36
|
+
if (staticProps) _defineProperties(Constructor, staticProps);
|
|
37
|
+
Object.defineProperty(Constructor, "prototype", {
|
|
38
|
+
writable: false
|
|
39
|
+
});
|
|
40
|
+
return Constructor;
|
|
41
|
+
}
|
|
42
|
+
function _toPrimitive(input, hint) {
|
|
43
|
+
if (typeof input !== "object" || input === null) return input;
|
|
44
|
+
var prim = input[Symbol.toPrimitive];
|
|
45
|
+
if (prim !== undefined) {
|
|
46
|
+
var res = prim.call(input, hint || "default");
|
|
47
|
+
if (typeof res !== "object") return res;
|
|
48
|
+
throw new TypeError("@@toPrimitive must return a primitive value.");
|
|
49
|
+
}
|
|
50
|
+
return (hint === "string" ? String : Number)(input);
|
|
51
|
+
}
|
|
52
|
+
function _toPropertyKey(arg) {
|
|
53
|
+
var key = _toPrimitive(arg, "string");
|
|
54
|
+
return typeof key === "symbol" ? key : String(key);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Converts a Uint8Array to a String.
|
|
59
|
+
* @param {Uint8Array} array that should be converted
|
|
60
|
+
* @param {Number} offset array offset in case only subset of array items should
|
|
61
|
+
be extracted (default: 0)
|
|
62
|
+
* @param {Number} limit maximum number of array items that should be extracted
|
|
63
|
+
(defaults to length of array)
|
|
64
|
+
* @returns {String}
|
|
65
|
+
*/
|
|
66
|
+
function uint8ArrayToString(arr) {
|
|
67
|
+
var offset = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
|
|
68
|
+
var limit = arguments.length > 2 ? arguments[2] : undefined;
|
|
69
|
+
var itemLimit = limit || arr.length - offset;
|
|
70
|
+
var str = '';
|
|
71
|
+
for (var i = offset; i < offset + itemLimit; i++) {
|
|
72
|
+
str += String.fromCharCode(arr[i]);
|
|
73
|
+
}
|
|
74
|
+
return str;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Converts a String to a Uint8Array.
|
|
79
|
+
* @param {String} str string that should be converted
|
|
80
|
+
* @returns {Uint8Array}
|
|
81
|
+
*/
|
|
82
|
+
function stringToUint8Array(str) {
|
|
83
|
+
var arr = new Uint8Array(str.length);
|
|
84
|
+
for (var i = 0, j = str.length; i < j; i++) {
|
|
85
|
+
arr[i] = str.charCodeAt(i);
|
|
86
|
+
}
|
|
87
|
+
return arr;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Identifies the boundary in a multipart/related message header.
|
|
92
|
+
* @param {String} header message header
|
|
93
|
+
* @returns {String} boundary
|
|
94
|
+
*/
|
|
95
|
+
function identifyBoundary(header) {
|
|
96
|
+
var parts = header.split('\r\n');
|
|
97
|
+
for (var i = 0; i < parts.length; i++) {
|
|
98
|
+
if (parts[i].substr(0, 2) === '--') {
|
|
99
|
+
return parts[i];
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Checks whether a given token is contained by a message at a given offset.
|
|
107
|
+
* @param {Uint8Array} message message content
|
|
108
|
+
* @param {Uint8Array} token substring that should be present
|
|
109
|
+
* @param {Number} offset offset in message content from where search should start
|
|
110
|
+
* @returns {Boolean} whether message contains token at offset
|
|
111
|
+
*/
|
|
112
|
+
function containsToken(message, token) {
|
|
113
|
+
var offset = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
|
|
114
|
+
if (offset + token.length > message.length) {
|
|
115
|
+
return false;
|
|
116
|
+
}
|
|
117
|
+
var index = offset;
|
|
118
|
+
for (var i = 0; i < token.length; i++) {
|
|
119
|
+
if (token[i] !== message[index]) {
|
|
120
|
+
return false;
|
|
121
|
+
}
|
|
122
|
+
index += 1;
|
|
123
|
+
}
|
|
124
|
+
return true;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Finds a given token in a message at a given offset.
|
|
129
|
+
* @param {Uint8Array} message message content
|
|
130
|
+
* @param {Uint8Array} token substring that should be found
|
|
131
|
+
* @param {String} offset message body offset from where search should start
|
|
132
|
+
* @returns {Boolean} whether message has a part at given offset or not
|
|
133
|
+
*/
|
|
134
|
+
function findToken(message, token) {
|
|
135
|
+
var offset = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
|
|
136
|
+
var maxSearchLength = arguments.length > 3 ? arguments[3] : undefined;
|
|
137
|
+
var searchLength = message.length;
|
|
138
|
+
if (maxSearchLength) {
|
|
139
|
+
searchLength = Math.min(offset + maxSearchLength, message.length);
|
|
140
|
+
}
|
|
141
|
+
for (var i = offset; i < searchLength; i++) {
|
|
142
|
+
// If the first value of the message matches
|
|
143
|
+
// the first value of the token, check if
|
|
144
|
+
// this is the full token.
|
|
145
|
+
if (message[i] === token[0]) {
|
|
146
|
+
if (containsToken(message, token, i)) {
|
|
147
|
+
return i;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
return -1;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Create a random GUID
|
|
156
|
+
*
|
|
157
|
+
* @return {string}
|
|
158
|
+
*/
|
|
159
|
+
function guid() {
|
|
160
|
+
function s4() {
|
|
161
|
+
return Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1);
|
|
162
|
+
}
|
|
163
|
+
return "".concat(s4() + s4(), "-").concat(s4(), "-").concat(s4(), "-").concat(s4(), "-").concat(s4()).concat(s4()).concat(s4());
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* @typedef {Object} MultipartEncodedData
|
|
168
|
+
* @property {ArrayBuffer} data The encoded Multipart Data
|
|
169
|
+
* @property {String} boundary The boundary used to divide pieces of the encoded data
|
|
170
|
+
*/
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Encode one or more DICOM datasets into a single body so it can be
|
|
174
|
+
* sent using the Multipart Content-Type.
|
|
175
|
+
*
|
|
176
|
+
* @param {ArrayBuffer[]} datasets Array containing each file to be encoded in the
|
|
177
|
+
multipart body, passed as ArrayBuffers.
|
|
178
|
+
* @param {String} [boundary] Optional string to define a boundary between each part
|
|
179
|
+
of the multipart body. If this is not specified, a random
|
|
180
|
+
GUID will be generated.
|
|
181
|
+
* @return {MultipartEncodedData} The Multipart encoded data returned as an Object. This
|
|
182
|
+
contains both the data itself, and the boundary string
|
|
183
|
+
used to divide it.
|
|
184
|
+
*/
|
|
185
|
+
function multipartEncode(datasets) {
|
|
186
|
+
var boundary = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : guid();
|
|
187
|
+
var contentType = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'application/dicom';
|
|
188
|
+
var contentTypeString = "Content-Type: ".concat(contentType);
|
|
189
|
+
var header = "\r\n--".concat(boundary, "\r\n").concat(contentTypeString, "\r\n\r\n");
|
|
190
|
+
var footer = "\r\n--".concat(boundary, "--");
|
|
191
|
+
var headerArray = stringToUint8Array(header);
|
|
192
|
+
var footerArray = stringToUint8Array(footer);
|
|
193
|
+
var headerLength = headerArray.length;
|
|
194
|
+
var footerLength = footerArray.length;
|
|
195
|
+
var length = 0;
|
|
196
|
+
|
|
197
|
+
// Calculate the total length for the final array
|
|
198
|
+
var contentArrays = datasets.map(function (datasetBuffer) {
|
|
199
|
+
var contentArray = new Uint8Array(datasetBuffer);
|
|
200
|
+
var contentLength = contentArray.length;
|
|
201
|
+
length += headerLength + contentLength + footerLength;
|
|
202
|
+
return contentArray;
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
// Allocate the array
|
|
206
|
+
var multipartArray = new Uint8Array(length);
|
|
207
|
+
|
|
208
|
+
// Set the initial header
|
|
209
|
+
multipartArray.set(headerArray, 0);
|
|
210
|
+
|
|
211
|
+
// Write each dataset into the multipart array
|
|
212
|
+
var position = 0;
|
|
213
|
+
contentArrays.forEach(function (contentArray) {
|
|
214
|
+
multipartArray.set(headerArray, position);
|
|
215
|
+
multipartArray.set(contentArray, position + headerLength);
|
|
216
|
+
position += headerLength + contentArray.length;
|
|
217
|
+
});
|
|
218
|
+
multipartArray.set(footerArray, position);
|
|
219
|
+
return {
|
|
220
|
+
data: multipartArray.buffer,
|
|
221
|
+
boundary: boundary
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Decode a Multipart encoded ArrayBuffer and return the components as an Array.
|
|
227
|
+
*
|
|
228
|
+
* @param {ArrayBuffer} response Data encoded as a 'multipart/related' message
|
|
229
|
+
* @returns {Array} The content
|
|
230
|
+
*/
|
|
231
|
+
function multipartDecode(response) {
|
|
232
|
+
var message = new Uint8Array(response);
|
|
233
|
+
|
|
234
|
+
/* Set a maximum length to search for the header boundaries, otherwise
|
|
235
|
+
findToken can run for a long time
|
|
236
|
+
*/
|
|
237
|
+
var maxSearchLength = 1000;
|
|
238
|
+
|
|
239
|
+
// First look for the multipart mime header
|
|
240
|
+
var separator = stringToUint8Array('\r\n\r\n');
|
|
241
|
+
var headerIndex = findToken(message, separator, 0, maxSearchLength);
|
|
242
|
+
if (headerIndex === -1) {
|
|
243
|
+
throw new Error('Response message has no multipart mime header');
|
|
244
|
+
}
|
|
245
|
+
var header = uint8ArrayToString(message, 0, headerIndex);
|
|
246
|
+
var boundaryString = identifyBoundary(header);
|
|
247
|
+
if (!boundaryString) {
|
|
248
|
+
throw new Error('Header of response message does not specify boundary');
|
|
249
|
+
}
|
|
250
|
+
var boundary = stringToUint8Array(boundaryString);
|
|
251
|
+
var boundaryLength = boundary.length;
|
|
252
|
+
var components = [];
|
|
253
|
+
var offset = boundaryLength;
|
|
254
|
+
|
|
255
|
+
// Loop until we cannot find any more boundaries
|
|
256
|
+
var boundaryIndex;
|
|
257
|
+
while (boundaryIndex !== -1) {
|
|
258
|
+
// Search for the next boundary in the message, starting
|
|
259
|
+
// from the current offset position
|
|
260
|
+
boundaryIndex = findToken(message, boundary, offset);
|
|
261
|
+
|
|
262
|
+
// If no further boundaries are found, stop here.
|
|
263
|
+
if (boundaryIndex === -1) {
|
|
264
|
+
break;
|
|
265
|
+
}
|
|
266
|
+
var headerTokenIndex = findToken(message, separator, offset, maxSearchLength);
|
|
267
|
+
if (headerTokenIndex === -1) {
|
|
268
|
+
throw new Error('Response message part has no mime header');
|
|
269
|
+
}
|
|
270
|
+
offset = headerTokenIndex + separator.length;
|
|
271
|
+
|
|
272
|
+
// Extract data from response message, excluding "\r\n"
|
|
273
|
+
var spacingLength = 2;
|
|
274
|
+
var data = response.slice(offset, boundaryIndex - spacingLength);
|
|
275
|
+
|
|
276
|
+
// Add the data to the array of results
|
|
277
|
+
components.push(data);
|
|
278
|
+
|
|
279
|
+
// Move the offset to the end of the current section,
|
|
280
|
+
// plus the identified boundary
|
|
281
|
+
offset = boundaryIndex + boundaryLength;
|
|
282
|
+
}
|
|
283
|
+
return components;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
function isObject(obj) {
|
|
287
|
+
return _typeof(obj) === 'object' && obj !== null;
|
|
288
|
+
}
|
|
289
|
+
function isEmptyObject(obj) {
|
|
290
|
+
return Object.keys(obj).length === 0 && obj.constructor === Object;
|
|
291
|
+
}
|
|
292
|
+
function areValidRequestHooks(requestHooks) {
|
|
293
|
+
var isValid = Array.isArray(requestHooks) && requestHooks.every(function (requestHook) {
|
|
294
|
+
return typeof requestHook === 'function' && requestHook.length === 2;
|
|
295
|
+
});
|
|
296
|
+
if (!isValid) {
|
|
297
|
+
console.warn('Request hooks should have the following signature: ' + 'function requestHook(request, metadata) { return request; }');
|
|
298
|
+
}
|
|
299
|
+
return isValid;
|
|
300
|
+
}
|
|
301
|
+
var getFirstResult = function getFirstResult(result) {
|
|
302
|
+
return result[0];
|
|
303
|
+
};
|
|
304
|
+
var MEDIATYPES = {
|
|
305
|
+
DICOM: 'application/dicom',
|
|
306
|
+
DICOM_JSON: 'application/dicom+json',
|
|
307
|
+
OCTET_STREAM: 'application/octet-stream',
|
|
308
|
+
PDF: 'application/pdf',
|
|
309
|
+
JPEG: 'image/jpeg',
|
|
310
|
+
PNG: 'image/png'
|
|
311
|
+
};
|
|
312
|
+
|
|
313
|
+
/**
|
|
314
|
+
* @typedef { import("../types/types").InstanceMetadata } InstanceMetadata
|
|
315
|
+
*/
|
|
316
|
+
|
|
317
|
+
/**
|
|
318
|
+
* A callback with the request instance and metadata information
|
|
319
|
+
* of the currently request being executed that should necessarily
|
|
320
|
+
* return the given request optionally modified.
|
|
321
|
+
* @typedef {function} RequestHook
|
|
322
|
+
* @param {XMLHttpRequest} request - The original XMLHttpRequest instance.
|
|
323
|
+
* @param {object} metadata - The metadata used by the request.
|
|
324
|
+
*/
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* Class for interacting with DICOMweb RESTful services.
|
|
328
|
+
*/
|
|
329
|
+
var DICOMwebClient = /*#__PURE__*/function () {
|
|
330
|
+
/**
|
|
331
|
+
* @constructor
|
|
332
|
+
* @param {Object} options
|
|
333
|
+
* @param {String} options.url - URL of the DICOMweb RESTful Service endpoint
|
|
334
|
+
* @param {String=} options.qidoURLPrefix - URL path prefix for QIDO-RS
|
|
335
|
+
* @param {String=} options.wadoURLPrefix - URL path prefix for WADO-RS
|
|
336
|
+
* @param {String=} options.stowURLPrefix - URL path prefix for STOW-RS
|
|
337
|
+
* @param {String=} options.username - Username
|
|
338
|
+
* @param {String=} options.password - Password
|
|
339
|
+
* @param {Object=} options.headers - HTTP headers
|
|
340
|
+
* @param {Array.<RequestHook>=} options.requestHooks - Request hooks.
|
|
341
|
+
* @param {Object=} options.verbose - print to console request warnings and errors, default true
|
|
342
|
+
*/
|
|
343
|
+
function DICOMwebClient(options) {
|
|
344
|
+
_classCallCheck(this, DICOMwebClient);
|
|
345
|
+
this.baseURL = options.url;
|
|
346
|
+
if (!this.baseURL) {
|
|
347
|
+
console.error('no DICOMweb base url provided - calls that require a URL will fail');
|
|
348
|
+
}
|
|
349
|
+
if ('username' in options) {
|
|
350
|
+
this.username = options.username;
|
|
351
|
+
if (!('password' in options)) {
|
|
352
|
+
console.error('no password provided to authenticate with DICOMweb service');
|
|
353
|
+
}
|
|
354
|
+
this.password = options.password;
|
|
355
|
+
}
|
|
356
|
+
if ('qidoURLPrefix' in options) {
|
|
357
|
+
console.log("use URL prefix for QIDO-RS: ".concat(options.qidoURLPrefix));
|
|
358
|
+
this.qidoURL = "".concat(this.baseURL, "/").concat(options.qidoURLPrefix);
|
|
359
|
+
} else {
|
|
360
|
+
this.qidoURL = this.baseURL;
|
|
361
|
+
}
|
|
362
|
+
if ('wadoURLPrefix' in options) {
|
|
363
|
+
console.log("use URL prefix for WADO-RS: ".concat(options.wadoURLPrefix));
|
|
364
|
+
this.wadoURL = "".concat(this.baseURL, "/").concat(options.wadoURLPrefix);
|
|
365
|
+
} else {
|
|
366
|
+
this.wadoURL = this.baseURL;
|
|
367
|
+
}
|
|
368
|
+
if ('stowURLPrefix' in options) {
|
|
369
|
+
console.log("use URL prefix for STOW-RS: ".concat(options.stowURLPrefix));
|
|
370
|
+
this.stowURL = "".concat(this.baseURL, "/").concat(options.stowURLPrefix);
|
|
371
|
+
} else {
|
|
372
|
+
this.stowURL = this.baseURL;
|
|
373
|
+
}
|
|
374
|
+
if ('requestHooks' in options) {
|
|
375
|
+
this.requestHooks = options.requestHooks;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
// Headers to pass to requests.
|
|
379
|
+
this.headers = options.headers || {};
|
|
380
|
+
|
|
381
|
+
// Optional error interceptor callback to handle any failed request.
|
|
382
|
+
this.errorInterceptor = options.errorInterceptor || function () {
|
|
383
|
+
return undefined;
|
|
384
|
+
};
|
|
385
|
+
|
|
386
|
+
// Verbose - print to console request warnings and errors, default true
|
|
387
|
+
this.verbose = options.verbose !== false;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
/**
|
|
391
|
+
* Sets verbose flag.
|
|
392
|
+
*
|
|
393
|
+
* @param {Boolean} verbose
|
|
394
|
+
*/
|
|
395
|
+
_createClass(DICOMwebClient, [{
|
|
396
|
+
key: "setVerbose",
|
|
397
|
+
value: function setVerbose(verbose) {
|
|
398
|
+
this.verbose = verbose;
|
|
399
|
+
}
|
|
400
|
+
/**
|
|
401
|
+
* Gets verbose flag.
|
|
402
|
+
*
|
|
403
|
+
* @return {Boolean} verbose
|
|
404
|
+
*/
|
|
405
|
+
}, {
|
|
406
|
+
key: "getVerbose",
|
|
407
|
+
value: function getVerbose() {
|
|
408
|
+
return this.verbose;
|
|
409
|
+
}
|
|
410
|
+
}, {
|
|
411
|
+
key: "_httpRequest",
|
|
412
|
+
/**
|
|
413
|
+
* Performs an HTTP request.
|
|
414
|
+
*
|
|
415
|
+
* @param {String} url
|
|
416
|
+
* @param {String} method
|
|
417
|
+
* @param {Object} headers
|
|
418
|
+
* @param {Object} options
|
|
419
|
+
* @param {Array.<RequestHook>} options.requestHooks - Request hooks.
|
|
420
|
+
* @param {XMLHttpRequest} [options.request] - if specified, the request to use, otherwise one will be created; useful for adding custom upload and abort listeners/objects
|
|
421
|
+
* @return {*}
|
|
422
|
+
* @private
|
|
423
|
+
*/
|
|
424
|
+
value: function _httpRequest(url, method) {
|
|
425
|
+
var _this = this;
|
|
426
|
+
var headers = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
|
427
|
+
var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
|
|
428
|
+
var errorInterceptor = this.errorInterceptor,
|
|
429
|
+
requestHooks = this.requestHooks;
|
|
430
|
+
return new Promise(function (resolve, reject) {
|
|
431
|
+
var request = options.request ? options.request : new XMLHttpRequest();
|
|
432
|
+
request.open(method, url, true);
|
|
433
|
+
if ('responseType' in options) {
|
|
434
|
+
request.responseType = options.responseType;
|
|
435
|
+
}
|
|
436
|
+
if (_typeof(headers) === 'object') {
|
|
437
|
+
Object.keys(headers).forEach(function (key) {
|
|
438
|
+
request.setRequestHeader(key, headers[key]);
|
|
439
|
+
});
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
// now add custom headers from the user
|
|
443
|
+
// (e.g. access tokens)
|
|
444
|
+
var userHeaders = _this.headers;
|
|
445
|
+
Object.keys(userHeaders).forEach(function (key) {
|
|
446
|
+
request.setRequestHeader(key, userHeaders[key]);
|
|
447
|
+
});
|
|
448
|
+
|
|
449
|
+
// Event triggered when upload starts
|
|
450
|
+
request.onloadstart = function onloadstart() {
|
|
451
|
+
// console.log('upload started: ', url)
|
|
452
|
+
};
|
|
453
|
+
|
|
454
|
+
// Event triggered when upload ends
|
|
455
|
+
request.onloadend = function onloadend() {
|
|
456
|
+
// console.log('upload finished')
|
|
457
|
+
};
|
|
458
|
+
|
|
459
|
+
// Handle response message
|
|
460
|
+
request.onreadystatechange = function () {
|
|
461
|
+
if (request.readyState === 4) {
|
|
462
|
+
if (request.status === 200) {
|
|
463
|
+
resolve(request.response);
|
|
464
|
+
} else if (request.status === 202) {
|
|
465
|
+
if (_this.verbose) {
|
|
466
|
+
console.warn('some resources already existed: ', request);
|
|
467
|
+
}
|
|
468
|
+
resolve(request.response);
|
|
469
|
+
} else if (request.status === 204) {
|
|
470
|
+
if (_this.verbose) {
|
|
471
|
+
console.warn('empty response for request: ', request);
|
|
472
|
+
}
|
|
473
|
+
resolve([]);
|
|
474
|
+
} else {
|
|
475
|
+
var error = new Error('request failed');
|
|
476
|
+
error.request = request;
|
|
477
|
+
error.response = request.response;
|
|
478
|
+
error.status = request.status;
|
|
479
|
+
if (_this.verbose) {
|
|
480
|
+
console.error('request failed: ', request);
|
|
481
|
+
console.error(error);
|
|
482
|
+
console.error(error.response);
|
|
483
|
+
}
|
|
484
|
+
errorInterceptor(error);
|
|
485
|
+
reject(error);
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
};
|
|
489
|
+
|
|
490
|
+
// Event triggered while download progresses
|
|
491
|
+
if ('progressCallback' in options) {
|
|
492
|
+
if (typeof options.progressCallback === 'function') {
|
|
493
|
+
request.onprogress = options.progressCallback;
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
if (requestHooks && areValidRequestHooks(requestHooks)) {
|
|
497
|
+
var combinedHeaders = Object.assign({}, headers, _this.headers);
|
|
498
|
+
var metadata = {
|
|
499
|
+
method: method,
|
|
500
|
+
url: url,
|
|
501
|
+
headers: combinedHeaders
|
|
502
|
+
};
|
|
503
|
+
var pipeRequestHooks = function pipeRequestHooks(functions) {
|
|
504
|
+
return function (args) {
|
|
505
|
+
return functions.reduce(function (props, fn) {
|
|
506
|
+
return fn(props, metadata);
|
|
507
|
+
}, args);
|
|
508
|
+
};
|
|
509
|
+
};
|
|
510
|
+
var pipedRequest = pipeRequestHooks(requestHooks);
|
|
511
|
+
request = pipedRequest(request);
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
// Add withCredentials to request if needed
|
|
515
|
+
if ('withCredentials' in options) {
|
|
516
|
+
if (options.withCredentials) {
|
|
517
|
+
request.withCredentials = true;
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
if ('data' in options) {
|
|
521
|
+
request.send(options.data);
|
|
522
|
+
} else {
|
|
523
|
+
request.send();
|
|
524
|
+
}
|
|
525
|
+
});
|
|
526
|
+
}
|
|
527
|
+
/**
|
|
528
|
+
* Performs an HTTP GET request.
|
|
529
|
+
*
|
|
530
|
+
* @param {String} url
|
|
531
|
+
* @param {Object} headers
|
|
532
|
+
* @param {Object} responseType
|
|
533
|
+
* @param {Function} progressCallback
|
|
534
|
+
* @return {*}
|
|
535
|
+
* @private
|
|
536
|
+
*/
|
|
537
|
+
}, {
|
|
538
|
+
key: "_httpGet",
|
|
539
|
+
value: function _httpGet(url, headers, responseType, progressCallback, withCredentials) {
|
|
540
|
+
return this._httpRequest(url, 'get', headers, {
|
|
541
|
+
responseType: responseType,
|
|
542
|
+
progressCallback: progressCallback,
|
|
543
|
+
withCredentials: withCredentials
|
|
544
|
+
});
|
|
545
|
+
}
|
|
546
|
+
/**
|
|
547
|
+
* Performs an HTTP GET request that accepts a message with application/json
|
|
548
|
+
* media type.
|
|
549
|
+
*
|
|
550
|
+
* @param {String} url
|
|
551
|
+
* @param {Object} params
|
|
552
|
+
* @param {Function} progressCallback
|
|
553
|
+
* @return {*}
|
|
554
|
+
* @private
|
|
555
|
+
*/
|
|
556
|
+
}, {
|
|
557
|
+
key: "_httpGetApplicationJson",
|
|
558
|
+
value: function _httpGetApplicationJson(url) {
|
|
559
|
+
var params = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
560
|
+
var progressCallback = arguments.length > 2 ? arguments[2] : undefined;
|
|
561
|
+
var withCredentials = arguments.length > 3 ? arguments[3] : undefined;
|
|
562
|
+
var urlWithQueryParams = url;
|
|
563
|
+
if (_typeof(params) === 'object') {
|
|
564
|
+
if (!isEmptyObject(params)) {
|
|
565
|
+
urlWithQueryParams += DICOMwebClient._parseQueryParameters(params);
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
var headers = {
|
|
569
|
+
Accept: MEDIATYPES.DICOM_JSON
|
|
570
|
+
};
|
|
571
|
+
var responseType = 'json';
|
|
572
|
+
return this._httpGet(urlWithQueryParams, headers, responseType, progressCallback, withCredentials);
|
|
573
|
+
}
|
|
574
|
+
/**
|
|
575
|
+
* Performs an HTTP GET request that accepts a message with application/pdf
|
|
576
|
+
* media type.
|
|
577
|
+
*
|
|
578
|
+
* @param {String} url
|
|
579
|
+
* @param {Object} params
|
|
580
|
+
* @param {Function} progressCallback
|
|
581
|
+
* @return {*}
|
|
582
|
+
* @private
|
|
583
|
+
*/
|
|
584
|
+
}, {
|
|
585
|
+
key: "_httpGetApplicationPdf",
|
|
586
|
+
value: function _httpGetApplicationPdf(url) {
|
|
587
|
+
var params = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
588
|
+
var progressCallback = arguments.length > 2 ? arguments[2] : undefined;
|
|
589
|
+
var withCredentials = arguments.length > 3 ? arguments[3] : undefined;
|
|
590
|
+
var urlWithQueryParams = url;
|
|
591
|
+
if (_typeof(params) === 'object') {
|
|
592
|
+
if (!isEmptyObject(params)) {
|
|
593
|
+
urlWithQueryParams += DICOMwebClient._parseQueryParameters(params);
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
var headers = {
|
|
597
|
+
Accept: MEDIATYPES.PDF
|
|
598
|
+
};
|
|
599
|
+
var responseType = 'json';
|
|
600
|
+
return this._httpGet(urlWithQueryParams, headers, responseType, progressCallback, withCredentials);
|
|
601
|
+
}
|
|
602
|
+
/**
|
|
603
|
+
* Performs an HTTP GET request that accepts a message with an image
|
|
604
|
+
media type.
|
|
605
|
+
*
|
|
606
|
+
* @param {String} url
|
|
607
|
+
* @param {Object[]} mediaTypes
|
|
608
|
+
* @param {Object} params
|
|
609
|
+
* @param {Function} progressCallback
|
|
610
|
+
* @return {*}
|
|
611
|
+
* @private
|
|
612
|
+
*/
|
|
613
|
+
}, {
|
|
614
|
+
key: "_httpGetImage",
|
|
615
|
+
value: function _httpGetImage(url, mediaTypes) {
|
|
616
|
+
var params = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
|
617
|
+
var progressCallback = arguments.length > 3 ? arguments[3] : undefined;
|
|
618
|
+
var withCredentials = arguments.length > 4 ? arguments[4] : undefined;
|
|
619
|
+
var urlWithQueryParams = url;
|
|
620
|
+
if (_typeof(params) === 'object') {
|
|
621
|
+
if (!isEmptyObject(params)) {
|
|
622
|
+
urlWithQueryParams += DICOMwebClient._parseQueryParameters(params);
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
var supportedMediaTypes = ['image/', 'image/*', 'image/jpeg', 'image/jp2', 'image/gif', 'image/png'];
|
|
626
|
+
var acceptHeaderFieldValue = DICOMwebClient._buildAcceptHeaderFieldValue(mediaTypes, supportedMediaTypes);
|
|
627
|
+
var headers = {
|
|
628
|
+
Accept: acceptHeaderFieldValue
|
|
629
|
+
};
|
|
630
|
+
var responseType = 'arraybuffer';
|
|
631
|
+
return this._httpGet(urlWithQueryParams, headers, responseType, progressCallback, withCredentials);
|
|
632
|
+
}
|
|
633
|
+
/**
|
|
634
|
+
* Performs an HTTP GET request that accepts a message with a text
|
|
635
|
+
media type.
|
|
636
|
+
*
|
|
637
|
+
* @param {String} url
|
|
638
|
+
* @param {Object[]} mediaTypes
|
|
639
|
+
* @param {Object} params
|
|
640
|
+
* @param {Function} progressCallback
|
|
641
|
+
* @return {*}
|
|
642
|
+
* @private
|
|
643
|
+
*/
|
|
644
|
+
}, {
|
|
645
|
+
key: "_httpGetText",
|
|
646
|
+
value: function _httpGetText(url, mediaTypes) {
|
|
647
|
+
var params = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
|
648
|
+
var progressCallback = arguments.length > 3 ? arguments[3] : undefined;
|
|
649
|
+
var withCredentials = arguments.length > 4 ? arguments[4] : undefined;
|
|
650
|
+
var urlWithQueryParams = url;
|
|
651
|
+
if (_typeof(params) === 'object') {
|
|
652
|
+
if (!isEmptyObject(params)) {
|
|
653
|
+
urlWithQueryParams += DICOMwebClient._parseQueryParameters(params);
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
var supportedMediaTypes = ['text/', 'text/*', 'text/html', 'text/plain', 'text/rtf', 'text/xml'];
|
|
657
|
+
var acceptHeaderFieldValue = DICOMwebClient._buildAcceptHeaderFieldValue(mediaTypes, supportedMediaTypes);
|
|
658
|
+
var headers = {
|
|
659
|
+
Accept: acceptHeaderFieldValue
|
|
660
|
+
};
|
|
661
|
+
var responseType = 'arraybuffer';
|
|
662
|
+
return this._httpGet(urlWithQueryParams, headers, responseType, progressCallback, withCredentials);
|
|
663
|
+
}
|
|
664
|
+
/**
|
|
665
|
+
* Performs an HTTP GET request that accepts a message with a video
|
|
666
|
+
media type.
|
|
667
|
+
*
|
|
668
|
+
* @param {String} url
|
|
669
|
+
* @param {Object[]} mediaTypes
|
|
670
|
+
* @param {Object} params
|
|
671
|
+
* @param {Function} progressCallback
|
|
672
|
+
* @return {*}
|
|
673
|
+
* @private
|
|
674
|
+
*/
|
|
675
|
+
}, {
|
|
676
|
+
key: "_httpGetVideo",
|
|
677
|
+
value: function _httpGetVideo(url, mediaTypes) {
|
|
678
|
+
var params = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
|
679
|
+
var progressCallback = arguments.length > 3 ? arguments[3] : undefined;
|
|
680
|
+
var withCredentials = arguments.length > 4 ? arguments[4] : undefined;
|
|
681
|
+
var urlWithQueryParams = url;
|
|
682
|
+
if (_typeof(params) === 'object') {
|
|
683
|
+
if (!isEmptyObject(params)) {
|
|
684
|
+
urlWithQueryParams += DICOMwebClient._parseQueryParameters(params);
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
var supportedMediaTypes = ['video/', 'video/*', 'video/mpeg', 'video/mp4', 'video/H265'];
|
|
688
|
+
var acceptHeaderFieldValue = DICOMwebClient._buildAcceptHeaderFieldValue(mediaTypes, supportedMediaTypes);
|
|
689
|
+
var headers = {
|
|
690
|
+
Accept: acceptHeaderFieldValue
|
|
691
|
+
};
|
|
692
|
+
var responseType = 'arraybuffer';
|
|
693
|
+
return this._httpGet(urlWithQueryParams, headers, responseType, progressCallback, withCredentials);
|
|
694
|
+
}
|
|
695
|
+
/**
|
|
696
|
+
* Asserts that a given media type is valid.
|
|
697
|
+
*
|
|
698
|
+
* @params {String} mediaType media type
|
|
699
|
+
*/
|
|
700
|
+
}, {
|
|
701
|
+
key: "_httpGetMultipartImage",
|
|
702
|
+
/**
|
|
703
|
+
* Performs an HTTP GET request that accepts a multipart message with an image media type.
|
|
704
|
+
*
|
|
705
|
+
* @param {String} url - Unique resource locator
|
|
706
|
+
* @param {Object[]} mediaTypes - Acceptable media types and optionally the UIDs of the
|
|
707
|
+
corresponding transfer syntaxes
|
|
708
|
+
* @param {Array} byteRange - Start and end of byte range
|
|
709
|
+
* @param {Object} params - Additional HTTP GET query parameters
|
|
710
|
+
* @param {Boolean} rendered - Whether resource should be requested using rendered media types
|
|
711
|
+
* @param {Function} progressCallback
|
|
712
|
+
* @private
|
|
713
|
+
* @returns {Promise<Array>} Content of HTTP message body parts
|
|
714
|
+
*/
|
|
715
|
+
value: function _httpGetMultipartImage(url, mediaTypes, byteRange, params) {
|
|
716
|
+
var rendered = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
|
|
717
|
+
var progressCallback = arguments.length > 5 ? arguments[5] : undefined;
|
|
718
|
+
var withCredentials = arguments.length > 6 ? arguments[6] : undefined;
|
|
719
|
+
var headers = {};
|
|
720
|
+
var supportedMediaTypes;
|
|
721
|
+
if (rendered) {
|
|
722
|
+
supportedMediaTypes = ['image/jpeg', 'image/gif', 'image/png', 'image/jp2'];
|
|
723
|
+
} else {
|
|
724
|
+
supportedMediaTypes = {
|
|
725
|
+
'1.2.840.10008.1.2.5': ['image/x-dicom-rle'],
|
|
726
|
+
'1.2.840.10008.1.2.4.50': ['image/jpeg'],
|
|
727
|
+
'1.2.840.10008.1.2.4.51': ['image/jpeg'],
|
|
728
|
+
'1.2.840.10008.1.2.4.57': ['image/jpeg'],
|
|
729
|
+
'1.2.840.10008.1.2.4.70': ['image/jpeg'],
|
|
730
|
+
'1.2.840.10008.1.2.4.80': ['image/x-jls', 'image/jls'],
|
|
731
|
+
'1.2.840.10008.1.2.4.81': ['image/x-jls', 'image/jls'],
|
|
732
|
+
'1.2.840.10008.1.2.4.90': ['image/jp2'],
|
|
733
|
+
'1.2.840.10008.1.2.4.91': ['image/jp2'],
|
|
734
|
+
'1.2.840.10008.1.2.4.92': ['image/jpx'],
|
|
735
|
+
'1.2.840.10008.1.2.4.93': ['image/jpx']
|
|
736
|
+
};
|
|
737
|
+
if (byteRange) {
|
|
738
|
+
headers.Range = DICOMwebClient._buildRangeHeaderFieldValue(byteRange);
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
headers.Accept = DICOMwebClient._buildMultipartAcceptHeaderFieldValue(mediaTypes, supportedMediaTypes);
|
|
742
|
+
return this._httpGet(url, headers, 'arraybuffer', progressCallback, withCredentials).then(multipartDecode);
|
|
743
|
+
}
|
|
744
|
+
/**
|
|
745
|
+
* Performs an HTTP GET request that accepts a multipart message with a video media type.
|
|
746
|
+
*
|
|
747
|
+
* @param {String} url - Unique resource locator
|
|
748
|
+
* @param {Object[]} mediaTypes - Acceptable media types and optionally the UIDs of the
|
|
749
|
+
corresponding transfer syntaxes
|
|
750
|
+
* @param {Array} byteRange - Start and end of byte range
|
|
751
|
+
* @param {Object} params - Additional HTTP GET query parameters
|
|
752
|
+
* @param {Boolean} rendered - Whether resource should be requested using rendered media types
|
|
753
|
+
* @param {Function} progressCallback
|
|
754
|
+
* @private
|
|
755
|
+
* @returns {Promise<Array>} Content of HTTP message body parts
|
|
756
|
+
*/
|
|
757
|
+
}, {
|
|
758
|
+
key: "_httpGetMultipartVideo",
|
|
759
|
+
value: function _httpGetMultipartVideo(url, mediaTypes, byteRange, params) {
|
|
760
|
+
var rendered = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
|
|
761
|
+
var progressCallback = arguments.length > 5 ? arguments[5] : undefined;
|
|
762
|
+
var withCredentials = arguments.length > 6 ? arguments[6] : undefined;
|
|
763
|
+
var headers = {};
|
|
764
|
+
var supportedMediaTypes;
|
|
765
|
+
if (rendered) {
|
|
766
|
+
supportedMediaTypes = ['video/', 'video/*', 'video/mpeg2', 'video/mp4', 'video/H265'];
|
|
767
|
+
} else {
|
|
768
|
+
supportedMediaTypes = {
|
|
769
|
+
'1.2.840.10008.1.2.4.100': ['video/mpeg2'],
|
|
770
|
+
'1.2.840.10008.1.2.4.101': ['video/mpeg2'],
|
|
771
|
+
'1.2.840.10008.1.2.4.102': ['video/mp4'],
|
|
772
|
+
'1.2.840.10008.1.2.4.103': ['video/mp4'],
|
|
773
|
+
'1.2.840.10008.1.2.4.104': ['video/mp4'],
|
|
774
|
+
'1.2.840.10008.1.2.4.105': ['video/mp4'],
|
|
775
|
+
'1.2.840.10008.1.2.4.106': ['video/mp4']
|
|
776
|
+
};
|
|
777
|
+
if (byteRange) {
|
|
778
|
+
headers.Range = DICOMwebClient._buildRangeHeaderFieldValue(byteRange);
|
|
779
|
+
}
|
|
780
|
+
}
|
|
781
|
+
headers.Accept = DICOMwebClient._buildMultipartAcceptHeaderFieldValue(mediaTypes, supportedMediaTypes);
|
|
782
|
+
return this._httpGet(url, headers, 'arraybuffer', progressCallback, withCredentials).then(multipartDecode);
|
|
783
|
+
}
|
|
784
|
+
/**
|
|
785
|
+
* Performs an HTTP GET request that accepts a multipart message
|
|
786
|
+
* with a application/dicom media type.
|
|
787
|
+
*
|
|
788
|
+
* @param {String} url - Unique resource locator
|
|
789
|
+
* @param {Object[]} mediaTypes - Acceptable media types and optionally the UIDs of the
|
|
790
|
+
corresponding transfer syntaxes
|
|
791
|
+
* @param {Object} params - Additional HTTP GET query parameters
|
|
792
|
+
* @param {Function} progressCallback
|
|
793
|
+
* @private
|
|
794
|
+
* @returns {Promise<Array>} Content of HTTP message body parts
|
|
795
|
+
*/
|
|
796
|
+
}, {
|
|
797
|
+
key: "_httpGetMultipartApplicationDicom",
|
|
798
|
+
value: function _httpGetMultipartApplicationDicom(url, mediaTypes, params, progressCallback, withCredentials) {
|
|
799
|
+
var headers = {};
|
|
800
|
+
var defaultMediaType = 'application/dicom';
|
|
801
|
+
var supportedMediaTypes = {
|
|
802
|
+
'1.2.840.10008.1.2.1': [defaultMediaType],
|
|
803
|
+
'1.2.840.10008.1.2.5': [defaultMediaType],
|
|
804
|
+
'1.2.840.10008.1.2.4.50': [defaultMediaType],
|
|
805
|
+
'1.2.840.10008.1.2.4.51': [defaultMediaType],
|
|
806
|
+
'1.2.840.10008.1.2.4.57': [defaultMediaType],
|
|
807
|
+
'1.2.840.10008.1.2.4.70': [defaultMediaType],
|
|
808
|
+
'1.2.840.10008.1.2.4.80': [defaultMediaType],
|
|
809
|
+
'1.2.840.10008.1.2.4.81': [defaultMediaType],
|
|
810
|
+
'1.2.840.10008.1.2.4.90': [defaultMediaType],
|
|
811
|
+
'1.2.840.10008.1.2.4.91': [defaultMediaType],
|
|
812
|
+
'1.2.840.10008.1.2.4.92': [defaultMediaType],
|
|
813
|
+
'1.2.840.10008.1.2.4.93': [defaultMediaType],
|
|
814
|
+
'1.2.840.10008.1.2.4.100': [defaultMediaType],
|
|
815
|
+
'1.2.840.10008.1.2.4.101': [defaultMediaType],
|
|
816
|
+
'1.2.840.10008.1.2.4.102': [defaultMediaType],
|
|
817
|
+
'1.2.840.10008.1.2.4.103': [defaultMediaType],
|
|
818
|
+
'1.2.840.10008.1.2.4.104': [defaultMediaType],
|
|
819
|
+
'1.2.840.10008.1.2.4.105': [defaultMediaType],
|
|
820
|
+
'1.2.840.10008.1.2.4.106': [defaultMediaType]
|
|
821
|
+
};
|
|
822
|
+
var acceptableMediaTypes = mediaTypes;
|
|
823
|
+
if (!mediaTypes) {
|
|
824
|
+
acceptableMediaTypes = [{
|
|
825
|
+
mediaType: defaultMediaType
|
|
826
|
+
}];
|
|
827
|
+
}
|
|
828
|
+
headers.Accept = DICOMwebClient._buildMultipartAcceptHeaderFieldValue(acceptableMediaTypes, supportedMediaTypes);
|
|
829
|
+
return this._httpGet(url, headers, 'arraybuffer', progressCallback, withCredentials).then(multipartDecode);
|
|
830
|
+
}
|
|
831
|
+
/**
|
|
832
|
+
* Performs an HTTP GET request that accepts a multipart message
|
|
833
|
+
* with a application/octet-stream media type.
|
|
834
|
+
*
|
|
835
|
+
* @param {String} url - Unique resource locator
|
|
836
|
+
* @param {Object[]} mediaTypes - Acceptable media types and optionally the UIDs of the
|
|
837
|
+
corresponding transfer syntaxes
|
|
838
|
+
* @param {Array} byteRange start and end of byte range
|
|
839
|
+
* @param {Object} params - Additional HTTP GET query parameters
|
|
840
|
+
* @param {Function} progressCallback
|
|
841
|
+
* @private
|
|
842
|
+
* @returns {Promise<Array>} Content of HTTP message body parts
|
|
843
|
+
*/
|
|
844
|
+
}, {
|
|
845
|
+
key: "_httpGetMultipartApplicationOctetStream",
|
|
846
|
+
value: function _httpGetMultipartApplicationOctetStream(url, mediaTypes, byteRange, params, progressCallback, withCredentials) {
|
|
847
|
+
var headers = {};
|
|
848
|
+
var defaultMediaType = 'application/octet-stream';
|
|
849
|
+
var supportedMediaTypes = {
|
|
850
|
+
'1.2.840.10008.1.2.1': [defaultMediaType]
|
|
851
|
+
};
|
|
852
|
+
var acceptableMediaTypes = mediaTypes;
|
|
853
|
+
if (!mediaTypes) {
|
|
854
|
+
acceptableMediaTypes = [{
|
|
855
|
+
mediaType: defaultMediaType
|
|
856
|
+
}];
|
|
857
|
+
}
|
|
858
|
+
if (byteRange) {
|
|
859
|
+
headers.Range = DICOMwebClient._buildRangeHeaderFieldValue(byteRange);
|
|
860
|
+
}
|
|
861
|
+
headers.Accept = DICOMwebClient._buildMultipartAcceptHeaderFieldValue(acceptableMediaTypes, supportedMediaTypes);
|
|
862
|
+
return this._httpGet(url, headers, 'arraybuffer', progressCallback, withCredentials).then(multipartDecode);
|
|
863
|
+
}
|
|
864
|
+
/**
|
|
865
|
+
* Performs an HTTP POST request.
|
|
866
|
+
*
|
|
867
|
+
* @param {String} url - Unique resource locator
|
|
868
|
+
* @param {Object} headers - HTTP header fields
|
|
869
|
+
* @param {Array} data - Data that should be stored
|
|
870
|
+
* @param {Function} progressCallback
|
|
871
|
+
* @param {Function} progressCallback
|
|
872
|
+
* @param {XMLHttpRequest} request - if specified, the request to use, otherwise one will be created; useful for adding custom upload and abort listeners/objects
|
|
873
|
+
* @private
|
|
874
|
+
* @returns {Promise} Response
|
|
875
|
+
*/
|
|
876
|
+
}, {
|
|
877
|
+
key: "_httpPost",
|
|
878
|
+
value: function _httpPost(url, headers, data, progressCallback, withCredentials, request) {
|
|
879
|
+
return this._httpRequest(url, 'post', headers, {
|
|
880
|
+
data: data,
|
|
881
|
+
progressCallback: progressCallback,
|
|
882
|
+
withCredentials: withCredentials,
|
|
883
|
+
request: request
|
|
884
|
+
});
|
|
885
|
+
}
|
|
886
|
+
/**
|
|
887
|
+
* Performs an HTTP POST request with content-type application/dicom+json.
|
|
888
|
+
*
|
|
889
|
+
* @param {String} url - Unique resource locator
|
|
890
|
+
* @param {Object} headers - HTTP header fields
|
|
891
|
+
* @param {Array} data - Data that should be stored
|
|
892
|
+
* @param {Function} progressCallback
|
|
893
|
+
* @private
|
|
894
|
+
* @returns {Promise} Response
|
|
895
|
+
*/
|
|
896
|
+
}, {
|
|
897
|
+
key: "_httpPostApplicationJson",
|
|
898
|
+
value: function _httpPostApplicationJson(url, data, progressCallback, withCredentials) {
|
|
899
|
+
var headers = {
|
|
900
|
+
'Content-Type': MEDIATYPES.DICOM_JSON
|
|
901
|
+
};
|
|
902
|
+
return this._httpPost(url, headers, data, progressCallback, withCredentials);
|
|
903
|
+
}
|
|
904
|
+
/**
|
|
905
|
+
* Parses media type and extracts its type and subtype.
|
|
906
|
+
*
|
|
907
|
+
* @param {String} mediaType - HTTP media type (e.g. image/jpeg)
|
|
908
|
+
* @private
|
|
909
|
+
* @returns {String[]} Media type and subtype
|
|
910
|
+
*/
|
|
911
|
+
}, {
|
|
912
|
+
key: "searchForStudies",
|
|
913
|
+
/**
|
|
914
|
+
* Searches for DICOM studies.
|
|
915
|
+
*
|
|
916
|
+
* @param {Object} options
|
|
917
|
+
* @param {Object} [options.queryParams] - HTTP query parameters
|
|
918
|
+
* @return {Object[]} Study representations (http://dicom.nema.org/medical/dicom/current/output/chtml/part18/sect_6.7.html#table_6.7.1-2)
|
|
919
|
+
*/
|
|
920
|
+
value: function searchForStudies() {
|
|
921
|
+
var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
922
|
+
console.log('search for studies');
|
|
923
|
+
var withCredentials = false;
|
|
924
|
+
var url = "".concat(this.qidoURL, "/studies");
|
|
925
|
+
if ('queryParams' in options) {
|
|
926
|
+
url += DICOMwebClient._parseQueryParameters(options.queryParams);
|
|
927
|
+
}
|
|
928
|
+
if ('withCredentials' in options) {
|
|
929
|
+
if (options.withCredentials) {
|
|
930
|
+
withCredentials = options.withCredentials;
|
|
931
|
+
}
|
|
932
|
+
}
|
|
933
|
+
return this._httpGetApplicationJson(url, {}, false, withCredentials);
|
|
934
|
+
}
|
|
935
|
+
/**
|
|
936
|
+
* Retrieves metadata for a DICOM study.
|
|
937
|
+
*
|
|
938
|
+
* @param {Object} options
|
|
939
|
+
* @param {String} options.studyInstanceUID - Study Instance UID
|
|
940
|
+
* @returns {Promise<InstanceMetadata[]>} Metadata elements in DICOM JSON format for each instance
|
|
941
|
+
belonging to the study
|
|
942
|
+
*/
|
|
943
|
+
}, {
|
|
944
|
+
key: "retrieveStudyMetadata",
|
|
945
|
+
value: function retrieveStudyMetadata(options) {
|
|
946
|
+
if (!('studyInstanceUID' in options)) {
|
|
947
|
+
throw new Error('Study Instance UID is required for retrieval of study metadata');
|
|
948
|
+
}
|
|
949
|
+
console.log("retrieve metadata of study ".concat(options.studyInstanceUID));
|
|
950
|
+
var url = "".concat(this.wadoURL, "/studies/").concat(options.studyInstanceUID, "/metadata");
|
|
951
|
+
var withCredentials = false;
|
|
952
|
+
if ('withCredentials' in options) {
|
|
953
|
+
if (options.withCredentials) {
|
|
954
|
+
withCredentials = options.withCredentials;
|
|
955
|
+
}
|
|
956
|
+
}
|
|
957
|
+
return this._httpGetApplicationJson(url, {}, false, withCredentials);
|
|
958
|
+
}
|
|
959
|
+
/**
|
|
960
|
+
* Searches for DICOM series.
|
|
961
|
+
*
|
|
962
|
+
* @param {Object} options
|
|
963
|
+
* @param {Object} [options.studyInstanceUID] - Study Instance UID
|
|
964
|
+
* @param {Object} [options.queryParams] - HTTP query parameters
|
|
965
|
+
* @returns {Object[]} Series representations (http://dicom.nema.org/medical/dicom/current/output/chtml/part18/sect_6.7.html#table_6.7.1-2a)
|
|
966
|
+
*/
|
|
967
|
+
}, {
|
|
968
|
+
key: "searchForSeries",
|
|
969
|
+
value: function searchForSeries() {
|
|
970
|
+
var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
971
|
+
var url = this.qidoURL;
|
|
972
|
+
if ('studyInstanceUID' in options) {
|
|
973
|
+
console.log("search series of study ".concat(options.studyInstanceUID));
|
|
974
|
+
url += "/studies/".concat(options.studyInstanceUID);
|
|
975
|
+
}
|
|
976
|
+
url += '/series';
|
|
977
|
+
if ('queryParams' in options) {
|
|
978
|
+
url += DICOMwebClient._parseQueryParameters(options.queryParams);
|
|
979
|
+
}
|
|
980
|
+
var withCredentials = false;
|
|
981
|
+
if ('withCredentials' in options) {
|
|
982
|
+
if (options.withCredentials) {
|
|
983
|
+
withCredentials = options.withCredentials;
|
|
984
|
+
}
|
|
985
|
+
}
|
|
986
|
+
return this._httpGetApplicationJson(url, {}, false, withCredentials);
|
|
987
|
+
}
|
|
988
|
+
/**
|
|
989
|
+
* Retrieves metadata for a DICOM series.
|
|
990
|
+
*
|
|
991
|
+
* @param {Object} options
|
|
992
|
+
* @param {String} options.studyInstanceUID - Study Instance UID
|
|
993
|
+
* @param {String} options.seriesInstanceUID - Series Instance UID
|
|
994
|
+
* @returns {Promise<InstanceMetadata[]>} Metadata elements in DICOM JSON format for each instance
|
|
995
|
+
belonging to the series
|
|
996
|
+
*/
|
|
997
|
+
}, {
|
|
998
|
+
key: "retrieveSeriesMetadata",
|
|
999
|
+
value: function retrieveSeriesMetadata(options) {
|
|
1000
|
+
if (!('studyInstanceUID' in options)) {
|
|
1001
|
+
throw new Error('Study Instance UID is required for retrieval of series metadata');
|
|
1002
|
+
}
|
|
1003
|
+
if (!('seriesInstanceUID' in options)) {
|
|
1004
|
+
throw new Error('Series Instance UID is required for retrieval of series metadata');
|
|
1005
|
+
}
|
|
1006
|
+
console.log("retrieve metadata of series ".concat(options.seriesInstanceUID));
|
|
1007
|
+
var url = "".concat(this.wadoURL, "/studies/").concat(options.studyInstanceUID, "/series/").concat(options.seriesInstanceUID, "/metadata");
|
|
1008
|
+
var withCredentials = false;
|
|
1009
|
+
if ('withCredentials' in options) {
|
|
1010
|
+
if (options.withCredentials) {
|
|
1011
|
+
withCredentials = options.withCredentials;
|
|
1012
|
+
}
|
|
1013
|
+
}
|
|
1014
|
+
return this._httpGetApplicationJson(url, {}, false, withCredentials);
|
|
1015
|
+
}
|
|
1016
|
+
/**
|
|
1017
|
+
* Searches for DICOM Instances.
|
|
1018
|
+
*
|
|
1019
|
+
* @param {Object} options
|
|
1020
|
+
* @param {String} [options.studyInstanceUID] - Study Instance UID
|
|
1021
|
+
* @param {String} [options.seriesInstanceUID] - Series Instance UID
|
|
1022
|
+
* @param {Object} [options.queryParams] - HTTP query parameters
|
|
1023
|
+
* @returns {Object[]} Instance representations (http://dicom.nema.org/medical/dicom/current/output/chtml/part18/sect_6.7.html#table_6.7.1-2b)
|
|
1024
|
+
*/
|
|
1025
|
+
}, {
|
|
1026
|
+
key: "searchForInstances",
|
|
1027
|
+
value: function searchForInstances() {
|
|
1028
|
+
var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
1029
|
+
var url = this.qidoURL;
|
|
1030
|
+
var withCredentials = false;
|
|
1031
|
+
if ('studyInstanceUID' in options) {
|
|
1032
|
+
url += "/studies/".concat(options.studyInstanceUID);
|
|
1033
|
+
if ('seriesInstanceUID' in options) {
|
|
1034
|
+
console.log("search for instances of series ".concat(options.seriesInstanceUID));
|
|
1035
|
+
url += "/series/".concat(options.seriesInstanceUID);
|
|
1036
|
+
} else {
|
|
1037
|
+
console.log("search for instances of study ".concat(options.studyInstanceUID));
|
|
1038
|
+
}
|
|
1039
|
+
} else {
|
|
1040
|
+
console.log('search for instances');
|
|
1041
|
+
}
|
|
1042
|
+
url += '/instances';
|
|
1043
|
+
if ('queryParams' in options) {
|
|
1044
|
+
url += DICOMwebClient._parseQueryParameters(options.queryParams);
|
|
1045
|
+
}
|
|
1046
|
+
if ('withCredentials' in options) {
|
|
1047
|
+
if (options.withCredentials) {
|
|
1048
|
+
withCredentials = options.withCredentials;
|
|
1049
|
+
}
|
|
1050
|
+
}
|
|
1051
|
+
return this._httpGetApplicationJson(url, {}, false, withCredentials);
|
|
1052
|
+
}
|
|
1053
|
+
/** Returns a WADO-URI URL for an instance
|
|
1054
|
+
*
|
|
1055
|
+
* @param {Object} options
|
|
1056
|
+
* @param {String} options.studyInstanceUID - Study Instance UID
|
|
1057
|
+
* @param {String} options.seriesInstanceUID - Series Instance UID
|
|
1058
|
+
* @param {String} options.sopInstanceUID - SOP Instance UID
|
|
1059
|
+
* @returns {String} WADO-URI URL
|
|
1060
|
+
*/
|
|
1061
|
+
}, {
|
|
1062
|
+
key: "buildInstanceWadoURIUrl",
|
|
1063
|
+
value: function buildInstanceWadoURIUrl(options) {
|
|
1064
|
+
if (!('studyInstanceUID' in options)) {
|
|
1065
|
+
throw new Error('Study Instance UID is required.');
|
|
1066
|
+
}
|
|
1067
|
+
if (!('seriesInstanceUID' in options)) {
|
|
1068
|
+
throw new Error('Series Instance UID is required.');
|
|
1069
|
+
}
|
|
1070
|
+
if (!('sopInstanceUID' in options)) {
|
|
1071
|
+
throw new Error('SOP Instance UID is required.');
|
|
1072
|
+
}
|
|
1073
|
+
var contentType = options.contentType || MEDIATYPES.DICOM;
|
|
1074
|
+
var transferSyntax = options.transferSyntax || '*';
|
|
1075
|
+
var params = [];
|
|
1076
|
+
params.push('requestType=WADO');
|
|
1077
|
+
params.push("studyUID=".concat(options.studyInstanceUID));
|
|
1078
|
+
params.push("seriesUID=".concat(options.seriesInstanceUID));
|
|
1079
|
+
params.push("objectUID=".concat(options.sopInstanceUID));
|
|
1080
|
+
params.push("contentType=".concat(contentType));
|
|
1081
|
+
params.push("transferSyntax=".concat(transferSyntax));
|
|
1082
|
+
var paramString = params.join('&');
|
|
1083
|
+
return "".concat(this.wadoURL, "?").concat(paramString);
|
|
1084
|
+
}
|
|
1085
|
+
/**
|
|
1086
|
+
* Retrieves metadata for a DICOM Instance.
|
|
1087
|
+
*
|
|
1088
|
+
* @param {Object} options object
|
|
1089
|
+
* @param {String} options.studyInstanceUID - Study Instance UID
|
|
1090
|
+
* @param {String} options.seriesInstanceUID - Series Instance UID
|
|
1091
|
+
* @param {String} options.sopInstanceUID - SOP Instance UID
|
|
1092
|
+
* @returns {Promise<InstanceMetadata>} metadata elements in DICOM JSON format
|
|
1093
|
+
*/
|
|
1094
|
+
}, {
|
|
1095
|
+
key: "retrieveInstanceMetadata",
|
|
1096
|
+
value: function retrieveInstanceMetadata(options) {
|
|
1097
|
+
if (!('studyInstanceUID' in options)) {
|
|
1098
|
+
throw new Error('Study Instance UID is required for retrieval of instance metadata');
|
|
1099
|
+
}
|
|
1100
|
+
if (!('seriesInstanceUID' in options)) {
|
|
1101
|
+
throw new Error('Series Instance UID is required for retrieval of instance metadata');
|
|
1102
|
+
}
|
|
1103
|
+
if (!('sopInstanceUID' in options)) {
|
|
1104
|
+
throw new Error('SOP Instance UID is required for retrieval of instance metadata');
|
|
1105
|
+
}
|
|
1106
|
+
console.log("retrieve metadata of instance ".concat(options.sopInstanceUID));
|
|
1107
|
+
var url = "".concat(this.wadoURL, "/studies/").concat(options.studyInstanceUID, "/series/").concat(options.seriesInstanceUID, "/instances/").concat(options.sopInstanceUID, "/metadata");
|
|
1108
|
+
var withCredentials = false;
|
|
1109
|
+
if ('withCredentials' in options) {
|
|
1110
|
+
if (options.withCredentials) {
|
|
1111
|
+
withCredentials = options.withCredentials;
|
|
1112
|
+
}
|
|
1113
|
+
}
|
|
1114
|
+
return this._httpGetApplicationJson(url, {}, false, withCredentials);
|
|
1115
|
+
}
|
|
1116
|
+
/**
|
|
1117
|
+
* Retrieves frames for a DICOM Instance.
|
|
1118
|
+
* @param {Object} options options object
|
|
1119
|
+
* @param {String} options.studyInstanceUID - Study Instance UID
|
|
1120
|
+
* @param {String} options.seriesInstanceUID - Series Instance UID
|
|
1121
|
+
* @param {String} options.sopInstanceUID - SOP Instance UID
|
|
1122
|
+
* @param {String} options.frameNumbers - One-based indices of Frame Items
|
|
1123
|
+
* @returns {Array} frame items as byte arrays of the pixel data element
|
|
1124
|
+
*/
|
|
1125
|
+
}, {
|
|
1126
|
+
key: "retrieveInstanceFrames",
|
|
1127
|
+
value: function retrieveInstanceFrames(options) {
|
|
1128
|
+
if (!('studyInstanceUID' in options)) {
|
|
1129
|
+
throw new Error('Study Instance UID is required for retrieval of instance frames');
|
|
1130
|
+
}
|
|
1131
|
+
if (!('seriesInstanceUID' in options)) {
|
|
1132
|
+
throw new Error('Series Instance UID is required for retrieval of instance frames');
|
|
1133
|
+
}
|
|
1134
|
+
if (!('sopInstanceUID' in options)) {
|
|
1135
|
+
throw new Error('SOP Instance UID is required for retrieval of instance frames');
|
|
1136
|
+
}
|
|
1137
|
+
if (!('frameNumbers' in options)) {
|
|
1138
|
+
throw new Error('frame numbers are required for retrieval of instance frames');
|
|
1139
|
+
}
|
|
1140
|
+
console.log("retrieve frames ".concat(options.frameNumbers.toString(), " of instance ").concat(options.sopInstanceUID));
|
|
1141
|
+
var url = "".concat(this.wadoURL, "/studies/").concat(options.studyInstanceUID, "/series/").concat(options.seriesInstanceUID, "/instances/").concat(options.sopInstanceUID, "/frames/").concat(options.frameNumbers.toString());
|
|
1142
|
+
var mediaTypes = options.mediaTypes;
|
|
1143
|
+
var withCredentials = false;
|
|
1144
|
+
if ('withCredentials' in options) {
|
|
1145
|
+
if (options.withCredentials) {
|
|
1146
|
+
withCredentials = options.withCredentials;
|
|
1147
|
+
}
|
|
1148
|
+
}
|
|
1149
|
+
var progressCallback = false;
|
|
1150
|
+
if ('progressCallback' in options) {
|
|
1151
|
+
progressCallback = options.progressCallback;
|
|
1152
|
+
}
|
|
1153
|
+
if (!mediaTypes) {
|
|
1154
|
+
return this._httpGetMultipartApplicationOctetStream(url, false, false, false, progressCallback, withCredentials);
|
|
1155
|
+
}
|
|
1156
|
+
var sharedMediaTypes = DICOMwebClient._getSharedMediaTypes(mediaTypes);
|
|
1157
|
+
if (sharedMediaTypes.length > 1) {
|
|
1158
|
+
/**
|
|
1159
|
+
* Enable request of frames that are stored either compressed
|
|
1160
|
+
* (image/* media type) or uncompressed (application/octet-stream
|
|
1161
|
+
* media type).
|
|
1162
|
+
*/
|
|
1163
|
+
var supportedMediaTypes = {
|
|
1164
|
+
'1.2.840.10008.1.2.1': ['application/octet-stream'],
|
|
1165
|
+
'1.2.840.10008.1.2.5': ['image/x-dicom-rle'],
|
|
1166
|
+
'1.2.840.10008.1.2.4.50': ['image/jpeg'],
|
|
1167
|
+
'1.2.840.10008.1.2.4.51': ['image/jpeg'],
|
|
1168
|
+
'1.2.840.10008.1.2.4.57': ['image/jpeg'],
|
|
1169
|
+
'1.2.840.10008.1.2.4.70': ['image/jpeg'],
|
|
1170
|
+
'1.2.840.10008.1.2.4.80': ['image/x-jls', 'image/jls'],
|
|
1171
|
+
'1.2.840.10008.1.2.4.81': ['image/x-jls', 'image/jls'],
|
|
1172
|
+
'1.2.840.10008.1.2.4.90': ['image/jp2'],
|
|
1173
|
+
'1.2.840.10008.1.2.4.91': ['image/jp2'],
|
|
1174
|
+
'1.2.840.10008.1.2.4.92': ['image/jpx'],
|
|
1175
|
+
'1.2.840.10008.1.2.4.93': ['image/jpx']
|
|
1176
|
+
};
|
|
1177
|
+
var headers = {
|
|
1178
|
+
Accept: DICOMwebClient._buildMultipartAcceptHeaderFieldValue(mediaTypes, supportedMediaTypes)
|
|
1179
|
+
};
|
|
1180
|
+
return this._httpGet(url, headers, 'arraybuffer', progressCallback, withCredentials).then(multipartDecode);
|
|
1181
|
+
}
|
|
1182
|
+
var commonMediaType = DICOMwebClient._getCommonMediaType(mediaTypes);
|
|
1183
|
+
if (commonMediaType.startsWith('application')) {
|
|
1184
|
+
return this._httpGetMultipartApplicationOctetStream(url, mediaTypes, false, false, progressCallback, withCredentials);
|
|
1185
|
+
}
|
|
1186
|
+
if (commonMediaType.startsWith('image')) {
|
|
1187
|
+
return this._httpGetMultipartImage(url, mediaTypes, false, false, false, progressCallback, withCredentials);
|
|
1188
|
+
}
|
|
1189
|
+
if (commonMediaType.startsWith('video')) {
|
|
1190
|
+
return this._httpGetMultipartVideo(url, mediaTypes, false, false, false, progressCallback, withCredentials);
|
|
1191
|
+
}
|
|
1192
|
+
throw new Error("Media type ".concat(commonMediaType, " is not supported for retrieval of frames."));
|
|
1193
|
+
}
|
|
1194
|
+
/**
|
|
1195
|
+
* Retrieves an individual, server-side rendered DICOM Instance.
|
|
1196
|
+
*
|
|
1197
|
+
* @param {Object} options
|
|
1198
|
+
* @param {String} options.studyInstanceUID - Study Instance UID
|
|
1199
|
+
* @param {String} options.seriesInstanceUID - Series Instance UID
|
|
1200
|
+
* @param {String} options.sopInstanceUID - SOP Instance UID
|
|
1201
|
+
* @param {String[]} [options.mediaType] - Acceptable HTTP media types
|
|
1202
|
+
* @param {Object} [options.queryParams] - HTTP query parameters
|
|
1203
|
+
* @returns {Promise<ArrayBuffer>} Rendered DICOM Instance
|
|
1204
|
+
*/
|
|
1205
|
+
}, {
|
|
1206
|
+
key: "retrieveInstanceRendered",
|
|
1207
|
+
value: function retrieveInstanceRendered(options) {
|
|
1208
|
+
if (!('studyInstanceUID' in options)) {
|
|
1209
|
+
throw new Error('Study Instance UID is required for retrieval of rendered instance');
|
|
1210
|
+
}
|
|
1211
|
+
if (!('seriesInstanceUID' in options)) {
|
|
1212
|
+
throw new Error('Series Instance UID is required for retrieval of rendered instance');
|
|
1213
|
+
}
|
|
1214
|
+
if (!('sopInstanceUID' in options)) {
|
|
1215
|
+
throw new Error('SOP Instance UID is required for retrieval of rendered instance');
|
|
1216
|
+
}
|
|
1217
|
+
var url = "".concat(this.wadoURL, "/studies/").concat(options.studyInstanceUID, "/series/").concat(options.seriesInstanceUID, "/instances/").concat(options.sopInstanceUID, "/rendered");
|
|
1218
|
+
var mediaTypes = options.mediaTypes,
|
|
1219
|
+
queryParams = options.queryParams;
|
|
1220
|
+
var headers = {};
|
|
1221
|
+
var withCredentials = false;
|
|
1222
|
+
if ('withCredentials' in options) {
|
|
1223
|
+
if (options.withCredentials) {
|
|
1224
|
+
withCredentials = options.withCredentials;
|
|
1225
|
+
}
|
|
1226
|
+
}
|
|
1227
|
+
var progressCallback = false;
|
|
1228
|
+
if ('progressCallback' in options) {
|
|
1229
|
+
progressCallback = options.progressCallback;
|
|
1230
|
+
}
|
|
1231
|
+
if (!mediaTypes) {
|
|
1232
|
+
var responseType = 'arraybuffer';
|
|
1233
|
+
if (queryParams) {
|
|
1234
|
+
url += DICOMwebClient._parseQueryParameters(queryParams);
|
|
1235
|
+
}
|
|
1236
|
+
return this._httpGet(url, headers, responseType, progressCallback, withCredentials);
|
|
1237
|
+
}
|
|
1238
|
+
var commonMediaType = DICOMwebClient._getCommonMediaType(mediaTypes);
|
|
1239
|
+
if (commonMediaType.startsWith('image')) {
|
|
1240
|
+
return this._httpGetImage(url, mediaTypes, queryParams, progressCallback, withCredentials);
|
|
1241
|
+
}
|
|
1242
|
+
if (commonMediaType.startsWith('video')) {
|
|
1243
|
+
return this._httpGetVideo(url, mediaTypes, queryParams, progressCallback, withCredentials);
|
|
1244
|
+
}
|
|
1245
|
+
if (commonMediaType.startsWith('text')) {
|
|
1246
|
+
return this._httpGetText(url, mediaTypes, queryParams, progressCallback, withCredentials);
|
|
1247
|
+
}
|
|
1248
|
+
if (commonMediaType === MEDIATYPES.PDF) {
|
|
1249
|
+
return this._httpGetApplicationPdf(url, queryParams, progressCallback, withCredentials);
|
|
1250
|
+
}
|
|
1251
|
+
throw new Error("Media type ".concat(commonMediaType, " is not supported ") + 'for retrieval of rendered instance.');
|
|
1252
|
+
}
|
|
1253
|
+
/**
|
|
1254
|
+
* Retrieves a thumbnail of an DICOM Instance.
|
|
1255
|
+
*
|
|
1256
|
+
* @param {Object} options
|
|
1257
|
+
* @param {String} options.studyInstanceUID - Study Instance UID
|
|
1258
|
+
* @param {String} options.seriesInstanceUID - Series Instance UID
|
|
1259
|
+
* @param {String} options.sopInstanceUID - SOP Instance UID
|
|
1260
|
+
* @param {String[]} [options.mediaType] - Acceptable HTTP media types
|
|
1261
|
+
* @param {Object} [options.queryParams] - HTTP query parameters
|
|
1262
|
+
* @returns {ArrayBuffer} Thumbnail
|
|
1263
|
+
*/
|
|
1264
|
+
}, {
|
|
1265
|
+
key: "retrieveInstanceThumbnail",
|
|
1266
|
+
value: function retrieveInstanceThumbnail(options) {
|
|
1267
|
+
if (!('studyInstanceUID' in options)) {
|
|
1268
|
+
throw new Error('Study Instance UID is required for retrieval of rendered instance');
|
|
1269
|
+
}
|
|
1270
|
+
if (!('seriesInstanceUID' in options)) {
|
|
1271
|
+
throw new Error('Series Instance UID is required for retrieval of rendered instance');
|
|
1272
|
+
}
|
|
1273
|
+
if (!('sopInstanceUID' in options)) {
|
|
1274
|
+
throw new Error('SOP Instance UID is required for retrieval of rendered instance');
|
|
1275
|
+
}
|
|
1276
|
+
var url = "".concat(this.wadoURL, "/studies/").concat(options.studyInstanceUID, "/series/").concat(options.seriesInstanceUID, "/instances/").concat(options.sopInstanceUID, "/thumbnail");
|
|
1277
|
+
var mediaTypes = options.mediaTypes,
|
|
1278
|
+
queryParams = options.queryParams;
|
|
1279
|
+
var headers = {};
|
|
1280
|
+
var withCredentials = false;
|
|
1281
|
+
if ('withCredentials' in options) {
|
|
1282
|
+
if (options.withCredentials) {
|
|
1283
|
+
withCredentials = options.withCredentials;
|
|
1284
|
+
}
|
|
1285
|
+
}
|
|
1286
|
+
var progressCallback = false;
|
|
1287
|
+
if ('progressCallback' in options) {
|
|
1288
|
+
progressCallback = options.progressCallback;
|
|
1289
|
+
}
|
|
1290
|
+
if (!mediaTypes) {
|
|
1291
|
+
var responseType = 'arraybuffer';
|
|
1292
|
+
if (queryParams) {
|
|
1293
|
+
url += DICOMwebClient._parseQueryParameters(queryParams);
|
|
1294
|
+
}
|
|
1295
|
+
return this._httpGet(url, headers, responseType, progressCallback, withCredentials);
|
|
1296
|
+
}
|
|
1297
|
+
var commonMediaType = DICOMwebClient._getCommonMediaType(mediaTypes);
|
|
1298
|
+
if (commonMediaType.startsWith('image')) {
|
|
1299
|
+
return this._httpGetImage(url, mediaTypes, queryParams, progressCallback, withCredentials);
|
|
1300
|
+
}
|
|
1301
|
+
throw new Error("Media type ".concat(commonMediaType, " is not supported ") + 'for retrieval of rendered instance.');
|
|
1302
|
+
}
|
|
1303
|
+
/**
|
|
1304
|
+
* Retrieves rendered frames for a DICOM Instance.
|
|
1305
|
+
*
|
|
1306
|
+
* @param {Object} options
|
|
1307
|
+
* @param {String} options.studyInstanceUID - Study Instance UID
|
|
1308
|
+
* @param {String} options.seriesInstanceUID - Series Instance UID
|
|
1309
|
+
* @param {String} options.sopInstanceUID - SOP Instance UID
|
|
1310
|
+
* @param {String} options.frameNumbers - One-based indices of Frame Items
|
|
1311
|
+
* @param {String[]} [options.mediaType] - Acceptable HTTP media types
|
|
1312
|
+
* @param {Object} [options.queryParams] - HTTP query parameters
|
|
1313
|
+
* @returns {ArrayBuffer[]} Rendered Frame Items as byte arrays
|
|
1314
|
+
*/
|
|
1315
|
+
}, {
|
|
1316
|
+
key: "retrieveInstanceFramesRendered",
|
|
1317
|
+
value: function retrieveInstanceFramesRendered(options) {
|
|
1318
|
+
if (!('studyInstanceUID' in options)) {
|
|
1319
|
+
throw new Error('Study Instance UID is required for retrieval of rendered instance frames');
|
|
1320
|
+
}
|
|
1321
|
+
if (!('seriesInstanceUID' in options)) {
|
|
1322
|
+
throw new Error('Series Instance UID is required for retrieval of rendered instance frames');
|
|
1323
|
+
}
|
|
1324
|
+
if (!('sopInstanceUID' in options)) {
|
|
1325
|
+
throw new Error('SOP Instance UID is required for retrieval of rendered instance frames');
|
|
1326
|
+
}
|
|
1327
|
+
if (!('frameNumbers' in options)) {
|
|
1328
|
+
throw new Error('frame numbers are required for retrieval of rendered instance frames');
|
|
1329
|
+
}
|
|
1330
|
+
console.debug("retrieve rendered frames ".concat(options.frameNumbers.toString(), " of instance ").concat(options.sopInstanceUID));
|
|
1331
|
+
var url = "".concat(this.wadoURL, "/studies/").concat(options.studyInstanceUID, "/series/").concat(options.seriesInstanceUID, "/instances/").concat(options.sopInstanceUID, "/frames/").concat(options.frameNumbers.toString(), "/rendered");
|
|
1332
|
+
var mediaTypes = options.mediaTypes,
|
|
1333
|
+
queryParams = options.queryParams;
|
|
1334
|
+
var headers = {};
|
|
1335
|
+
var withCredentials = false;
|
|
1336
|
+
if ('withCredentials' in options) {
|
|
1337
|
+
if (options.withCredentials) {
|
|
1338
|
+
withCredentials = options.withCredentials;
|
|
1339
|
+
}
|
|
1340
|
+
}
|
|
1341
|
+
var progressCallback = false;
|
|
1342
|
+
if ('progressCallback' in options) {
|
|
1343
|
+
progressCallback = options.progressCallback;
|
|
1344
|
+
}
|
|
1345
|
+
if (!mediaTypes) {
|
|
1346
|
+
var responseType = 'arraybuffer';
|
|
1347
|
+
if (queryParams) {
|
|
1348
|
+
url += DICOMwebClient._parseQueryParameters(queryParams);
|
|
1349
|
+
}
|
|
1350
|
+
return this._httpGet(url, headers, responseType, false, withCredentials);
|
|
1351
|
+
}
|
|
1352
|
+
var commonMediaType = DICOMwebClient._getCommonMediaType(mediaTypes);
|
|
1353
|
+
if (commonMediaType.startsWith('image')) {
|
|
1354
|
+
return this._httpGetImage(url, mediaTypes, queryParams, progressCallback, withCredentials);
|
|
1355
|
+
}
|
|
1356
|
+
if (commonMediaType.startsWith('video')) {
|
|
1357
|
+
return this._httpGetVideo(url, mediaTypes, queryParams, progressCallback, withCredentials);
|
|
1358
|
+
}
|
|
1359
|
+
throw new Error("Media type ".concat(commonMediaType, " is not supported ") + 'for retrieval of rendered frame.');
|
|
1360
|
+
}
|
|
1361
|
+
/**
|
|
1362
|
+
* Retrieves thumbnail of frames for a DICOM Instance.
|
|
1363
|
+
*
|
|
1364
|
+
* @param {Object} options
|
|
1365
|
+
* @param {String} options.studyInstanceUID - Study Instance UID
|
|
1366
|
+
* @param {String} options.seriesInstanceUID - Series Instance UID
|
|
1367
|
+
* @param {String} options.sopInstanceUID - SOP Instance UID
|
|
1368
|
+
* @param {String} options.frameNumbers - One-based indices of Frame Items
|
|
1369
|
+
* @param {Object} [options.queryParams] - HTTP query parameters
|
|
1370
|
+
* @returns {ArrayBuffer[]} Rendered Frame Items as byte arrays
|
|
1371
|
+
*/
|
|
1372
|
+
}, {
|
|
1373
|
+
key: "retrieveInstanceFramesThumbnail",
|
|
1374
|
+
value: function retrieveInstanceFramesThumbnail(options) {
|
|
1375
|
+
if (!('studyInstanceUID' in options)) {
|
|
1376
|
+
throw new Error('Study Instance UID is required for retrieval of rendered instance frames');
|
|
1377
|
+
}
|
|
1378
|
+
if (!('seriesInstanceUID' in options)) {
|
|
1379
|
+
throw new Error('Series Instance UID is required for retrieval of rendered instance frames');
|
|
1380
|
+
}
|
|
1381
|
+
if (!('sopInstanceUID' in options)) {
|
|
1382
|
+
throw new Error('SOP Instance UID is required for retrieval of rendered instance frames');
|
|
1383
|
+
}
|
|
1384
|
+
if (!('frameNumbers' in options)) {
|
|
1385
|
+
throw new Error('frame numbers are required for retrieval of rendered instance frames');
|
|
1386
|
+
}
|
|
1387
|
+
console.debug("retrieve rendered frames ".concat(options.frameNumbers.toString(), " of instance ").concat(options.sopInstanceUID));
|
|
1388
|
+
var url = "".concat(this.wadoURL, "/studies/").concat(options.studyInstanceUID, "/series/").concat(options.seriesInstanceUID, "/instances/").concat(options.sopInstanceUID, "/frames/").concat(options.frameNumbers.toString(), "/thumbnail");
|
|
1389
|
+
var mediaTypes = options.mediaTypes,
|
|
1390
|
+
queryParams = options.queryParams;
|
|
1391
|
+
var headers = {};
|
|
1392
|
+
var withCredentials = false;
|
|
1393
|
+
if ('withCredentials' in options) {
|
|
1394
|
+
if (options.withCredentials) {
|
|
1395
|
+
withCredentials = options.withCredentials;
|
|
1396
|
+
}
|
|
1397
|
+
}
|
|
1398
|
+
var progressCallback = false;
|
|
1399
|
+
if ('progressCallback' in options) {
|
|
1400
|
+
progressCallback = options.progressCallback;
|
|
1401
|
+
}
|
|
1402
|
+
if (!mediaTypes) {
|
|
1403
|
+
var responseType = 'arraybuffer';
|
|
1404
|
+
if (queryParams) {
|
|
1405
|
+
url += DICOMwebClient._parseQueryParameters(queryParams);
|
|
1406
|
+
}
|
|
1407
|
+
return this._httpGet(url, headers, responseType, progressCallback, withCredentials);
|
|
1408
|
+
}
|
|
1409
|
+
var commonMediaType = DICOMwebClient._getCommonMediaType(mediaTypes);
|
|
1410
|
+
if (commonMediaType.startsWith('image')) {
|
|
1411
|
+
return this._httpGetImage(url, mediaTypes, queryParams, progressCallback, withCredentials);
|
|
1412
|
+
}
|
|
1413
|
+
throw new Error("Media type ".concat(commonMediaType, " is not supported ") + 'for retrieval of rendered frame.');
|
|
1414
|
+
}
|
|
1415
|
+
/**
|
|
1416
|
+
* Retrieves a DICOM Instance.
|
|
1417
|
+
*
|
|
1418
|
+
* @param {Object} options
|
|
1419
|
+
* @param {String} options.studyInstanceUID - Study Instance UID
|
|
1420
|
+
* @param {String} options.seriesInstanceUID - Series Instance UID
|
|
1421
|
+
* @param {String} options.sopInstanceUID - SOP Instance UID
|
|
1422
|
+
* @returns {Promise<ArrayBuffer>} DICOM Part 10 file as Arraybuffer
|
|
1423
|
+
*/
|
|
1424
|
+
}, {
|
|
1425
|
+
key: "retrieveInstance",
|
|
1426
|
+
value: function retrieveInstance(options) {
|
|
1427
|
+
if (!('studyInstanceUID' in options)) {
|
|
1428
|
+
throw new Error('Study Instance UID is required');
|
|
1429
|
+
}
|
|
1430
|
+
if (!('seriesInstanceUID' in options)) {
|
|
1431
|
+
throw new Error('Series Instance UID is required');
|
|
1432
|
+
}
|
|
1433
|
+
if (!('sopInstanceUID' in options)) {
|
|
1434
|
+
throw new Error('SOP Instance UID is required');
|
|
1435
|
+
}
|
|
1436
|
+
var url = "".concat(this.wadoURL, "/studies/").concat(options.studyInstanceUID, "/series/").concat(options.seriesInstanceUID, "/instances/").concat(options.sopInstanceUID);
|
|
1437
|
+
var mediaTypes = options.mediaTypes;
|
|
1438
|
+
var _options$withCredenti = options.withCredentials,
|
|
1439
|
+
withCredentials = _options$withCredenti === void 0 ? false : _options$withCredenti;
|
|
1440
|
+
var _options$progressCall = options.progressCallback,
|
|
1441
|
+
progressCallback = _options$progressCall === void 0 ? false : _options$progressCall;
|
|
1442
|
+
if (!mediaTypes) {
|
|
1443
|
+
return this._httpGetMultipartApplicationDicom(url, false, false, progressCallback, withCredentials).then(getFirstResult);
|
|
1444
|
+
}
|
|
1445
|
+
var commonMediaType = DICOMwebClient._getCommonMediaType(mediaTypes);
|
|
1446
|
+
if (commonMediaType === MEDIATYPES.DICOM) {
|
|
1447
|
+
return this._httpGetMultipartApplicationDicom(url, mediaTypes, false, progressCallback, withCredentials).then(getFirstResult);
|
|
1448
|
+
}
|
|
1449
|
+
throw new Error("Media type ".concat(commonMediaType, " is not supported for retrieval of instance."));
|
|
1450
|
+
}
|
|
1451
|
+
/**
|
|
1452
|
+
* Retrieves all DICOM Instances of a Series.
|
|
1453
|
+
*
|
|
1454
|
+
* @param {Object} options
|
|
1455
|
+
* @param {String} options.studyInstanceUID - Study Instance UID
|
|
1456
|
+
* @param {String} options.seriesInstanceUID - Series Instance UID
|
|
1457
|
+
* @param {Function} options.progressCallback
|
|
1458
|
+
* @returns {Promise<ArrayBuffer[]>} DICOM Instances
|
|
1459
|
+
*/
|
|
1460
|
+
}, {
|
|
1461
|
+
key: "retrieveSeries",
|
|
1462
|
+
value: function retrieveSeries(options) {
|
|
1463
|
+
if (!('studyInstanceUID' in options)) {
|
|
1464
|
+
throw new Error('Study Instance UID is required');
|
|
1465
|
+
}
|
|
1466
|
+
if (!('seriesInstanceUID' in options)) {
|
|
1467
|
+
throw new Error('Series Instance UID is required');
|
|
1468
|
+
}
|
|
1469
|
+
var url = "".concat(this.wadoURL, "/studies/").concat(options.studyInstanceUID, "/series/").concat(options.seriesInstanceUID);
|
|
1470
|
+
var mediaTypes = options.mediaTypes;
|
|
1471
|
+
var withCredentials = false;
|
|
1472
|
+
if ('withCredentials' in options) {
|
|
1473
|
+
if (options.withCredentials) {
|
|
1474
|
+
withCredentials = options.withCredentials;
|
|
1475
|
+
}
|
|
1476
|
+
}
|
|
1477
|
+
var progressCallback = false;
|
|
1478
|
+
if ('progressCallback' in options) {
|
|
1479
|
+
progressCallback = options.progressCallback;
|
|
1480
|
+
}
|
|
1481
|
+
if (!mediaTypes) {
|
|
1482
|
+
return this._httpGetMultipartApplicationDicom(url, false, false, progressCallback, withCredentials);
|
|
1483
|
+
}
|
|
1484
|
+
var commonMediaType = DICOMwebClient._getCommonMediaType(mediaTypes);
|
|
1485
|
+
if (commonMediaType === MEDIATYPES.DICOM) {
|
|
1486
|
+
return this._httpGetMultipartApplicationDicom(url, mediaTypes, false, progressCallback, withCredentials);
|
|
1487
|
+
}
|
|
1488
|
+
throw new Error("Media type ".concat(commonMediaType, " is not supported for retrieval of series."));
|
|
1489
|
+
}
|
|
1490
|
+
/**
|
|
1491
|
+
* Retrieves all DICOM Instances of a Study.
|
|
1492
|
+
*
|
|
1493
|
+
* @param {Object} options
|
|
1494
|
+
* @param {String} options.studyInstanceUID - Study Instance UID
|
|
1495
|
+
* @returns {ArrayBuffer[]} DICOM Instances
|
|
1496
|
+
*/
|
|
1497
|
+
}, {
|
|
1498
|
+
key: "retrieveStudy",
|
|
1499
|
+
value: function retrieveStudy(options) {
|
|
1500
|
+
if (!('studyInstanceUID' in options)) {
|
|
1501
|
+
throw new Error('Study Instance UID is required');
|
|
1502
|
+
}
|
|
1503
|
+
var url = "".concat(this.wadoURL, "/studies/").concat(options.studyInstanceUID);
|
|
1504
|
+
var mediaTypes = options.mediaTypes;
|
|
1505
|
+
var _options$withCredenti2 = options.withCredentials,
|
|
1506
|
+
withCredentials = _options$withCredenti2 === void 0 ? false : _options$withCredenti2;
|
|
1507
|
+
var _options$progressCall2 = options.progressCallback,
|
|
1508
|
+
progressCallback = _options$progressCall2 === void 0 ? false : _options$progressCall2;
|
|
1509
|
+
if (!mediaTypes) {
|
|
1510
|
+
return this._httpGetMultipartApplicationDicom(url, false, false, progressCallback, withCredentials);
|
|
1511
|
+
}
|
|
1512
|
+
var commonMediaType = DICOMwebClient._getCommonMediaType(mediaTypes);
|
|
1513
|
+
if (commonMediaType === MEDIATYPES.DICOM) {
|
|
1514
|
+
return this._httpGetMultipartApplicationDicom(url, mediaTypes, false, progressCallback, withCredentials);
|
|
1515
|
+
}
|
|
1516
|
+
throw new Error("Media type ".concat(commonMediaType, " is not supported for retrieval of study."));
|
|
1517
|
+
}
|
|
1518
|
+
/**
|
|
1519
|
+
* Retrieves and parses BulkData from a BulkDataURI location.
|
|
1520
|
+
* Decodes the multipart encoded data and returns the resulting data
|
|
1521
|
+
* as an ArrayBuffer.
|
|
1522
|
+
*
|
|
1523
|
+
* See http://dicom.nema.org/medical/dicom/current/output/chtml/part18/sect_6.5.5.html
|
|
1524
|
+
*
|
|
1525
|
+
* @param {Object} options
|
|
1526
|
+
* @param {String} BulkDataURI - URI for retrieval of bulkdata
|
|
1527
|
+
* @returns {Promise<Array>} Bulkdata parts
|
|
1528
|
+
*/
|
|
1529
|
+
}, {
|
|
1530
|
+
key: "retrieveBulkData",
|
|
1531
|
+
value: function retrieveBulkData(options) {
|
|
1532
|
+
if (!('BulkDataURI' in options)) {
|
|
1533
|
+
throw new Error('BulkDataURI is required.');
|
|
1534
|
+
}
|
|
1535
|
+
var url = options.BulkDataURI;
|
|
1536
|
+
var mediaTypes = options.mediaTypes,
|
|
1537
|
+
byteRange = options.byteRange;
|
|
1538
|
+
var _options$withCredenti3 = options.withCredentials,
|
|
1539
|
+
withCredentials = _options$withCredenti3 === void 0 ? false : _options$withCredenti3;
|
|
1540
|
+
var _options$progressCall3 = options.progressCallback,
|
|
1541
|
+
progressCallback = _options$progressCall3 === void 0 ? false : _options$progressCall3;
|
|
1542
|
+
if (!mediaTypes) {
|
|
1543
|
+
return this._httpGetMultipartApplicationOctetStream(url, mediaTypes, byteRange, false, false, withCredentials);
|
|
1544
|
+
}
|
|
1545
|
+
var commonMediaType = DICOMwebClient._getCommonMediaType(mediaTypes);
|
|
1546
|
+
if (commonMediaType === MEDIATYPES.OCTET_STREAM) {
|
|
1547
|
+
return this._httpGetMultipartApplicationOctetStream(url, mediaTypes, byteRange, false, progressCallback, withCredentials);
|
|
1548
|
+
}
|
|
1549
|
+
if (commonMediaType.startsWith('image')) {
|
|
1550
|
+
return this._httpGetMultipartImage(url, mediaTypes, byteRange, false, false, progressCallback, withCredentials);
|
|
1551
|
+
}
|
|
1552
|
+
throw new Error("Media type ".concat(commonMediaType, " is not supported for retrieval of bulk data."));
|
|
1553
|
+
}
|
|
1554
|
+
/**
|
|
1555
|
+
* Stores DICOM Instances.
|
|
1556
|
+
*
|
|
1557
|
+
* @param {Object} options
|
|
1558
|
+
* @param {ArrayBuffer[]} options.datasets - DICOM Instances in PS3.10 format
|
|
1559
|
+
* @param {String} [options.studyInstanceUID] - Study Instance UID
|
|
1560
|
+
* @param {XMLHttpRequest} [options.request] - if specified, the request to use, otherwise one will be created; useful for adding custom upload and abort listeners/objects
|
|
1561
|
+
* @returns {Promise} Response message
|
|
1562
|
+
*/
|
|
1563
|
+
}, {
|
|
1564
|
+
key: "storeInstances",
|
|
1565
|
+
value: function storeInstances(options) {
|
|
1566
|
+
if (!('datasets' in options)) {
|
|
1567
|
+
throw new Error('datasets are required for storing');
|
|
1568
|
+
}
|
|
1569
|
+
var url = "".concat(this.stowURL, "/studies");
|
|
1570
|
+
if ('studyInstanceUID' in options) {
|
|
1571
|
+
url += "/".concat(options.studyInstanceUID);
|
|
1572
|
+
}
|
|
1573
|
+
var _multipartEncode = multipartEncode(options.datasets),
|
|
1574
|
+
data = _multipartEncode.data,
|
|
1575
|
+
boundary = _multipartEncode.boundary;
|
|
1576
|
+
var headers = {
|
|
1577
|
+
'Content-Type': "multipart/related; type=\"application/dicom\"; boundary=\"".concat(boundary, "\"")
|
|
1578
|
+
};
|
|
1579
|
+
var _options$withCredenti4 = options.withCredentials,
|
|
1580
|
+
withCredentials = _options$withCredenti4 === void 0 ? false : _options$withCredenti4;
|
|
1581
|
+
return this._httpPost(url, headers, data, options.progressCallback, withCredentials, options.request);
|
|
1582
|
+
}
|
|
1583
|
+
}], [{
|
|
1584
|
+
key: "_parseQueryParameters",
|
|
1585
|
+
value: function _parseQueryParameters() {
|
|
1586
|
+
var params = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
1587
|
+
var queryString = '?';
|
|
1588
|
+
Object.keys(params).forEach(function (key, index) {
|
|
1589
|
+
if (index !== 0) {
|
|
1590
|
+
queryString += '&';
|
|
1591
|
+
}
|
|
1592
|
+
queryString += "".concat(key, "=").concat(encodeURIComponent(params[key]));
|
|
1593
|
+
});
|
|
1594
|
+
return queryString;
|
|
1595
|
+
}
|
|
1596
|
+
}, {
|
|
1597
|
+
key: "_assertMediaTypeIsValid",
|
|
1598
|
+
value: function _assertMediaTypeIsValid(mediaType) {
|
|
1599
|
+
if (!mediaType) {
|
|
1600
|
+
throw new Error("Not a valid media type: ".concat(mediaType));
|
|
1601
|
+
}
|
|
1602
|
+
var sepIndex = mediaType.indexOf('/');
|
|
1603
|
+
if (sepIndex === -1) {
|
|
1604
|
+
throw new Error("Not a valid media type: ".concat(mediaType));
|
|
1605
|
+
}
|
|
1606
|
+
var mediaTypeType = mediaType.slice(0, sepIndex);
|
|
1607
|
+
var types = ['application', 'image', 'text', 'video'];
|
|
1608
|
+
if (!types.includes(mediaTypeType)) {
|
|
1609
|
+
throw new Error("Not a valid media type: ".concat(mediaType));
|
|
1610
|
+
}
|
|
1611
|
+
if (mediaType.slice(sepIndex + 1).includes('/')) {
|
|
1612
|
+
throw new Error("Not a valid media type: ".concat(mediaType));
|
|
1613
|
+
}
|
|
1614
|
+
}
|
|
1615
|
+
}, {
|
|
1616
|
+
key: "_parseMediaType",
|
|
1617
|
+
value: function _parseMediaType(mediaType) {
|
|
1618
|
+
DICOMwebClient._assertMediaTypeIsValid(mediaType);
|
|
1619
|
+
return mediaType.split('/');
|
|
1620
|
+
}
|
|
1621
|
+
/**
|
|
1622
|
+
* Builds an accept header field value for HTTP GET request messages.
|
|
1623
|
+
*
|
|
1624
|
+
* @param {Object[]} mediaTypes - Acceptable media types
|
|
1625
|
+
* @param {Object[]} supportedMediaTypes - Supported media types
|
|
1626
|
+
* @return {*}
|
|
1627
|
+
* @private
|
|
1628
|
+
*/
|
|
1629
|
+
}, {
|
|
1630
|
+
key: "_buildAcceptHeaderFieldValue",
|
|
1631
|
+
value: function _buildAcceptHeaderFieldValue(mediaTypes, supportedMediaTypes) {
|
|
1632
|
+
if (!Array.isArray(mediaTypes)) {
|
|
1633
|
+
throw new Error('Acceptable media types must be provided as an Array');
|
|
1634
|
+
}
|
|
1635
|
+
var fieldValueParts = mediaTypes.map(function (item) {
|
|
1636
|
+
var mediaType = item.mediaType;
|
|
1637
|
+
DICOMwebClient._assertMediaTypeIsValid(mediaType);
|
|
1638
|
+
if (!supportedMediaTypes.includes(mediaType)) {
|
|
1639
|
+
throw new Error("Media type ".concat(mediaType, " is not supported for requested resource"));
|
|
1640
|
+
}
|
|
1641
|
+
return mediaType;
|
|
1642
|
+
});
|
|
1643
|
+
return fieldValueParts.join(', ');
|
|
1644
|
+
}
|
|
1645
|
+
/**
|
|
1646
|
+
* Builds an accept header field value for HTTP GET multipart request
|
|
1647
|
+
messages.
|
|
1648
|
+
*
|
|
1649
|
+
* @param {Object[]} mediaTypes - Acceptable media types
|
|
1650
|
+
* @param {Object[]} supportedMediaTypes - Supported media types
|
|
1651
|
+
* @private
|
|
1652
|
+
*/
|
|
1653
|
+
}, {
|
|
1654
|
+
key: "_buildMultipartAcceptHeaderFieldValue",
|
|
1655
|
+
value: function _buildMultipartAcceptHeaderFieldValue(mediaTypes, supportedMediaTypes) {
|
|
1656
|
+
if (!Array.isArray(mediaTypes)) {
|
|
1657
|
+
throw new Error('Acceptable media types must be provided as an Array');
|
|
1658
|
+
}
|
|
1659
|
+
if (!Array.isArray(supportedMediaTypes) && !isObject(supportedMediaTypes)) {
|
|
1660
|
+
throw new Error('Supported media types must be provided as an Array or an Object');
|
|
1661
|
+
}
|
|
1662
|
+
var fieldValueParts = [];
|
|
1663
|
+
mediaTypes.forEach(function (item) {
|
|
1664
|
+
var transferSyntaxUID = item.transferSyntaxUID,
|
|
1665
|
+
mediaType = item.mediaType;
|
|
1666
|
+
DICOMwebClient._assertMediaTypeIsValid(mediaType);
|
|
1667
|
+
var fieldValue = "multipart/related; type=\"".concat(mediaType, "\"");
|
|
1668
|
+
if (isObject(supportedMediaTypes)) {
|
|
1669
|
+
// SupportedMediaTypes is a lookup table that maps Transfer Syntax UID
|
|
1670
|
+
// to one or more Media Types
|
|
1671
|
+
if (!Object.values(supportedMediaTypes).flat(1).includes(mediaType)) {
|
|
1672
|
+
if (!mediaType.endsWith('/*') || !mediaType.endsWith('/')) {
|
|
1673
|
+
throw new Error("Media type ".concat(mediaType, " is not supported for requested resource"));
|
|
1674
|
+
}
|
|
1675
|
+
}
|
|
1676
|
+
if (transferSyntaxUID) {
|
|
1677
|
+
if (transferSyntaxUID !== '*') {
|
|
1678
|
+
if (!Object.keys(supportedMediaTypes).includes(transferSyntaxUID)) {
|
|
1679
|
+
throw new Error("Transfer syntax ".concat(transferSyntaxUID, " is not supported for requested resource"));
|
|
1680
|
+
}
|
|
1681
|
+
var expectedMediaTypes = supportedMediaTypes[transferSyntaxUID];
|
|
1682
|
+
if (!expectedMediaTypes.includes(mediaType)) {
|
|
1683
|
+
var actualType = DICOMwebClient._parseMediaType(mediaType)[0];
|
|
1684
|
+
expectedMediaTypes.map(function (expectedMediaType) {
|
|
1685
|
+
var expectedType = DICOMwebClient._parseMediaType(expectedMediaType)[0];
|
|
1686
|
+
var haveSameType = actualType === expectedType;
|
|
1687
|
+
if (haveSameType && (mediaType.endsWith('/*') || mediaType.endsWith('/'))) {
|
|
1688
|
+
return;
|
|
1689
|
+
}
|
|
1690
|
+
throw new Error("Transfer syntax ".concat(transferSyntaxUID, " is not supported for requested resource"));
|
|
1691
|
+
});
|
|
1692
|
+
}
|
|
1693
|
+
}
|
|
1694
|
+
fieldValue += "; transfer-syntax=".concat(transferSyntaxUID);
|
|
1695
|
+
}
|
|
1696
|
+
} else if (Array.isArray(supportedMediaTypes) && !supportedMediaTypes.includes(mediaType)) {
|
|
1697
|
+
throw new Error("Media type ".concat(mediaType, " is not supported for requested resource"));
|
|
1698
|
+
}
|
|
1699
|
+
fieldValueParts.push(fieldValue);
|
|
1700
|
+
});
|
|
1701
|
+
return fieldValueParts.join(', ');
|
|
1702
|
+
}
|
|
1703
|
+
/**
|
|
1704
|
+
* Builds a range header field value for HTTP GET request messages.
|
|
1705
|
+
*
|
|
1706
|
+
* @param {Array} byteRange - Start and end of byte range
|
|
1707
|
+
* @returns {String} Range header field value
|
|
1708
|
+
* @private
|
|
1709
|
+
*/
|
|
1710
|
+
}, {
|
|
1711
|
+
key: "_buildRangeHeaderFieldValue",
|
|
1712
|
+
value: function _buildRangeHeaderFieldValue() {
|
|
1713
|
+
var byteRange = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
|
|
1714
|
+
if (byteRange.length === 1) {
|
|
1715
|
+
return "bytes=".concat(byteRange[0], "-");
|
|
1716
|
+
}
|
|
1717
|
+
if (byteRange.length === 2) {
|
|
1718
|
+
return "bytes=".concat(byteRange[0], "-").concat(byteRange[1]);
|
|
1719
|
+
}
|
|
1720
|
+
return 'bytes=0-';
|
|
1721
|
+
}
|
|
1722
|
+
/**
|
|
1723
|
+
* Gets types that are shared among acceptable media types.
|
|
1724
|
+
*
|
|
1725
|
+
* @param {Object[]} mediaTypes - Acceptable media types and optionally the UIDs of the
|
|
1726
|
+
corresponding transfer syntaxes
|
|
1727
|
+
* @private
|
|
1728
|
+
* @returns {String[]} Types that are shared among acceptable media types
|
|
1729
|
+
*/
|
|
1730
|
+
}, {
|
|
1731
|
+
key: "_getSharedMediaTypes",
|
|
1732
|
+
value: function _getSharedMediaTypes(mediaTypes) {
|
|
1733
|
+
var types = new Set();
|
|
1734
|
+
if (!mediaTypes || !mediaTypes.length) {
|
|
1735
|
+
return types;
|
|
1736
|
+
}
|
|
1737
|
+
mediaTypes.forEach(function (item) {
|
|
1738
|
+
var mediaType = item.mediaType;
|
|
1739
|
+
var type = DICOMwebClient._parseMediaType(mediaType)[0];
|
|
1740
|
+
types.add("".concat(type, "/"));
|
|
1741
|
+
});
|
|
1742
|
+
return Array.from(types);
|
|
1743
|
+
}
|
|
1744
|
+
/**
|
|
1745
|
+
* Gets common type of acceptable media types and asserts that only
|
|
1746
|
+
one type is specified. For example, ``("image/jpeg", "image/jp2")``
|
|
1747
|
+
will pass, but ``("image/jpeg", "video/mpeg2")`` will raise an
|
|
1748
|
+
exception.
|
|
1749
|
+
*
|
|
1750
|
+
* @param {Object[]} mediaTypes - Acceptable media types and optionally the UIDs of the
|
|
1751
|
+
corresponding transfer syntaxes
|
|
1752
|
+
* @private
|
|
1753
|
+
* @returns {String[]} Common media type
|
|
1754
|
+
*/
|
|
1755
|
+
}, {
|
|
1756
|
+
key: "_getCommonMediaType",
|
|
1757
|
+
value: function _getCommonMediaType(mediaTypes) {
|
|
1758
|
+
if (!mediaTypes || !mediaTypes.length) {
|
|
1759
|
+
throw new Error('No acceptable media types provided');
|
|
1760
|
+
}
|
|
1761
|
+
var sharedMediaTypes = DICOMwebClient._getSharedMediaTypes(mediaTypes);
|
|
1762
|
+
if (sharedMediaTypes.length === 0) {
|
|
1763
|
+
throw new Error('No common acceptable media type could be identified.');
|
|
1764
|
+
} else if (sharedMediaTypes.length > 1) {
|
|
1765
|
+
throw new Error('Acceptable media types must have the same type.');
|
|
1766
|
+
}
|
|
1767
|
+
return sharedMediaTypes[0];
|
|
1768
|
+
}
|
|
1769
|
+
}]);
|
|
1770
|
+
return DICOMwebClient;
|
|
1771
|
+
}();
|
|
1772
|
+
|
|
1773
|
+
function findSubstring(str, before, after) {
|
|
1774
|
+
var beforeIndex = str.lastIndexOf(before) + before.length;
|
|
1775
|
+
if (beforeIndex < before.length) {
|
|
1776
|
+
return null;
|
|
1777
|
+
}
|
|
1778
|
+
if (after !== undefined) {
|
|
1779
|
+
var afterIndex = str.lastIndexOf(after);
|
|
1780
|
+
if (afterIndex < 0) {
|
|
1781
|
+
return null;
|
|
1782
|
+
}
|
|
1783
|
+
return str.substring(beforeIndex, afterIndex);
|
|
1784
|
+
}
|
|
1785
|
+
return str.substring(beforeIndex);
|
|
1786
|
+
}
|
|
1787
|
+
function getStudyInstanceUIDFromUri(uri) {
|
|
1788
|
+
var uid = findSubstring(uri, 'studies/', '/series');
|
|
1789
|
+
if (!uid) {
|
|
1790
|
+
uid = findSubstring(uri, 'studies/');
|
|
1791
|
+
}
|
|
1792
|
+
if (!uid) {
|
|
1793
|
+
console.debug("Study Instance UID could not be dertermined from URI \"".concat(uri, "\""));
|
|
1794
|
+
}
|
|
1795
|
+
return uid;
|
|
1796
|
+
}
|
|
1797
|
+
function getSeriesInstanceUIDFromUri(uri) {
|
|
1798
|
+
var uid = findSubstring(uri, 'series/', '/instances');
|
|
1799
|
+
if (!uid) {
|
|
1800
|
+
uid = findSubstring(uri, 'series/');
|
|
1801
|
+
}
|
|
1802
|
+
if (!uid) {
|
|
1803
|
+
console.debug("Series Instance UID could not be dertermined from URI \"".concat(uri, "\""));
|
|
1804
|
+
}
|
|
1805
|
+
return uid;
|
|
1806
|
+
}
|
|
1807
|
+
function getSOPInstanceUIDFromUri(uri) {
|
|
1808
|
+
var uid = findSubstring(uri, '/instances/', '/frames');
|
|
1809
|
+
if (!uid) {
|
|
1810
|
+
uid = findSubstring(uri, '/instances/', '/metadata');
|
|
1811
|
+
}
|
|
1812
|
+
if (!uid) {
|
|
1813
|
+
uid = findSubstring(uri, '/instances/');
|
|
1814
|
+
}
|
|
1815
|
+
if (!uid) {
|
|
1816
|
+
console.debug("SOP Instance UID could not be dertermined from URI\"".concat(uri, "\""));
|
|
1817
|
+
}
|
|
1818
|
+
return uid;
|
|
1819
|
+
}
|
|
1820
|
+
function getFrameNumbersFromUri(uri) {
|
|
1821
|
+
var numbers = findSubstring(uri, '/frames/', '/rendered');
|
|
1822
|
+
if (!numbers) {
|
|
1823
|
+
numbers = findSubstring(uri, '/frames/');
|
|
1824
|
+
}
|
|
1825
|
+
if (numbers === undefined) {
|
|
1826
|
+
console.debug("Frame Numbers could not be dertermined from URI\"".concat(uri, "\""));
|
|
1827
|
+
}
|
|
1828
|
+
return numbers.split(',');
|
|
1829
|
+
}
|
|
1830
|
+
|
|
1831
|
+
var version = '0.5.2';
|
|
1832
|
+
|
|
1833
|
+
var api = {
|
|
1834
|
+
DICOMwebClient: DICOMwebClient
|
|
1835
|
+
};
|
|
1836
|
+
var utils = {
|
|
1837
|
+
getStudyInstanceUIDFromUri: getStudyInstanceUIDFromUri,
|
|
1838
|
+
getSeriesInstanceUIDFromUri: getSeriesInstanceUIDFromUri,
|
|
1839
|
+
getSOPInstanceUIDFromUri: getSOPInstanceUIDFromUri,
|
|
1840
|
+
getFrameNumbersFromUri: getFrameNumbersFromUri
|
|
1841
|
+
};
|
|
1842
|
+
|
|
1843
|
+
|
|
1844
|
+
//# sourceMappingURL=dicomweb-client.es.js.map
|
|
1845
|
+
|
|
1846
|
+
|
|
1847
|
+
/***/ })
|
|
1848
|
+
|
|
1849
|
+
}]);
|