Apri un file HEIC in un editor esadecimale. I primi dodici byte:
00 00 00 18 66 74 79 70 68 65 69 63
Questo è ISOBMFF, lo stesso standard di contenitore usato da MP4. 0x18 (24 byte) è la dimensione della box, ftyp è la box del tipo di file, heic è il brand principale. Un file HEIC non è una codifica di immagine. È un contenitore con un marker di brand che ospita immagini codificate in HEVC.
Cos'è realmente HEIC
HEIC = High Efficiency Image Container. È l'implementazione con marchio Apple di HEIF, standardizzato dal MPEG come ISO/IEC 23008-12 nel 2015. JPEG è sia un algoritmo di compressione che un formato di file. HEIC, invece, è principalmente un contenitore. La compressione interna è HEVC (H.265), lo stesso codec utilizzato per il video 4K.
Un singolo file HEIC può memorizzare:
- Un'immagine primaria
- Più immagini alternative (scatti in sequenza)
- Sequenze di immagini (Live Photos: immagine fissa + video di 3 secondi)
- Canali alpha e mappe di profondità
- Profondità di colore a 16 bit per canale (JPEG è limitato a 8 bit)
Il contenitore usa una struttura di box, esattamente come MP4:
| Box | Scopo |
|---|---|
ftyp | Tipo di file e brand compatibili |
meta | Metadati e proprietà dell'elemento |
mdat | Dati immagine codificati grezzi (flusso di bit HEVC) |
iloc | Posizioni degli elementi all'interno di mdat |
Questa struttura consente funzionalità che JPEG non supporta. Per fare il parsing devi conoscere la gerarchia dei box, non bastano i byte grezzi.
Perché Apple ha cambiato
Apple non ha inventato HEIC. MPEG ha pubblicato HEIF nel 2015. Apple lo ha adottato come formato fotocamera predefinito dell'iPhone in iOS 11 (2017).
Il cambiamento era aritmetico, non marketing. Una tipica foto iPhone da 12 MP in JPEG pesa circa 3,5 MB. In HEIC, circa 1,8 MB. Con 50 GB di piano iCloud gratuito, questa differenza significa circa 14.000 foto aggiuntive. Apple vende piani di archiviazione. Il conto si fa da sé.
C'era anche l'allineamento dell'ecosistema. Apple aveva già adottato HEVC per il video (H.265 in iOS 11). Riutilizzare lo stesso codec per le immagini fisse significava blocchi di decodifica hardware condivisi sui chip della serie A, minore consumo di energia e un unico percorso di licenza.
I compromessi
Dal punto di vista tecnico, HEIC supera JPEG su quasi ogni fronte. Il problema è la compatibilità.
| Aspetto | HEIC | JPEG |
|---|---|---|
| Efficienza di compressione | ~40–50% più piccolo alla stessa qualità | Baseline |
| Profondità di colore | Fino a 16 bit | 8 bit |
| Trasparenza | Sì | No |
| Immagini multiple per file | Sì | No |
| Riediting senza perdita | Sì | No |
| Supporto Windows nativo | Richiede estensione HEIF | Universale |
| Supporto browser web | Solo Safari | Universale |
| Supporto Android | Nativo su 9+ | Universale |
| Licenza brevettuale | Pool di brevetti HEVC | JPEG è royalty-free |
L'HEVC è coperto da più pool di brevetti (MPEG LA, Access Advance). Apple copre le tariffe per gli utenti iOS. Le terze parti non hanno quel vantaggio. Questa incertezza è in gran parte il motivo per cui l'adozione al di fuori dell'ecosistema Apple è stagnata.
Rilevare HEIC leggendo la firma del file
Non fidarti dell'estensione .heic. Leggi i primi 32 byte e analizza la box ftyp.
Layout esatto dei byte di un'intestazione di file HEIC valida:
Bytes 0–3: Dimensione della box (uint32 big-endian)
Bytes 4–7: Tipo di box: "ftyp" (0x66 0x74 0x79 0x70)
Bytes 8–11: Brand principale: "heic" o "heif" o "mif1"
Bytes 12–15: Versione minore (generalmente 0x00000000)
Bytes 16+: Elenco di brand compatibili (es. "mif1", "heic", "MiHE")
TypeScript lato browser:
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)
}
Il nostro convertitore esegue questo controllo prima di tentare la decodifica. Se il brand è sbagliato, il file viene rifiutato immediatamente senza sprecare cicli CPU.
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"}
Controllo di livello superiore con filetype:
import filetype
kind = filetype.guess("photo.heic")
if kind and kind.extension in ("heic", "heif"):
print(kind.mime) # image/heic
O con pillow-heif:
from pillow_heif import is_heif
if is_heif("photo.heic"):
# contenitore valido
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);
}
Con fileinfo:
$finfo = new finfo(FILEINFO_MIME_TYPE);
$mime = $finfo->file('photo.heic');
// image/heic o image/heif
ImageMagick CLI
ImageMagick 7+ supporta HEIC se compilato con libheif:
magick identify -verbose photo.heic | grep "Format:"
# Format: HEIC (High Efficiency Image Container)
Senza libheif: no decode delegate for this image format. Nella maggior parte delle distribuzioni Linux, libheif-examples fornisce heif-convert come alternativa.
Il percorso di conversione
Sapere che un file è HEIC non significa che puoi aprirlo. Windows richiede le HEIF Image Extensions. La maggior parte dei browser rifiuta ancora di renderizzare HEIC nei tag <img>. Android 9+ lo gestisce nativamente; i dispositivi più vecchi no.
La soluzione è convertire. Il nostro convertitore da HEIC a JPG gestisce l'intero pipeline nel tuo browser. Puoi trascinare foto singole o intere cartelle, e l'elaborazione batch parte automaticamente. Ogni file viene validato con il controllo byte per byte descritto sopra; i file non HEIC vengono rifiutati subito con un messaggio chiaro. La decodifica avviene lato client tramite una build WebAssembly di libheif, quindi non c'è caricamento verso server esterni. L'output è JPG al 90% di qualità, che conserva risoluzione e accuratezza del colore originali. Puoi scaricare i file singoli o un unico archivio ZIP.
Per output senza perdita con trasparenza: HEIC a PNG. Per dimensioni ottimizzate per il web: HEIC a WebP.
I file restano sempre sul tuo dispositivo, senza mai raggiungere un server.



