diff --git a/src/lib/client/heicConverter.ts b/src/lib/client/heicConverter.ts index 5fc04f5..6c65414 100644 --- a/src/lib/client/heicConverter.ts +++ b/src/lib/client/heicConverter.ts @@ -1,10 +1,12 @@ /** - * Convertit un Blob HEIC/HEIF en Blob JPEG via heic2any. + * Convertit un Blob HEIC/HEIF en Blob JPEG. + * Tente d'abord la conversion native du navigateur (instantané sur Safari/macOS), + * puis repasse sur heic2any si le natif échoue (Chrome, Firefox). * À utiliser uniquement côté client (navigateur). */ export async function convertHeicToJpeg(blob: Blob): Promise { if (!(blob instanceof Blob)) { - throw new TypeError('L\'entrée doit être un Blob') + throw new TypeError("L'entrée doit être un Blob") } const type = blob.type.toLowerCase() @@ -12,14 +14,26 @@ export async function convertHeicToJpeg(blob: Blob): Promise { throw new TypeError(`Format attendu : HEIC/HEIF. Reçu : ${blob.type || '(vide)'}`) } + // Méthode 1 : conversion native (Safari 14+, macOS Chrome 105+) + try { + const result = await convertNative(blob) + console.log('[heicConverter] ✅ Conversion native réussie') + return result + } catch (e) { + console.warn(`[heicConverter] Conversion native échouée (${(e as Error).message}), repasse sur heic2any…`) + } + + // Méthode 2 : heic2any fallback (plus lent, ~10-30s) const heic2any = (await import('heic2any')).default const timeout = new Promise((_, reject) => - setTimeout(() => reject(new Error('Timeout conversion HEIC (120s)')), 120_000), + setTimeout( + () => reject(new Error('Timeout conversion HEIC (30s). Essayez de convertir le fichier en JPG avant de le déposer.')), + 30_000, + ), ) const conversion = heic2any({ blob, toType: 'image/jpeg', quality: 0.92 }) - const result = await Promise.race([conversion, timeout]) const output = Array.isArray(result) ? result[0] : result @@ -27,5 +41,24 @@ export async function convertHeicToJpeg(blob: Blob): Promise { throw new Error("heic2any n'a pas retourné un Blob") } + console.log('[heicConverter] ✅ Conversion heic2any réussie') return output } + +async function convertNative(blob: Blob): Promise { + // Force le type MIME pour que le navigateur reconnaisse le format + const typed = blob.type ? blob : new Blob([blob], { type: 'image/heic' }) + const bitmap = await createImageBitmap(typed) + const canvas = document.createElement('canvas') + canvas.width = bitmap.width + canvas.height = bitmap.height + canvas.getContext('2d')!.drawImage(bitmap, 0, 0) + bitmap.close() + return new Promise((resolve, reject) => { + canvas.toBlob( + b => (b ? resolve(b) : reject(new Error('canvas.toBlob a retourné null'))), + 'image/jpeg', + 0.92, + ) + }) +}