Skip to content

MostafaSensei106/Flutter-Dicom

Flutter-Dicom

Banner

An advanced medical imaging and DICOM processing library for Flutter, poIred by a high-performance Rust core and GPU Shaders.
Go beyond basic image loading. Deliver workstation-grade rendering, 16-bit precision, and real-time windowing in your medical apps.

Why? β€’ Key Features β€’ Installation β€’ Basic Usage β€’ Advanced Usage β€’ Contributing


πŸ€” Why Choose Flutter-Dicom?

In medical imaging, an 8-bit approximation is often a liability. Your app needs clinical precision, not just a picture.

Most image libraries in Flutter are designed for JPEGs and PNGs. They clamp your data to 8-bits per channel and lack the mathematical context needed for medical diagnostics. A doctor needs to see the exact Hounsfield Units, adjust the contrast (Windowing) in real-time, and zoom without UI stutter. Pure Dart DICOM parsers struggle with the sheer size of 16-bit volumetric data, leading to memory crashes and frozen screens.

πŸ“Š How I compare

Feature Standard Image dart_dicom (Pure Dart) Flutter-Dicom
Parsing Engine Platform Native Dart πŸš€ High-Perf Rust Native Core
Bit-Depth Precision 8-bit (Lossy) 16-bit (Slow) βœ… Native 16-bit (Full Range)
Rendering Engine Skia/Impeller CPU Canvas ⚑ GPU Fragment Shaders
UI Responsiveness βœ… ⚠️ ⚑ Zero UI-Thread Blocking
Interactive Windowing ❌ ❌ πŸ“ˆ Real-time Contrast/Brightness
Detailed Metadata ❌ βœ… 🩺 Full Tag Dictionary Access
Memory Efficiency πŸ”΄ High πŸ”΄ High πŸ”‹ Zero-Copy FFI Buffers
Ready-to-use Widget ❌ ❌ 🀝 Built-in DicomViewer

πŸ“Έ Screenshots & Demo

Demo
Viewer View Viewer View Metadata View

πŸ“¦ Installation

Tip

Don't worry about the "Rust Core"! Adding Flutter-Dicom to your project is designed to be as simple as adding any other Flutter package. While it uses a high-performance Rust engine, you don't need to be a Rust expert or manage complex builds manually. You just install the language once, and the library handles all the heavy lifting, compiling itself automatically for whatever platform (Android, iOS, macOS, Windows, Linux) or architecture you are targeting.

1. Prerequisites (The Rust Toolchain)

Since this library uses a high-speed bridge to connect Flutter and Rust, you need the Rust compiler installed on your development machine.

  • Windows: Download and run rustup-init.exe.
  • macOS / Linux: Run the following command in your terminal:
    curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

Important

Once Rust is installed, the build system will automatically detect your Flutter target and compile the Rust core into a high-performance native shared library. You only need to set this up once!

2. Add the Dependency

Add the package to your pubspec.yaml:

dependencies:
  flutter_dicom: ^0.1.0+2

πŸš€ Basic Usage

1. Initialization

Initialize the library in your main() function before starting the app.

import 'package:flutter/material.dart';
import 'package:flutter_dicom/flutter_dicom.dart';

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  // Load the native Rust binary into memory
  await RustLib.init();
  
  runApp(const MyApp());
}

2. Loading and Displaying DICOM

The DicomController is the brain of your Viewer. Pair it with the DicomViewer widget for an instant medical-grade experience.

import 'package:flutter/material.dart';
import 'package:flutter_dicom/flutter_dicom.dart';

class MyMedicalApp extends StatefulWidget {
  @override
  State<MyMedicalApp> createState() => _MyMedicalAppState();
}

class _MyMedicalAppState extends State<MyMedicalApp> {
  final _controller = DicomController();

  @override
  void initState() {
    super.initState();
    // Initialize shaders and load a file
    _controller.initialize().then((_) {
      _controller.loadFromFile(filePath: '/sdcard/scans/head_ct.dcm');
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: DicomViewer(controller: _controller),
    );
  }

  @override
  void dispose() {
    _controller.dispose(); // Critical: Free GPU textures
    super.dispose();
  }
}

3. Adjusting Windowing Programmatically

// Manually set Window Center and Width
void applyBoneWindow() {
  _controller.adjustWindowing(deltaX: 1500, deltaY: 300);
}

// Reset to file defaults
void reset() => _controller.resetWindowing();

πŸ”¬ Advanced Usage

Custom Rust Logic with DicomConfig

You can tune the Rust engine for specific use cases, such as fast-loading metadata while skipping expensive pixel processing.

await _controller.loadFromFile(
  filePath: path,
  config: DicomConfig(
    autoNormalize: true, 
    skipPixels: true, // Meta-data only mode
  ),
);

Dependency Injection (DI) Architecture

For enterprise apps, inject a custom DicomService to handle different storage backends (S3, local cache, etc.).

// 1. Define the service with a specific loader
final service = DicomService(loader: FileDicomLoader());

// 2. Inject into the controller
final controller = DicomController(service: service);

Precision Texture Unpacking (GLSL)

If you are curious about how I maintain 16-bit integrity through an 8-bit texture interface, look at shader logic:

void main() {
    vec4 texColor = texture(u_texture, uv);
    
    // Unpack R (High Byte) and G (Low Byte)
    float high = texColor.r * 255.0;
    float low = texColor.g * 255.0;
    float raw_value = (high * 256.0 + low) - 32768.0;
    
    // HU = (Pixel * Slope) + Intercept
    float hu = (raw_value * u_rescale_slope) + u_rescale_intercept;
    // ... Windowing calculations follow
}

⚑ Performance Benchmarks

The Flutter-Dicom library is meticulously optimized for both blistering speed and strict memory efficiency. The following benchmarks were executed on an AMD Ryzenβ„’ 7 5800H (16 Threads) using a clinical dataset of 267 DICOM frames. The results highlight the massive performance overhead provided by our Rust + GPU Shader architecture.

πŸ“Š At-a-Glance Summary

Metric Performance Status
Max Throughput ~296 FPS βœ… Ultra Fast
Pipeline Latency 3.73 ms / frame βœ… Sub-16ms
Windowing Speed 3,402 Ops/s βœ… Real-time
Scrubbing Speed 323 Ops/s βœ… Fluid
Stability (p99) 6.00 ms βœ… Consistent

πŸ”¬ Detailed Deep Dive

πŸš€ 1. Raw Rendering & Latency Distribution

FFI bridge ensures that frame data flows from disk to GPU without bogging down the Dart isolate. Averaging 296.2 FPS, the engine delivers rock-solid consistency.

Latency Distribution: Out of 801 sampled frames, the mean processing time was 2.68 ms. Even the 99th percentile (p99) maxed out at just 6.00 ms, keeping us well below the 16.6ms threshold required for 60 FPS.

β–Ά LATENCY DISTRIBUTION (801 Samples)
────────────────────────────────────────────────────
  Mean Latency   : 2.68 ms
  p50 (Median)   : 2.00 ms
  p95            : 4.00 ms
  p99            : 6.00 ms  βœ… (Well below 16.6ms target)
────────────────────────────────────────────────────
  Latency Histogram (bucket=5 ms):
    0– 5 ms β”‚ β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ   766
    5–10 ms β”‚ β–ˆ                               35
   10–15 ms β”‚                                  0
   15–20 ms β”‚                                  0
   20–25 ms β”‚                                  0
────────────────────────────────────────────────────

πŸŽ›οΈ 2. Workstation-Grade Interaction

Offloading Hounsfield Unit (HU) mapping to the GPU means complex math doesn't slow down your UI.

  • Windowing Stress Test: Processed 14,685 rapid contrast adjustments in just 4.32 seconds (~3,402 ops/sec). Doctors can drag to adjust window levels as fast as humanly possible with instantaneous visual feedback.
  • Rapid Scrubbing: Simulating fast bidirectional scrolling through the 267-frame series yielded 323 operations per second.

🧽 3. Memory Safety & Full Pipeline

Testing the complete lifecycle ensures there are no memory leaks during extended diagnostic sessions.

  • Full Pipeline: Loading, parsing, rendering, windowing (x5), and disposing of all 267 files sequentially took under 1 second (996.0 ms total).
  • Controller Lifecycle: Creating, loading, and safely destroying controllers for 267 frames averaged 3.57 ms per file, proving rock-solid garbage collection and GPU texture freeing.

πŸ›‘οΈ 4. Edge-Case Resilience

Medical data can be messy. The core engine is built to handle anomalies gracefully without crashing your Flutter app.

  • Mathematical Overflow: Passing extreme windowing values (e.g., 9.0e+307 and -9.0e+307) resulted in safe handling with 0 load errors.
  • Concurrency Handling: Rapid burst loads (firing 10 file loads with minimal await gaps) maintained a 232.6 Effective FPS without race conditions.

🀝 Contributing

Contributions are welcome! Here’s how to get started:

  1. Fork the repository.
  2. Create a new branch: git checkout -b feature/YourFeature
  3. Commit your changes: git commit -m "Add amazing feature"
  4. Push to your branch: git push origin feature/YourFeature
  5. Open a pull request.

πŸ’‘ Please read our Contributing Guidelines and open an issue first for major feature ideas or changes.


πŸ“œ License

This project is licensed under the GPL-3.0 License. See the LICENSE file for full details.

Made with ❀️ by MostafaSensei106

About

An advanced medical imaging and DICOM processing library for Flutter, poIred by a high-performance Rust core and GPU Shaders.

Topics

Resources

License

Code of conduct

Contributing

Stars

Watchers

Forks

Contributors