dicom_viewer 0.6.0
dicom_viewer: ^0.6.0 copied to clipboard
A pure-Dart DICOM viewer for Flutter. Parses uncompressed, RLE, and JPEG DICOM files, applies VOI windowing and PALETTE LUTs, and renders images across Web, Desktop, and Mobile.
dicom_viewer #
A pure-Dart, cross-platform DICOM viewer package for Flutter. Parses uncompressed, RLE Lossless, and JPEG compressed (Baseline & Lossless SV1) DICOM medical images, applies Hounsfield Unit rescaling, linear VOI windowing (contrast/brightness), and PALETTE COLOR lookup tables, and provides interactive 2D distance measurements, rectangular ROI statistics, and pixel probe inspection β on Android, iOS, macOS, Windows, Linux, and Web from a single codebase with no native/FFI dependencies.
π Live Demo #
Experience the Flutter DICOM viewer directly in your web browser with interactive windowing, pan/zoom, measurement tools, and sample DICOM loading:
π Open Live DICOM Viewer Demo
Privacy Note: DICOM files are processed entirely locally in your browser memory and are never uploaded by the demo application.
βοΈ Medical Use Disclaimer #
dicom_viewer is an open-source software library intended for image processing, visualization, and application development. It is not a certified or approved medical device and has not been evaluated or authorized by regulatory authorities for clinical diagnosis, treatment, or other patient-care decisions. It is not intended to replace the judgment of qualified healthcare professionals or to be used as the sole basis for clinical decision-making.
Developers are responsible for determining the suitability, validation, regulatory requirements, and intended use of applications built using this library.
β¨ Features #
- β‘ 100% Pure Dart: Zero C/C++ or FFI native code dependencies. Completely self-contained.
- π True Cross-Platform: Runs natively on Mobile (Android, iOS), Desktop (Windows, macOS, Linux), and Web (CanvasKit & Skwasm).
- π©Ί DICOM PS3.10 & PS3.5 Parsing: Parses
Explicit VR Little Endian(clinical fixtures validated),Implicit VR Little Endian(synthetically tested), andExplicit VR Big Endian(retired DICOM transfer syntax; synthetically tested with generated byte stream, unverified on clinical fixtures). Includes dynamic parser fallback for malformed datasets declaring Explicit VR in File Meta whose dataset body elements are encoded in Implicit VR, while properly encoded Explicit VR datasets retain standard Explicit VR parsing. - πΌοΈ Pure-Dart JPEG Baseline Decompressor (
1.2.840.10008.1.2.4.50):- 8-bit lossy DCT decompressor complying with ISO/IEC 10918-1 / ITU-T T.81.
- Native support for grayscale (
MONOCHROME1,MONOCHROME2),RGB, and subsampledYBR_FULL_422with accurate ITU-R BT.601 color conversion. - Supports restart markers (
RST0βRST7) and DRI markers.
- π Pure-Dart JPEG Lossless SV1 Decompressor (
1.2.840.10008.1.2.4.70):- First-order prediction (Process 14, Selection Value 1) decompressor for medical imaging.
- Supports 8-bit, 12-bit, and 16-bit sample precision with bit-exact reference oracle validation on single-frame clinical datasets (
JPEG-LL.dcm,JPGLosslessP14SV1_1s_1f_8b.dcm). - Note: Multi-frame
.70framing is synthetically tested; no suitable real fixture with sufficiently clear redistribution rights was identified in the investigated sources.
- π¦ Encapsulated Pixel Data & RLE Lossless (
1.2.840.10008.1.2.5):- RLE Lossless decompressor for 8-bit, 16-bit MSB/LSB, and 24-bit RGB segments, verified with real-world clinical fixtures across single-frame (
OBXXXX1A_rle.dcm) and multi-frame datasets (emri_small_RLE.dcm10 frames,OBXXXX1A_rle_2frame.dcm2 frames).
- RLE Lossless decompressor for 8-bit, 16-bit MSB/LSB, and 24-bit RGB segments, verified with real-world clinical fixtures across single-frame (
- π§© Modular Internal Codec Registry Architecture:
- Pluggable
CodecRegistryandDicomFrameCodecsubsystem isolating transfer syntax decoding from rendering pipelines. - Frame-accurate payload extraction via dedicated framing strategies (
JpegFramingStrategy,RleFramingStrategy).
- Pluggable
- π¬ Multi-Frame Navigation & Cine Playback:
- Frame slice extraction and dynamic navigation for multi-frame uncompressed (
emri_small.dcm, 10 frames), RLE (emri_small_RLE.dcm, 10 frames), and JPEG datasets (examples_ybr_color.dcm, 30 frames). - Supports Basic Offset Tables (BOT), empty BOT fallback with 1:1 fragment-to-frame mapping, and multi-fragment-per-frame scanning.
- Frame slice extraction and dynamic navigation for multi-frame uncompressed (
- π Physical Pixel Spacing & Geometry:
- Automatic geometric aspect-ratio correction preserving physical pixel geometry from
Pixel Spacing (0028,0030). - Canonical image geometry with strict fallback hierarchy (Verified Physical Spacing $\to$ Display-Only Pixel Aspect Ratio $\to$ Native Matrix Fallback).
- Automatic geometric aspect-ratio correction preserving physical pixel geometry from
- π 2D Distance Measurement (
DicomTool.measure):- Interactive caliper line drawing with draggable endpoints and hit-testing.
- Euclidean physical distance in millimeters ($mm$) when Pixel Spacing is present, or pixel fallback ($px$).
- π² Rectangle ROI & Quantitative Statistics (
DicomTool.rectangleRoi):- Interactive rectangular ROI creation with corner normalization.
- Reports physical dimensions ($W \times H$ in $mm$, Area in $mm^2$) or pixel fallback ($px, px^2$).
- Evaluates enclosed discrete pixels: Mean, Population Standard Deviation ($\sigma_N$), Min, Max, Median, and Pixel Count.
- Verified Hounsfield Unit ($HU$) statistics on CT datasets (including JPEG Lossless CT) with explicit valid rescale metadata.
- Unitless intensity statistics on non-CT modalities (MR, CR, US) with pre-rescale Pixel Padding exclusion.
- π Pixel Probe Tool (
DicomTool.probe):- Real-time hover inspection overlay showing discrete coordinates $(c, r)$, stored scalar intensity, and modality/HU rescaled values.
- RGB triplet and palette index inspection for PALETTE COLOR, RGB, and YBR datasets.
- High-performance current-frame caching without full-image re-decoding or render pipeline overhead.
- π¨ Color Pipeline & PALETTE COLOR LUT Rendering:
- Direct Palette Color Lookup Table mapping (Red, Green, Blue) supporting 8-bit and 16-bit entries with signed/unsigned descriptor handling (
OBXXXX1A_rle.dcm). - Planar configuration:
PlanarConfiguration=0(interleaved) andPlanarConfiguration=1(planar separate: PlanarConfiguration=1 rendering is validated for single-frame 8-bit uncompressed RGB Ultrasoundcolor-pl.dcm, while ROI and Pixel Probe remain unvalidated for planar-separated RGB data). - ITU-R BT.601 color conversion for
YBR_FULLandYBR_FULL_422. Synthetic-only BT.601 limited-range conversion forYBR_PARTIAL_422(no suitable real fixture with sufficiently clear redistribution rights was identified in the investigated sources).
- Direct Palette Color Lookup Table mapping (Red, Green, Blue) supporting 8-bit and 16-bit entries with signed/unsigned descriptor handling (
- ποΈ VOI Windowing & Rescale Math:
- Rescale Slope & Intercept ($RealWorldValue = StoredPixel \times Slope + Intercept$).
- DICOM PS3.3 C.11.2.1.2 Linear VOI Window Center ($WC$) & Window Width ($WW$) contrast mapping for grayscale modalities.
- Automatic
MONOCHROME1vsMONOCHROME2grayscale intensity inversion (validated on real single-frame 16/12-bit unsigned CR fixtureCR1_6154.dcm). - Note: Windowing is not applicable to
PALETTE COLOR,RGB, orYBR_FULLcolor rendering.
- π Comprehensive Metadata API: 25+ strongly-typed convenience getters for Patient, Study, Series, Equipment, Instance, and Acquisition attributes.
- ποΈ Interactive UI Widget:
DicomImageWidgetwith touch/pan drag gestures for windowing, pan/zoom, distance measurement, rectangle ROI, and pixel probe inspection. - π‘οΈ Graceful Error Handling: Clear, version-neutral
UnsupportedErrornotifications for unsupported or deferred transfer syntaxes.
π Authoritative Transfer Syntax Support Matrix #
The following table defines the official transfer syntax capabilities and evidence levels in dicom_viewer (baseline v0.6.0):
| Transfer Syntax UID | Transfer Syntax Name | Compression / Encoding | Status in v0.6.0 | Evidence Level |
|---|---|---|---|---|
1.2.840.10008.1.2 |
Implicit VR Little Endian | Default Uncompressed Little Endian | β οΈ Implemented | Synthetically tested (unverified on clinical fixture) |
1.2.840.10008.1.2.1 |
Explicit VR Little Endian | Uncompressed Little Endian | β Real-Fixture Validated | Real-fixture validated across documented fixture scope (single-frame CT, MR, CR, US and 10-frame multi-frame emri_small.dcm) |
1.2.840.10008.1.2.2 |
Explicit VR Big Endian | Uncompressed Big Endian (Retired) | β οΈ Retired / Unverified | Synthetically tested (generated 4Γ4 byte stream; no clinical fixture) |
1.2.840.10008.1.2.1.99 |
Deflated Explicit VR Little Endian | Deflated Stream Compression | β Unsupported | Explicitly rejected with UnsupportedError |
1.2.840.10008.1.2.5 |
RLE Lossless | Run Length Encoding (PS3.5 Annex G) | β Real-Fixture Validated | Real-fixture validated across documented fixture scope (single-frame and 10-frame multi-frame emri_small_RLE.dcm) |
1.2.840.10008.1.2.4.50 |
JPEG Baseline (Process 1) | 8-bit Lossy DCT JPEG | β Real-Fixture Validated | Real-fixture validated across documented fixture scope (single-frame RGB/YBR and 30-frame multi-frame examples_ybr_color.dcm) |
1.2.840.10008.1.2.4.70 |
JPEG Lossless, Non-Hierarchical, First-Order Prediction (Process 14 SV1) | 8-bit / 12-bit / 16-bit Lossless Huffman JPEG | β οΈ Partially Validated | Single-frame: Real-fixture validated (JPEG-LL.dcm, JPGLosslessP14SV1_1s_1f_8b.dcm); Multi-frame: Synthetic framing tested (no suitable fixture identified in investigated sources) |
1.2.840.10008.1.2.4.51 |
JPEG Extended (Process 2 & 4) | 12-bit Lossy DCT JPEG | β Unsupported | UnsupportedError |
1.2.840.10008.1.2.4.57 |
JPEG Lossless (Process 14) | General Selection Value Lossless JPEG | β³ Deferred | UnsupportedError |
1.2.840.10008.1.2.4.80 |
JPEG-LS Lossless Image Compression | Context-based Lossless | β Unsupported | UnsupportedError |
1.2.840.10008.1.2.4.81 |
JPEG-LS Lossy (Near-Lossless) Image Compression | Context-based Near-Lossless | β Unsupported | UnsupportedError |
1.2.840.10008.1.2.4.90 |
JPEG 2000 Image Compression (Lossless Only) | Wavelet Lossless | β Unsupported | UnsupportedError |
1.2.840.10008.1.2.4.91 |
JPEG 2000 Image Compression | Wavelet Lossy | β Unsupported | UnsupportedError |
β Other Scope Boundaries & Limitations #
- β Deflated Transfer Syntax (
1.2.840.10008.1.2.1.99) β throws clearUnsupportedError(whole-stream compression is explicitly rejected). - β Segmented Palette Color LUT Data (
0028,1221-1223) and Enhanced Palette Color Sequence (0028,140B) β throws clearUnsupportedError(only direct Palette Color LUT Data0028,1201-1203is supported). - β οΈ PlanarConfiguration=1 Scope: PlanarConfiguration=1 rendering is validated for single-frame 8-bit uncompressed RGB Ultrasound (
color-pl.dcm), while ROI and Pixel Probe remain unvalidated for planar-separated RGB data. - β οΈ MONOCHROME1 Scope: Validated for narrow scope on single-frame CR uncompressed (
CR1_6154.dcm); compressed MONOCHROME1 and other modalities/bit depths remain unverified. - β οΈ YBR_PARTIAL_422 Scope: BT.601 limited-range mathematical conversion is synthetically tested; no suitable real fixture with sufficiently clear redistribution rights was identified in the investigated sources.
- β 3D spatial geometry (Image Position / Image Orientation Patient slice reconstruction).
- β Multi-Planar Reconstruction (MPR) & 3D volume rendering.
- β DICOM Structured Reporting (SR) & Grayscale Softcopy Presentation State (GSPS).
π Getting Started #
Add dicom_viewer to your pubspec.yaml:
flutter pub add dicom_viewer
Or import it directly in your Dart code:
import 'package:dicom_viewer/dicom_viewer.dart';
π‘ Usage Examples #
1. Interactive UI Widget with Tool Selection & Gestures #
Use DicomImageWidget with tool selection (DicomTool.pan, DicomTool.windowing, DicomTool.measure, DicomTool.rectangleRoi, DicomTool.probe):
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:dicom_viewer/dicom_viewer.dart';
class MedicalViewerScreen extends StatefulWidget {
final Uint8List dicomBytes;
const MedicalViewerScreen({super.key, required this.dicomBytes});
@override
State<MedicalViewerScreen> createState() => _MedicalViewerScreenState();
}
class _MedicalViewerScreenState extends State<MedicalViewerScreen> {
DicomTool _selectedTool = DicomTool.pan;
@override
Widget build(BuildContext context) {
final dataset = DicomDataset.fromBytes(widget.dicomBytes);
return Scaffold(
appBar: AppBar(
title: Text('DICOM Viewer - ${dataset.patientName}'),
actions: [
SegmentedButton<DicomTool>(
segments: const [
ButtonSegment(value: DicomTool.pan, label: Text('Pan')),
ButtonSegment(value: DicomTool.windowing, label: Text('Window')),
ButtonSegment(value: DicomTool.measure, label: Text('Measure')),
ButtonSegment(value: DicomTool.rectangleRoi, label: Text('ROI')),
ButtonSegment(value: DicomTool.probe, label: Text('Probe')),
],
selected: {_selectedTool},
onSelectionChanged: (tools) => setState(() => _selectedTool = tools.first),
),
],
),
body: Center(
child: DicomImageWidget(
dataset: dataset,
enableZoom: true,
tool: _selectedTool,
showOverlay: true,
onWindowChanged: (windowCenter, windowWidth) {
print('New Windowing: WC=$windowCenter, WW=$windowWidth');
},
),
),
);
}
}
2. Programmatic Rendering to ui.Image with Multi-Frame Support #
Convert a DicomDataset frame directly to a Flutter ui.Image:
import 'dart:ui' as ui;
import 'package:dicom_viewer/dicom_viewer.dart';
Future<ui.Image> renderDicomFile(Uint8List fileBytes, {int frameIndex = 0}) async {
// Parse DICOM dataset
final dataset = DicomDataset.fromBytes(fileBytes);
// Render frame to ui.Image with specific Window Center (40) & Window Width (400)
final ui.Image image = await DicomRenderer.renderToImage(
dataset,
frameIndex: frameIndex,
windowCenter: 40.0,
windowWidth: 400.0,
);
return image;
}
3. Extracting DICOM Metadata & Presets #
Access typed DICOM header attributes and clinical presets:
final dataset = DicomDataset.fromBytes(dicomBytes);
// Study & Series
print('Study UID: ${dataset.studyInstanceUid}');
print('Series Description: ${dataset.seriesDescription}');
print('Modality: ${dataset.modality}'); // e.g. 'CT', 'MR', 'US'
// Patient
print('Patient Name: ${dataset.patientName}');
print('Patient ID: ${dataset.patientId}');
// Geometry & Multi-Frame
print('Dimensions: ${dataset.columns} x ${dataset.rows}');
print('Number of Frames: ${dataset.numberOfFrames}');
print('Pixel Spacing: ${dataset.pixelSpacing}'); // [rowSpacing, columnSpacing]
print('Window Center Presets: ${dataset.windowCenterPresets}');
print('Window Width Presets: ${dataset.windowWidthPresets}');
π API Summary #
| Class / Widget | Description |
|---|---|
DicomDataset |
Parses and stores DICOM dataset attributes and metadata from raw binary streams. |
DicomRenderer |
Renders a DicomDataset frame to a displayable Flutter ui.Image using ui.decodeImageFromPixels. |
DicomImageWidget |
Interactive Flutter StatefulWidget supporting interactive tools (DicomTool), drag windowing, pan/zoom, distance measurement, rectangular ROI statistics, pixel probe, and medical overlays. |
DicomTool |
Enum defining active tool mode: pan, windowing, measure, rectangleRoi, probe. |
PixelDataDecoder |
Decodes raw pixel bytes (8-bit, 16-bit signed/unsigned 2's complement) into normalized integer arrays. |
Windowing |
Pure math class for Rescale Slope/Intercept and DICOM PS3.3 C.11.2.1.2 Linear VOI Windowing. |
πΊοΈ Roadmap #
- β
v0.1.0 β Uncompressed single-frame DICOM parsing, linear VOI windowing math,
ui.Imagerenderer, interactiveDicomImageWidget, cross-platform support. - β
v0.2.0 β Pure-Dart RLE Lossless decompressor groundwork, Pixel Padding Value filtering, multi-valued clinical window presets, multi-frame groundwork (
frameIndex), interactive pan/zoom & double-tap reset. - β v0.3.0 β Real-world DICOM RLE fixture validation, multi-frame navigation & Cine playback, PALETTE COLOR direct LUT rendering, physical Pixel Spacing display aspect-ratio correction, rich Metadata API, medical disclaimer.
- β
v0.5.0 β Pure-Dart JPEG Baseline (
.50) & JPEG Lossless SV1 (.70) decompressors, modular codec registry architecture, multi-frame JPEG framing and navigation, ITU-R BT.601 YBR-to-RGB color pipeline, verified quantitative ROI statistics and Pixel Probe across JPEG datasets. - β
v0.6.0 β Compatibility consolidation: Real uncompressed multi-frame validation (
emri_small.dcm), RLE multi-frame validation (emri_small_RLE.dcm), real PlanarConfiguration=1 fixture validation (color-pl.dcm), real MONOCHROME1 CR fixture validation (CR1_6154.dcm), P0 compatibility hardening, and authoritative evidence matrix consolidation.
π License #
Distributed under the MIT License. See LICENSE for details.