Download src/lib/utils/image.ts from Fraser/piclets: direct link, hf CLI and curl.
- Browser
- Download file 1.72 kB
-
https://huggingface.co/spaces/Fraser/piclets/resolve/main/src/lib/utils/image.ts
- Command line
-
hf download hf://spaces/Fraser/piclets/src/lib/utils/image.ts
-
curl -L -o image.ts https://huggingface.co/spaces/Fraser/piclets/resolve/main/src/lib/utils/image.ts
1.72 kB
| /** | |
| * Downscale an image File to a max dimension and re-encode as JPEG. | |
| * Phone photos routinely exceed the backend's upload limit; this keeps | |
| * uploads well under it while preserving enough detail for captioning. | |
| */ | |
| export async function downscaleImage( | |
| file: File, | |
| maxDim = 1536, | |
| quality = 0.85, | |
| ): Promise<File> { | |
| const bitmap = await loadImageBitmap(file); | |
| const { width, height } = scaleDimensions(bitmap.width, bitmap.height, maxDim); | |
| const canvas = document.createElement('canvas'); | |
| canvas.width = width; | |
| canvas.height = height; | |
| const ctx = canvas.getContext('2d'); | |
| if (!ctx) throw new Error('Canvas 2D context unavailable'); | |
| ctx.drawImage(bitmap, 0, 0, width, height); | |
| const blob = await new Promise<Blob>((resolve, reject) => { | |
| canvas.toBlob( | |
| (b) => (b ? resolve(b) : reject(new Error('canvas.toBlob returned null'))), | |
| 'image/jpeg', | |
| quality, | |
| ); | |
| }); | |
| const name = file.name.replace(/\.[^.]+$/, '') + '.jpg'; | |
| return new File([blob], name, { type: 'image/jpeg' }); | |
| } | |
| function scaleDimensions(w: number, h: number, maxDim: number): { width: number; height: number } { | |
| if (w <= maxDim && h <= maxDim) return { width: w, height: h }; | |
| const ratio = w > h ? maxDim / w : maxDim / h; | |
| return { width: Math.round(w * ratio), height: Math.round(h * ratio) }; | |
| } | |
| async function loadImageBitmap(file: File): Promise<ImageBitmap | HTMLImageElement> { | |
| if ('createImageBitmap' in window) { | |
| return createImageBitmap(file); | |
| } | |
| return new Promise((resolve, reject) => { | |
| const img = new Image(); | |
| img.onload = () => resolve(img); | |
| img.onerror = () => reject(new Error('Failed to load image')); | |
| img.src = URL.createObjectURL(file); | |
| }); | |
| } | |