import { HttpError } from "@/lib/security/http"; import { hasValidImageSignature, MAX_MEDIA_BYTES, type IMAGE_MIME_TYPES } from "./validation"; export const MAX_IMAGE_PIXELS = 40_000_000; export async function inspectImage(bytes: Uint8Array, mimeType: (typeof IMAGE_MIME_TYPES)[number]) { if (bytes.byteLength > MAX_MEDIA_BYTES) throw new HttpError(413, "image-too-large"); if (!hasValidImageSignature(bytes.subarray(0, 16), mimeType)) throw new HttpError(422, "invalid-image"); try { const image = new Bun.Image(bytes, { maxPixels: MAX_IMAGE_PIXELS }); const metadata = await image.metadata(); const { width, height } = metadata; if (!width || !height || width * height > MAX_IMAGE_PIXELS) throw new Error("invalid dimensions"); // Metadata alone accepts truncated images; decode pixels before publishing. await image.bytes(); return { width, height }; } catch { throw new HttpError(422, "invalid-image"); } }