@niivue/nv-ohif 0.1.0-rc.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/README.md +210 -0
- package/dist/index.js +2952 -0
- package/dist/types/NiivueViewport.d.ts +14 -0
- package/dist/types/classifyDisplaySet.d.ts +7 -0
- package/dist/types/commands.d.ts +202 -0
- package/dist/types/dicomToNiivue.d.ts +21 -0
- package/dist/types/dicomWadoRs.d.ts +22 -0
- package/dist/types/displaySetToNiivue.d.ts +7 -0
- package/dist/types/getNiivueViewportModule.d.ts +4 -0
- package/dist/types/index.d.ts +12 -0
- package/dist/types/niivueRegistry.d.ts +60 -0
- package/dist/types/ohif-types.d.ts +97 -0
- package/dist/types/reconstructP10.d.ts +35 -0
- package/dist/types/sopClassHandler.d.ts +16 -0
- package/dist/types/toolBridge.d.ts +16 -0
- package/dist/types/toolbar.d.ts +38 -0
- package/dist/types/volumeAnnotationOverlay.d.ts +20 -0
- package/dist/types/wsiSlideView.d.ts +30 -0
- package/dist/types/wsiThumbnail.d.ts +40 -0
- package/dist/types/wsiTileSource.d.ts +68 -0
- package/package.json +52 -0
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
interface WsiThumbInstance extends Record<string, unknown> {
|
|
2
|
+
imageId?: unknown;
|
|
3
|
+
ImageType?: unknown;
|
|
4
|
+
NumberOfFrames?: unknown;
|
|
5
|
+
Rows?: unknown;
|
|
6
|
+
Columns?: unknown;
|
|
7
|
+
SamplesPerPixel?: unknown;
|
|
8
|
+
PhotometricInterpretation?: unknown;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Choose the best ready-made preview image in the pyramid: prefer an OVERVIEW,
|
|
12
|
+
* then a THUMBNAIL, then any non-LABEL side image, then a LABEL; tie-break on the
|
|
13
|
+
* fewest frames (the side images are single-frame). Only instances with an
|
|
14
|
+
* imageId are eligible. Returns undefined when the series has no usable instance.
|
|
15
|
+
*/
|
|
16
|
+
export declare function pickThumbnailInstance(instances: ReadonlyArray<Record<string, unknown>>): WsiThumbInstance | undefined;
|
|
17
|
+
/** Encoded-image signature of a frame's bytes, or 'raw' for uncompressed pixels. */
|
|
18
|
+
export declare function frameEncoding(bytes: Uint8Array): 'jpeg' | 'png' | 'raw';
|
|
19
|
+
export declare const MAX_THUMBNAIL_FETCH_BYTES: number;
|
|
20
|
+
export declare const MAX_THUMBNAIL_DECODE_PIXELS: number;
|
|
21
|
+
interface RawImageInfo {
|
|
22
|
+
width: number;
|
|
23
|
+
height: number;
|
|
24
|
+
channels: number;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* The dimensions for decoding a raw (uncompressed) frame, when the instance
|
|
28
|
+
* describes an 8-bit RGB or grayscale image whose pixel count matches the byte
|
|
29
|
+
* length. Returns null for anything else (leave those to the encoded path or the
|
|
30
|
+
* panel's default tile) so a mismatched buffer never paints garbage.
|
|
31
|
+
*/
|
|
32
|
+
export declare function rawImageInfo(inst: WsiThumbInstance, byteLength: number): RawImageInfo | null;
|
|
33
|
+
/**
|
|
34
|
+
* Fetch a WSI series' preview image and return an image URL for the study panel
|
|
35
|
+
* (a Blob URL for an encoded frame, a data URL for a decoded raw frame), or null
|
|
36
|
+
* if there is no usable instance or the fetch/decode fails. The caller treats the
|
|
37
|
+
* result as an `<img src>`.
|
|
38
|
+
*/
|
|
39
|
+
export declare function fetchWsiThumbnailObjectUrl(instances: ReadonlyArray<Record<string, unknown>>, headers?: Record<string, string>, signal?: AbortSignal): Promise<string | null>;
|
|
40
|
+
export {};
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import type { NVSlideLevelManifest, NVSlideManifest, NVSlideTileManifest, SlideSourceHost, SlideTileSource } from '@niivue/niivue';
|
|
2
|
+
import type { OhifDisplaySet } from './ohif-types';
|
|
3
|
+
/**
|
|
4
|
+
* A multi-valued DICOM attribute (e.g. ImageType) as a backslash-joined string.
|
|
5
|
+
* Depending on the data source the value arrives either already joined
|
|
6
|
+
* ('DERIVED\\PRIMARY\\VOLUME\\NONE') or as a string array (OHIF's
|
|
7
|
+
* dcmjs-naturalized instances deliver ['DERIVED', 'PRIMARY', 'VOLUME', 'NONE']);
|
|
8
|
+
* normalize both to the joined form so flavor matching sees every value.
|
|
9
|
+
*/
|
|
10
|
+
export declare function imageTypeString(value: unknown): string | undefined;
|
|
11
|
+
interface WsiLevel {
|
|
12
|
+
matrixColumns: number;
|
|
13
|
+
matrixRows: number;
|
|
14
|
+
tileColumns: number;
|
|
15
|
+
tileRows: number;
|
|
16
|
+
/** Frame base URL (`.../instances/{sop}/frames`); a tile fetch appends `/{n}`. */
|
|
17
|
+
frameBaseUrl: string;
|
|
18
|
+
/** Query string (with leading `?`) to re-append after the frame index, or ''. */
|
|
19
|
+
frameQuery: string;
|
|
20
|
+
isJpeg: boolean;
|
|
21
|
+
/** Physical spacing `[dx, dy]` in mm for this tier, when the SM metadata carries it. */
|
|
22
|
+
spacingMM?: readonly [number, number];
|
|
23
|
+
/**
|
|
24
|
+
* True when the frames are (or default to) TILED_FULL row-major order — the
|
|
25
|
+
* only layout levelTiles maps correctly (frame = row*cols + col + 1). False
|
|
26
|
+
* only when DimensionOrganizationType is explicitly a non-full value
|
|
27
|
+
* (e.g. TILED_SPARSE), where frame positions come from PlanePositionSlide.
|
|
28
|
+
*/
|
|
29
|
+
tiledFull: boolean;
|
|
30
|
+
}
|
|
31
|
+
/** Extract the VOLUME pyramid levels from an SM display set, finest first. */
|
|
32
|
+
export declare function wsiVolumeLevels(ds: OhifDisplaySet): WsiLevel[];
|
|
33
|
+
export interface BuiltWsiManifest {
|
|
34
|
+
manifest: NVSlideManifest;
|
|
35
|
+
/** Frame base URL by level.index (aligned with manifest.levels). */
|
|
36
|
+
levelBaseUrls: string[];
|
|
37
|
+
/** Query string (with leading `?`, or '') by level.index, re-appended per tile. */
|
|
38
|
+
levelQueries: string[];
|
|
39
|
+
/** True when every kept level is JPEG (v1-renderable). */
|
|
40
|
+
allJpeg: boolean;
|
|
41
|
+
/**
|
|
42
|
+
* True when every kept level is TILED_FULL (row-major) — the only frame layout
|
|
43
|
+
* the row-major tile grid maps correctly. False for a TILED_SPARSE slide, which
|
|
44
|
+
* would otherwise render scrambled.
|
|
45
|
+
*/
|
|
46
|
+
tiledFull: boolean;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Build an {@link NVSlideManifest} (+ per-level frame base URLs) from an OHIF
|
|
50
|
+
* DICOM-WSI (SM) display set, or null when it has no VOLUME pyramid levels.
|
|
51
|
+
*/
|
|
52
|
+
export declare function buildWsiManifest(ds: OhifDisplaySet): BuiltWsiManifest | null;
|
|
53
|
+
/**
|
|
54
|
+
* A live DICOM-WSI tile source: fetches encoded JPEG tiles on demand from a
|
|
55
|
+
* DICOMweb server via WADO-RS `/frames/{n}`, one HTTP request per tile. NVSlide
|
|
56
|
+
* owns the pyramid manifest, LOD, decoding and caching; this only supplies the
|
|
57
|
+
* per-level frame base URLs + the encoded bytes.
|
|
58
|
+
*/
|
|
59
|
+
export declare class DicomWsiTileSource implements SlideTileSource {
|
|
60
|
+
readonly manifest: NVSlideManifest;
|
|
61
|
+
private readonly levelBaseUrls;
|
|
62
|
+
private readonly levelQueries;
|
|
63
|
+
private readonly headers;
|
|
64
|
+
constructor(built: BuiltWsiManifest, headers?: Record<string, string>);
|
|
65
|
+
bind(_host: SlideSourceHost): void;
|
|
66
|
+
fetchTileBytes(level: NVSlideLevelManifest, tile: NVSlideTileManifest): Promise<Uint8Array>;
|
|
67
|
+
}
|
|
68
|
+
export {};
|
package/package.json
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@niivue/nv-ohif",
|
|
3
|
+
"version": "0.1.0-rc.0",
|
|
4
|
+
"private": false,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"description": "NiiVue viewport extension for the OHIF Viewer (render series with NiiVue: 3D volume rendering, meshes, overlays, multiplanar, drawing).",
|
|
7
|
+
"main": "./dist/index.js",
|
|
8
|
+
"module": "./dist/index.js",
|
|
9
|
+
"types": "./dist/types/index.d.ts",
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"types": "./dist/types/index.d.ts",
|
|
13
|
+
"import": "./dist/index.js"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"publishConfig": {
|
|
17
|
+
"access": "public"
|
|
18
|
+
},
|
|
19
|
+
"files": [
|
|
20
|
+
"dist"
|
|
21
|
+
],
|
|
22
|
+
"scripts": {
|
|
23
|
+
"dev": "vite",
|
|
24
|
+
"build:lib": "NODE_ENV=production bun build ./src/index.ts --outdir=dist --target=browser --format=esm --external react --external react-dom --external @niivue/niivue --external @niivue/uikit --external @niivue/dcm2niix --external dcmjs",
|
|
25
|
+
"build:types": "tsc -p tsconfig.build.json",
|
|
26
|
+
"build:package": "bun run build:lib && bun run build:types",
|
|
27
|
+
"test": "bun test"
|
|
28
|
+
},
|
|
29
|
+
"comment:peers": "The host OHIF app (>= 3.12, React 18) provides @ohif/core, @ohif/extension-default and react-dom. They are intentionally NOT peerDependencies here: bun would install the whole OHIF tree (pinned to react-dom 18) into this monorepo, colliding with @niivue/nvreact (React 19). This package builds against local OHIF typings (src/ohif-types.ts) and externalizes react. The react peer allows 18 or 19 so bun reuses the monorepo's React 19 for dev; the component's simple hook usage is compatible with both, and the OHIF host supplies React 18 at runtime.",
|
|
30
|
+
"peerDependencies": {
|
|
31
|
+
"@niivue/niivue": "1.0.0-rc.13",
|
|
32
|
+
"react": "^18.3.1 || ^19"
|
|
33
|
+
},
|
|
34
|
+
"comment:dcm2niix-pin": "The dcm2niix Web-Worker exit fix (wrap callMain in try/catch, read err.status) is PUBLISHED: @niivue/dcm2niix 1.3.20260724 (calendar-versioned, now npm 'latest') contains it (verified in the published dist/worker.js + worker.jpeg.js). The pin requires that fixed release or newer, so DICOM conversion now works for npm-install consumers. The dev-rig local-patched dcm2niix override can be dropped in favor of the published package. See README '## DICOM support'.",
|
|
35
|
+
"comment:uikit-dep": "@niivue/uikit is externalized in build:lib and is a runtime dependency (its ruler/line/text overlays, loadDefaultFont, and the inlined MSDF font are imported at runtime, not bundled). It is published from this monorepo in the same Nx release group, so `npm install @niivue/nv-ohif` resolves it. The workspace range is rewritten to the published version on pack/release. Its only @niivue/niivue import is type-only, so no niivue runtime is duplicated.",
|
|
36
|
+
"dependencies": {
|
|
37
|
+
"@niivue/dcm2niix": "^1.3.20260724",
|
|
38
|
+
"@niivue/uikit": "0.1.0-rc.0",
|
|
39
|
+
"dcmjs": "^0.49.0"
|
|
40
|
+
},
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"@niivue/niivue": "1.0.0-rc.13",
|
|
43
|
+
"@types/bun": "^1.3.12",
|
|
44
|
+
"@types/react": "^19",
|
|
45
|
+
"@types/react-dom": "^19",
|
|
46
|
+
"@vitejs/plugin-react": "^6.0.1",
|
|
47
|
+
"react": "^19",
|
|
48
|
+
"react-dom": "^19",
|
|
49
|
+
"typescript": "^5.9.3",
|
|
50
|
+
"vite": "^8.0.9"
|
|
51
|
+
}
|
|
52
|
+
}
|