Gitea Actions / Deploy (push) Successful in 29s
sessions fix password change sign-in fix
30 lines
1.1 KiB
TypeScript
30 lines
1.1 KiB
TypeScript
/**
|
|
* Shrinks an image so its longest side is at most `maxSize` px before upload.
|
|
* GIFs are kept as is (canvas would drop the animation), as are images the
|
|
* browser cannot decode — the server decides what to do with those.
|
|
*/
|
|
export async function resizeImage(file: File, maxSize: number): Promise<File> {
|
|
if (file.type === 'image/gif') return file
|
|
|
|
let bitmap: ImageBitmap
|
|
try {
|
|
bitmap = await createImageBitmap(file)
|
|
} catch {
|
|
return file
|
|
}
|
|
|
|
const scale = Math.min(1, maxSize / Math.max(bitmap.width, bitmap.height))
|
|
const canvas = document.createElement('canvas')
|
|
canvas.width = Math.round(bitmap.width * scale)
|
|
canvas.height = Math.round(bitmap.height * scale)
|
|
canvas.getContext('2d')?.drawImage(bitmap, 0, 0, canvas.width, canvas.height)
|
|
bitmap.close()
|
|
|
|
// Browsers without WebP encoding (Safari) fall back to PNG
|
|
const blob = await new Promise<Blob | null>((resolve) => canvas.toBlob(resolve, 'image/webp', 0.9))
|
|
if (!blob || blob.size >= file.size) return file
|
|
|
|
const ext = blob.type === 'image/webp' ? 'webp' : 'png'
|
|
return new File([blob], `${file.name.replace(/\.[^.]+$/, '')}.${ext}`, { type: blob.type })
|
|
}
|