{"version":3,"file":"pipeline.cjs","names":[],"sources":["../../../src/vision/preprocess/pipeline.ts"],"sourcesContent":["/** @generated Vendored from @mauriciobenjamin700/ort-vision-sdk-web. Do not hand-edit — regenerate with `npm run vendor:vision`. */\n/**\n * Fused letterbox → CHW float32 pipeline with reusable buffers.\n *\n * The composable primitives in {@link ./image.js} each allocate and each walk\n * their input end to end, which is the right shape for a library but the wrong\n * shape for a video loop. Chaining them costs eleven full-buffer passes and six\n * large allocations per frame:\n *\n * `getImageData` → RGBA→RGB → RGB→RGBA → `putImageData` → `drawImage` →\n * `getImageData` → RGBA→RGB → fill → row copies → `toFloat32` → `toCHW`.\n *\n * This module collapses the second half of that into two: one `drawImage` that\n * resizes *and* positions the content inside the padded target in a single\n * accelerated operation, and one loop that reads the resulting RGBA and writes\n * planar float32 directly. The intermediate `RGBImage` at target size, the fill\n * loop, the row copies and the two 4.9 MB `Float32Array` allocations all go\n * away.\n *\n * The primitives stay exactly as they are — they are public API and they are\n * what makes a custom pipeline writable. This is the fast path the built-in\n * tasks take.\n */\n\nimport {\n    createCanvas,\n    get2DContext,\n    rgbToImageData,\n    type Canvas2D,\n    type Context2D,\n} from \"../core/canvas\";\nimport type { RGBImage } from \"../types\";\n\nconst INV_255 = 1 / 255;\n\n/** One claim on a {@link ReusableBuffer}. */\ninterface BufferClaim {\n    /** The buffer to write into, always `size` long. */\n    readonly data: Float32Array;\n    /** Whether {@link data} is the held buffer rather than a fresh allocation. */\n    readonly reused: boolean;\n}\n\n/**\n * A `Float32Array` held across calls, handed out one claim at a time.\n *\n * Both pipelines want the same thing — allocate once, write into it every frame,\n * and fall back to a fresh array when a previous result has not been released\n * yet — so the bookkeeping lives here instead of twice.\n *\n * The part that is not obvious is {@link claim} re-allocating a buffer that is\n * *detached*. `ort.env.wasm.proxy` runs ONNX Runtime in a worker and posts the\n * input tensors with their `ArrayBuffer`s in the transfer list, which detaches\n * them on this side. A detached `Float32Array` is silently 0 long: writing to it\n * is a no-op, and the next `InferenceSession.run` rejects with\n * `Tensor's size(N) does not match data length(0)` on every other call — once for\n * the detached buffer, then the throw leaves the claim outstanding so the call\n * after it allocates and succeeds. Treating a buffer that changed length as spent\n * turns that into one extra allocation per transfer, which is what reuse was\n * avoiding, and keeps it correct for any consumer that transfers the tensor\n * rather than copying it.\n */\nclass ReusableBuffer {\n    private readonly _size: number;\n    private _buffer: Float32Array;\n    private _inUse = false;\n\n    /** @param size Length in floats of every buffer this hands out. */\n    constructor(size: number) {\n        this._size = size;\n        this._buffer = new Float32Array(size);\n    }\n\n    /**\n     * Take the held buffer, or a fresh one when it is unavailable.\n     *\n     * Unavailable means either still checked out by an unreleased claim, or\n     * detached by whoever it was handed to. The first case allocates for this call\n     * only; the second replaces the held buffer, so the allocation is paid once per\n     * transfer rather than on every call after it.\n     */\n    claim(): BufferClaim {\n        if (this._inUse) return { data: new Float32Array(this._size), reused: false };\n        if (this._buffer.length !== this._size) this._buffer = new Float32Array(this._size);\n        this._inUse = true;\n        return { data: this._buffer, reused: true };\n    }\n\n    /** Mark the held buffer free for the next {@link claim}. */\n    release(): void {\n        this._inUse = false;\n    }\n}\n\n/** Geometry of a letterbox, plus the planar tensor data it produced. */\nexport interface FusedLetterboxResult {\n    /** CHW float32 in `[0, 1]`, length `3 * targetHeight * targetWidth`. */\n    readonly data: Float32Array;\n    /** Factor applied to the original image (`< 1` if downscaled). */\n    readonly scale: number;\n    /** Horizontal padding in pixels. */\n    readonly padLeft: number;\n    /** Vertical padding in pixels. */\n    readonly padTop: number;\n    /**\n     * Whether {@link data} is the pipeline's reusable buffer.\n     *\n     * `true` means the next {@link LetterboxPipeline.run} overwrites it, so a\n     * caller keeping the values past its own inference has to copy them.\n     */\n    readonly reused: boolean;\n}\n\n/**\n * Reusable letterbox → tensor pipeline for one target resolution.\n *\n * Holds a target canvas and an output buffer across calls, so a steady stream\n * of frames at the same size allocates nothing. Create one per task, not per\n * frame.\n */\nexport class LetterboxPipeline {\n    private readonly _targetWidth: number;\n    private readonly _targetHeight: number;\n    private readonly _fill: readonly [number, number, number];\n    private readonly _target: Canvas2D;\n    private readonly _targetContext: Context2D;\n    private readonly _buffer: ReusableBuffer;\n    private _source: Canvas2D | null = null;\n    private _sourceContext: Context2D | null = null;\n\n    /**\n     * @param targetWidth Model input width in pixels.\n     * @param targetHeight Model input height in pixels.\n     * @param fill RGB padding colour; defaults to YOLO grey.\n     */\n    constructor(\n        targetWidth: number,\n        targetHeight: number,\n        fill: readonly [number, number, number] = [114, 114, 114],\n    ) {\n        if (targetWidth <= 0 || targetHeight <= 0) {\n            throw new Error(`Invalid letterbox target ${targetWidth}x${targetHeight}.`);\n        }\n        this._targetWidth = targetWidth;\n        this._targetHeight = targetHeight;\n        this._fill = fill;\n        this._target = createCanvas(targetWidth, targetHeight);\n        this._targetContext = get2DContext(this._target, { willReadFrequently: true });\n        this._targetContext.imageSmoothingEnabled = true;\n        this._targetContext.imageSmoothingQuality = \"high\";\n        this._buffer = new ReusableBuffer(3 * targetHeight * targetWidth);\n    }\n\n    /** The `[width, height]` this pipeline letterboxes into. */\n    get targetSize(): readonly [number, number] {\n        return [this._targetWidth, this._targetHeight];\n    }\n\n    /**\n     * Letterbox an image and write it as planar float32.\n     *\n     * The returned buffer is reused between calls unless a previous result is\n     * still checked out — {@link release} marks it free again. A second `run`\n     * before the first is released allocates a fresh buffer rather than\n     * corrupting it, so concurrent `predict()` calls on one task stay correct at\n     * the cost of the allocation they were trying to avoid. A buffer that was\n     * detached by a consumer that transferred it is replaced rather than written\n     * into — see {@link ReusableBuffer}.\n     *\n     * @param image Source image in the SDK's canonical HWC RGB layout.\n     */\n    run(image: RGBImage): FusedLetterboxResult {\n        const targetWidth = this._targetWidth;\n        const targetHeight = this._targetHeight;\n        const scale = Math.min(targetWidth / image.width, targetHeight / image.height);\n        const scaledWidth = Math.round(image.width * scale);\n        const scaledHeight = Math.round(image.height * scale);\n        const padLeft = Math.floor((targetWidth - scaledWidth) / 2);\n        const padTop = Math.floor((targetHeight - scaledHeight) / 2);\n\n        const source = this._ensureSource(image.width, image.height);\n        source.putImageData(rgbToImageData(image), 0, 0);\n\n        const context = this._targetContext;\n        if (\n            padLeft > 0 ||\n            padTop > 0 ||\n            scaledWidth !== targetWidth ||\n            scaledHeight !== targetHeight\n        ) {\n            context.fillStyle = `rgb(${this._fill[0]},${this._fill[1]},${this._fill[2]})`;\n            context.fillRect(0, 0, targetWidth, targetHeight);\n        }\n        context.drawImage(\n            this._source as CanvasImageSource,\n            0,\n            0,\n            image.width,\n            image.height,\n            padLeft,\n            padTop,\n            scaledWidth,\n            scaledHeight,\n        );\n\n        const rgba = context.getImageData(0, 0, targetWidth, targetHeight).data;\n        const { data, reused } = this._buffer.claim();\n\n        const plane = targetWidth * targetHeight;\n        for (let pixel = 0, offset = 0; pixel < plane; pixel++, offset += 4) {\n            data[pixel] = (rgba[offset] as number) * INV_255;\n            data[plane + pixel] = (rgba[offset + 1] as number) * INV_255;\n            data[2 * plane + pixel] = (rgba[offset + 2] as number) * INV_255;\n        }\n\n        return { data, scale, padLeft, padTop, reused };\n    }\n\n    /**\n     * Mark the reusable buffer free again.\n     *\n     * Call it once the tensor built from a {@link run} result has been handed to\n     * ONNX Runtime and the run has resolved — after that the values are inside\n     * the WASM heap and the buffer can be overwritten.\n     */\n    release(): void {\n        this._buffer.release();\n    }\n\n    /**\n     * Grow the scratch source canvas to fit an image, reusing it when possible.\n     *\n     * A canvas is only reallocated when a frame arrives at a different size than\n     * the last one, which for a camera or video source is never after the first.\n     *\n     * @param width Source width in pixels.\n     * @param height Source height in pixels.\n     */\n    private _ensureSource(width: number, height: number): Context2D {\n        if (\n            this._source === null ||\n            this._source.width !== width ||\n            this._source.height !== height\n        ) {\n            this._source = createCanvas(width, height);\n            this._sourceContext = get2DContext(this._source);\n        }\n        return this._sourceContext as Context2D;\n    }\n}\n\n/**\n * Write an RGBA buffer as normalized planar float32.\n *\n * Shared by {@link ResizePipeline} and exported for a custom pipeline that\n * already holds pixels and wants the SDK's exact arithmetic.\n *\n * The expression is `(value / 255 - mean) / std`, evaluated in that order on\n * purpose: folding it into a single multiply-add (`value * k + b`) computes the\n * same quantity but rounds differently, and the tasks' output is asserted to be\n * bit-identical to the composable `normalize` → `toCHW` path.\n *\n * @param rgba Source pixels, 4 bytes per pixel, `width * height` long.\n * @param width Image width in pixels.\n * @param height Image height in pixels.\n * @param mean Per-channel RGB mean, already in `[0, 1]`.\n * @param std Per-channel RGB standard deviation.\n * @param out Destination buffer, `3 * width * height` long.\n * @param stride Bytes per source pixel: 4 for canvas RGBA, 3 for packed RGB.\n */\nexport function writePlanarFloat32(\n    rgba: Uint8ClampedArray | Uint8Array,\n    width: number,\n    height: number,\n    mean: readonly [number, number, number],\n    std: readonly [number, number, number],\n    out: Float32Array,\n    stride: number = 4,\n): void {\n    const plane = width * height;\n    const m0 = mean[0];\n    const m1 = mean[1];\n    const m2 = mean[2];\n    const s0 = std[0];\n    const s1 = std[1];\n    const s2 = std[2];\n    for (let pixel = 0, offset = 0; pixel < plane; pixel++, offset += stride) {\n        out[pixel] = ((rgba[offset] as number) * INV_255 - m0) / s0;\n        out[plane + pixel] = ((rgba[offset + 1] as number) * INV_255 - m1) / s1;\n        out[2 * plane + pixel] = ((rgba[offset + 2] as number) * INV_255 - m2) / s2;\n    }\n}\n\n/** Planar tensor data produced by {@link ResizePipeline}. */\nexport interface FusedResizeResult {\n    /** CHW float32, normalized, length `3 * targetHeight * targetWidth`. */\n    readonly data: Float32Array;\n    /**\n     * Whether {@link data} is the pipeline's reusable buffer.\n     *\n     * `true` means the next {@link ResizePipeline.run} overwrites it, so a caller\n     * keeping the values past its own inference has to copy them.\n     */\n    readonly reused: boolean;\n}\n\n/**\n * Reusable stretch-resize → normalized tensor pipeline for one target size.\n *\n * The classification counterpart of {@link LetterboxPipeline}. A classifier\n * stretches to the model's square input instead of letterboxing into it — no\n * padding, no scale to invert later, because nothing is mapped back onto the\n * source image afterwards. That difference is why it cannot simply reuse the\n * letterbox path.\n *\n * What it does share is the technique. The composable route\n * (`resize` → `normalize` → `toCHW`) allocates an `RGBImage` and two\n * `Float32Array`s and walks each end to end on every call: about 1.4 MB of\n * fresh garbage per 224×224 `predict()`, produced at the exact moment a phone\n * near its memory ceiling can least afford it. Here one `drawImage` resizes,\n * and one loop reads the resulting RGBA and writes normalized planar float32\n * into a buffer held across calls.\n *\n * Create one per task, not per frame.\n */\nexport class ResizePipeline {\n    private readonly _targetWidth: number;\n    private readonly _targetHeight: number;\n    private readonly _mean: readonly [number, number, number];\n    private readonly _std: readonly [number, number, number];\n    private readonly _buffer: ReusableBuffer;\n    private _target: Canvas2D | null = null;\n    private _targetContext: Context2D | null = null;\n    private _source: Canvas2D | null = null;\n    private _sourceContext: Context2D | null = null;\n\n    /**\n     * @param targetWidth Model input width in pixels.\n     * @param targetHeight Model input height in pixels.\n     * @param mean Per-channel RGB mean in `[0, 1]`. Defaults to no shift.\n     * @param std Per-channel RGB standard deviation. Defaults to no scaling.\n     */\n    constructor(\n        targetWidth: number,\n        targetHeight: number,\n        mean: readonly [number, number, number] = [0, 0, 0],\n        std: readonly [number, number, number] = [1, 1, 1],\n    ) {\n        if (targetWidth <= 0 || targetHeight <= 0) {\n            throw new Error(`Invalid resize target ${targetWidth}x${targetHeight}.`);\n        }\n        this._targetWidth = targetWidth;\n        this._targetHeight = targetHeight;\n        this._mean = mean;\n        this._std = std;\n        this._buffer = new ReusableBuffer(3 * targetHeight * targetWidth);\n    }\n\n    /** The `[width, height]` this pipeline resizes into. */\n    get targetSize(): readonly [number, number] {\n        return [this._targetWidth, this._targetHeight];\n    }\n\n    /**\n     * Resize an image to the target size and write it as normalized planar float32.\n     *\n     * An image that already arrives at the target size skips the canvas entirely\n     * and is read straight out of its packed RGB — which is both faster and what\n     * keeps the result identical to `resize()`, whose own fast path returns the\n     * input untouched.\n     *\n     * Buffer reuse follows {@link ReusableBuffer}: held across calls, replaced when\n     * a consumer detached it by transferring the tensor.\n     *\n     * @param image Source image in the SDK's canonical HWC RGB layout.\n     */\n    run(image: RGBImage): FusedResizeResult {\n        const targetWidth = this._targetWidth;\n        const targetHeight = this._targetHeight;\n        const { data, reused } = this._buffer.claim();\n\n        if (image.width === targetWidth && image.height === targetHeight) {\n            writePlanarFloat32(\n                image.data,\n                targetWidth,\n                targetHeight,\n                this._mean,\n                this._std,\n                data,\n                3,\n            );\n            return { data, reused };\n        }\n\n        const source = this._ensureSource(image.width, image.height);\n        source.putImageData(rgbToImageData(image), 0, 0);\n\n        const context = this._ensureTarget();\n        context.drawImage(this._source as CanvasImageSource, 0, 0, targetWidth, targetHeight);\n\n        const rgba = context.getImageData(0, 0, targetWidth, targetHeight).data;\n        writePlanarFloat32(rgba, targetWidth, targetHeight, this._mean, this._std, data);\n        return { data, reused };\n    }\n\n    /**\n     * Mark the reusable buffer free again.\n     *\n     * Call it once the tensor built from a {@link run} result has been handed to\n     * ONNX Runtime and the run has resolved — after that the values are inside\n     * the WASM heap and the buffer can be overwritten.\n     */\n    release(): void {\n        this._buffer.release();\n    }\n\n    /**\n     * Build the target canvas on first use.\n     *\n     * Lazily, so a pipeline constructed where no canvas implementation exists\n     * (a Node test, a worker without OffscreenCanvas) only fails if it is asked\n     * to resize something.\n     */\n    private _ensureTarget(): Context2D {\n        if (this._target === null) {\n            this._target = createCanvas(this._targetWidth, this._targetHeight);\n            this._targetContext = get2DContext(this._target, { willReadFrequently: true });\n            this._targetContext.imageSmoothingEnabled = true;\n            this._targetContext.imageSmoothingQuality = \"high\";\n        }\n        return this._targetContext as Context2D;\n    }\n\n    /** Grow the scratch source canvas to fit an image, reusing it when possible. */\n    private _ensureSource(width: number, height: number): Context2D {\n        if (\n            this._source === null ||\n            this._source.width !== width ||\n            this._source.height !== height\n        ) {\n            this._source = createCanvas(width, height);\n            this._sourceContext = get2DContext(this._source);\n        }\n        return this._sourceContext as Context2D;\n    }\n}\n\n/**\n * Resize an image into normalized planar float32 without keeping any state.\n *\n * The allocation-free path is {@link ResizePipeline}; this is the one-shot\n * form, for a caller who wants the fused behaviour without owning a pipeline.\n *\n * @param image Source image in the SDK's canonical HWC RGB layout.\n * @param targetWidth Model input width in pixels.\n * @param targetHeight Model input height in pixels.\n * @param mean Per-channel RGB mean in `[0, 1]`. Defaults to no shift.\n * @param std Per-channel RGB standard deviation. Defaults to no scaling.\n */\nexport function resizeToTensorData(\n    image: RGBImage,\n    targetWidth: number,\n    targetHeight: number,\n    mean: readonly [number, number, number] = [0, 0, 0],\n    std: readonly [number, number, number] = [1, 1, 1],\n): FusedResizeResult {\n    return new ResizePipeline(targetWidth, targetHeight, mean, std).run(image);\n}\n\n/**\n * Build a zero-filled CHW tensor payload for a warm-up run.\n *\n * @param width Model input width in pixels.\n * @param height Model input height in pixels.\n */\nexport function zeroTensorData(width: number, height: number): Float32Array {\n    return new Float32Array(3 * height * width);\n}\n\n/**\n * Letterbox an image into planar float32 without keeping any state.\n *\n * The allocation-free path is {@link LetterboxPipeline}; this is the one-shot\n * form, for a caller who wants the fused behaviour without owning a pipeline.\n *\n * @param image Source image in the SDK's canonical HWC RGB layout.\n * @param targetWidth Model input width in pixels.\n * @param targetHeight Model input height in pixels.\n * @param fill RGB padding colour; defaults to YOLO grey.\n */\nexport function letterboxToTensorData(\n    image: RGBImage,\n    targetWidth: number,\n    targetHeight: number,\n    fill: readonly [number, number, number] = [114, 114, 114],\n): FusedLetterboxResult {\n    return new LetterboxPipeline(targetWidth, targetHeight, fill).run(image);\n}\n"],"mappings":"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"}