Spaces:
Running
Running
| const MAX_DIMENSION = 384; | |
| /** | |
| * Resize an image to fit within MAX_DIMENSION while preserving aspect ratio. | |
| * Returns a base64 data URL. | |
| */ | |
| export function resizeImage(file: File): Promise<string> { | |
| return new Promise((resolve, reject) => { | |
| const reader = new FileReader(); | |
| reader.onload = () => { | |
| const img = new Image(); | |
| img.onload = () => { | |
| let { width, height } = img; | |
| if (width > MAX_DIMENSION || height > MAX_DIMENSION) { | |
| const scale = MAX_DIMENSION / Math.max(width, height); | |
| width = Math.round(width * scale); | |
| height = Math.round(height * scale); | |
| } | |
| const canvas = document.createElement("canvas"); | |
| canvas.width = width; | |
| canvas.height = height; | |
| const ctx = canvas.getContext("2d")!; | |
| ctx.drawImage(img, 0, 0, width, height); | |
| resolve(canvas.toDataURL("image/jpeg", 0.9)); | |
| }; | |
| img.onerror = reject; | |
| img.src = reader.result as string; | |
| }; | |
| reader.onerror = reject; | |
| reader.readAsDataURL(file); | |
| }); | |
| } | |
| /** | |
| * Load an image URL, resize to MAX_DIMENSION, return as base64 data URL. | |
| */ | |
| export async function urlToDataUrl(url: string): Promise<string> { | |
| const response = await fetch(url); | |
| if (!response.ok) throw new Error(`HTTP ${response.status} for ${url}`); | |
| const blob = await response.blob(); | |
| const file = new File([blob], "image.jpg", { type: blob.type }); | |
| return resizeImage(file); | |
| } | |
| /** | |
| * Get image dimensions from a data URL. | |
| */ | |
| export function getImageDimensions( | |
| dataUrl: string, | |
| ): Promise<{ width: number; height: number }> { | |
| return new Promise((resolve, reject) => { | |
| const img = new Image(); | |
| img.onload = () => resolve({ width: img.width, height: img.height }); | |
| img.onerror = reject; | |
| img.src = dataUrl; | |
| }); | |
| } | |