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 che usa 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 è solo 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 estensibilità permette a HEIC di fare cose che JPEG non ha mai potuto fare. Il parsing richiede la comprensione della gerarchia dei box, non solo la lettura di un flusso di bit grezzo.
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 è ~3,5 MB. In HEIC, ~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
HEIC è superioreriormente tecnicamente a JPEG in quasi ogni metrica, tranne 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. Brand sbagliato = rifiuto immediato, nessun ciclo CPU sprecato.
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:
- Rilascia file — foto singole o intere cartelle, l'elaborazione batch è automatica.
- Validazione della firma — il controllo esatto dei byte sopra descritto viene eseguito su ogni file. I file non-HEIC vengono immediatamente rifiutati con un messaggio chiaro.
- Decodifica lato client — una build WebAssembly di libheif viene eseguita localmente. Nessun caricamento. Nessun server.
- Output che preserva la qualità — JPG al 90% di qualità preserva risoluzione e accuratezza del colore originali.
- Download batch — file individuali o un unico archivio ZIP.
Per output senza perdita con trasparenza: HEIC a PNG. Per dimensioni ottimizzate per il web: HEIC a WebP.
I tuoi file non lasciano mai il tuo dispositivo. Questo è il punto.


