Extensions, DICOM and image processing
The core @niivue/niivue package views images. Heavier jobs, such as
converting DICOM or running image filters, live in separate extension
packages so you only ship what you use. Each one lists @niivue/niivue as a
peer dependency, so install it alongside the extension. The packages are in prerelease, published
under the next tag:
npm install @niivue/niivue@next
Most extensions run their work in a Web Worker, so the page stays responsive while they compute.
DICOM: nv-ext-dcm2niix
npm install @niivue/nv-ext-dcm2niix@next
NiiVue does not read DICOM directly. @niivue/nv-ext-dcm2niix runs
dcm2niix (compiled to WebAssembly) in the browser and returns NIfTI files
you can load:
import { runDcm2niix } from '@niivue/nv-ext-dcm2niix'
// <input id="dicomFolder" type="file" webkitdirectory multiple />
input.addEventListener('change', async () => {
const niftiFiles = await runDcm2niix(input.files)
await nv.loadVolumes([{ url: niftiFiles[0] }])
})
For a dropped folder, traverseDataTransferItems(e.dataTransfer.items)
collects the files first. The Dcm2niix class is also exported for full
control over the dcm2niix flags:
import { Dcm2niix } from '@niivue/nv-ext-dcm2niix'
const dcm2niix = new Dcm2niix()
await dcm2niix.init()
const result = await dcm2niix.input(files).compressionLevel(9).bids('n').run()
Filters: nv-ext-niimath
npm install @niivue/nv-ext-niimath@next
@niivue/nv-ext-niimath runs niimath
(an fslmaths clone) on a NIfTI file. Each step is one niimath operation, and
the steps run in order:
import { Niimath, runNiimathPipeline } from '@niivue/nv-ext-niimath'
const niimath = new Niimath() // create one per page; the worker is costly
await niimath.init()
const result = await runNiimathPipeline(niimath, file, [
{ method: 's', args: [3] }, // smooth, sigma 3 mm
{ method: 'thr', args: [0.5] },
{ method: 'bin', args: [] },
])
await nv.loadVolumes([{ url: new File([result], 'processed.nii.gz') }])
Segmentation: nv-ext-image-processing
npm install @niivue/nv-ext-image-processing@next
@niivue/nv-ext-image-processing provides volume transforms: otsu
(threshold into 2 to 4 classes), removeHaze, conform and
connectedLabel. You register them on an extension context and apply them
to a loaded volume:
import { otsu } from '@niivue/nv-ext-image-processing'
const ctx = nv.createExtensionContext()
ctx.registerVolumeTransform(otsu)
const segmented = await ctx.applyVolumeTransform('otsu', ctx.volumes[0])
await ctx.addVolume(segmented)
Drawing tools: nv-ext-drawing
npm install @niivue/nv-ext-drawing@next
@niivue/nv-ext-drawing works on the drawing layer. It can find the first
and last drawn slices, fill the slices between them by interpolation, and
run a 3D magic wand (magicWand) from a seed point:
import { SLICE_TYPE } from '@niivue/niivue'
import { interpolateMaskSlices } from '@niivue/nv-ext-drawing'
const ctx = nv.createExtensionContext()
const dr = ctx.drawing
if (dr) {
const filled = await interpolateMaskSlices(
dr.bitmap, dr.dims, null, 1, undefined, undefined,
{ sliceType: SLICE_TYPE.AXIAL },
)
dr.update(filled)
}
See Drawing and segmentation for painting the drawing itself.
Export: nv-ext-save-html
npm install @niivue/nv-ext-save-html@next
@niivue/nv-ext-save-html saves the current scene as one self-contained
HTML file that opens without a server. You supply the NiiVue code to embed,
as a standalone ES module bundle with all dependencies inlined:
import { saveHTML } from '@niivue/nv-ext-save-html'
const bundleSource = await fetch('/niivue-standalone.js').then((r) => r.text())
await saveHTML(nv, 'scene.html', { niivueBundleSource: bundleSource, title: 'My scene' })
generateHTML(nv, options) returns the same page as a string instead of
downloading it.
Whole-slide TIFF: nv-ext-tiff
npm install @niivue/nv-ext-tiff@next
@niivue/nv-ext-tiff streams tiled/pyramidal TIFF, BigTIFF, OME-TIFF and
Aperio SVS slides into NVSlide over HTTP Range, reading and decoding
(with geotiff) only the tiles in
view. The server must answer Range requests with 206 and allow them
cross-origin; one that sends the whole file is refused.
import { NVSlide } from '@niivue/niivue'
import { TiffSlideSource } from '@niivue/nv-ext-tiff'
const source = await TiffSlideSource.fromUrl('https://example.org/slide.svs')
const slide = NVSlide.fromSource(source)
// when done: slide.dispose() and source.dispose()
TiffSlideSource.fromGeoTIFF(await fromBlob(file)) opens a local file.
More demos
The image-processing and drawing demo apps are deployed too: image processing, drawing and magic wand. Their source is in apps/demo-ext-image-processing and apps/demo-ext-drawing.