export type BrowserImageFile = { name: string; mimeType: string; source: string; intrinsicSize: { w: number; h: number }; release(): void; }; export async function decodeBrowserImageFile(file: File): Promise { if (!file.type.startsWith("image/")) return undefined; if (file.size > 128 * 1024 * 1024) throw new Error("Image file is too large. The import limit is 128 MB."); const objectUrl = URL.createObjectURL(file); let intrinsicSize: { w: number; h: number }; try { intrinsicSize = await loadImageSize(objectUrl); assertCanvasRasterSize(intrinsicSize.w, intrinsicSize.h, "Imported image"); } finally { URL.revokeObjectURL(objectUrl); } const source = await fileToDataUrl(file); return { name: file.name, mimeType: file.type, source, intrinsicSize, release: () => undefined }; } function fileToDataUrl(file: File): Promise { return new Promise((resolve, reject) => { const reader = new FileReader(); reader.onload = () => typeof reader.result === "string" ? resolve(reader.result) : reject(new Error("Failed to read image file")); reader.onerror = () => reject(reader.error ?? new Error("Failed to read image file")); reader.readAsDataURL(file); }); } function loadImageSize(source: string): Promise<{ w: number; h: number }> { return new Promise((resolve, reject) => { const image = new Image(); image.onload = () => resolve({ w: image.naturalWidth, h: image.naturalHeight }); image.onerror = () => reject(new Error("Failed to load image")); image.src = source; }); } import { assertCanvasRasterSize } from "./rasterLimits";