Approfondimenti

Cos'è HEIC? Un approfondimento tecnico su firme dei file, rilevamento e conversione

koboshiCo-founder
·6 min di lettura
Cos'è HEIC? Un approfondimento tecnico su firme dei file, rilevamento e conversione
Riepilogo

HEIC non è solo un JPEG più piccolo. È un formato contenitore basato su ISO Base Media File Format con immagini codificate in HEVC al suo interno. Ecco come funziona, come rilevarlo leggendo byte raw, e come convertirlo quando la compatibilità fallisce.

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:

BoxScopo
ftypTipo di file e brand compatibili
metaMetadati e proprietà dell'elemento
mdatDati immagine codificati grezzi (flusso di bit HEVC)
ilocPosizioni 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à.

AspettoHEICJPEG
Efficienza di compressione~40–50% più piccolo alla stessa qualitàBaseline
Profondità di coloreFino a 16 bit8 bit
TrasparenzaNo
Immagini multiple per fileNo
Riediting senza perditaNo
Supporto Windows nativoRichiede estensione HEIFUniversale
Supporto browser webSolo SafariUniversale
Supporto AndroidNativo su 9+Universale
Licenza brevettualePool di brevetti HEVCJPEG è 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:

  1. Rilascia file — foto singole o intere cartelle, l'elaborazione batch è automatica.
  2. 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.
  3. Decodifica lato client — una build WebAssembly di libheif viene eseguita localmente. Nessun caricamento. Nessun server.
  4. Output che preserva la qualità — JPG al 90% di qualità preserva risoluzione e accuratezza del colore originali.
  5. 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.

Altri post del blog da leggere