A DICOM viewer that runs in your browser.
Drop in a folder of .dcm files and read the study — windowing,
slice scrolling, real Hounsfield units. Everything is decoded on your own
machine. Nothing is ever uploaded.
What it does
-
Opens whole studies
Drop a folder and it walks it recursively, groups instances into studies and series, and sorts each series correctly. Thousands of files index in about a second.
-
Real Hounsfield windowing
The modality LUT is applied before display, so CT presets — soft tissue, lung, bone, temporal bone — operate on true HU, not raw stored values.
-
Anatomically ordered slices
Slices are ordered by position along the scan normal rather than by filename, so scrolling moves through the patient in the right order.
-
16-bit compressed DICOM
Handles JPEG Lossless, JPEG-LS, JPEG 2000 and uncompressed data at full 16-bit depth, decoded in parallel web workers.
-
Built for reading
Wheel and arrow keys step through the stack. Left-drag windows, middle-drag pans, right-drag zooms. Invert and reset are one click.
-
Private by construction
There is no server. Files are read by the browser and decoded in memory, so patient data physically cannot leave the machine.
Engineering notes
The parts that were actually hard, and what the numbers were.
-
Decoding
16-bit JPEG Lossless is not the easy path
The reference study was entirely JPEG Lossless SV1 (
1.2.840.10008.1.2.4.70) at 16 bits — not the 8-bit baseline JPEG a browser can decode natively. Getting it rendering meant fixing three separate integration failures: CommonJS codec interop, a transitive dependency extending Node'sEventEmitterin the browser, and a metadata path that silently dropped pixel data for encapsulated local files. -
Correctness
Windowing has to happen in Hounsfield units
CT pixels are stored rescaled — the reference study used a slope of 1 and an intercept of −1024. Apply the window before the modality LUT and a lung preset produces a white rectangle. Applied in the right order, air reads at −1000 HU and the presets mean what radiologists expect.
-
Ordering
Filename order is not slice order
Series are sorted by projecting each image's patient position onto the slice normal, derived from the orientation cosines. Verified across twenty series: spacing came out perfectly uniform every time — 0.61mm, 0.40mm, 0.50mm, 1.0mm, 5.0mm — with no gaps or duplicates.
-
Performance
Indexing got 73× faster by measuring first
Indexing 311 files took 8148ms. Rather than guess, the header extent was measured across all 2486 files in the reference study: the longest was 11KB, against the 256KB being read per file. Reading 64KB instead brought the same work down to 112ms.
-
Delivery
Threaded WASM needs cross-origin isolation
One bundled codec is thread-enabled and needs
SharedArrayBuffer, which browsers only expose underCOOP/COEP. Those headers are set in production and mirrored in local preview, so the constraint is caught before a deploy rather than after. -
Architecture
This page carries none of the viewer
The viewer is roughly 9MB once the WASM codecs are counted. It lives on its own entry point, so reading this page never downloads any of it.
Your images stay on your machine
DOCOC has no backend and no analytics. Studies you open are read directly from disk by the browser and decoded in memory. There is no upload step to opt out of, because there is nowhere for the data to go. A Hide patient info toggle blanks identifiers in the overlay for screen sharing.
Open the viewer