/** * Resize an image file while preserving aspect ratio. * * @param {File|Blob} file * @param {number} maxWidth * @param {number} maxHeight * @param {number} [quality=0.7] - JPEG/WebP quality (0–1) * @returns {Promise} * * @example * const resized = await resizeImage(file, 800, 800) */ export function resizeImage(file, maxWidth, maxHeight, quality = 0.7) { return new Promise((resolve, reject) => { if (!(file instanceof Blob)) { reject(new Error('Invalid file')) return } const reader = new FileReader() reader.onload = e => { const img = new Image() img.onload = () => { let { width, height } = img const widthRatio = maxWidth / width const heightRatio = maxHeight / height const ratio = Math.min(widthRatio, heightRatio, 1) width = Math.round(width * ratio) height = Math.round(height * ratio) const canvas = document.createElement('canvas') canvas.width = width canvas.height = height const ctx = canvas.getContext('2d') ctx.drawImage(img, 0, 0, width, height) canvas.toBlob( blob => { if (!blob) { reject(new Error('Image resize failed')) return } resolve(blob) }, file.type || 'image/jpeg', quality ) } img.onerror = () => reject(new Error('Invalid image')) img.src = e.target.result } reader.onerror = () => reject(new Error('File read error')) reader.readAsDataURL(file) }) }