@knopkem/dicomview 0.2.0 → 0.2.1
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 +49 -1
- package/package.json +1 -1
- package/wasm/dicomview_wasm_bg.wasm +0 -0
package/dist/loader.js
CHANGED
|
@@ -99,7 +99,12 @@ export class DICOMwebLoader {
|
|
|
99
99
|
return response.json();
|
|
100
100
|
}
|
|
101
101
|
async #fetchBytes(url, signal) {
|
|
102
|
-
const response = await this.#fetch(url, signal, "application/dicom
|
|
102
|
+
const response = await this.#fetch(url, signal, 'multipart/related; type="application/dicom"');
|
|
103
|
+
const contentType = response.headers.get("Content-Type") ?? "";
|
|
104
|
+
if (contentType.includes("multipart/related")) {
|
|
105
|
+
return extractMultipartDicom(new Uint8Array(await response.arrayBuffer()), contentType);
|
|
106
|
+
}
|
|
107
|
+
// Fallback: server returned a single-part DICOM response
|
|
103
108
|
return new Uint8Array(await response.arrayBuffer());
|
|
104
109
|
}
|
|
105
110
|
async #fetch(url, signal, accept) {
|
|
@@ -343,3 +348,46 @@ function normalize(vector) {
|
|
|
343
348
|
}
|
|
344
349
|
return [vector[0] / length, vector[1] / length, vector[2] / length];
|
|
345
350
|
}
|
|
351
|
+
/**
|
|
352
|
+
* Extract the DICOM file bytes from a WADO-RS multipart/related response.
|
|
353
|
+
*
|
|
354
|
+
* The response body contains one or more parts separated by a MIME boundary.
|
|
355
|
+
* We extract the first part (single-instance retrieval returns exactly one).
|
|
356
|
+
*/
|
|
357
|
+
function extractMultipartDicom(body, contentType) {
|
|
358
|
+
const boundaryMatch = contentType.match(/boundary=([^\s;]+)/);
|
|
359
|
+
if (!boundaryMatch) {
|
|
360
|
+
// No boundary found — assume the body is the raw DICOM bytes
|
|
361
|
+
return body;
|
|
362
|
+
}
|
|
363
|
+
const boundary = boundaryMatch[1].replace(/^"(.*)"$/, "$1");
|
|
364
|
+
const boundaryBytes = new TextEncoder().encode("--" + boundary);
|
|
365
|
+
// Find the first boundary
|
|
366
|
+
const firstBoundary = indexOfBytes(body, boundaryBytes, 0);
|
|
367
|
+
if (firstBoundary === -1) {
|
|
368
|
+
return body;
|
|
369
|
+
}
|
|
370
|
+
// After the boundary line, skip until we find \r\n\r\n (end of part headers)
|
|
371
|
+
const headerStart = firstBoundary + boundaryBytes.length;
|
|
372
|
+
const headerEnd = indexOfBytes(body, new Uint8Array([0x0d, 0x0a, 0x0d, 0x0a]), headerStart);
|
|
373
|
+
if (headerEnd === -1) {
|
|
374
|
+
return body;
|
|
375
|
+
}
|
|
376
|
+
const partStart = headerEnd + 4;
|
|
377
|
+
// Find the next boundary (or end boundary) — the part data ends 2 bytes before it (\r\n)
|
|
378
|
+
const nextBoundary = indexOfBytes(body, boundaryBytes, partStart);
|
|
379
|
+
const partEnd = nextBoundary === -1 ? body.length : nextBoundary - 2;
|
|
380
|
+
return body.subarray(partStart, partEnd);
|
|
381
|
+
}
|
|
382
|
+
function indexOfBytes(haystack, needle, offset) {
|
|
383
|
+
const end = haystack.length - needle.length;
|
|
384
|
+
outer: for (let i = offset; i <= end; i++) {
|
|
385
|
+
for (let j = 0; j < needle.length; j++) {
|
|
386
|
+
if (haystack[i + j] !== needle[j]) {
|
|
387
|
+
continue outer;
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
return i;
|
|
391
|
+
}
|
|
392
|
+
return -1;
|
|
393
|
+
}
|
package/package.json
CHANGED
|
Binary file
|