API

Image helpers

OffscreenCanvas and ImageBitmap only — which is what lets the whole pipeline run in a worker.

import {
    createCanvas, context2d, decodeImage, toImageData, imageDataToCanvas,
    encodeImage, probeImageSize, letterbox, resize, cropGeometry, cropBox,
    toNchwFloat32, IMAGENET_MEAN, IMAGENET_STD,
} from '@stabrise/scaledp'

No DOM, anywhere

Never document.createElement, HTMLImageElement or toDataURL. That constraint is what makes every stage worker-safe, and it is enforced by the fact that the browser test suite runs stages inside a worker.

Decode, encode, measure

decodeImage(data)Promise<ImageBitmap> from bytes or a Blob
encodeImage(source, type = 'image/png', quality?)Promise<Uint8Array>
probeImageSize(data)Promise<{ width, height }> without retaining a bitmap
toImageData(source) / imageDataToCanvas(image)Between the two representations

probeImageSize is what lets DataToImage wrap a 40 MB scan for the price of a header read.

Letterboxing

interface LetterboxResult { canvas: OffscreenCanvas; scale: number; resized: Size; source: Size }

letterbox(source, { width: 1280, height: 1280 }, { padding: 'end', fill: '#ffffff' })

padding: 'end' (the default) pads bottom and right — what PaddleOCR and DBNet expect. 'center' pads evenly — what YOLO expects. Getting this wrong shifts every box by half the padding, which looks like a subtly bad model rather than a preprocessing bug.

scale is what you divide detected coordinates by to get back to the source image's space.

Cropping a box

cropBox(source, box, { scaleFactor: 1, padding: 5 })   // OffscreenCanvas
cropGeometry(box, { scaleFactor, padding })            // { scaled, width, height, map }

cropBox straightens rotated boxes with an affine transform onto the box's own axes — a port of TesseractRecognizer._prepare_box_for_ocr. cropGeometry returns the same geometry without doing the work, including a map(x, y) that takes a coordinate inside the crop back to the page. That is how TesseractRecognizer's boxLevel: 'word' returns word boxes in page space.

Tensor construction

toNchwFloat32(imageData, { mean: IMAGENET_MEAN, std: IMAGENET_STD, scale: 1 / 255, bgr: true })

scale defaults to 1 / 255. bgr: true swaps the channel order — DbnetOnnxDetector needs it, and needs it with RGB statistics, reproducing a quirk of the Python implementation that parity requires.

On this page