Ouvrez un fichier HEIC dans un éditeur hexadécimal. Les douze premiers octets :
00 00 00 18 66 74 79 70 68 65 69 63
C'est l'ISOBMFF — le même standard de conteneur que MP4 utilise. 0x18 (24 octets) est la taille de la boîte, ftyp est la boîte de type de fichier, heic est la marque principale. Un fichier HEIC n'est pas un encodage d'image. C'est un conteneur avec un marqueur de marque, contenant des images encodées en HEVC.
Ce qu'est réellement le HEIC
HEIC = High Efficiency Image Container. La version sous marque Apple de HEIF, standardisée par le MPEG en 2015 sous la référence ISO/IEC 23008-12. JPEG est à la fois un algorithme de compression et un format de fichier. Le HEIC n'est qu'un conteneur. La compression interne est du HEVC (H.265), le même codec utilisé pour la vidéo 4K.
Un seul fichier HEIC peut stocker :
- Une image principale
- Plusieurs images alternatives (photos en rafale)
- Des séquences d'images (Live Photos : image fixe + vidéo de 3 secondes)
- Des canaux alpha et des cartes de profondeur
- Une profondeur de couleur de 16 bits par canal (JPEG est limité à 8 bits)
Le conteneur utilise des boîtes — même structure que MP4 :
| Box | Fonction |
|---|---|
ftyp | Type de fichier et marques compatibles |
meta | Métadonnées et propriétés des éléments |
mdat | Données d'image brutes encodées (flux binaire HEVC) |
iloc | Emplacements des éléments dans mdat |
Cette extensibilité permet au HEIC de faire des choses que le JPEG n'a jamais pu faire. L'analyse nécessite de comprendre la hiérarchie des boîtes, pas seulement de lire un flux binaire brut.
Pourquoi Apple a changé
Apple n'a pas inventé le HEIC. Le MPEG a publié le HEIF en 2015. Apple l'a adopté comme format par défaut de l'iPhone dans iOS 11 (2017).
Le changement était arithmétique, pas marketing. Une photo iPhone de 12 MP en JPEG fait ~3,5 Mo. En HEIC, ~1,8 Mo. À 50 Go de stockage iCloud gratuit, cet écart représente environ 14 000 photos supplémentaires. Apple vend des paliers de stockage. Le calcul se fait tout seul.
Il y avait aussi l'alignement de l'écosystème. Apple avait déjà adopté le HEVC pour la vidéo (H.265 dans iOS 11). Réutiliser le même codec pour les images fixes signifiait des blocs de décodage matériel partagés sur les puces de série A, une consommation électrique réduite et un seul chemin de licence.
Les compromis
Le HEIC bat le JPEG sur presque toutes les métriques, sauf la compatibilité.
| Aspect | HEIC | JPEG |
|---|---|---|
| Efficacité de compression | ~40–50% plus petit à qualité égale | Référence |
| Profondeur de couleur | Jusqu'à 16 bits | 8 bits |
| Transparence | Oui | Non |
| Images multiples par fichier | Oui | Non |
| Réédition sans perte | Oui | Non |
| Support natif Windows | Nécessite l'extension HEIF | Universel |
| Support navigateur web | Safari uniquement | Universel |
| Support Android | Natif à partir de 9+ | Universel |
| Licence de brevet | Pool de brevets HEVC | JPEG est libre de droits |
Le HEVC est couvert par plusieurs pools de brevets (MPEG LA, Access Advance). Apple couvre les frais pour les utilisateurs iOS. Les tiers n'ont pas cet avantage. Cette incertitude est en grande partie la raison pour laquelle l'adoption en dehors de l'écosystème Apple a stagné.
Détecter le HEIC en lisant la signature du fichier
Ne faites pas confiance à l'extension .heic. Lisez les 32 premiers octets et analysez la boîte ftyp.
Disposition exacte des octets d'un en-tête HEIC valide :
Bytes 0–3: Taille de la boîte (uint32 big-endian)
Bytes 4–7: Type de boîte : "ftyp" (0x66 0x74 0x79 0x70)
Bytes 8–11: Marque principale : "heic" ou "heif" ou "mif1"
Bytes 12–15: Version mineure (généralement 0x00000000)
Bytes 16+: Liste des marques compatibles (ex. "mif1", "heic", "MiHE")
TypeScript côté navigateur :
async function isHeic(file: File): Promise<boolean> {
const buffer = await file.slice(0, 32).arrayBuffer()
const bytes = new Uint8Array(buffer)
if (String.fromCharCode(...bytes.slice(4, 8)) !== "ftyp") return false
const brand = String.fromCharCode(...bytes.slice(8, 12))
return ["heic", "heif", "mif1", "msf1"].includes(brand)
}
Notre convertisseur exécute cette vérification avant de tenter le décodage. Mauvaise marque = rejet immédiat, aucun cycle CPU gaspillé.
Python
def is_heic(path: str) -> bool:
with open(path, "rb") as f:
header = f.read(32)
if len(header) < 12:
return False
if header[4:8].decode("ascii", errors="ignore") != "ftyp":
return False
return header[8:12].decode("ascii", errors="ignore") in {"heic", "heif", "mif1", "msf1"}
Vérification de niveau supérieur avec filetype :
import filetype
kind = filetype.guess("photo.heic")
if kind and kind.extension in ("heic", "heif"):
print(kind.mime) # image/heic
Ou pillow-heif :
from pillow_heif import is_heif
if is_heif("photo.heic"):
# conteneur valide
pass
Go
func isHeic(path string) bool {
f, err := os.Open(path)
if err != nil {
return false
}
defer f.Close()
buf := make([]byte, 32)
if _, err := f.Read(buf); err != nil {
return false
}
if string(buf[4:8]) != "ftyp" {
return false
}
brand := string(buf[8:12])
return brand == "heic" || brand == "heif" || brand == "mif1" || brand == "msf1"
}
PHP
function isHeic(string $path): bool {
$header = file_get_contents($path, false, null, 0, 32);
if (strlen($header) < 12) return false;
if (substr($header, 4, 4) !== 'ftyp') return false;
return in_array(substr($header, 8, 4), ['heic', 'heif', 'mif1', 'msf1'], true);
}
Avec fileinfo :
$finfo = new finfo(FILEINFO_MIME_TYPE);
$mime = $finfo->file('photo.heic');
// image/heic ou image/heif
ImageMagick CLI
ImageMagick 7+ prend en charge le HEIC s'il est compilé avec libheif :
magick identify -verbose photo.heic | grep "Format:"
# Format: HEIC (High Efficiency Image Container)
Sans libheif : no decode delegate for this image format. Sur la plupart des distributions Linux, libheif-examples fournit heif-convert comme alternative.
Le chemin de conversion
Savoir qu'un fichier est HEIC ne l'ouvre pas. Windows a besoin des HEIF Image Extensions. La plupart des navigateurs refusent de rendre le HEIC dans les balises <img>. Android 9+ le gère nativement ; les anciens appareils non.
La solution : convertir. Notre convertisseur HEIC vers JPG gère l'intégralité du pipeline dans votre navigateur :
- Déposer des fichiers — photos uniques ou dossiers entiers, le traitement par lots est automatique.
- Validation de signature — la vérification d'octets exacte ci-dessus s'exécute sur chaque fichier. Les fichiers non-HEIC sont immédiatement rejetés avec un message clair.
- Décodage côté client — une build WebAssembly de libheif s'exécute localement. Aucun téléversement. Aucun serveur.
- Sortie préservant la qualité — JPG à 90% de qualité conserve la résolution et la précision des couleurs d'origine.
- Téléchargement par lots — fichiers individuels ou une archive ZIP unique.
Pour une sortie sans perte avec transparence : HEIC vers PNG. Pour des tailles optimisées pour le web : HEIC vers WebP.
Vos fichiers ne quittent jamais votre appareil. C'est tout le point.


