API Reference
Single class, two static convenience methods, three custom errors.
class Quadscan
import { Quadscan } from 'quadscan';
const q = new Quadscan(options?);
A Quadscan instance holds an onnxruntime-web InferenceSession. Keep one
warm for batch / real-time work; or skip the constructor entirely and use
the static Quadscan.scan / Quadscan.extract for one-offs (they share a
lazy internal singleton).
Constructor options: QuadscanOptions
| Option | Type | Default | Description |
|---|---|---|---|
model | 'lcnet' | 'fastvit' | 'lcnet' | Built-in preset. LCNet (4.5 MB) is fast and accurate; FastViT (13 MB) is more accurate on hard cases. |
modelUrl | string | resolved from model | Override the model URL entirely. Useful for self-hosting (see Self-hosting recipe). |
normalization | 'zero-one' | 'minus-one-one' | inferred from URL | Input normalization. LCNet wants zero-one, FastViT wants minus-one-one. The library guesses correctly for the bundled models; override if you bring a custom one. |
executionProviders | Array<'webgpu' | 'wasm'> | ['webgpu', 'wasm'] | ORT execution providers, tried in order. The runtime falls back to the next if a provider isn’t supported. |
wasmPaths | string | jsdelivr CDN | Where onnxruntime-web looks for its .wasm files. Override to self-host. |
Instance methods
async initialize(): Promise<void>
Eagerly download the model and create the ORT session. Optional; scan()
and extract() do this on first call. Call it during app startup if you
want to amortize the load.
async scan(input, options?): Promise<ScanResult>
Detect document corners; optionally perspective-warp.
input is one of:
| Type | Notes |
|---|---|
HTMLImageElement | Must be loaded (complete && naturalWidth > 0). |
HTMLCanvasElement | Any size. |
HTMLVideoElement | Current frame; works while playing. |
ImageBitmap | Decoded off-thread; great for workers. |
ImageData | Raw pixels. |
Blob | File | Auto-decoded via createImageBitmap. |
async extract(input, corners, options?): Promise<ScanResult>
Perspective-warp input using user-supplied corners, skipping detection.
Does not invoke the model, does not download it either. Use this when
corners come from manual UI adjustment, a prior scan, or another detector.
dispose(): void
Release the ORT session. Subsequent scan() calls re-initialize. Idempotent.
[Symbol.dispose]()
Enables using q = new Quadscan() syntax (TypeScript 5.2+).
Static methods
| Method | Notes |
|---|---|
Quadscan.scan(input, options?) | One-shot via internal singleton. |
Quadscan.extract(input, corners, options?) | One-shot warp via singleton. Does not load the model. |
Quadscan.disposeShared() | Dispose the internal singleton. Idempotent. |
ScanOptions
Per-call options for scan().
| Option | Type | Default | Description |
|---|---|---|---|
mode | 'detect' | 'extract' | 'detect' | detect returns corners only (no warp); extract also returns the warped image in output. |
output | 'canvas' | 'imagedata' | 'dataurl' | 'canvas' | Warp output format. |
maxOutputDimension | number | 2048 | Cap on the longer side of the warped output. |
minDetectionConfidence | number | 0.1 | Detection floor; if peak heatmap confidence is below this, returns { success: false }. |
signal | AbortSignal | none | Cancels scan; throws DOMException('AbortError'). |
onProgress | (e: ProgressEvent) => void | none | Lifecycle progress events (see below). |
debug | boolean | false | Populate result.debug with the raw heatmap and pre-reorder corners. |
ProgressEvent
type ProgressEvent =
| { phase: 'model-download'; loaded: number; total: number }
| { phase: 'model-compile' }
| { phase: 'preprocess' }
| { phase: 'inference' }
| { phase: 'decode' }
| { phase: 'warp' };
model-download is the only event with progress; the rest are lifecycle
markers. total may be 0 if the server didn’t send Content-Length.
ScanResult
interface ScanResult {
success: boolean;
message: string;
confidence: number | null;
output: HTMLCanvasElement | ImageData | string | null;
corners: CornerPoints | null;
timings: Timing[];
debug: DebugInfo | null;
}
| Field | When success: true | When success: false |
|---|---|---|
confidence | min of the four corner confidences (0..1) | null |
output | the warped image (mode extract) or null (mode detect) | null |
corners | TL/TR/BR/BL in source-image coords | null |
timings | per-step durations | partial (whatever ran) |
Always check result.success before reading corners or output. In
TypeScript, the result is structurally typed. Narrow with if (r.success)
and treat r.corners as non-null inside.
CornerPoints
interface CornerPoint { x: number; y: number; confidence: number }
interface CornerPoints {
topLeft: CornerPoint;
topRight: CornerPoint;
bottomRight: CornerPoint;
bottomLeft: CornerPoint;
}
Coordinates are in source-image pixels (not normalized). confidence
is the heatmap peak value at that corner.
For input to extract(), confidence is optional and defaults to 1.
Errors
All errors inherit from QuadscanError and carry a stable code:
| Class | code | Thrown when |
|---|---|---|
ModelLoadError | MODEL_LOAD_FAILED | The .onnx couldn’t be fetched, parsed, or compiled. Includes the URL and HTTP status in message; original error in cause. |
InvalidInputError | INVALID_INPUT | input is not a supported type, or corners is missing fields. |
DegenerateQuadError | DEGENERATE_QUAD | The four corners can’t form a convex quad (e.g. > 45° rotation, collinear points). Rare. |
import { Quadscan, ModelLoadError } from 'quadscan';
try {
await Quadscan.scan(file);
} catch (err) {
if (err instanceof ModelLoadError) {
console.error('Model fetch failed:', err.message, err.cause);
} else throw err;
}
Failed detection (the model ran but found no document) is not an error.
It comes back as { success: false, message } in the ScanResult.
Exports
export { Quadscan } from 'quadscan';
export {
QuadscanError, ModelLoadError, InvalidInputError, DegenerateQuadError,
} from 'quadscan';
export type {
ScanResult, ScanOptions, ScanInput, ScanMode, OutputFormat,
CornerPoint, CornerPoints, CornerPointInput, CornerPointsInput,
QuadscanOptions, ModelPreset, ExecutionProvider, Normalization,
ProgressEvent, Timing, DebugInfo,
} from 'quadscan';