/**
* Decode an animated image (GIF / APNG / animated WebP / animated AVIF) into
* a list of frames with cumulative timing using the browser's ImageDecoder
* API. Used by the server-side export pipeline so that animated
elements
* can be rendered frame-accurately under our virtual clock — native
* playback ignores virtual time, so without this every captured frame would
* show the GIF stuck at frame 0.
*
* Live `/present` keeps using
directly; only the export pipeline opts
* into the canvas-from-decoded-frames path.
*/
export interface DecodedFrame {
bitmap: ImageBitmap;
/** Frame display duration in ms. */
durationMs: number;
}
export interface DecodedAnimatedImage {
frames: DecodedFrame[];
totalMs: number;
width: number;
height: number;
}
/** True if the URL/data-URL looks like an animated container we can decode.
* We don't try to detect "animated PNG" vs "static PNG" upfront — the decoder
* call below will return one frame for static images and that's fine. */
export declare function isLikelyAnimated(src: string): boolean;
/** Decode every frame of an animated image. Falls back to a single-frame
* result for static images. Returns null when ImageDecoder is unavailable
* (e.g. older browsers) so callers can degrade gracefully. */
export declare function decodeAnimatedImage(src: string): Promise;
/** Pick the frame that should be visible at `elapsedMs` for a looping animation
* of total `totalMs`. Returns the index. */
export declare function frameIndexAt(decoded: DecodedAnimatedImage, elapsedMs: number): number;
/** Draw the frame visible at `elapsedMs` into the given canvas. */
export declare function drawFrameAt(canvas: HTMLCanvasElement, decoded: DecodedAnimatedImage, elapsedMs: number): void;