{"version":3,"file":"thumbnails.cjs","names":[],"sources":["../../src/imaging/thumbnails.ts"],"sourcesContent":["/**\n * Producing several sizes from one decode.\n *\n * A gallery needs a grid thumbnail, a list avatar and a detail view. Doing\n * that with three `resizeImage` calls decodes the same photo three times,\n * which on a 12-megapixel picture is most of the cost — the decode dominates,\n * not the scaling.\n */\n\nimport { createSurface, drawScaled } from \"./canvas\";\nimport { decodeImage } from \"./decode\";\nimport { encodeImage } from \"./encode\";\nimport type { EncodeOptions, ImageSource, ProcessedImage } from \"./types\";\n\n/** One requested size. */\nexport interface ThumbnailSpec {\n    /** Name to find it by in the result. */\n    readonly name: string;\n    /** Longest edge in pixels. */\n    readonly size: number;\n    /** Format and quality, overriding the shared options. */\n    readonly encode?: EncodeOptions;\n}\n\n/** A produced thumbnail. */\nexport interface Thumbnail extends ProcessedImage {\n    readonly name: string;\n}\n\n/**\n * Produce several sizes from a single decode.\n *\n * @example\n * ```ts\n * const [thumb, card] = await createThumbnails(file, [\n *     { name: \"thumb\", size: 96 },\n *     { name: \"card\", size: 480 },\n * ]);\n * ```\n *\n * Sizes are the **longest edge**, and the aspect ratio is kept, so a\n * portrait and a landscape photo both fit the same grid cell without a\n * separate calculation per orientation.\n *\n * @param source Anything decodable.\n * @param specs The sizes to produce.\n * @param options Shared format and quality.\n * @returns One result per spec, in the order requested.\n * @throws {@link ImageDecodeError} when the source cannot be decoded.\n */\nexport async function createThumbnails(\n    source: ImageSource,\n    specs: readonly ThumbnailSpec[],\n    options: EncodeOptions = {},\n): Promise<Thumbnail[]> {\n    const { bitmap } = await decodeImage(source);\n    try {\n        const results: Thumbnail[] = [];\n        for (const spec of specs) {\n            const scale = Math.min(1, spec.size / Math.max(bitmap.width, bitmap.height));\n            const width = Math.max(1, Math.round(bitmap.width * scale));\n            const height = Math.max(1, Math.round(bitmap.height * scale));\n\n            const surface = createSurface(width, height);\n            drawScaled(bitmap, surface, { x: 0, y: 0, width, height });\n            const encoded = await encodeImage(surface, { ...options, ...spec.encode });\n            results.push({ ...encoded, name: spec.name });\n        }\n        return results;\n    } finally {\n        bitmap.close?.();\n    }\n}\n"],"mappings":"oFAkDA,eAAsB,EAClB,EACA,EACA,EAAyB,CAAC,EACN,CACpB,GAAM,CAAE,UAAW,MAAM,EAAA,YAAY,CAAM,EAC3C,GAAI,CACA,IAAM,EAAuB,CAAC,EAC9B,IAAK,IAAM,KAAQ,EAAO,CACtB,IAAM,EAAQ,KAAK,IAAI,EAAG,EAAK,KAAO,KAAK,IAAI,EAAO,MAAO,EAAO,MAAM,CAAC,EACrE,EAAQ,KAAK,IAAI,EAAG,KAAK,MAAM,EAAO,MAAQ,CAAK,CAAC,EACpD,EAAS,KAAK,IAAI,EAAG,KAAK,MAAM,EAAO,OAAS,CAAK,CAAC,EAEtD,EAAU,EAAA,cAAc,EAAO,CAAM,EAC3C,EAAA,WAAW,EAAQ,EAAS,CAAE,EAAG,EAAG,EAAG,EAAG,QAAO,QAAO,CAAC,EACzD,IAAM,EAAU,MAAM,EAAA,YAAY,EAAS,CAAE,GAAG,EAAS,GAAG,EAAK,MAAO,CAAC,EACzE,EAAQ,KAAK,CAAE,GAAG,EAAS,KAAM,EAAK,IAAK,CAAC,CAChD,CACA,OAAO,CACX,QAAU,CACN,EAAO,QAAQ,CACnB,CACJ"}