@knopkem/dicomview 0.2.0 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/loader.js +61 -3
- package/package.json +1 -1
- package/wasm/dicomview_wasm.js +1 -1
- package/wasm/dicomview_wasm_bg.wasm +0 -0
package/dist/loader.js
CHANGED
|
@@ -50,7 +50,12 @@ export class DICOMwebLoader {
|
|
|
50
50
|
};
|
|
51
51
|
requestFrame(() => {
|
|
52
52
|
renderScheduled = false;
|
|
53
|
-
|
|
53
|
+
try {
|
|
54
|
+
viewer.render();
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
// Viewer may have been destroyed between scheduling and callback
|
|
58
|
+
}
|
|
54
59
|
});
|
|
55
60
|
};
|
|
56
61
|
try {
|
|
@@ -85,7 +90,12 @@ export class DICOMwebLoader {
|
|
|
85
90
|
}
|
|
86
91
|
});
|
|
87
92
|
await Promise.all(workers);
|
|
88
|
-
|
|
93
|
+
try {
|
|
94
|
+
viewer.render();
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
97
|
+
// Viewer may have been destroyed during load
|
|
98
|
+
}
|
|
89
99
|
}
|
|
90
100
|
finally {
|
|
91
101
|
pool?.destroy();
|
|
@@ -99,7 +109,12 @@ export class DICOMwebLoader {
|
|
|
99
109
|
return response.json();
|
|
100
110
|
}
|
|
101
111
|
async #fetchBytes(url, signal) {
|
|
102
|
-
const response = await this.#fetch(url, signal, "application/dicom
|
|
112
|
+
const response = await this.#fetch(url, signal, 'multipart/related; type="application/dicom"');
|
|
113
|
+
const contentType = response.headers.get("Content-Type") ?? "";
|
|
114
|
+
if (contentType.includes("multipart/related")) {
|
|
115
|
+
return extractMultipartDicom(new Uint8Array(await response.arrayBuffer()), contentType);
|
|
116
|
+
}
|
|
117
|
+
// Fallback: server returned a single-part DICOM response
|
|
103
118
|
return new Uint8Array(await response.arrayBuffer());
|
|
104
119
|
}
|
|
105
120
|
async #fetch(url, signal, accept) {
|
|
@@ -343,3 +358,46 @@ function normalize(vector) {
|
|
|
343
358
|
}
|
|
344
359
|
return [vector[0] / length, vector[1] / length, vector[2] / length];
|
|
345
360
|
}
|
|
361
|
+
/**
|
|
362
|
+
* Extract the DICOM file bytes from a WADO-RS multipart/related response.
|
|
363
|
+
*
|
|
364
|
+
* The response body contains one or more parts separated by a MIME boundary.
|
|
365
|
+
* We extract the first part (single-instance retrieval returns exactly one).
|
|
366
|
+
*/
|
|
367
|
+
function extractMultipartDicom(body, contentType) {
|
|
368
|
+
const boundaryMatch = contentType.match(/boundary=([^\s;]+)/);
|
|
369
|
+
if (!boundaryMatch) {
|
|
370
|
+
// No boundary found — assume the body is the raw DICOM bytes
|
|
371
|
+
return body;
|
|
372
|
+
}
|
|
373
|
+
const boundary = boundaryMatch[1].replace(/^"(.*)"$/, "$1");
|
|
374
|
+
const boundaryBytes = new TextEncoder().encode("--" + boundary);
|
|
375
|
+
// Find the first boundary
|
|
376
|
+
const firstBoundary = indexOfBytes(body, boundaryBytes, 0);
|
|
377
|
+
if (firstBoundary === -1) {
|
|
378
|
+
return body;
|
|
379
|
+
}
|
|
380
|
+
// After the boundary line, skip until we find \r\n\r\n (end of part headers)
|
|
381
|
+
const headerStart = firstBoundary + boundaryBytes.length;
|
|
382
|
+
const headerEnd = indexOfBytes(body, new Uint8Array([0x0d, 0x0a, 0x0d, 0x0a]), headerStart);
|
|
383
|
+
if (headerEnd === -1) {
|
|
384
|
+
return body;
|
|
385
|
+
}
|
|
386
|
+
const partStart = headerEnd + 4;
|
|
387
|
+
// Find the next boundary (or end boundary) — the part data ends 2 bytes before it (\r\n)
|
|
388
|
+
const nextBoundary = indexOfBytes(body, boundaryBytes, partStart);
|
|
389
|
+
const partEnd = nextBoundary === -1 ? body.length : nextBoundary - 2;
|
|
390
|
+
return body.subarray(partStart, partEnd);
|
|
391
|
+
}
|
|
392
|
+
function indexOfBytes(haystack, needle, offset) {
|
|
393
|
+
const end = haystack.length - needle.length;
|
|
394
|
+
outer: for (let i = offset; i <= end; i++) {
|
|
395
|
+
for (let j = 0; j < needle.length; j++) {
|
|
396
|
+
if (haystack[i + j] !== needle[j]) {
|
|
397
|
+
continue outer;
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
return i;
|
|
401
|
+
}
|
|
402
|
+
return -1;
|
|
403
|
+
}
|
package/package.json
CHANGED
package/wasm/dicomview_wasm.js
CHANGED
|
@@ -1379,7 +1379,7 @@ function __wbg_get_imports() {
|
|
|
1379
1379
|
return ret;
|
|
1380
1380
|
},
|
|
1381
1381
|
__wbindgen_cast_0000000000000002: function(arg0, arg1) {
|
|
1382
|
-
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx:
|
|
1382
|
+
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx: 697, ret: Result(Unit), inner_ret: Some(Result(Unit)) }, mutable: true }) -> Externref`.
|
|
1383
1383
|
const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__h77f088fde8c66f5c);
|
|
1384
1384
|
return ret;
|
|
1385
1385
|
},
|
|
Binary file
|