{"version":3,"file":"decode.cjs","names":[],"sources":["../../src/imaging/decode.ts"],"sourcesContent":["/**\n * Turning whatever the app has into pixels.\n *\n * A PWA receives images from a file input, a camera capture, a paste, a\n * fetch, or a canvas it drew itself. They all become an `ImageBitmap` here,\n * with the one correction that matters on phones applied: **EXIF\n * orientation**.\n *\n * A photo taken in portrait is usually stored landscape plus an orientation\n * tag. Decode it without honouring the tag and every user sees their photo\n * sideways — the single most reported bug in upload flows. `createImageBitmap`\n * accepts `imageOrientation: \"from-image\"`, and that is what this module\n * asks for.\n */\n\nimport { ImageDecodeError } from \"./exceptions\";\nimport type { DecodedImage, ImageInfo, ImageSource } from \"./types\";\n\n/**\n * Decode any supported source into a bitmap, oriented as the photographer\n * held the camera.\n *\n * @example\n * ```ts\n * const { bitmap, width, height } = await decodeImage(file);\n * ```\n *\n * @param source A `Blob`/`File`, URL string, `ImageBitmap`, `ImageData`,\n *   `HTMLImageElement`, or a canvas.\n * @returns The decoded pixels and their dimensions.\n * @throws {@link ImageDecodeError} when the bytes are not a decodable image,\n *   or the URL cannot be fetched.\n */\nexport async function decodeImage(source: ImageSource): Promise<DecodedImage> {\n    const bitmap = await toBitmap(source);\n    return { bitmap, width: bitmap.width, height: bitmap.height };\n}\n\n/**\n * Decode a source into an `ImageBitmap`.\n *\n * @param source The image source.\n * @returns The bitmap.\n * @throws {@link ImageDecodeError} when decoding fails.\n */\nasync function toBitmap(source: ImageSource): Promise<ImageBitmap> {\n    if (typeof ImageBitmap !== \"undefined\" && source instanceof ImageBitmap) {\n        return source;\n    }\n\n    if (typeof source === \"string\") {\n        let response: Response;\n        try {\n            response = await fetch(source);\n        } catch (error) {\n            throw new ImageDecodeError(`Could not fetch the image at ${source}`, {\n                cause: error,\n            });\n        }\n        if (!response.ok) {\n            throw new ImageDecodeError(\n                `Could not fetch the image at ${source}: ${response.status} ${response.statusText}`,\n            );\n        }\n        return await toBitmap(await response.blob());\n    }\n\n    try {\n        return await createImageBitmap(source as ImageBitmapSource, {\n            imageOrientation: \"from-image\",\n        });\n    } catch (error) {\n        throw new ImageDecodeError(\n            `Could not decode the image: ${error instanceof Error ? error.message : String(error)}`,\n            { cause: error },\n        );\n    }\n}\n\n/**\n * Read an image's dimensions, type and size.\n *\n * Decodes to measure, which is the only reliable way in a browser — there\n * is no header parser here, and guessing dimensions from a MIME type is not\n * a thing. Cheap enough for a preview, not for a thousand files in a loop.\n *\n * @example\n * ```ts\n * const info = await readImageInfo(file);\n * if (info.bytes > 5_000_000) {\n *     // ask before uploading\n * }\n * ```\n *\n * @param blob The image file.\n * @returns Its dimensions, MIME type, byte size and aspect ratio.\n * @throws {@link ImageDecodeError} when the blob is not a decodable image.\n */\nexport async function readImageInfo(blob: Blob): Promise<ImageInfo> {\n    const { bitmap } = await decodeImage(blob);\n    const info: ImageInfo = {\n        width: bitmap.width,\n        height: bitmap.height,\n        type: blob.type,\n        bytes: blob.size,\n        aspectRatio: bitmap.height === 0 ? 0 : bitmap.width / bitmap.height,\n    };\n    bitmap.close?.();\n    return info;\n}\n"],"mappings":"oCAiCA,eAAsB,EAAY,EAA4C,CAC1E,IAAM,EAAS,MAAM,EAAS,CAAM,EACpC,MAAO,CAAE,SAAQ,MAAO,EAAO,MAAO,OAAQ,EAAO,MAAO,CAChE,CASA,eAAe,EAAS,EAA2C,CAC/D,GAAI,OAAO,YAAgB,KAAe,aAAkB,YACxD,OAAO,EAGX,GAAI,OAAO,GAAW,SAAU,CAC5B,IAAI,EACJ,GAAI,CACA,EAAW,MAAM,MAAM,CAAM,CACjC,OAAS,EAAO,CACZ,MAAM,IAAI,EAAA,iBAAiB,gCAAgC,IAAU,CACjE,MAAO,CACX,CAAC,CACL,CACA,GAAI,CAAC,EAAS,GACV,MAAM,IAAI,EAAA,iBACN,gCAAgC,EAAO,IAAI,EAAS,OAAO,GAAG,EAAS,YAC3E,EAEJ,OAAO,MAAM,EAAS,MAAM,EAAS,KAAK,CAAC,CAC/C,CAEA,GAAI,CACA,OAAO,MAAM,kBAAkB,EAA6B,CACxD,iBAAkB,YACtB,CAAC,CACL,OAAS,EAAO,CACZ,MAAM,IAAI,EAAA,iBACN,+BAA+B,aAAiB,MAAQ,EAAM,QAAU,OAAO,CAAK,IACpF,CAAE,MAAO,CAAM,CACnB,CACJ,CACJ,CAqBA,eAAsB,EAAc,EAAgC,CAChE,GAAM,CAAE,UAAW,MAAM,EAAY,CAAI,EACnC,EAAkB,CACpB,MAAO,EAAO,MACd,OAAQ,EAAO,OACf,KAAM,EAAK,KACX,MAAO,EAAK,KACZ,YAAa,EAAO,SAAW,EAAI,EAAI,EAAO,MAAQ,EAAO,MACjE,EAEA,OADA,EAAO,QAAQ,EACR,CACX"}