scanic
v1.6.0
Published
Modern document scanner in pure JavaScript and Wasm
Maintainers
Readme
Scanic
Ultra-fast, production-ready document scanning for the modern Web.
Scanic is a high-performance document scanner library that brings professional-grade document edge detection and perspective correction to the browser and Node.js. By combining Rust-powered WebAssembly for pixel crunching and a fast bilinear inverse-map warp for image extraction, Scanic delivers near-native performance (~10ms transforms) with a tiny footprint.
Documentation | Live Demo | Framework Examples | API Reference
🚀 Why Scanic?
Traditional web scanning solutions often force a trade-off:
- OpenCV.js: Powerful, but requires a massive 30MB+ download.
- Pure JS: Lightweight, but struggles with real-time performance and complex transforms.
Scanic bridges this gap:
- Hybrid Engine: Rust/WASM handles the CPU-heavy edge detection.
- Turbo Warp: A per-pixel bilinear inverse-map does perspective correction with no Canvas state-machine overhead or seam artifacts.
- Zero Latency: Designed for real-time applications like webcam scanning.
✨ Features
- 🎯 Pinpoint Accuracy: Robust document contour detection even in low-contrast environments.
- ⚡ Turbocharged Warp: Perspective transforms in < 10ms (vs 500ms+ in standard loops).
- 🦀 WASM Core: High-performance Gaussian Blur, Canny Edge Detection, and Dilation.
- 🛠️ Modern API: Clean, Promise-based API with full TypeScript support.
- 📦 Featherweight: Under 100KB total size (gzipped).
- 🤖 Optional ML detector: switch to a neural corner detector for hard photos with
detector: 'ml'. It is lazy loaded, needs no extra install, and uses a custom minimal ONNX Runtime build of about 1.5 MB instead of the usual 13 MB. See the ML detection guide. - 🧪 Production Grade: Built-in regression tests with physical image baselines.
🆕 What's New
See the full documentation, the changelog, and the releases for the latest. Recent highlights:
- Optional ML detector: a neural corner detector (
detector: 'ml') for hard photos such as cluttered backgrounds, low contrast, or strong perspective. Lazy loaded and opt in. See the ML detection guide. - Styleable corner editor: a built-in, touch friendly UI to fine tune detected corners, now fully themeable via CSS variables with a polished default toolbar. See the corner editor guide.
- New docs site with guides for Web/Node.js/Electron/React/Vue and an interactive in-browser playground.
🛠️ Installation
# via npm
npm install scanic
# via yarn
yarn add scanicCDN
<script src="https://unpkg.com/scanic/dist/scanic.js"></script>🎮 Demo
Try the interactive scanner in your browser: 👉 Open Scanic Live Demo
📖 Usage
Simple Usage
import { scanDocument, extractDocument } from 'scanic';
// Simple usage - just detect document
const result = await scanDocument(imageElement);
if (result.success) {
console.log('Document found at corners:', result.corners);
}
// Extract the document (with perspective correction)
const extracted = await scanDocument(imageElement, { mode: 'extract' });
if (extracted.success) {
document.body.appendChild(extracted.output); // Display extracted document
}ML detection (optional)
On harder photos you can switch to a neural detector that is more robust. It is
opt in per call with detector: 'ml', and it needs no extra install:
npm install scanicimport { scanDocument } from 'scanic';
const result = await scanDocument(imageElement, { detector: 'ml' });
if (result.success) {
console.log(result.corners);
console.log(result.score); // P(document present), 0 to 1
}The ONNX Runtime JavaScript API is bundled as a lazy chunk (about 50 KB, roughly
15 KB gzipped) that loads only when you use detector: 'ml'. On that first call
scanic fetches about 2 MB from a CDN (the companion
scanic-ml package): a 1.9 MB model
plus a custom minimal ONNX Runtime build of about 1.5 MB, which is roughly 88
percent smaller than the stock 13 MB runtime while running at the same speed. See
the ML detection guide
for options, self hosting, and threading.
Manual corner adjustment UI
Use the built-in corner editor to let users drag corners on mobile and desktop, then pass the confirmed corners into extraction.
import { createCornerEditor, extractDocument } from 'scanic';
const editor = createCornerEditor({
container: document.getElementById('editorHost'),
image: imageElement,
corners: detectedCorners, // optional: defaults to an inset quad
magnifier: {
zoom: 2,
size: 110
},
nudges: {
enabled: true,
steps: [1, 5]
},
onConfirm: async (corners) => {
const extracted = await extractDocument(imageElement, corners, { output: 'canvas' });
document.getElementById('output').appendChild(extracted.output);
editor.destroy();
}
});Optimized Usage (Recommended for Batch/Real-time)
The Scanner class maintains a persistent WebAssembly instance, avoiding the overhead of re-initializing WASM for every scan.
import { Scanner } from 'scanic';
const scanner = new Scanner();
// Initialize once (optional, scan() will initialize if needed)
await scanner.initialize();
// Scan multiple images efficiently
async function onFrame(img) {
const result = await scanner.scan(img, { mode: 'extract' });
if (result.success) {
// Process result...
}
}Examples
const options = {
mode: 'extract',
maxProcessingDimension: 1000, // Higher quality, slower processing
lowThreshold: 50, // More sensitive edge detection
highThreshold: 150,
dilationKernelSize: 5, // Larger dilation kernel
minArea: 2000, // Larger minimum document area
debug: true // Enable debug information
};
const result = await scanDocument(imageElement, options);Different Modes and Output Formats
// Just detect (no image processing)
const detection = await scanDocument(imageElement, { mode: 'detect' });
// Extract as canvas
const extracted = await scanDocument(imageElement, {
mode: 'extract',
output: 'canvas'
});
// Extract as ImageData
const rawData = await scanDocument(imageElement, {
mode: 'extract',
output: 'imagedata'
});
// Extract as DataURI
const rawData = await scanDocument(imageElement, {
mode: 'extract',
output: 'dataurl'
});
🛠️ Development
Clone the repository and set up the development environment:
git clone https://github.com/marquaye/scanic.git
cd scanic
npm installStart the development server:
npm run devBuild for production:
npm run buildThe built files will be available in the dist/ directory.
Building the WebAssembly Module
The Rust WASM module is pre-compiled and included in the repository. If you need to rebuild it:
npm run build:wasmThis uses Docker to build the WASM module without requiring local Rust installation.
Testing
Scanic uses Vitest for unit and regression testing. We test against real document images to ensure detection accuracy remains consistent.
npm testThe regression suite covers both the classical detector and the optional ML detector
(src/baseline.test.js and src/baseline.ml.test.js), each checked against its own
golden baseline in testImages/:
npm run baseline:check # classical detector vs testImages/baseline-results.json
npm run baseline:check:ml # ML detector vs testImages/baseline-results.ml.json
npm run baseline:update # regenerate the classical baseline
npm run baseline:update:ml # regenerate the ML baselineThe ML baseline test skips automatically when onnxruntime-web or the scanic-ml
model assets aren't available locally.
📊 Comparison
| Feature | Scanic | jscanify | OpenCV.js | | :--- | :--- | :--- | :--- | | Download Size | ~100KB | ~31MB | ~30MB | | Perspective Speed | ~10ms | ~200ms | ~5ms | | WASM Optimized | ✅ Yes | ❌ No | ✅ Yes | | GPU Acceleration | ✅ Yes | ❌ No | ❌ No | | TypeScript | ✅ Yes | ❌ No | ✅ Yes |
🤝 Contributing
Contributions are welcome! Whether it's reporting a bug, suggesting a feature, or submitting a pull request, your help is appreciated.
- Report Issues: Use the GitHub Issue tracker.
- Pull Requests:
- Fork the repository.
- Create a feature branch.
- Commit your changes.
- Open a Pull Request.
📜 Credits
- Inspired by jscanify.
- WASM Blur module powered by Rust.
- The optional ML corner detector's architecture is DocCornerNet (MIT licensed) by mapo80, based on SimCC (Li et al., ECCV 2022). See the ML detection guide for how it's trained, slimmed, and deployed in scanic.
💖 Sponsors
🏆 Gold Sponsors
🗺️ Roadmap
See ROADMAP.md for what's shipped and what's planned.
License
MIT License © marquaye
