/** * Convertit un fichier/blob HEIC/HEIF en Blob JPEG. * @param {File|Blob} fileOrBlob — fichier HEIC/HEIF (File depuis l'input, ou Blob extrait d'un ZIP) * @returns {Promise} * @throws {TypeError} si l'entrée n'est pas un Blob HEIC/HEIF * @throws {Error} si la conversion échoue ou dépasse 30s */ export async function convertHeicToJpeg(fileOrBlob) { if (!(fileOrBlob instanceof Blob)) { throw new TypeError("L'entrée doit être un Blob ou un File"); } // Certains iPhone envoient un type MIME vide pour les HEIC — on l'autorise const type = fileOrBlob.type.toLowerCase(); if (type !== '' && !['image/heic', 'image/heif'].includes(type)) { throw new TypeError(`Format attendu : HEIC/HEIF. Reçu : ${fileOrBlob.type || '(vide)'}`); } const label = fileOrBlob instanceof File ? `${fileOrBlob.name} (${fileOrBlob.type || 'type vide'}, ${(fileOrBlob.size / 1024).toFixed(0)} Ko)` : `blob HEIC (${(fileOrBlob.size / 1024).toFixed(0)} Ko)`; console.log(`[heicConverter] Début conversion : ${label}`); const timeout = new Promise((_, reject) => setTimeout(() => reject(new Error('Timeout : conversion > 120s. Vérifiez que le fichier est bien un HEIC valide.')), 120_000) ); const conversion = heic2any({ blob: fileOrBlob, toType: 'image/jpeg', quality: 0.92, }); const result = await Promise.race([conversion, timeout]); const blob = Array.isArray(result) ? result[0] : result; if (!(blob instanceof Blob)) { throw new Error("heic2any n'a pas retourné un Blob"); } console.log(`[heicConverter] ✅ Conversion réussie → ${(blob.size / 1024).toFixed(0)} Ko`); return blob; }